ClassUtil

/*
 * JBoss, Home of Professional Open Source
 * Copyright 2006, JBoss Inc., and individual contributors as indicated
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * This 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 software 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 software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package org.jboss.soa.esb.util;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Proxy;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import org.apache.log4j.Logger;

/**
 * Utility methods to aid in class/resource loading.
 * 
 * @author kevin
 */
public class ClassUtil
{
    private static Logger logger = Logger.getLogger(ClassUtil.class);

    /**
     * Load the specified class.
     * 
     * @param className The name of the class to load.
     * @param caller The class of the caller.
     * @return The specified class.
     * @throws ClassNotFoundException If the class cannot be found.
     */
    public static Class forName(final String className, final Class caller) throws ClassNotFoundException
    {
        final ClassLoader threadClassLoader = Thread.currentThread().getContextClassLoader();
        if (threadClassLoader != null)
        {
            try
            {
                return Class.forName(className, true, threadClassLoader);
            }
            catch (final ClassNotFoundException cnfe)
            {
                if (cnfe.getException() != null)
                {
                    throw cnfe;
                }
            }
        }

        final ClassLoader classLoader = caller.getClassLoader();
        if (classLoader != null)
        {
            try
            {
                return Class.forName(className, true, classLoader);
            }
            catch (final ClassNotFoundException cnfe)
            {
                if (cnfe.getException() != null)
                {
                    throw cnfe;
                }
            }
        }

        return Class.forName(className, true, ClassLoader.getSystemClassLoader());
    }

    /**
     * Resolve a proxy for the specified interfaces.
     * 
     * @param interfaces The interfaces associated with the proxy.
     * @param caller The class of the caller.
     * @return The specified proxy class.
     * @throws ClassNotFoundException If the class cannot be found.
     */
    public static Class resolveProxy(final String[] interfaces, final Class caller) throws ClassNotFoundException
    {
        final int numInterfaces = (interfaces == null ? 0 : interfaces.length);
        if (numInterfaces == 0)
        {
            throw new ClassNotFoundException("Cannot generate proxy with no interfaces");
        }

        final Class[] interfaceClasses = new Class[numInterfaces];
        for (int count = 0; count < numInterfaces; count++)
        {
            interfaceClasses[count] = forName(interfaces[count], caller);
        }

        final ClassLoader proxyClassLoader;
        final ClassLoader threadClassLoader = Thread.currentThread().getContextClassLoader();
        if (threadClassLoader != null)
        {
            proxyClassLoader = threadClassLoader;
        }
        else
        {
            final ClassLoader classLoader = caller.getClassLoader();
            if (classLoader != null)
            {
                proxyClassLoader = classLoader;
            }
            else
            {
                proxyClassLoader = ClassLoader.getSystemClassLoader();
            }
        }

        return Proxy.getProxyClass(proxyClassLoader, interfaceClasses);
    }

    /**
     * Get the specified resource as a stream.
     * 
     * @param resourceName The name of the class to load.
     * @param caller The class of the caller.
     * @return The input stream for the resource or null if not found.
     */
    public static InputStream getResourceAsStream(final String resourceName, final Class caller)
    {
        final String resource;
        if (resourceName.startsWith("/"))
        {
            resource = resourceName.substring(1);
        }
        else
        {
            final Package callerPackage = caller.getPackage();
            if (callerPackage != null)
            {
                resource = callerPackage.getName().replace('.', '/') + '/' + resourceName;
            }
            else
            {
                resource = resourceName;
            }
        }
        final ClassLoader threadClassLoader = Thread.currentThread().getContextClassLoader();
        if (threadClassLoader != null)
        {
            final InputStream is = threadClassLoader.getResourceAsStream(resource);
            if (is != null)
            {
                return is;
            }
        }

        final ClassLoader classLoader = caller.getClassLoader();
        if (classLoader != null)
        {
            final InputStream is = classLoader.getResourceAsStream(resource);
            if (is != null)
            {
                return is;
            }
        }

        return ClassLoader.getSystemResourceAsStream(resource);
    }

    public static URL getResource(final String resourceName, final Class<?> caller)
    {
        final String resource;
        if (resourceName.startsWith("/"))
        {
            resource = resourceName.substring(1);
        }
        else
        {
            final Package callerPackage = caller.getPackage();
            if (callerPackage != null)
            {
                resource = callerPackage.getName().replace('.', '/') + '/' + resourceName;
            }
            else
            {
                resource = resourceName;
            }
        }
        final ClassLoader threadClassLoader = Thread.currentThread().getContextClassLoader();
        if (threadClassLoader != null)
        {
            final URL url = threadClassLoader.getResource(resource);
            if (url != null)
            {
                return url;
            }
        }

        final ClassLoader classLoader = caller.getClassLoader();
        if (classLoader != null)
        {
            final URL url = classLoader.getResource(resource);
            if (url != null)
            {
                return url;
            }
        }

        return ClassLoader.getSystemResource(resource);
    }

    public static List<URL> getResources(String resourcePath, Class<?> caller) throws IOException
    {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();

        if (resourcePath.startsWith("/"))
        {
            resourcePath = resourcePath.substring(1);
        }

        if (classLoader != null)
        {
            return toList(classLoader.getResources(resourcePath));
        }

        classLoader = caller.getClassLoader();
        if (classLoader != null)
        {
            return toList(classLoader.getResources(resourcePath));
        }

        return new ArrayList<URL>();
    }

    private static <T> List<T> toList(Enumeration<T> objects)
    {
        List<T> theList = new ArrayList<T>();
        while (objects.hasMoreElements())
        {
            theList.add(objects.nextElement());
        }
        return theList;
    }

    /**
     * Get a package name and convert it to a path value, so it can be used in calls to methods like
     * {@link #getResourceAsStream}.
     * <p/>
     * Adds a '/' prefix and converts all '." characters to '/'. Doesn't add a trailing slash.
     * 
     * @param packageObj The package.
     * @return The package path.
     */
    public static String getPath(Package packageObj)
    {
        return "/" + packageObj.getName().replace('.', '/');
    }

    public static List<String> getResourceList(String regex, Class caller)
    {
        ClasspathResourceFilter filter = new ClasspathResourceFilter(regex);
        ClassLoader classLoader;

        classLoader = Thread.currentThread().getContextClassLoader();
        if (classLoader instanceof URLClassLoader)
        {
            filter.filter((URLClassLoader) classLoader);
        }
        classLoader = caller.getClassLoader();
        if (classLoader instanceof URLClassLoader)
        {
            filter.filter((URLClassLoader) classLoader);
        }

        return filter.getResourceList();
    }

    private static class ClasspathResourceFilter
    {

        private List<String> resourceList = new ArrayList<String>();
        private Pattern pattern;

        private ClasspathResourceFilter(String regex)
        {
            pattern = Pattern.compile(regex);
        }

        private void filter(URLClassLoader classLoader)
        {
            URL[] cpUrls = classLoader.getURLs();

            for (int i = 0; i < cpUrls.length; i++)
            {
                try
                {
                    File file = new File(cpUrls[i].toURI());
                    if (file.isDirectory())
                    {
                        searchClasspathDirTree(file, "");
                    }
                    else
                    {
                        searchArchive(file);
                    }
                }
                catch (URISyntaxException e)
                {
                    logger.warn("Error searching classpath resource URL '" + cpUrls[i] + "' for resource '"
                            + pattern.pattern() + "': " + e.getMessage());
                }
                catch (IOException e)
                {
                    logger.warn("Error searching classpath resource URL '" + cpUrls[i] + "' for resource '"
                            + pattern.pattern() + "': " + e.getMessage());
                }
            }
        }

        private void searchClasspathDirTree(File rootDir, String subDir)
        {
            File currentDir = new File(rootDir, subDir);
            File[] contents = currentDir.listFiles();

            for (File file : contents)
            {
                if (file.isDirectory())
                {
                    String subSubDir = subDir + "/" + file.getName();
                    searchClasspathDirTree(rootDir, subSubDir);
                }
                else
                {
                    String resClasspathPath = file.toURI().toString()
                            .substring(rootDir.toURI().toString().length() - 1);
                    if (isToBeAdded(resClasspathPath))
                    {
                        resourceList.add(resClasspathPath);
                    }
                }
            }
        }

        private void searchArchive(File archiveFile) throws IOException
        {
            ZipFile zip = new ZipFile(archiveFile);
            Enumeration<? extends ZipEntry> entries = zip.entries();

            while (entries.hasMoreElements())
            {
                ZipEntry entry = entries.nextElement();
                String resClasspathPath = "/" + entry.getName();
                if (isToBeAdded(resClasspathPath))
                {
                    resourceList.add(resClasspathPath);
                }
            }
        }

        private boolean isToBeAdded(String resClasspathPath)
        {
            if (resourceList.contains(resClasspathPath))
            {
                // Already in the list e.g. same resource in different archives...
                return false;
            }

            Matcher matcher = pattern.matcher(resClasspathPath);
            return matcher.matches();
        }

        private List<String> getResourceList()
        {
            return resourceList;
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值