-
Notifications
You must be signed in to change notification settings - Fork 138
/
ACCPersistenceArchivist.java
202 lines (171 loc) · 8.21 KB
/
ACCPersistenceArchivist.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
/*
* Copyright (c) 2022 Contributors to the Eclipse Foundation
* Copyright (c) 2009, 2018 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
* version 2 with the GNU Classpath Exception, which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/
package com.sun.enterprise.deployment.archivist;
import com.sun.enterprise.deploy.shared.ArchiveFactory;
import com.sun.enterprise.deployment.ApplicationClientDescriptor;
import com.sun.enterprise.deployment.deploy.shared.MultiReadableArchive;
import com.sun.enterprise.deployment.util.DOLUtils;
import jakarta.inject.Inject;
import java.io.IOException;
import java.net.URI;
import java.util.HashMap;
import java.util.Map;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
import java.util.logging.Level;
import org.glassfish.api.admin.ProcessEnvironment;
import org.glassfish.api.admin.ProcessEnvironment.ProcessType;
import org.glassfish.api.deployment.archive.ArchiveType;
import org.glassfish.api.deployment.archive.ReadableArchive;
import org.glassfish.deployment.common.RootDeploymentDescriptor;
import org.jvnet.hk2.annotations.Service;
import org.xml.sax.SAXException;
/**
* PersistenceArchivist for app clients that knows how to scan for PUs in
* the app client itself as well as in library JARs (or top-level JARs from
* the containing EAR) that might accompany the app client.
*/
@Service
@ExtensionsArchivistFor("jpa")
public class ACCPersistenceArchivist extends PersistenceArchivist {
@Inject
private ProcessEnvironment env;
@Inject
private ArchiveFactory archiveFactory;
@Override
public boolean supportsModuleType(ArchiveType moduleType) {
return DOLUtils.carType().equals(moduleType) && env.getProcessType() == ProcessType.ACC ;
}
@Override
public RootDeploymentDescriptor open(Archivist main, ReadableArchive archive, RootDeploymentDescriptor descriptor)
throws IOException, SAXException {
deplLogger.logp(Level.FINE, "ACCPersistencerArchivist", "readPersistenceDeploymentDescriptors", "archive = {0}",
archive.getURI());
// The descriptor had better be an ApplicationClientDescriptor!
if ( ! (descriptor instanceof ApplicationClientDescriptor)) {
return null;
}
final Map<String, ReadableArchive> candidatePersistenceArchives = new HashMap<>();
final ApplicationClientDescriptor acDescr = ApplicationClientDescriptor.class.cast(descriptor);
final Manifest mf = archive.getManifest();
final Attributes mainAttrs = mf.getMainAttributes();
/*
* We must scan the app client archive itself.
*/
URI clientURI = clientURI(archive, acDescr);
candidatePersistenceArchives.put(clientURI.toASCIIString(), archive);
/*
* If this app client
* was deployed as part of an EAR then scan any library JARs and, if the
* client was also deployed or launched in v2-compatibility mode, any
* top-level JARs in the EAR.
* Exactly how we do this depends on whether this is a deployed client
* (which will reside in a client download directory) or a non-deployed
* one (which will reside either as a stand-alone client or within an
* EAR).
*/
if (isDeployed(mainAttrs)) {
if (!isDeployedClientAlsoStandAlone(mainAttrs)) {
addOtherDeployedScanTargets(archive, mainAttrs, candidatePersistenceArchives);
}
} else if (!isStandAlone(acDescr)) {
addOtherNondeployedScanTargets(archive, acDescr, candidatePersistenceArchives);
}
for (Map.Entry<String, ReadableArchive> pathToArchiveEntry : candidatePersistenceArchives.entrySet()) {
readPersistenceDeploymentDescriptor(main, pathToArchiveEntry.getValue(), pathToArchiveEntry.getKey(),
descriptor);
}
return null;
}
private boolean isDeployedClientAlsoStandAlone(final Attributes mainAttrs) {
final String relativePathToGroupFacade = mainAttrs.getValue(AppClientArchivist.GLASSFISH_GROUP_FACADE);
return relativePathToGroupFacade == null;
}
private URI clientURI(final ReadableArchive archive, final ApplicationClientDescriptor acDesc) throws IOException {
if (archive instanceof MultiReadableArchive) {
/*
* Getting the manifest from a MultiReadableArchive returns the
* manifest from the facade.
*/
final Manifest facadeMF = archive.getManifest();
final Attributes facadeMainAttrs = facadeMF.getMainAttributes();
final URI clientRelativeURI = URI.create(
facadeMainAttrs.getValue(AppClientArchivist.GLASSFISH_APPCLIENT));
if (isDeployedClientAlsoStandAlone(facadeMainAttrs)) {
return clientRelativeURI;
}
/*
* We need the relative URI to the developer's client JAR within
* the download directory.
*/
final URI absURIToClient = ((MultiReadableArchive) archive).getURI(1);
final String relativeURIPathToAnchorDir = facadeMainAttrs.getValue(AppClientArchivist.GLASSFISH_ANCHOR_DIR);
final URI absURIToAnchorDir = archive.getURI().resolve(relativeURIPathToAnchorDir);
return absURIToAnchorDir.relativize(absURIToClient);
}
return archive.getURI();
}
private boolean isStandAlone(final ApplicationClientDescriptor ac) {
/*
* For a non-deployed app (this case), the descriptor for a stand-alone
* app client has a null application value.
*/
return ac.getApplication() == null || ac.isStandalone();
}
private boolean isDeployed(final Attributes mainAttrs) throws IOException {
final String gfClient = mainAttrs.getValue(AppClientArchivist.GLASSFISH_APPCLIENT);
return gfClient != null;
}
private void addOtherDeployedScanTargets(
final ReadableArchive archive,
final Attributes mainAttrs,
Map<String,ReadableArchive> candidates) throws IOException {
final String otherPUScanTargets = mainAttrs.getValue(
AppClientArchivist.GLASSFISH_CLIENT_PU_SCAN_TARGETS_NAME);
/*
* Include library JARs - listed in the facade's Class-Path - and
* any additional (typically top-level) JARs to be scanned.
*/
addScanTargetsFromURIList(archive, otherPUScanTargets, candidates);
}
private void addOtherNondeployedScanTargets(final ReadableArchive clientArchive,
final ApplicationClientDescriptor acDescr,
final Map<String,ReadableArchive> candidates) {
/*
* The archive is a non-deployed one. We know from an earlier check
* that this is not a stand-alone app client, so we can use the
* app client archive's parent archive to get to the containing EAR for
* use in a subarchive scanner.
*/
final ReadableArchive earArchive = clientArchive.getParentArchive();
EARBasedPersistenceHelper.addLibraryAndTopLevelCandidates(earArchive,
acDescr.getApplication(),
true,
candidates);
}
private void addScanTargetsFromURIList(final ReadableArchive archive, final String relativeURIList,
final Map<String, ReadableArchive> candidates) throws IOException {
if (relativeURIList == null || relativeURIList.isEmpty()) {
return;
}
final String[] relativeURIs = relativeURIList.split(" ");
for (String uriText : relativeURIs) {
final URI scanTargetURI = archive.getURI().resolve(uriText);
candidates.put(uriText, archiveFactory.openArchive(scanTargetURI));
}
}
}