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

com.impetus.kundera.classreading.ClasspathReader Maven / Gradle / Ivy

There is a newer version: 3.13
Show newest version
/*******************************************************************************
 * * Copyright 2012 Impetus Infotech.
 *  *
 *  * 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 com.impetus.kundera.classreading;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.StringTokenizer;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.Manifest;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.impetus.kundera.Constants;
import com.impetus.kundera.loader.PersistenceXMLLoader.AllowedProtocol;

/**
 * The Class ClasspathReader.
 * 
 * @author animesh.kumar
 */
public class ClasspathReader extends Reader
{
    private static Logger logger = LoggerFactory.getLogger(ClasspathReader.class);

    /**
     * The filter.
     */
    private Filter filter;

    /** The classes to scan. */
    private List classesToScan;

    /**
     * Instantiates a new classpath reader.
     */
    public ClasspathReader()
    {
        filter = new FilterImpl();
    }

    /**
     * Instantiates a new classpath reader.
     * 
     * @param classesToScan
     *            the classes to scan
     */
    public ClasspathReader(List classesToScan)
    {
        this();
        this.classesToScan = classesToScan;
    }

    @Override
    public final void read()
    {
        URL[] resources = findResources();
        for (URL resource : resources)
        {

            try
            {
                ResourceIterator itr = getResourceIterator(resource, getFilter());

                InputStream is = null;
                while ((is = itr.next()) != null)
                {
                    scanClass(is);
                }
            }
            catch (IOException e)
            {
                logger.error("Error during reading via classpath, Caused by:" + e.getMessage());
                throw new ResourceReadingException(e);
            }
        }
    }

    /**
     * Uses the java.class.path system property to obtain a list of URLs that
     * represent the CLASSPATH
     * 
     * @return the URl[]
     */
    @SuppressWarnings("deprecation")
    @Override
    public final URL[] findResourcesByClasspath()
    {
        List list = new ArrayList();
        String classpath = System.getProperty("java.class.path");
        StringTokenizer tokenizer = new StringTokenizer(classpath, File.pathSeparator);

        while (tokenizer.hasMoreTokens())
        {
            String path = tokenizer.nextToken();

            File fp = new File(path);
            if (!fp.exists())
                throw new ResourceReadingException("File in java.class.path does not exist: " + fp);
            try
            {
                list.add(fp.toURL());
            }
            catch (MalformedURLException e)
            {
                throw new ResourceReadingException(e);
            }
        }
        return list.toArray(new URL[list.size()]);
    }

    /**
     * Scan class resource in the provided urls with the additional Class-Path
     * of each jar checking
     * 
     * @param classRelativePath
     *            relative path to a class resource
     * @param urls
     *            urls to be checked
     * @return list of class path included in the base package
     */
    private URL[] findResourcesInUrls(String classRelativePath, URL[] urls)
    {
        List list = new ArrayList();
        for (URL url : urls)
        {
            if (AllowedProtocol.isValidProtocol(url.getProtocol().toUpperCase()) && url.getPath().endsWith(".jar"))
            {
                try
                {
                    JarFile jarFile = new JarFile(URLDecoder.decode(url.getFile(), Constants.CHARSET_UTF8));

                    // Checking the dependencies of this jar file
                    Manifest manifest = jarFile.getManifest();
                    if (manifest != null)
                    {
                        String classPath = manifest.getMainAttributes().getValue("Class-Path");
                        // Scan all entries in the classpath if they are
                        // specified in the jar
                        if (!StringUtils.isEmpty(classPath))
                        {
                            List subList = new ArrayList();
                            for (String cpEntry : classPath.split(" "))
                            {
                                try
                                {
                                    subList.add(new URL(cpEntry));
                                }
                                catch (MalformedURLException e)
                                {
                                    URL subResources = ClasspathReader.class.getClassLoader().getResource(cpEntry);
                                    if (subResources != null)
                                    {
                                        subList.add(subResources);
                                    }
                                    // logger.warn("Incorrect URL in the classpath of a jar file ["
                                    // + url.toString()
                                    // + "]: " + cpEntry);
                                }
                            }
                            list.addAll(Arrays.asList(findResourcesInUrls(classRelativePath,
                                    subList.toArray(new URL[subList.size()]))));
                        }
                    }
                    JarEntry present = jarFile.getJarEntry(classRelativePath + ".class");
                    if (present != null)
                    {
                        list.add(url);
                    }
                }
                catch (IOException e)
                {
                    logger.warn("Error during loading from context , Caused by:" + e.getMessage());
                }

            }
            else if (url.getPath().endsWith("/"))
            {
                File file = new File(url.getPath() + classRelativePath + ".class");
                if (file.exists())
                {
                    try
                    {
                        list.add(file.toURL());
                    }
                    catch (MalformedURLException e)
                    {
                        throw new ResourceReadingException(e);
                    }
                }
            }

        }
        return list.toArray(new URL[list.size()]);
    }

    /**
     * Scan class resources into a basePackagetoScan path.
     * 
     * @return list of class path included in the base package
     */

    private final URL[] findResourcesByContextLoader()
    {
        List list = new ArrayList();
        ClassLoader classLoader = this.getClass().getClassLoader();
        assert classLoader != null;        
        URL[] urls = ((URLClassLoader) classLoader).getURLs();
        
        for (String fullyQualifiedClassName : classesToScan)
        {
            String classRelativePath = fullyQualifiedClassName.replace(".", "/");
            list.addAll(Arrays.asList(findResourcesInUrls(classRelativePath, urls)));
        }

        return list.toArray(new URL[list.size()]);
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.impetus.kundera.classreading.Reader#findResources()
     */
    @Override
    public URL[] findResources()
    {
        URL[] result = null;

        if (classesToScan != null && !classesToScan.isEmpty())
        {
            result = findResourcesByContextLoader();
        }
        // else
        // {
        // result = findResourcesByClasspath();
        // }
        return result;
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.impetus.kundera.classreading.Reader#getFilter()
     */

    public final Filter getFilter()
    {
        return filter;
    }

    /**
     * Sets the filter.
     * 
     * @param filter
     *            the new filter
     */
    public final void setFilter(Filter filter)
    {
        this.filter = filter;
    }
    
    @Override
    public InputStream[] findResourcesAsStream()
    {
        ClassLoader classLoader = this.getClass().getClassLoader();
        assert classLoader != null;

        InputStream[] iStreams = null;
        int counter = 0;
        if(classesToScan != null)
        {
            for (String fullyQualifiedClassName : classesToScan)
            {
                if (iStreams == null)
                {
                    iStreams = new InputStream[classesToScan.size()];
                }

                String classRelativePath = fullyQualifiedClassName.replace(".", "/");
                InputStream is = this.getClass().getClassLoader().getResourceAsStream(classRelativePath + ".class");
                iStreams[counter++] = is;
            }
        }
        return iStreams;

    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy