View Javadoc

1   /**********************************************************************
2    * EJClassLoader.java
3    * created on 08.08.2004 by netseeker
4    * $Source: /cvsroot/ejoe/EJOE/src/de/netseeker/ejoe/EJClassLoader.java,v $
5    * $Date: 2006/02/04 14:16:35 $
6    * $Revision: 1.15 $
7    *********************************************************************/
8   
9   package de.netseeker.ejoe;
10  
11  import java.io.IOException;
12  import java.io.Serializable;
13  
14  import de.netseeker.ejoe.adapter.ObjectStreamAdapter;
15  import de.netseeker.ejoe.cache.SoftKeyedObjectCache;
16  
17  /***
18   * A remote classloader using an EJClient instance to retrieve class definitions
19   * from an EJOE classloaderserver. The last thousand retrieved classes are
20   * cached global over all instances of EJClassLoader. The used cache uses soft
21   * references.
22   * 
23   * @author netseeker aka Michael Manske
24   */
25  public class EJClassLoader extends ClassLoader implements Serializable
26  {
27  	private static final long					serialVersionUID	= 3835151740298408496L;
28  
29  	private static final SoftKeyedObjectCache	_classCache			= new SoftKeyedObjectCache(1000);
30  
31  	private final EJClient						_client;
32  
33  	/***
34  	 * Creates a new instance of this classloader using the EJOE server on the
35  	 * given host and port for loading unknown class definitions.
36  	 * 
37  	 * @param host
38  	 *            ip address or dns name where the EJOE classloader server is
39  	 *            running
40  	 * @param port
41  	 *            port to which the EJOE classloader serve is listening
42  	 */
43  	public EJClassLoader(String host, int port)
44  	{
45  		super();
46  		_client = new EJClient(host, port, new ObjectStreamAdapter());
47  	}
48  
49  	/***
50  	 * /** Creates a new instance of this classloader using the EJOE server on
51  	 * the given host and port for loading unknown class definitions. The
52  	 * classloader will delegate calls first to the given parent classloader.
53  	 * 
54  	 * @param parent
55  	 *            parent classloader
56  	 * @param host
57  	 *            ip address or dns name where the EJOE classloader server is
58  	 *            running
59  	 * @param port
60  	 *            port to which the EJOE classloader serve is listening
61  	 */
62  	public EJClassLoader(ClassLoader parent, String host, int port)
63  	{
64  		super(parent);
65  		_client = new EJClient(host, port, new ObjectStreamAdapter());
66  	}
67  
68  	/*
69  	 * (non-Javadoc)
70  	 * 
71  	 * @see java.lang.ClassLoader#loadClass(java.lang.String, boolean)
72  	 */
73  	protected synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException
74  	{
75  		Class clazz = (Class) _classCache.get(name);
76  
77  		if (clazz == null)
78  		{
79  			// ----- Check with the primordial class loader
80  			try
81  			{
82  				clazz = super.findSystemClass(name);
83  				return clazz;
84  			}
85  			catch (ClassNotFoundException e)
86  			{
87  				// do nothing, it's just not a system class
88  			}
89  
90  			clazz = loadRemoteClass(name);
91  			_classCache.put(name, clazz);
92  
93  			if (resolve)
94  			{
95  				resolveClass(clazz);
96  			}
97  		}
98  
99  		return clazz;
100 	}
101 
102 	/*
103 	 * (non-Javadoc)
104 	 * 
105 	 * @see java.lang.ClassLoader#loadClass(java.lang.String)
106 	 */
107 	public Class loadClass(String name) throws ClassNotFoundException
108 	{
109 		return loadClass(name, true);
110 	}
111 
112 	/***
113 	 * @param name
114 	 * @return
115 	 * @throws IOException
116 	 */
117 	private Class loadRemoteClass(String name) throws ClassNotFoundException
118 	{
119 		Class result = null;
120 
121 		try
122 		{
123 			byte[] classRaw = (byte[]) _client.execute(name);
124 			if (classRaw == null)
125 			{
126 				throw new ClassNotFoundException("Class " + name + " not found!");
127 			}
128 
129 			result = defineClass(name, classRaw, 0, classRaw.length);
130 		}
131 		catch (IOException e)
132 		{
133 			throw new ClassNotFoundException(e.getMessage());
134 		}
135 
136 		return result;
137 	}
138 }