final ReadableArchive ra,
final String callerSuppliedMainClassName,
final String callerSuppliedAppName,
final ClassLoader classLoader) throws IOException, SAXParseException, UserError {
ArchivistFactory af = Util.getArchivistFactory();
/*
* Try letting the factory decide what type of archive this is. That
* will often allow an app client or an EAR archive to be detected
* automatically.
*/
Archivist archivist = af.getArchivist(ModuleType.CAR.toString(), classLoader);
if (archivist == null) {
throw new UserError(localStrings.get("appclient.invalidArchive",
ra.getURI().toASCIIString()));
}
final ArchiveType moduleType = archivist.getModuleType();
if (moduleType != null && moduleType.equals(DOLUtils.carType())) {
return new UndeployedLaunchable(habitat, ra,
(AppClientArchivist) archivist, callerSuppliedMainClassName);
} else if (moduleType != null && moduleType.equals(DOLUtils.earType())) {
/*
* Locate the app client submodule that matches the main class name
* or the app client name.
*/
Application app = (Application) archivist.open(ra);
for (ModuleDescriptor<BundleDescriptor> md : app.getModules()) {
if ( ! md.getModuleType().equals(DOLUtils.carType())) {
continue;
}
ApplicationClientDescriptor acd = (ApplicationClientDescriptor) md.getDescriptor();
final String displayName = acd.getDisplayName();
final String appName = acd.getModuleID();
ArchiveFactory archiveFactory = Util.getArchiveFactory();
ReadableArchive clientRA = archiveFactory.openArchive(ra.getURI().resolve(md.getArchiveUri()));
/*
* Choose this nested app client if the caller-supplied name
* matches, or if the caller-supplied main class matches, or
* if neither was provided.
*/
final boolean useThisClient =
(displayName != null && displayName.equals(callerSuppliedAppName))
|| (appName != null && appName.equals(callerSuppliedAppName))
|| (callerSuppliedMainClassName != null && clientRA.exists(classToResource(callerSuppliedMainClassName))
|| (callerSuppliedAppName == null && callerSuppliedMainClassName == null));
if (useThisClient) {
return new UndeployedLaunchable(habitat, clientRA, acd,
callerSuppliedMainClassName);
}
clientRA.close();
}
throw new UserError(localStrings.get("appclient.noMatchingClientInEAR",
ra.getURI(), callerSuppliedMainClassName, callerSuppliedAppName));
} else {
/*
* There is a possibility that the user is trying to launch an
* archive that is more than one type of archive: such as an EJB
* but also an app client (because the manifest identifies a main
* class, for example).
*
* Earlier the archivist factory might have returned the other type
* of archivist - such as the EJB archivist. Now see if the app
* client archivist will work when selected directly.
*/
archivist = af.getArchivist(DOLUtils.carType());
/*
* Try to open the archive as an app client archive just to see
* if it works.
*/
RootDeploymentDescriptor tempACD = archivist.open(ra);
if (tempACD != null && tempACD instanceof ApplicationClientDescriptor) {
/*
* Start with a fresh archivist - unopened - so we can request
* anno processing, etc. before opening it for real.
*/
archivist = af.getArchivist(DOLUtils.carType());
return new UndeployedLaunchable(habitat, ra, (AppClientArchivist) archivist,
callerSuppliedMainClassName);
}
throw new UserError(
localStrings.get("appclient.unexpectedArchive", ra.getURI()));