All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.glassfish.appclient.client.acc.Launchable Maven / Gradle / Ivy

/*
 * 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);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy