Package org.glassfish.loader.util

Source Code of org.glassfish.loader.util.ASClassLoaderUtil

/*
* 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.loader.util;

import com.sun.enterprise.module.Module;
import com.sun.enterprise.module.ModulesRegistry;
import com.sun.enterprise.util.io.FileUtils;
import org.glassfish.api.deployment.DeployCommandParameters;
import org.glassfish.api.deployment.DeploymentContext;
import org.glassfish.hk2.api.ServiceLocator;
import org.glassfish.internal.api.ClassLoaderHierarchy;
import org.glassfish.internal.data.ApplicationRegistry;
import org.glassfish.internal.data.ApplicationInfo;
import org.glassfish.api.admin.ServerEnvironment;
import com.sun.enterprise.deployment.deploy.shared.Util;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.FileInputStream;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.net.URISyntaxException;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.LogRecord;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import java.util.jar.Attributes;
import java.util.*;

import org.glassfish.logging.annotation.LogMessageInfo;

public class ASClassLoaderUtil {

    public static final Logger deplLogger = org.glassfish.deployment.common.DeploymentContextImpl.deplLogger;

    @LogMessageInfo(message = "Cannot convert classpath to URL {0}", level="WARNING")
    private static final String CLASSPATH_ERROR = "NCLS-DEPLOYMENT-00045";

    @LogMessageInfo(message = "Exception:  {0}", level="WARNING")
    private static final String EXCEPTION = "NCLS-DEPLOYMENT-00017";

    @LogMessageInfo(message = "unexpected error in getting urls", level="WARNING")
    private static final String UNEXPECTED_EXCEPTION = "NCLS-DEPLOYMENT-00018";

    private static String modulesClassPath = null;

    /** The manifest file name from an archive. */
    private static final String MANIFEST_ENTRY  =
                    "META-INF" + File.separator + "MANIFEST.MF";

    /**
     * Gets the classpath associated with a module, suffixing libraries
     * defined [if any] for the application
     *
     * @param habitat the habitat the application resides in.
     * @param moduleId Module id of the module
     * @param deploymentLibs libraries option passed through deployment
     * @return A <code>File.pathSeparator</code> separated list of classpaths
     *         for the passed in module, including the module specified
     *         "libraries" defined for the module.
     */
    public static String getModuleClassPath
        (ServiceLocator habitat, String moduleId, String deploymentLibs) {

        if (deplLogger.isLoggable(Level.FINE)) {
          deplLogger.log(Level.FINE,
                         "ASClassLoaderUtil.getModuleClassPath " + "for module Id : " + moduleId);
        }

        StringBuilder classpath = new StringBuilder(getModulesClasspath(habitat));
        ClassLoaderHierarchy clh =
                habitat.getService(ClassLoaderHierarchy.class);
        final String commonClassPath = clh.getCommonClassPath();
        if (commonClassPath != null && commonClassPath.length() > 0) {
            classpath.append(commonClassPath).append(File.pathSeparator);
        }
        addDeployParamLibrariesForModule(classpath, moduleId, deploymentLibs, habitat);
        if (deplLogger.isLoggable(Level.FINE)) {
            deplLogger.log(Level.FINE,
                           "Final classpath: " + classpath.toString());
        }
        return classpath.toString();

    }

    public static String getModuleClassPath (ServiceLocator habitat,
        DeploymentContext context) {
        DeployCommandParameters params =
            context.getCommandParameters(DeployCommandParameters.class);
        return getModuleClassPath(habitat, params.name(), params.libraries());
    }


    private static void addDeployParamLibrariesForModule(StringBuilder sb,
        String moduleId, String deploymentLibs, ServiceLocator habitat) {
        if (moduleId.indexOf("#") != -1) {
            moduleId = moduleId.substring(0, moduleId.indexOf("#"));
        }
 
        if (deploymentLibs == null) {
            ApplicationInfo appInfo =
                habitat.<ApplicationRegistry>getService(ApplicationRegistry.class).get(moduleId);
            if (appInfo == null) {
                // this might be an internal container app,
                // like _default_web_app, ignore.
                return;
            }
            deploymentLibs = appInfo.getLibraries();
        }
        final URL[] libs =
            getDeployParamLibrariesAsURLs(deploymentLibs, habitat);
        if (libs != null) {
            for (final URL u : libs) {
                sb.append(u.getPath());
                sb.append(File.pathSeparator);                   
            }
        }
    }

    private static URL[] getDeployParamLibrariesAsURLs(String librariesStr,
        ServiceLocator habitat) {
            return getDeployParamLibrariesAsURLs(librariesStr,
                habitat.<ServerEnvironment>getService(ServerEnvironment.class));
    }


    /**
     * converts libraries specified via EXTENSION_LIST entry in MANIFEST.MF of
     * all of the libraries of the deployed archive to
     * The libraries  are made available to
     * the application in the order specified.
     *
     * @param librariesStr is a comma-separated list of library JAR files
     * @param env the server environment
     * @return array of URL
     */
    public static URL[] getLibrariesAsURLs(Set<String> librariesStr,
        ServerEnvironment env) {
        if(librariesStr == null)
            return null;
        final URL [] urls = new URL[librariesStr.size()];
        String [] librariesStrArray  = new String[librariesStr.size()];
        librariesStrArray  = librariesStr.toArray(librariesStrArray);
        return getDeployParamLibrariesAsURLs(env, librariesStrArray, urls);
    }

    /**
     * converts libraries specified via the --libraries deployment option to
     * URL[].  The library JAR files are specified by either relative or
     * absolute paths.  The relative path is relative to
     * instance-root/lib/applibs. The libraries  are made available to
     * the application in the order specified.
     *
     * @param librariesStr is a comma-separated list of library JAR files
     * @param env the server environment
     * @return array of URL
     */
    public static URL[] getDeployParamLibrariesAsURLs(String librariesStr,
        ServerEnvironment env) {
        if(librariesStr == null)
            return null;
        String [] librariesStrArray = librariesStr.split(",");
        final URL [] urls = new URL[librariesStrArray.length];
        return getDeployParamLibrariesAsURLs(env, librariesStrArray, urls);
    }

    private static URL[] getDeployParamLibrariesAsURLs(ServerEnvironment env, String[] librariesStrArray,
                                                       URL[] urls) {
        final String appLibsDir = env.getLibPath()
                + File.separator + "applibs";

        int i=0;
        for(final String libraryStr:librariesStrArray){
            try {
                File f = new File(libraryStr);
                if(!f.isAbsolute())
                    f = new File(appLibsDir, libraryStr);
                URL url =f.toURI().toURL();
                urls[i++] = url;
            } catch (MalformedURLException malEx) {
                deplLogger.log(Level.WARNING,
                               CLASSPATH_ERROR,
                               libraryStr);
                LogRecord lr = new LogRecord(Level.WARNING, EXCEPTION);
                lr.setParameters(new Object[] { malEx.getMessage() });
                lr.setThrown(malEx);
                deplLogger.log(lr);
            }
        }
        return urls;
    }

    private static synchronized String getModulesClasspath(ServiceLocator habitat) {
        synchronized (ASClassLoaderUtil.class) {
            if (modulesClassPath == null) {
                final StringBuilder tmpString = new StringBuilder();
                ModulesRegistry mr = habitat.getService(ModulesRegistry.class);
                if (mr != null) {
                    for (Module module : mr.getModules()) {
                        for (URI uri : module.getModuleDefinition().getLocations()) {
                            tmpString.append(uri.getPath());
                            tmpString.append(File.pathSeparator);
                        }
                    }
                }

                //set shared classpath for module so that it doesn't need to be
                //recomputed for every other invocation
                modulesClassPath = tmpString.toString();
            }
        }
        return modulesClassPath;
    }

    /**
     * Returns an array of urls that contains ..
     * <pre>
     *    i.   all the valid directories from the given directory (dirs) array
     *    ii.  all jar files from the given directory (jarDirs) array
     *    iii. all zip files from the given directory (jarDirs) array if
     *         not ignoring zip file (ignoreZip is false).
     * </pre>
     *
     * @param    dirs     array of directory path names
     * @param    jarDirs  array of path name to directories that contains
     *                    JAR & ZIP files.
     * @param    ignoreZip whether to ignore zip files
     * @return   an array of urls that contains all the valid dirs,
     *           *.jar & *.zip
     *
     * @throws  IOException  if an i/o error while constructing the urls
     */
    public static URL[] getURLs(File[] dirs, File[] jarDirs,
        boolean ignoreZip) throws IOException {
        return convertURLListToArray(getURLsAsList(dirs, jarDirs, ignoreZip));
    }

    /**
     * Returns a list of urls that contains ..
     * <pre>
     *    i.   all the valid directories from the given directory (dirs) array
     *    ii.  all jar files from the given directory (jarDirs) array
     *    iii. all zip files from the given directory (jarDirs) array if
     *         not ignoring zip file (ignoreZip is false).
     * </pre>
     *
     * @param    dirs     array of directory path names
     * @param    jarDirs  array of path name to directories that contains
     *                    JAR & ZIP files.
     * @param    ignoreZip whether to ignore zip files
     * @return   an array of urls that contains all the valid dirs,
     *           *.jar & *.zip
     *
     * @throws  IOException  if an i/o error while constructing the urls
     */
    public static List<URL> getURLsAsList(File[] dirs, File[] jarDirs,
        boolean ignoreZip) throws IOException {
        List<URL> list = new ArrayList<URL>();

        // adds all directories
        if (dirs != null) {
            for (int i=0; i<dirs.length; i++) {
                File dir = dirs[i];
                if (dir.isDirectory() || dir.canRead()) {
                    URL url = dir.toURI().toURL();
                    list.add(url);

                    if (deplLogger.isLoggable(Level.FINE)) {
                       deplLogger.log(Level.FINE,
                                      "Adding directory to class path:" + url.toString());
                    }
                }
            }
        }

        // adds all the jars
        if (jarDirs != null) {
            for (int i=0; i<jarDirs.length; i++) {
                File jarDir =  jarDirs[i];

                if (jarDir.isDirectory() || jarDir.canRead()) {
                    File[] files = jarDir.listFiles();

                    for (int j=0; j<files.length; j++) {
                        File jar = files[j];

                        if ( FileUtils.isJar(jar) ||
                            (!ignoreZip && FileUtils.isZip(jar)) ) {
                            list.add(jar.toURI().toURL());

                            if (deplLogger.isLoggable(Level.FINE)) {
                                deplLogger.log(Level.FINE,
                                               "Adding jar to class path:" + jar.toURL());
                            }
                        }
                    }
                }
            }
        }
        return list;
    }
 
    public static URL[] convertURLListToArray(List<URL> list) {
        // converts the list to an array
        URL[] urls = new URL[0];
        if (list != null && list.size() > 0) {
            urls = new URL[list.size()];
            urls = (URL[]) list.toArray(urls);
        }
        return urls;
    }

    /**
     * get URL list from classpath
     * @param classpath classpath string containing the classpaths
     * @param delimiter delimiter to separate the classpath components
     *                  in the classpath string
     * @param rootPath root path of the classpath if the paths are relative
    
     * @return urlList URL list from the given classpath
     */
    public static List<URL> getURLsFromClasspath(String classpath,
        String delimiter, String rootPath) {
        final List<URL> urls  = new ArrayList<URL>();

        if (classpath == null || classpath.length() == 0) {
            return urls;
        }

        // tokenize classpath
        final StringTokenizer st = new StringTokenizer(classpath, delimiter);
        while (st.hasMoreTokens()) {
            try {
                String path = st.nextToken();
                try {
                    // try to see if the path is absolute
                    URL url = new URL(path);
                    URI uri = url.toURI();
                    if (uri.isAbsolute()) {
                        urls.add(uri.toURL());
                        continue;
                    }
                } catch (Exception ie) {
                    // ignore
                }

                if (rootPath != null && rootPath.length() != 0) {
                    path = rootPath + File.separator + path;
                }
                File f = new File(path);
                urls.add(f.toURI().toURL());
            } catch(Exception e) {
                  deplLogger.log(Level.WARNING,
                                 UNEXPECTED_EXCEPTION,
                                 e);
            }
        }
        return urls;
    }

   /**
     * Returns the manifest file for the given root path.
     *
     * <xmp>
     *    Example:
     *     |--repository/
     *     |   |--applications/
     *     |        |--converter/
     *     |            |--ejb-jar-ic_jar/        <---- rootPath
     *     |                 |--META-INF/
     *     |                     |--MANIFEST.MF
     * </xmp>
     *
     * @param    rootPath    absolute path to the module
     *
     * @return   the manifest file for the given module
     */
    public static Manifest getManifest(String rootPath) {

        InputStream in  = null;
        Manifest mf     = null;

        // gets the input stream to the MANIFEST.MF file
        try {
            in = new FileInputStream(rootPath+File.separator+MANIFEST_ENTRY);

            if (in != null) {
                mf = new Manifest(in);
            }
        } catch (IOException ioe) {
            // ignore
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException ioe) {
                    // Ignore
                }
            }
        }
        return mf;
    }


    /**
     * Returns the class path (if any) from the given manifest file as an
     * URL list.
     *
     * @param    manifest    manifest file of an archive
     * @param    rootPath    root path to the module
     *
     * @return   a list of URLs
     *           an empty list if given manifest is null
     */
    public static List<URL> getManifestClassPathAsURLs(Manifest manifest,
            String rootPath) {
        List<URL> urlList = new ArrayList<URL>();
        if (manifest != null) {
            Attributes mainAttributes  = manifest.getMainAttributes();

            for (Map.Entry entry : mainAttributes.entrySet()) {

                Attributes.Name next = (Attributes.Name) entry.getKey();

                if (next.equals(Attributes.Name.CLASS_PATH)) {
                    String classpathString = (String) entry.getValue();
                    urlList = getURLsFromClasspath(classpathString, " ",
                        rootPath);
                }
            }
        }
        return urlList;
    }

    /**
     * add all the libraries packaged in the application library directory
     *
     * @param appRoot the application root
     * @param appLibDir the Application library directory
     * @param compatibilityProp the version of the release that we need to
     *        maintain backward compatibility
     * @return an array of URL
     */
    public static URL[] getAppLibDirLibraries(File appRoot, String appLibDir,
        String compatibilityProp)
        throws IOException {
        return convertURLListToArray(
            getAppLibDirLibrariesAsList(appRoot, appLibDir, compatibilityProp));
    }

    public static List<URL> getAppLibDirLibrariesAsList(File appRoot, String appLibDir, String compatibilityProp)
        throws IOException {
        URL[] libDirLibraries = new URL[0];
        // get all the app lib dir libraries
        if (appLibDir != null) {
            String libPath = appLibDir.replace('/', File.separatorChar);
            libDirLibraries =  getURLs(null,
                new File[] {new File(appRoot, libPath)}, true);
        }

        List<URL> allLibDirLibraries = new ArrayList<URL>();
        for (URL url : libDirLibraries) {
            allLibDirLibraries.add(url);
        }

        // if the compatibility property is set to "v2", we should add all the
        // jars under the application root to maintain backward compatibility
        // of v2 jar visibility
        if (compatibilityProp != null && compatibilityProp.equals("v2")) {
            List<URL> appRootLibraries = getURLsAsList(null, new File[] {appRoot}, true);
            allLibDirLibraries.addAll(appRootLibraries);
        }
        return allLibDirLibraries;
    }

    public static List<URI> getLibDirectoryJarURIs(File moduleLibDirectory) throws Exception {
        List<URI> libLibraryURIs = new ArrayList<URI>();
        File[] jarFiles = moduleLibDirectory.listFiles(new FileFilter() {
            public boolean accept(File pathname) {
                return (pathname.getAbsolutePath().endsWith(".jar"));
            }
        });

        if (jarFiles != null && jarFiles.length > 0) {
            for (File jarFile : jarFiles) {
                libLibraryURIs.add(Util.toURI(jarFile.toURL()));
            }
        }

        return libLibraryURIs;
    }
}
TOP

Related Classes of org.glassfish.loader.util.ASClassLoaderUtil

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.