Package org.mc4j.ems.connection.support.classloader

Source Code of org.mc4j.ems.connection.support.classloader.ClassLoaderFactory

/*
* Copyright 2002-2004 Greg Hinkle
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*       http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.mc4j.ems.connection.support.classloader;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.mc4j.ems.connection.EmsConnectException;
import org.mc4j.ems.connection.EmsException;
import org.mc4j.ems.connection.settings.ConnectionSettings;
import org.mc4j.ems.connection.support.metadata.JSR160ConnectionTypeDescriptor;
import org.mc4j.ems.connection.support.metadata.WeblogicConnectionTypeDescriptor;
import org.mc4j.ems.connection.support.metadata.WebsphereConnectionTypeDescriptor;

import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.HashMap;

/**
* @author Greg Hinkle (ghinkle@users.sourceforge.net), Apr 5, 2005
* @version $Revision: 1.3 $($Author: ghinkl $ / $Date: 2006/05/22 02:38:52 $)
*/
public class ClassLoaderFactory {

    private static ClassLoaderFactory INSTANCE;

    private static Log log = LogFactory.getLog(ClassLoaderFactory.class);

    private static Map<String, File> jarCache = new HashMap<String, File>();

    static {
        String className = System.getProperty("org.mc4j.ems.classloaderfactory");
        if (className != null) {
            try {
                INSTANCE = ((Class<ClassLoaderFactory>) Class.forName(className)).newInstance();
            } catch (Exception e) {
                throw new EmsException("Unable to load custom classloader factory " + className, e);
            }
        }

        if (INSTANCE == null) {
            INSTANCE = new ClassLoaderFactory();
        }
    }

    /**
     * Retrieves the configured classloader factory for EMS. This can be customized by
     * setting the system property "org.mc4j.ems.classloaderfactory".
     *
     * @return the Classloader Factory used to build the connection classloader
     */
    public static ClassLoaderFactory getInstance() {
        return INSTANCE;
    }

    /**
     * TODO GH: Implement a special classloader that can load classes from
     * within a jar inside another jar or perhaps just ship the impl jar separately...
     */
    protected URL storeImplToTemp(String archiveResource) {
        try {

            if (jarCache.containsKey(archiveResource)) {
                return jarCache.get(archiveResource).toURI().toURL();
            }

            InputStream is = ClassLoaderFactory.class.getClassLoader().getResourceAsStream(archiveResource);

            if (is == null) {
                throw new EmsException("Unable to find resource to store [" + archiveResource + "]");
            }

            // String tmpPath = System.getProperty("java.io.tmpdir");

            String jarName = new File(archiveResource).getName();
            jarName = jarName.substring(0, jarName.length() - 4);

            File tmpFile = File.createTempFile(jarName, ".jar");
            tmpFile.deleteOnExit();

            FileOutputStream fos = new FileOutputStream(tmpFile);
            byte[] buffer = new byte[4096];
            int size = is.read(buffer);
            while (size != -1) {
                fos.write(buffer, 0, size);
                size = is.read(buffer);
            }
            fos.close();
            is.close();

            jarCache.put(archiveResource, tmpFile);

            return tmpFile.toURI().toURL();

        } catch (FileNotFoundException e) {
            throw new EmsException("Unable to make temporary file store",e);
        } catch (IOException e) {
            throw new EmsException("Unable to make temporary file store",e);
        }
    }

    public ClassLoader buildClassLoader(ConnectionSettings settings) {
        // TODO GH: Implement configurable system to point at jar instead of creating temporary version

        List<URL> entries = new ArrayList<URL>();

        if (settings.getClassPathEntries() != null) {
            for (File file : settings.getClassPathEntries()) {
                try {
                    entries.add(file.toURI().toURL());
                } catch (MalformedURLException e) {
                    throw new EmsConnectException("Unable to read class path library url", e);
                }
            }
        }

        // Now load in the implementation jar
        // URL implURL = new URL(null, "deepjar://org-mc4j-ems-impl.jar", new Handler());
        URL implURL = storeImplToTemp("org-mc4j-ems-impl.jar");

        entries.add(implURL);

        // Add internal support jars for JSR160 on < jdk5
        if ((settings.getConnectionType() instanceof JSR160ConnectionTypeDescriptor) &&
                settings.getConnectionType().getConnectionClasspathEntries() == null &&
                Double.parseDouble(System.getProperty("java.version").substring(0, 3)) < 1.5) {
            entries.add(storeImplToTemp("lib/jsr160-includes/mx4j.jar"));
            entries.add(storeImplToTemp("lib/jsr160-includes/mx4j-remote.jar"));
        }

        // TODO: Check if file exists, log warning if not

        URL[] entryArray = entries.toArray(new URL[entries.size()]);

        // WARNING: Relatively disgusting hack. hiding classes is not a good thing
        URLClassLoader loader = null;
        if (settings.getConnectionType().isUseChildFirstClassLoader()) {
            loader = new ChildFirstClassloader(entryArray, ClassLoaderFactory.class.getClassLoader());
        } else {
            // TODO was NestedJarClassLoader
            //loader = new ChildFirstClassloader(entryArray, ClassLoaderFactory.class.getClassLoader());
            loader = new URLClassLoader(entryArray, ClassLoaderFactory.class.getClassLoader());
            //loader = new NestedJarClassLoader(entryArray, ClassLoaderFactory.class.getClassLoader());
        }

        if (log.isDebugEnabled()) {
            StringBuffer buf = new StringBuffer("Classloader built with: \n");
            for (URL url : entries) {
                buf.append("\t").append(url).append("\n");
            }
            log.debug(buf.toString());
        }
        return loader;
    }

}
TOP

Related Classes of org.mc4j.ems.connection.support.classloader.ClassLoaderFactory

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.