lucee.commons.io.res.util.ResourceClassLoader.java Source code

Java tutorial

Introduction

Here is the source code for lucee.commons.io.res.util.ResourceClassLoader.java

Source

/**
 *
 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either 
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public 
 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
 * 
 **/
package lucee.commons.io.res.util;

import java.io.Closeable;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import lucee.commons.digest.MD5;
import lucee.commons.io.res.Resource;
import lucee.commons.io.res.type.file.FileResource;
import lucee.runtime.exp.PageException;
import lucee.runtime.type.util.ArrayUtil;

import org.apache.commons.collections.map.ReferenceMap;

/**
 * Classloader that load classes from resources
 */
public final class ResourceClassLoader extends URLClassLoader implements Closeable {

    private List<Resource> resources = new ArrayList<Resource>();
    private Map<String, ResourceClassLoader> customCLs;

    /* *
     * Constructor of the class
     * @param resources
     * @throws PageException
         
    ResourceClassLoader(Resource[] resources) throws IOException {
       super(doURLs(resources));
    }*/

    /**
     * Constructor of the class
     * @param reses
     * @param parent
     * @throws PageException
     */
    public ResourceClassLoader(Resource[] resources, ClassLoader parent) throws IOException {
        super(doURLs(resources), parent);
        for (int i = 0; i < resources.length; i++) {
            this.resources.add(resources[i]);
        }
    }

    public ResourceClassLoader(ClassLoader parent) {
        super(new URL[0], parent);
    }

    /**
     * @return the resources
     */
    public Resource[] getResources() {
        return resources.toArray(new Resource[resources.size()]);
    }

    /**
     * translate resources to url Objects
     * @param reses
     * @return
     * @throws PageException
     */
    public static URL[] doURLs(Resource[] reses) throws IOException {
        List<URL> list = new ArrayList<URL>();
        for (int i = 0; i < reses.length; i++) {
            if (reses[i].isDirectory() || "jar".equalsIgnoreCase(ResourceUtil.getExtension(reses[i], null)))
                list.add(doURL(reses[i]));
        }
        return list.toArray(new URL[list.size()]);

    }

    private static URL doURL(Resource res) throws IOException {
        if (!(res instanceof FileResource))
            throw new IOException("resource [" + res.getPath() + "] must be a local file");
        return ((FileResource) res).toURL();
    }

    @Override
    public void close() {
    }

    public synchronized void addResourcesX(Resource[] reses) throws IOException {
        for (int i = 0; i < reses.length; i++) {
            if (!this.resources.contains(reses[i])) {
                this.resources.add(reses[i]);
                addURL(doURL(reses[i]));
            }
        }
    }

    public ResourceClassLoader getCustomResourceClassLoader(Resource[] resources) throws IOException {
        if (ArrayUtil.isEmpty(resources))
            return this;
        String key = hash(resources);
        ResourceClassLoader rcl = customCLs == null ? null : customCLs.get(key);
        if (rcl != null)
            return rcl;

        resources = ResourceUtil.merge(this.getResources(), resources);
        rcl = new ResourceClassLoader(resources, getParent());
        if (customCLs == null)
            customCLs = new ReferenceMap();
        customCLs.put(key, rcl);
        return rcl;
    }

    public ResourceClassLoader getCustomResourceClassLoader2(Resource[] resources) throws IOException {
        if (ArrayUtil.isEmpty(resources))
            return this;
        String key = hash(resources);
        ResourceClassLoader rcl = customCLs == null ? null : customCLs.get(key);
        if (rcl != null)
            return rcl;

        rcl = new ResourceClassLoader(resources, this);
        if (customCLs == null)
            customCLs = new ReferenceMap();
        customCLs.put(key, rcl);
        return rcl;
    }

    private String hash(Resource[] resources) {
        Arrays.sort(resources);
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < resources.length; i++) {
            sb.append(ResourceUtil.getCanonicalPathEL(resources[i]));
            sb.append(';');
        }
        return MD5.getDigestAsString(sb.toString(), null);
    }

}