ProviderClassLoader.java :  » Portal » Open-Portal » com » sun » portal » desktop » context » Java Open Source

Java Open Source » Portal » Open Portal 
Open Portal » com » sun » portal » desktop » context » ProviderClassLoader.java
/*
 * Copyright 2001 Sun Microsystems, Inc.  All rights reserved.
 * PROPRIETARY/CONFIDENTIAL.  Use of this product is subject to license terms.
 */
package com.sun.portal.desktop.context;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.File;

import java.net.URL;
import java.net.MalformedURLException;
import java.net.URLClassLoader;

import java.util.Collection;
import java.util.HashSet;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.ZipFile;
import java.util.zip.ZipEntry;

import java.lang.ClassLoader;

import com.sun.portal.log.common.PortalLogger;

/**
 * The ProviderClassLoader is responsible for loading new or modified
 * provider classes.
 *
 */
public class ProviderClassLoader extends ClassLoader {

    private static  ClassInfoCache cic = null;
    private static  String  baseSearchDir  = null;

    private static ProviderClassLoader instance;
    private static URLClassLoader urlClassLoader;
    private ClassLoader parent = null;
    private Collection failedToLoadClassSet;
    private static Logger logger = PortalLogger.getLogger(ProviderClassLoader.class);

    private List listeners;

    public static synchronized ProviderClassLoader getInstance(
        String providerBaseDir )
    {

        // create a new ProviderClassLoader instance when the loader is
        // out of date.
        if( instance == null ) {
            instance = new ProviderClassLoader( providerBaseDir );
        }
        return instance;
    }
    
    public static synchronized ProviderClassLoader getInstance(
        String providerClassName,
        String providerBaseDir )
    {

        // create a new ProviderClassLoader instance when the loader is
        // out of date.

        if( instance == null ||
            instance.isProviderClassOutOfDate(providerClassName)) {
            instance = new ProviderClassLoader( providerBaseDir );
        }
        return instance;
    }

    /**
     * This Constructor ensures that a values is set to the member variable
     * <CODE>baseSearchDir</CODE>. It calls the loadClass() method of the parent
     * to load the provider class
     * @param providerBaseDir Directory from which provider classes will be
     *                        loaded  as String
     */
    private ProviderClassLoader( String providerBaseDir) {
        super(ProviderClassLoader.class.getClassLoader());

        parent = ProviderClassLoader.class.getClassLoader();
        cic = ClassInfoCache.getInstance(providerBaseDir);
        if( cic != null) {
            baseSearchDir  = providerBaseDir;
        }
        failedToLoadClassSet = new HashSet();
        listeners = new ArrayList();

        try {
            if(System.getProperty("os.name").indexOf("indows") != -1)
            urlClassLoader = URLClassLoader.newInstance(new URL[]{new URL("file:///" + providerBaseDir + "/")});
            else
            urlClassLoader = URLClassLoader.newInstance(new URL[]{new URL("file://" + providerBaseDir + "/")});
        } catch (MalformedURLException e) {
            logger.log(Level.SEVERE, "PSDT_CSPDC0003", e);
        }

    }

    public synchronized void addListener( ProviderClassLoaderListener pcll ) {
        listeners.add( pcll );
    }

    public synchronized void notifyListeners( ) {
        for( int i = 0; i < listeners.size(); i++ ) {
            ((ProviderClassLoaderListener)listeners.get(i)).providerClassLoaderOutdated();
        }
        listeners.clear();
    }

    /**
     * Checks if the provider class has been modified on the file system
     * @return <I>true</I> if the class has been modified since it was loaded
     */
    public boolean isProviderClassOutOfDate( String theClassName ) {
        boolean outdated = false;   
  
        File fileHandle = cic.getHandle(theClassName);
        if (fileHandle != null) {
            // If class information exists, this class was loaded from the 
            // Provider classpath either from a class file or a Jar         
            long lastModTime = cic.getModifiedTime(theClassName);
            if(fileHandle != null && fileHandle.exists()) {
                // If lastmodified time of this classfile or Jar file to which
                // this class belongs to is greater than the value this class
                // information is stored in the cache then set the state to true
                if(fileHandle.lastModified() > lastModTime) {
                    outdated = true;
                    cic.removeClassInfo(theClassName);
                }
               
            } else {
                // If file handle is not more a valid file class file could have
                // could have been moved into a Jar or if it was previously
                // loaded from a Jar the Jarfile could have been renamed
                outdated = true;
                // Remove information about its class as the handle is invalid
                cic.removeClassInfo(theClassName);
             }                        
        } else {
            // If classInfo is null the provider was loaded initially by the
            // system classloader. Or the Provider Class loader failed to load
            // this class. If it failed to load the class then an attempt should
            // be made to load it again. Hence set outdated flag to true.
            if( failedToLoadClassSet.contains( theClassName ) ) {
                outdated = true;
            }
        }

        if( outdated == true ) {
            notifyListeners();
        }

        return outdated;
    }

    /**
     * This method overriddes the findClass method in the parent. It is called
     * by the loadclass method of the parent - java.lang.ClassLoader.
     * The parent calls this method at step (3) in the following
     * list of steps:
     * (1) Call <CODE>findLoadedClass(String)</CODE> to check if the class has
     *     already been loaded.
     * (2) Call the <CODE>loadClass</CODE> method on the parent class loader.
     * (3) Call the <CODE>findClass(String)</CODE> method to find the class.
     *
     * @param className  the class to load
     * @return Class representing the loaded class
     * @exception ClassNotFoundException Throws Class Not Found exception
     */
    
    public Class findClass(String className) throws ClassNotFoundException {
        Class rclass = null;
  byte[] classBytes = null;
        
  try {
    classBytes = findLocalClass(className);
  } catch (IOException ioe) {
    throw new ClassNotFoundException("ProviderClassLoader.findClass() : not found class Name = "+ className,ioe);
  }

        if (classBytes != null) {                                    
      
            rclass = defineClass(className, classBytes, 0, classBytes.length);
            if (rclass == null) {
                failedToLoadClassSet.add( className );
                throw new ClassNotFoundException("ProviderClassLoader.findClass() : not found class Name = "+ className);
            }            

        } else {
            failedToLoadClassSet.add( className );
            throw new ClassNotFoundException("ProviderClassLoader.findClass() : not found class Name = "+ className);            
        }

        return rclass;
    }

    
    /**
     * This method is responsible for finding the local class file and
     * returning its byte representation.
     *
     * @param className  the class to load
     * @return byte[] representing the class bytes
     * @exception IOException Throws I/O exception
     */
    public byte[] findLocalClass (String className) throws IOException {
            
        byte[] result = null;
        String cString = className.replace('.', '/') + ".class";
        String fullFileLocation = baseSearchDir + '/' + cString;
        File classFile = new File (fullFileLocation);

        if (!classFile.exists()) {
            File jarFile = cic.getJarFileHandle(className);
            if (jarFile != null && jarFile.isFile()) {
          ZipFile zip = new ZipFile(jarFile);
    ZipEntry    entryInJar = zip.getEntry(cString);
    InputStream istream    = zip.getInputStream(entryInJar);
    result = getClassData(istream);
    cic.setClassInfo(className, true, jarFile);
    istream.close();
    zip.close();
                
            }

        } else {
            FileInputStream fi = new FileInputStream(classFile);
      result = getClassData(fi);
      cic.setClassInfo(className, false, classFile);  
      fi.close();
            
        }

        return result;
    }


    /**
     * Gets a byte array from an InputStream
     *
     * @return byte bytearray specifying data from an InputStream
     * @exception IOException if any InputOutput exception occurs while reading the Stream
     */
    private byte[] getClassData(InputStream cistream)
        throws IOException {
            
        if (cistream == null) {
            return null;
        }
        byte[] byteBuf = new byte[1024];

        ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
        int len = 0;
            
        while((len = cistream.read(byteBuf)) != -1) {
            byteOut.write(byteBuf, 0, len);
        }
        
        return byteOut.toByteArray();
    }

    
    /**
     * This method overrides the one in the the parent java.lang.ClassLoader
     * It is called to get the URL of a resources like property files
     *
     * @return  A <tt>URL</tt> object for reading the resource, or
     *          <tt>null</tt> if the resource could not be found
     *
     * @param name Name of the resource that the classloader is doing the lookup
     *        for.
     */

    protected URL findResource(String name) {
        URL resURL = null;
        if(urlClassLoader!=null){
            resURL =  urlClassLoader.getResource(name);
        }else{
            resURL = super.findResource(name);
        }
        return resURL;
    }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.