org.glassfish.appclient.client.acc.Launchable Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of payara-embedded-web Show documentation
Show all versions of payara-embedded-web Show documentation
Embedded-Web Distribution of the Payara Project for IBM JDK
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 1997-2012 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can
* obtain a copy of the License at
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
* or packager/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package org.glassfish.appclient.client.acc;
import com.sun.enterprise.deploy.shared.ArchiveFactory;
import com.sun.enterprise.deployment.ApplicationClientDescriptor;
import com.sun.enterprise.deployment.archivist.AppClientArchivist;
import com.sun.enterprise.module.bootstrap.BootException;
import com.sun.enterprise.util.LocalStringManager;
import com.sun.enterprise.util.LocalStringManagerImpl;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLClassLoader;
import java.security.AccessController;
import java.security.PrivilegedAction;
import javax.xml.stream.XMLStreamException;
import org.glassfish.api.deployment.archive.ReadableArchive;
import org.glassfish.hk2.api.ServiceLocator;
import org.xml.sax.SAXParseException;
/**
* Something launchable by the ACC - an app client archive or a class.
*
* @author tjquinn
*/
interface Launchable {
/**
* Returns the main class for this Launchable.
* @return the main class
*
* @throws java.lang.ClassNotFoundException
*/
Class getMainClass() throws ClassNotFoundException;
ApplicationClientDescriptor getDescriptor(URLClassLoader loader) throws IOException, SAXParseException;
void validateDescriptor();
URI getURI();
String getAnchorDir();
static class LaunchableUtil {
private static final LocalStringManager localStrings = new LocalStringManagerImpl(Launchable.LaunchableUtil.class);
static Launchable newLaunchable(final URI uri,
final String callerSuppliedMainClassName,
final String callerSuppliedAppName,
final ServiceLocator habitat) throws IOException, BootException, URISyntaxException, XMLStreamException, SAXParseException, UserError {
/*
* Make sure the requested URI exists and is readable.
*/
ArchiveFactory af = ACCModulesManager.getService(ArchiveFactory.class);
ReadableArchive ra = null;
try {
ra = af.openArchive(uri);
} catch (IOException e) {
final String msg = localStrings.getLocalString(
Launchable.class,
"appclient.cannotFindJarFile",
"Could not locate the requested client JAR file {0}; please try again with an existing, valid client JAR",
new Object[] {uri});
throw new UserError(msg);
}
Launchable result = FacadeLaunchable.newFacade(
habitat, ra, callerSuppliedMainClassName, callerSuppliedAppName);
if (result == null) {
/*
* If newFacade found a facade JAR but could not find a suitable
* client it will have thrown a UserError. If we're here, then
* newFacade did not have a facade to work with. So the caller-
* provided URI should refer to an undeployed EAR or an undeployed
* app client JAR.
*/
result = UndeployedLaunchable.newUndeployedLaunchable(habitat, ra,
callerSuppliedMainClassName, callerSuppliedAppName,
Thread.currentThread().getContextClassLoader());
}
if ( ! (result instanceof JWSFacadeLaunchable)) {
URL clientOrFacadeURL = new URL("file:" + result.getURI().getSchemeSpecificPart());
/*
* For the embedded case especially there might not be an
* ACCClassLoader instance yet. Create one if needed
* before proceeding.
*/
ACCClassLoader cl = ACCClassLoader.instance();
if (cl == null) {
cl = ACCClassLoader.newInstance(Thread.currentThread().getContextClassLoader(), false);
}
cl.appendURL(clientOrFacadeURL);
}
return result;
}
static Launchable newLaunchable(final ServiceLocator habitat, final Class mainClass) {
return new MainClassLaunchable(habitat, mainClass);
}
static ApplicationClientDescriptor openWithAnnoProcessingAndTempLoader(
final AppClientArchivist archivist, final URLClassLoader loader,
final ReadableArchive facadeRA,
final ReadableArchive clientRA) throws IOException, SAXParseException {
archivist.setAnnotationProcessingRequested(true);
final ACCClassLoader tempLoader = AccessController.doPrivileged(
new PrivilegedAction() {
@Override
public ACCClassLoader run() {
return new ACCClassLoader(loader.getURLs(), loader.getParent());
}
}
);
archivist.setClassLoader(tempLoader);
final ApplicationClientDescriptor acDesc = archivist.open(facadeRA, clientRA);
archivist.setDescriptor(acDesc);
return acDesc;
}
static boolean matchesAnyClass(final ReadableArchive archive, final String callerSpecifiedMainClassName) throws IOException {
return (callerSpecifiedMainClassName != null) &&
archive.exists(classNameToArchivePath(callerSpecifiedMainClassName));
}
static String moduleID(
final URI groupFacadeURI,
final URI clientURI,
final ApplicationClientDescriptor clientFacadeDescriptor) {
String moduleID = clientFacadeDescriptor.getModuleID();
/*
* If the moduleID was never set explicitly in the descriptor then
* it will fall back to the URI of the archive...ending in .jar we
* presume. In that case, change the module ID to be the path
* relative to the downloaded root directory.
*/
if (moduleID.endsWith(".jar")) {
moduleID = deriveModuleID(groupFacadeURI, clientURI);
}
return moduleID;
}
static boolean matchesName(
final String moduleID,
final URI groupFacadeURI,
final ApplicationClientDescriptor clientFacadeDescriptor,
final String appClientName) throws IOException, SAXParseException {
/*
* The ReadableArchive argument should be the facade archive and
* not the developer's original one, because when we try to open it
* the archivist needs to have the augmented descriptor (which is
* in the client facade) not the minimal or non-existent
* descriptor (which could be in the developer's original client).
*/
final String displayName = clientFacadeDescriptor.getDisplayName();
return ( (moduleID != null && moduleID.equals(appClientName))
|| (displayName != null && displayName.equals(appClientName)));
}
private static String classNameToArchivePath(final String className) {
return new StringBuilder(className.replace('.', '/'))
.append(".class").toString();
}
private static String deriveModuleID(final URI groupFacadeURI,
final URI clientArchiveURI) {
/*
* The groupFacadeURI will be something like x/y/appName.jar and
* the clientArchiveURI will be something like x/y/appName/a/b/clientName.jar.
* The derived moduleID should be the client archive's URI relative
* to the x/y/appName directory with no file type: in this example a/b/clientName
*/
URI dirURI = stripDotJar(groupFacadeURI);
URI clientArchiveRelativeURI = stripDotJar(
dirURI.relativize(URI.create("file:" + clientArchiveURI.getRawSchemeSpecificPart())));
return clientArchiveRelativeURI.getRawSchemeSpecificPart();
}
private static URI stripDotJar(final URI uri) {
String pathWithoutDotJar = uri.getRawSchemeSpecificPart();
pathWithoutDotJar = pathWithoutDotJar.substring(0,
pathWithoutDotJar.length() - ".jar".length());
return URI.create("file:" + pathWithoutDotJar);
}
}
}