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

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

There is a newer version: 7.2024.1.Alpha1
Show newest version
/*
 * 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.deployment.Application;
import com.sun.enterprise.deployment.util.DOLUtils;
import com.sun.enterprise.deployment.ApplicationClientDescriptor;
import com.sun.enterprise.deployment.archivist.AppClientArchivist;
import com.sun.enterprise.deployment.archivist.ArchivistFactory;
import com.sun.enterprise.deployment.deploy.shared.MemoryMappedArchive;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URLClassLoader;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.jar.Attributes;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
import java.util.zip.ZipEntry;
import org.glassfish.api.deployment.archive.ReadableArchive;
import org.glassfish.hk2.api.ServiceLocator;
import org.xml.sax.SAXParseException;

/**
 * Represents a Launchable main class which the caller specifies by the
 * main class itself, rather than a facade JAR or an original developer-provided
 * JAR file.
 *
 * @author tjquinn
 */
public class
        MainClassLaunchable implements Launchable {

    private final Class mainClass;
    private ApplicationClientDescriptor acDesc = null;
    private ClassLoader classLoader = null;
    private AppClientArchivist archivist = null;

    MainClassLaunchable(final ServiceLocator habitat, final Class mainClass) {
        super();
        this.mainClass = mainClass;
    }

    public Class getMainClass() throws ClassNotFoundException {
        return mainClass;
    }

    public ApplicationClientDescriptor getDescriptor(final URLClassLoader loader) throws IOException, SAXParseException {
        /*
         * There is no developer-provided descriptor possible so just
         * use a default one.
         */
        if (acDesc == null) {
            ReadableArchive tempArchive = null;
            final ACCClassLoader tempLoader = AccessController.doPrivileged(
                    new PrivilegedAction() {

                        @Override
                        public ACCClassLoader run() {
                            return new ACCClassLoader(loader.getURLs(), loader.getParent());
                        }
                    });
            tempArchive = createArchive(tempLoader, mainClass);
            final AppClientArchivist acArchivist = getArchivist(tempArchive, tempLoader);
            archivist.setClassLoader(tempLoader);
            archivist.setDescriptor(acDesc);
            archivist.setAnnotationProcessingRequested(true);
            acDesc = acArchivist.open(tempArchive);
            Application.createVirtualApplication(null, acDesc.getModuleDescriptor());
            acDesc.getApplication().setAppName(appNameFromMainClass(mainClass));
            this.classLoader = loader;
        }
        return acDesc;
    }

    private String appNameFromMainClass(final Class c) {
        return c.getName();
    }
    
//    private ReadableArchive createArchive(final ClassLoader loader,
//            final Class mainClass) throws IOException, URISyntaxException {
//        Manifest mf = new Manifest();
//        mf.getMainAttributes().put(Attributes.Name.MAIN_CLASS, mainClass.getName());
//        final File tempFile = File.createTempFile("acc", ".jar");
//        tempFile.deleteOnExit();
//        JarOutputStream jos = new JarOutputStream(
//                new BufferedOutputStream(new FileOutputStream(tempFile)), mf);
//        final String mainClassResourceName = mainClass.getName().replace('.', '/') + ".class";
//        final ZipEntry mainClassEntry = new ZipEntry(mainClassResourceName);
//        jos.putNextEntry(mainClassEntry);
//        InputStream is = loader.getResourceAsStream(mainClassResourceName);
//        int bytesRead;
//        byte[] buffer = new byte[1024];
//        while ( (bytesRead = is.read(buffer)) != -1) {
//            jos.write(buffer, 0, bytesRead);
//        }
//        is.close();
//        jos.closeEntry();
//        jos.close();
//
//        final InputJarArchive result = new InputJarArchive();
//        result.open(new URI("jar", tempFile.toURI().toASCIIString(), null));
//        return result;
//    }

    private ReadableArchive createArchive(final ClassLoader loader,
            final Class mainClass) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();

        Manifest mf = new Manifest();
        Attributes mainAttrs = mf.getMainAttributes();
        /*
         * Note - must set the version or the attributes won't write
         * themselves to the output stream!
         */
        mainAttrs.put(Attributes.Name.MANIFEST_VERSION, "1.0");
        mainAttrs.put(Attributes.Name.MAIN_CLASS, mainClass.getName());
        JarOutputStream jos = new JarOutputStream(baos, mf);

        final String mainClassResourceName = mainClass.getName().replace('.', '/') + ".class";
        final ZipEntry mainClassEntry = new ZipEntry(mainClassResourceName);
        jos.putNextEntry(mainClassEntry);
        InputStream is = loader.getResourceAsStream(mainClassResourceName);
        int bytesRead;
        byte[] buffer = new byte[1024];
        while ( (bytesRead = is.read(buffer)) != -1) {
            jos.write(buffer, 0, bytesRead);
        }
        is.close();
        jos.closeEntry();
        jos.close();

        MemoryMappedArchive mma = new MemoryMappedArchive(baos.toByteArray());
        /*
         * Some archive-related processing looks for the file type from the URI, so set it
         * to something.
         */
        mma.setURI(URI.create("file:///tempClient.jar"));

        return mma;
    }


    private AppClientArchivist getArchivist(final ReadableArchive clientRA,
            final ClassLoader classLoader) throws IOException {
        if (archivist == null) {
            ArchivistFactory af = Util.getArchivistFactory();
            /*
             * Get the archivist by type rather than by archive to avoid
             * having to set the URI to some fake URI that the archivist
             * factory would understand.
             */
            archivist = completeInit((AppClientArchivist) 
                    af.getArchivist(DOLUtils.carType()));
        }
        return archivist;
    }

    private AppClientArchivist completeInit(final AppClientArchivist arch) {
            arch.setAnnotationProcessingRequested(true);
            return arch;
    }

    public void validateDescriptor() {
        archivist.validate(classLoader);
    }

    public URI getURI() {
        return null;
    }

    public String getAnchorDir() {
        return null;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy