Fields Summary |
---|
public static final String | USER_CODE_IS_SIGNED_PROPERTYNAME |
private static final String | SIGNED_USER_CODE_PERMISSION_TEMPLATE_NAME |
private static final String | UNSIGNED_USER_CODE_PERMISSION_TEMPLATE_NAME |
private static final String | CODE_BASE_PLACEHOLDER_NAME |
protected Logger | _loggerlogger |
private com.sun.enterprise.deployment.deploy.shared.AbstractArchive | appClientArchiveabstract representation of the storage location |
private File | appClientFileoriginal appclient (file or directory) |
private com.sun.enterprise.deployment.archivist.Archivist | archivistabstract archivist able to operate on the module in the location
(specified by archive |
protected String | mainClassFromCommandLinemain class name as the user specified it on the command line |
protected String | mainClassNameToRunmain class to be used - could come from the command line or from the
manifest of the selected app client archive |
private ClassLoader | classLoaderclass loader - cached |
protected boolean | isJWSindicates if the app client has been launched using Java Web Start |
protected com.sun.enterprise.util.i18n.StringManager | localStringsaccess to the localizable strings |
private PersistenceUnitLoader.ApplicationInfo | puAppInfo |
protected static final boolean | _keepExplodedDir |
Methods Summary |
---|
private boolean | appClientDependsOnPersistenceUnit(ApplicationClientDescriptor acDescr)Reports whether the selected app client depends on a persistence unit
or not.
/*
*If the descriptor contains at least one reference to an entity
*manager then it definitely depends on a persistence unit.
*/
return descriptorContainsPURefcs(acDescr)
|| mainClassContainsPURefcAnnotations(acDescr);
|
protected boolean | classContainsAnnotation(java.lang.String entry, com.sun.enterprise.deployment.util.AnnotationDetector detector, com.sun.enterprise.deployment.deploy.shared.AbstractArchive archive, ApplicationClientDescriptor descriptor)
String acRoot = getAppClientRoot(archive, descriptor);
String entryLocation = acRoot + File.separator + entry;
File entryFile = new File(entryLocation);
return detector.containsAnnotation(entryFile);
|
protected void | close()Closes the instance of AppClientInfo, deleting any temporary directory
created and closing the archive.
try {
if (puAppInfo != null) {
new PersistenceUnitLoaderImpl().unload(puAppInfo);
puAppInfo = null;
}
if (appClientArchive != null) {
appClientArchive.close();
}
if (classLoader != null &&
classLoader instanceof EJBClassLoader) {
((EJBClassLoader) classLoader).done();
}
} finally {
if (deleteAppClientDir()) {
if (appClientArchive != null) {
deleteFile(new File(appClientArchive.getArchiveUri()));
}
}
appClientArchive = null;
}
|
protected void | completeInit(java.net.URL[] persistenceURLs)Finishes initialization work.
The calling logic that instantiates this object must invoke completeInit
after instantiation but before using the object.
//expand if needed. initialize the appClientArchive
appClientArchive = expand(appClientFile);
//Create the class loader to be used for persistence unit checking,
//validation, and running the app client.
classLoader = createClassLoader(appClientArchive, persistenceURLs);
//Populate the deployment descriptor without validation.
//Note that validation is done only after the persistence handling
//has instructed the classloader created above.
populateDescriptor(appClientArchive, archivist, classLoader);
//If the selected app client depends on at least one persistence unit
//then handle the P.U. before proceeding.
if (appClientDependsOnPersistenceUnit(getAppClient())) {
//@@@check to see if the descriptor is metadata-complet=true
//if not, we would have loaded classes into the classloader
//during annotation processing. we need to hault and ask
//the user to deploy the application.
//if (!getAppClient().isFullFlag()) {
// throw new RuntimeException("Please deploy your application");
//}
handlePersistenceUnitDependency();
}
//Now that the persistence handling has run and instrumented the class
//loader - if it had to - it's ok to validate.
archivist.validate(classLoader);
fixupWSDLEntries();
if (isJWS) {
grantRequestedPermissionsToUserCode();
}
|
private java.lang.ClassLoader | createClassLoader(com.sun.enterprise.deployment.deploy.shared.AbstractArchive archive, java.net.URL[] persistenceURLs)
List<String> paths = getClassPaths(archive);
ClassLoader parent = Thread.currentThread().getContextClassLoader();
EJBClassLoader loader = new EJBClassLoader(parent);
final int LIST_SZ = paths.size();
for (int i=0; i<LIST_SZ; i++) {
String path = paths.get(i);
loader.appendURL(new File(path));
}
if (_logger.isLoggable(Level.FINE)) {
for (int i = 0; i < paths.size(); i++) {
_logger.fine("Added path to classloader ==> " + paths.get(i));
}
}
for (URL url : persistenceURLs) {
loader.appendURL(url);
_logger.fine("Added path to classloader ==> " + url);
}
return loader;
|
protected java.io.File | createTmpArchiveDir(java.io.File forArchive)
/*
*Create a temporary file (cannot create temp directories directly),
*use the unique file name as a directory name.
*/
String name = forArchive.getName();
File tmpDir = File.createTempFile("acc-" + name, "");
tmpDir.delete();
tmpDir.mkdirs();
/*
*We will try to delete the directory when we finish with it, but this
*is a back-up.
*/
if (!_keepExplodedDir) {
tmpDir.deleteOnExit();
}
return tmpDir;
|
protected boolean | deleteAppClientDir()
return !_keepExplodedDir;
|
private void | deleteFile(java.io.File f)
if (f.isDirectory()) {
for (File subFile : f.listFiles()) {
deleteFile(subFile);
}
}
f.delete();
|
private boolean | descriptorContainsPURefcs(ApplicationClientDescriptor descr)Reports whether the app client's descriptor shows a dependence on a
persistence unit.
return ! descr.getEntityManagerFactoryReferenceDescriptors().isEmpty();
|
protected abstract com.sun.enterprise.deployment.deploy.shared.AbstractArchive | expand(java.io.File file)Expands the contents of the source archive into a temporary
directory, using the same format as backend server expansions.
|
private void | fixupWSDLEntries()Adjusts the web services WSDL entries corresponding to where they
actually reside.
ApplicationClientDescriptor ac = getAppClient();
URI uri = (new File(getAppClientRoot(appClientArchive, ac))).toURI();
File moduleFile = new File(uri);
for (Iterator itr = ac.getServiceReferenceDescriptors().iterator();
itr.hasNext();) {
ServiceReferenceDescriptor serviceRef =
(ServiceReferenceDescriptor) itr.next();
if (serviceRef.getWsdlFileUri()!=null) {
// In case WebServiceRef does not specify wsdlLocation, we get
// wsdlLocation from @WebClient in wsimport generated source;
// If wsimport was given a local WSDL file, then WsdlURI will
// be an absolute path - in that case it should not be prefixed
// with modileFileDir
String wsdlURI = serviceRef.getWsdlFileUri();
File wsdlFile = new File(wsdlURI);
if(wsdlFile.isAbsolute()) {
serviceRef.setWsdlFileUrl(wsdlFile.toURI().toURL());
} else {
// This is the case where WsdlFileUri is a relative path
// (hence relative to the root of this module or wsimport
// was executed with WSDL in HTTP URL form
serviceRef.setWsdlFileUrl(FileUtil.getEntryAsUrl(
moduleFile, serviceRef.getWsdlFileUri()));
}
}
}
|
protected ApplicationClientDescriptor | getAppClient(com.sun.enterprise.deployment.archivist.Archivist archivist)
return ApplicationClientDescriptor.class.cast(
archivist.getDescriptor());
|
protected ApplicationClientDescriptor | getAppClient()Returns the app client descriptor to be run.
return getAppClient(archivist);
|
protected java.lang.String | getAppClientRoot(com.sun.enterprise.deployment.deploy.shared.AbstractArchive archive, ApplicationClientDescriptor descriptor)
return archive.getArchiveUri();
|
protected java.lang.ClassLoader | getClassLoader()
return classLoader;
|
protected java.util.List | getClassPaths(com.sun.enterprise.deployment.deploy.shared.AbstractArchive archive)
List<String> paths = new ArrayList();
paths.add(archive.getArchiveUri());
return paths;
|
protected java.lang.String | getMainClassNameToRun(ApplicationClientDescriptor acDescr)Returns the main class that should be executed.
if (mainClassNameToRun == null) {
if (mainClassFromCommandLine != null) {
mainClassNameToRun = mainClassFromCommandLine;
_logger.fine("Main class is " + mainClassNameToRun + " from command line");
} else {
/*
*Find out which class to execute from the descriptor.
*/
mainClassNameToRun = getAppClient().getMainClassName();
_logger.fine("Main class is " + mainClassNameToRun + " from descriptor");
}
}
return mainClassNameToRun;
|
private void | grantRequestedPermissionsToUserCode()Granting the appropriate level of permissions to user code, emulating
the Java Web Start behavior as required in the JNLP spec.
Classes from the user's app client jar are loaded using the EJBClassLoader
rather than the Java Web Start class loader. As a result, Java Web Start
cannot grant the appropriate level of permissions to the user code since
it is the JWS class loader that does that. So we need to grant the user
code the appropriate level of permissions, based on whether the user's
app client jar was signed or not.
/*
*Create a temporary file containing permissions grants. We will use
*this temp file to refresh the Policy objects's settings. The temp
*file will contain one segment for each element in the class path
*for the user code (from the expanded generated app client jar).
*The permissions granted will be the same for all class path elements,
*and the specific settings will either be the sandbox permissions
*as described in the JNLP spec or full permissions.
*/
boolean userJarIsSigned = Boolean.getBoolean(USER_CODE_IS_SIGNED_PROPERTYNAME);
boolean retainTempFiles = Boolean.getBoolean(MainWithModuleSupport.APPCLIENT_RETAIN_TEMP_FILES_PROPERTYNAME);
/*
*Use a template to construct each part of the policy file, choosing the
*template based on whether the user code is signed or not.
*/
String templateName = (userJarIsSigned ? SIGNED_USER_CODE_PERMISSION_TEMPLATE_NAME : UNSIGNED_USER_CODE_PERMISSION_TEMPLATE_NAME);
String template = Util.loadResource(JWSACCMain.class, templateName);
/*
*Create the temporary policy file to write to.
*/
File policyFile = File.createTempFile("accjws-user", ".policy");
if ( ! retainTempFiles) {
policyFile.deleteOnExit();
}
PrintStream ps = null;
try {
ps = new PrintStream(policyFile);
Properties p = new Properties();
/*
*Use the list of class paths already set up on the EJBClassLoader.
*Then for each element in the class path, write a part of the policy
*file granting the privs specified in the selected template to the code path.
*/
EJBClassLoader loader = (EJBClassLoader) getClassLoader();
for (URL classPathElement : loader.getURLs()) {
/*
*Convert the URL into a proper codebase expression suitable for
*a grant clause in the policy file.
*/
String codeBase = Util.URLtoCodeBase(classPathElement);
if (codeBase != null) {
p.setProperty(CODE_BASE_PLACEHOLDER_NAME, codeBase);
String policyPart = Util.replaceTokens(template, p);
ps.println(policyPart);
}
}
/*
*Close the temp file and use it to refresh the current Policy object.
*/
ps.close();
JWSACCMain.refreshPolicy(policyFile);
if ( ! retainTempFiles) {
policyFile.delete();
}
} finally {
if (ps != null) {
ps.close();
}
}
|
private void | handlePersistenceUnitDependency()Processes persistence unit handling for the ACC.
this.puAppInfo = new ApplicationInfoImpl(this);
new PersistenceUnitLoaderImpl().load(puAppInfo);
|
private boolean | mainClassContainsPURefcAnnotations(ApplicationClientDescriptor acDescr)Reports whether the main class in the archive contains annotations that
refer to persistence units.
AppClientPersistenceDependencyAnnotationDetector annoDetector =
new AppClientPersistenceDependencyAnnotationDetector();
//e.g. FROM a.b.Foo or Foo TO a/b/Foo.class or Foo.class
String mainClassEntryName =
acDescr.getMainClassName().replace('.", '/") + ".class";
return classContainsAnnotation
(mainClassEntryName, annoDetector, appClientArchive, acDescr);
|
protected void | messageDescriptor(RootDeploymentDescriptor d, com.sun.enterprise.deployment.archivist.Archivist archivist, com.sun.enterprise.deployment.deploy.shared.AbstractArchive archive)
//default behavor: no op
|
private RootDeploymentDescriptor | populateDescriptor(com.sun.enterprise.deployment.deploy.shared.AbstractArchive archive, com.sun.enterprise.deployment.archivist.Archivist theArchivist, java.lang.ClassLoader loader)
//@@@ Optimize it later.
//Here the application.xml is read twice for NestedAppClientInfo.
//Once already in expand() method.
theArchivist.setAnnotationProcessingRequested(true);
//@@@ setting of the classloader would trigger annotation processing
//for appclients that have only partial deployment descriptors or no
//descriptors at all.
//Note that the annotation processing is bypassed if the descriptors
//are meta-complete=true", which will be the case for anything that is
//generated by the backend, i.e. if the appclient being executed here
//is a generated jar produced by the appserver, obtained by deploying
//the original application client and retrieve.
theArchivist.setClassLoader(loader);
//open with Archivist./pen(AbstractArchive) to also ensure the
//validation is not called
//return archivist.open(archive);
RootDeploymentDescriptor d = null;
try {
d = theArchivist.open(archive);
} catch (Exception ex) {
close(); //make sure there is no junk tmp director left
throw ex;
}
//depend on the type of the appclient, additional work needs
//to be done.
messageDescriptor(d, theArchivist, archive);
theArchivist.setDescriptor(d);
return d;
|
public java.lang.String | toString()
String lineSep = System.getProperty("line.separator");
StringBuilder result = new StringBuilder();
result.append(this.getClass().getName() + ": " + lineSep);
result.append(" isJWS: " + isJWS);
result.append(" archive file: " + appClientFile.getAbsolutePath() + lineSep);
result.append(" archive type: " + appClientArchive.getClass().getName() + lineSep);
result.append(" archivist type: " + archivist.getClass().getName() + lineSep);
result.append(" main class to be run: " + mainClassNameToRun + lineSep);
result.append(" temporary archive directory: " + appClientArchive.getArchiveUri() + lineSep);
result.append(" class loader type: " + classLoader.getClass().getName() + lineSep);
return result.toString();
|