PageRenderTime 32ms CodeModel.GetById 20ms app.highlight 9ms RepoModel.GetById 1ms app.codeStats 0ms

/jEdit/tags/jedit-4-2-pre4/org/gjt/sp/jedit/JARClassLoader.java

#
Java | 288 lines | 179 code | 38 blank | 71 comment | 31 complexity | 1c71b87336c44f11362aed8aa00f10c5 MD5 | raw file
  1/*
  2 * JARClassLoader.java - Loads classes from JAR files
  3 * :tabSize=8:indentSize=8:noTabs=false:
  4 * :folding=explicit:collapseFolds=1:
  5 *
  6 * Copyright (C) 1999, 2003 Slava Pestov
  7 * Portions copyright (C) 1999 mike dillon
  8 *
  9 * This program is free software; you can redistribute it and/or
 10 * modify it under the terms of the GNU General Public License
 11 * as published by the Free Software Foundation; either version 2
 12 * of the License, or any later version.
 13 *
 14 * This program is distributed in the hope that it will be useful,
 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 17 * GNU General Public License for more details.
 18 *
 19 * You should have received a copy of the GNU General Public License
 20 * along with this program; if not, write to the Free Software
 21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 22 */
 23
 24package org.gjt.sp.jedit;
 25
 26//{{{ Imports
 27import java.io.InputStream;
 28import java.io.IOException;
 29import java.net.URL;
 30import java.util.Hashtable;
 31import java.util.Iterator;
 32import java.util.zip.ZipEntry;
 33import java.util.zip.ZipFile;
 34import org.gjt.sp.util.Log;
 35//}}}
 36
 37/**
 38 * A class loader implementation that loads classes from JAR files.
 39 * @author Slava Pestov
 40 * @version $Id: JARClassLoader.java 4669 2003-05-01 02:21:27Z spestov $
 41 */
 42public class JARClassLoader extends ClassLoader
 43{
 44	//{{{ JARClassLoader constructor
 45	/**
 46	 * This constructor creates a class loader for loading classes from all
 47	 * plugins. For example BeanShell uses one of these so that scripts can
 48	 * use plugin classes.
 49	 */
 50	public JARClassLoader()
 51	{
 52	} //}}}
 53
 54	//{{{ loadClass() method
 55	/**
 56	 * @exception ClassNotFoundException if the class could not be found
 57	 */
 58	public Class loadClass(String clazz, boolean resolveIt)
 59		throws ClassNotFoundException
 60	{
 61		// see what JARClassLoader this class is in
 62		Object obj = classHash.get(clazz);
 63		if(obj == NO_CLASS)
 64		{
 65			// we remember which classes we don't exist
 66			// because BeanShell tries loading all possible
 67			// <imported prefix>.<class name> combinations
 68			throw new ClassNotFoundException(clazz);
 69		}
 70		else if(obj instanceof JARClassLoader)
 71		{
 72			JARClassLoader classLoader = (JARClassLoader)obj;
 73			return classLoader._loadClass(clazz,resolveIt);
 74		}
 75
 76		// if it's not in the class hash, and not marked as
 77		// non-existent, try loading it from the CLASSPATH
 78		try
 79		{
 80			Class cls;
 81
 82			/* Defer to whoever loaded us (such as JShell,
 83			 * Echidna, etc) */
 84			ClassLoader parentLoader = getClass().getClassLoader();
 85			if (parentLoader != null)
 86				cls = parentLoader.loadClass(clazz);
 87			else
 88				cls = findSystemClass(clazz);
 89
 90			return cls;
 91		}
 92		catch(ClassNotFoundException cnf)
 93		{
 94			// remember that this class doesn't exist for
 95			// future reference
 96			classHash.put(clazz,NO_CLASS);
 97
 98			throw cnf;
 99		}
100	} //}}}
101
102	//{{{ getResourceAsStream() method
103	public InputStream getResourceAsStream(String name)
104	{
105		if(jar == null)
106			return null;
107
108		try
109		{
110			ZipFile zipFile = jar.getZipFile();
111			ZipEntry entry = zipFile.getEntry(name);
112			if(entry == null)
113				return getSystemResourceAsStream(name);
114			else
115				return zipFile.getInputStream(entry);
116		}
117		catch(IOException io)
118		{
119			Log.log(Log.ERROR,this,io);
120
121			return null;
122		}
123	} //}}}
124
125	//{{{ getResource() method
126	public URL getResource(String name)
127	{
128		if(jar == null)
129			return null;
130
131		try
132		{
133			ZipFile zipFile = jar.getZipFile();
134			ZipEntry entry = zipFile.getEntry(name);
135			if(entry == null)
136				return getSystemResource(name);
137			else
138				return new URL(getResourceAsPath(name));
139		}
140		catch(IOException io)
141		{
142			Log.log(Log.ERROR,this,io);
143			return null;
144		}
145	} //}}}
146
147	//{{{ getResourceAsPath() method
148	public String getResourceAsPath(String name)
149	{
150		if(jar == null)
151			return null;
152
153		if(!name.startsWith("/"))
154			name = "/" + name;
155
156		return "jeditresource:/" + MiscUtilities.getFileName(
157			jar.getPath()) + "!" + name;
158	} //}}}
159
160	//{{{ getZipFile() method
161	/**
162	 * @deprecated Call <code>PluginJAR.getZipFile()</code> instead.
163	 */
164	public ZipFile getZipFile()
165	{
166		try
167		{
168			return jar.getZipFile();
169		}
170		catch(IOException io)
171		{
172			Log.log(Log.ERROR,this,io);
173			return null;
174		}
175	} //}}}
176
177	//{{{ Package-private members
178
179	//{{{ JARClassLoader constructor
180	/**
181	 * @since jEdit 4.2pre1
182	 */
183	JARClassLoader(PluginJAR jar)
184	{
185		this.jar = jar;
186	} //}}}
187
188	//{{{ activate() method
189	void activate()
190	{
191		String[] classes = jar.getClasses();
192		if(classes != null)
193		{
194			for(int i = 0; i < classes.length; i++)
195			{
196				classHash.put(classes[i],this);
197			}
198		}
199	} //}}}
200
201	//{{{ deactivate() method
202	void deactivate()
203	{
204		String[] classes = jar.getClasses();
205		for(int i = 0; i < classes.length; i++)
206		{
207			Object loader = classHash.get(classes[i]);
208			if(loader == this)
209				classHash.remove(classes[i]);
210			else
211				/* two plugins provide same class! */;
212		}
213	} //}}}
214
215	//}}}
216
217	//{{{ Private members
218
219	// used to mark non-existent classes in class hash
220	private static final Object NO_CLASS = new Object();
221
222	private static Hashtable classHash = new Hashtable();
223
224	private PluginJAR jar;
225
226	//{{{ _loadClass() method
227	/**
228	 * Load class from this JAR only.
229	 */
230	private Class _loadClass(String clazz, boolean resolveIt)
231		throws ClassNotFoundException
232	{
233		jar.activatePlugin();
234
235		Class cls = findLoadedClass(clazz);
236		if(cls != null)
237		{
238			if(resolveIt)
239				resolveClass(cls);
240			return cls;
241		}
242
243		String name = MiscUtilities.classToFile(clazz);
244
245		try
246		{
247			ZipFile zipFile = jar.getZipFile();
248			ZipEntry entry = zipFile.getEntry(name);
249
250			if(entry == null)
251				throw new ClassNotFoundException(clazz);
252
253			InputStream in = zipFile.getInputStream(entry);
254
255			int len = (int)entry.getSize();
256			byte[] data = new byte[len];
257			int success = 0;
258			int offset = 0;
259			while(success < len)
260			{
261				len -= success;
262				offset += success;
263				success = in.read(data,offset,len);
264				if(success == -1)
265				{
266					Log.log(Log.ERROR,this,"Failed to load class "
267						+ clazz + " from " + zipFile.getName());
268					throw new ClassNotFoundException(clazz);
269				}
270			}
271
272			cls = defineClass(clazz,data,0,data.length);
273
274			if(resolveIt)
275				resolveClass(cls);
276
277			return cls;
278		}
279		catch(IOException io)
280		{
281			Log.log(Log.ERROR,this,io);
282
283			throw new ClassNotFoundException(clazz);
284		}
285	} //}}}
286
287	//}}}
288}