sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi/src/com/nokia/carbide/cpp/internal/pi/utils/PluginClassLoader.java
author Matti Laitinen <matti.t.laitinen@nokia.com>
Thu, 11 Feb 2010 15:32:31 +0200
changeset 2 b9ab3b238396
child 5 844b047e260d
permissions -rw-r--r--
Initial version of Performance Investigator under EPL

/*
 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
 * All rights reserved.
 * This component and the accompanying materials are made available
 * under the terms of the License "Eclipse Public License v1.0"
 * which accompanies this distribution, and is available
 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
 *
 * Initial Contributors:
 * Nokia Corporation - initial contribution.
 *
 * Contributors:
 *
 * Description: 
 *
 */

package com.nokia.carbide.cpp.internal.pi.utils;

import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import com.nokia.carbide.cpp.internal.pi.plugin.model.AbstractPiPlugin;


public class PluginClassLoader extends ClassLoader 
{	
	public ArrayList dirEntries;
	public ArrayList jarEntries;
	public Hashtable resolvedClasses;
	
	public PluginClassLoader(AbstractPiPlugin[] entries) 
	{
		super();
		
		dirEntries = new ArrayList();
		jarEntries = new ArrayList();
		resolvedClasses = new Hashtable();
	}
	
	@SuppressWarnings("unchecked") //$NON-NLS-1$
	public Class loadClass(String className) throws ClassNotFoundException
	{
		if (this.resolvedClasses.containsKey(className))
		{
			return (Class)this.resolvedClasses.get(className);
		}
		
		try
		{
			Class c = super.loadClass(className);
			return c;
		}
		catch(ClassNotFoundException e)
		{
			throw e;
		}
	}
	
	@SuppressWarnings("unchecked") //$NON-NLS-1$
	public Class findClass(String className) throws ClassNotFoundException
	{
		if (this.resolvedClasses.containsKey(className))
		{
			return (Class)this.resolvedClasses.get(className);
		}
		else
		{
			byte[] classBytes = findClassBytes(className);
			if (classBytes == null)
			{
				Class c = super.findLoadedClass(className);
				if (c == null)
					throw new ClassNotFoundException(className);
				else
					return c;
			} 
			else 
			{
				Class c = defineClass(className, classBytes, 0, classBytes.length);
				this.resolvedClasses.put(className,c);
				return c;
			}
		}
	}
	
	public byte[] findClassBytes(String className)
	{
		Iterator i = this.dirEntries.iterator();
		while(i.hasNext())
		{
			File f = (File)i.next();
			byte[] b = this.findClassBytesDir(f,className);
			if (b != null) return b;
		}
		
		i = this.jarEntries.iterator();
		while(i.hasNext())
		{
			File f = (File)i.next();
			byte[] b = this.findClassBytesJar(f,className);
			if (b != null) return b;
		}
		
		return null;
	}
	
	private byte[] findClassBytesJar(File jarFile, String className)
	{
		//System.out.println("Finding class bytes for "+className+" from "+jarFile.getName());
		try
		{
			ZipInputStream zis = new ZipInputStream(new FileInputStream(jarFile));
			ZipEntry ze = zis.getNextEntry();
			
			while(zis.available() == 1 && ze != null)
			{
				String entryName = ze.getName().replace('/','.');
				
				if (entryName.equals(className+Messages.getString("PluginClassLoader.classEntry"))) //$NON-NLS-1$
				{
					//System.out.println("FOUND!!!");
					ArrayList<byte[]>  data    = new ArrayList<byte[]>();
					ArrayList<Integer> amounts = new ArrayList<Integer>();
					int totalAmount = 0;
					while(true)
					{
						byte[] tempBytes = new byte[1024];
						int amount = zis.read(tempBytes);
						if (amount != -1) 
						{
							amounts.add(new Integer(amount));
							totalAmount+=amount;
							data.add(tempBytes);
						}
						else
						{
							break;	
						}
					}
						
					byte[] classBytes = new byte[totalAmount];
						
					Iterator<byte[]>  bI = data.iterator();
					Iterator<Integer> aI = amounts.iterator();
					int pos = 0;
					while(bI.hasNext())
					{
						byte[] a = bI.next();
						int am = aI.next().intValue();
						System.arraycopy(a,0,classBytes,pos,am);
						pos += am;
					}

					zis.closeEntry();
					return classBytes;
				}
				zis.closeEntry();
				ze = zis.getNextEntry();
			}
			zis.close();
			return null;
		}
		catch (Exception e)
		{
			e.printStackTrace();
			return null;
		}
	}
	
	private byte[] findClassBytesDir(File rootDir, String className) 
	{	
		try 
		{
			String pathName = rootDir.getAbsolutePath() + File.separatorChar
					+ className.replace('.', File.separatorChar) + Messages.getString("PluginClassLoader.classEntry"); //$NON-NLS-1$

			FileInputStream fis = new FileInputStream(pathName);
			byte[] classBytes = new byte[fis.available()];
			fis.read(classBytes);
			fis.close();
			return classBytes;
		} 
		catch (java.io.IOException ioEx)
		{
			return null;
		}
	}
}