KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > yagga > util > MetaJarClassLoader


1 /*
2  * This file is part of MiniInstaller, a self installer builder for Java
3  * Copyright (C) 2002 Walter Gamba
4  * mailto:walter@yagga.net
5  * http://www.yagga.net/java/miniinstaller
6  *
7  * MiniInstaller is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * MiniInstaller is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20  *
21  * As the time of writing, the GNU General Public Licene can be
22  * found at http://www.gnu.org/licenses/gpl.txt
23  *
24  */

25
26 package net.yagga.util;
27
28 import java.lang.reflect.*;
29 import java.io.IOException JavaDoc;
30 import java.util.jar.*;
31 import java.util.*;
32 import java.io.*;
33
34 /**
35  * A Meta class loader for loading jar files in many situations.
36  * It is interesting that the class, by using the MetajarResources class can load jar classes from Jars in the classpath
37  * <pre>
38  *
39  * ./Test.class
40  * ./net/yagga/util/MetaJarClassLoader.class
41  * ./sample.jar
42  * +- Difficult.class
43  * </pre>
44  *
45  * In this simple case one can read the class Difficult from the file "sample.jar" via this class, in the main method of the Test class.
46  * This case is more or less the same as seen in JavaWorld's tip 70 (JarClassLoader). The class reads the
47  * specified Jar entry and returns the byte array and then instantiate an object of the Class using the bytes.
48  * The trick is a bit more complicated if we are in such a case, executing the jar file named "all.jar":
49  * <pre>
50  *
51  * ./all.jar
52  * +- Test.class
53  * +- net/yagga/util/MetaJarClassLoader.class
54  * +- sample.jar
55  * +- Difficult.class
56  * </pre>
57  * In such a case JarClassLoader does not work. Instead we use the ability of MetJarResources to load bytes also from
58  * jars that are enclosedin the top-level (executing) jar.
59  *
60  * @see <a HREF="http://www.javaworld.com/javaworld/javatips/jw-javatip70.html"> JavaWorld's tip 70</a>
61  * @see net.yagga.util.MetaJarResources MetaJarResources
62  * @author Walter Gamba
63  */

64 public class MetaJarClassLoader extends ClassLoader JavaDoc
65 {
66     private MetaJarResources metaJarResources;
67     private String JavaDoc jarFile;
68     /**
69      * Construct the class loader givena a Jar File.
70      * @param jFile the name of the jar file.
71      */

72
73     public MetaJarClassLoader(String JavaDoc jFile)
74     {
75         super();
76         jarFile=jFile;
77         metaJarResources= new MetaJarResources(jarFile);
78     }
79
80     /**
81      * Return the actual jar name.
82      * This can be the top level Jar (whose name we usually ignore) or the jar file name
83      * we have passed in the constructor.
84      * @return the file name of the top-level jar file (if searching a Jar from inside an executing jar) or
85      * the jar name as we have passed it to the Constructor.
86      */

87     public String JavaDoc getActualJarName(){
88         return metaJarResources.getActualJarName();
89     }
90
91
92     /**
93      * Returns the name of the jar file main class, or null if
94      * no "Main-Class" manifest attributes was defined.
95      * @return the name of the main class of the Jar file
96      */

97     public String JavaDoc getMainClassName()
98     {
99         Manifest mf=metaJarResources.getManifest();
100         return mf != null ? mf.getMainAttributes().getValue(Attributes.Name.MAIN_CLASS) : null;
101     }
102
103     /**
104      * Invokes the application in this jar file given the name of the
105      * class, a static Method and an array of arguments.
106      * The class must define this
107      * static method which takes an array of Object arguments
108      * and can return anything.
109      * @param name the name of the class
110      * @param method the name of the method to invoke
111      * @param args the arguments to the method of this class of the jar file
112      */

113     public Object JavaDoc invokeMethod(String JavaDoc className, String JavaDoc method, Object JavaDoc[] args)
114         throws ClassNotFoundException JavaDoc,
115             NoSuchMethodException JavaDoc,
116             InvocationTargetException
117     {
118         Class JavaDoc c = loadClass(className);
119
120         //System.err.println("Class is "+c);
121
Method m = c.getMethod(method, new Class JavaDoc[] { args.getClass() });
122         //System.err.println("Method is "+m);
123
m.setAccessible(true);
124         int mods = m.getModifiers();
125         if (!Modifier.isStatic(mods) ||
126         !Modifier.isPublic(mods)) {
127             throw new NoSuchMethodException JavaDoc(method);
128         }
129                 Object JavaDoc ret=null;
130         try {
131             ret= m.invoke(null, new Object JavaDoc[] { args });
132         } catch (IllegalAccessException JavaDoc e) {
133         // This should not happen, as we have disabled access checks
134
}
135       return ret;
136     }
137
138     /**
139      * Invokes the application in this jar file given the name of the
140      * main class and an array of arguments.
141      * The class must define a
142      * static method "main" which takes an array of String arguemtns
143      * and is of return type "void".
144      * @param name the name of the main class
145      * @param args the arguments to the main method of the main class of the jar file
146      */

147     public void invokeClass(String JavaDoc name, String JavaDoc[] args)
148         throws ClassNotFoundException JavaDoc,
149             NoSuchMethodException JavaDoc,
150             InvocationTargetException
151     {
152         simpleInvokeMethod(name,"main",new Object JavaDoc[]{args});
153         /*
154         Class c = loadClass(name);
155
156         //System.err.println("Class is "+c);
157         Method m = c.getMethod("main", new Class[] { args.getClass() });
158         //System.err.println("Method is "+m);
159         m.setAccessible(true);
160         int mods = m.getModifiers();
161         if (m.getReturnType() != void.class || !Modifier.isStatic(mods) ||
162         !Modifier.isPublic(mods)) {
163             throw new NoSuchMethodException("main");
164         }
165         try {
166             m.invoke(null, new Object[] { args });
167         } catch (IllegalAccessException e) {
168         // This should not happen, as we have disabled access checks
169         }
170         */

171     }
172
173     /**
174      * Invokes a static method of a given class in this JAR.
175      * The class must define this
176      * static method which takes any number of arguments
177      * and can return anything.
178   * One must pass Strings as arguemnts, and they are converted to the appropriate
179   * native types. Only native types can be used, not even arrays of native types.<BR>
180   * Please note that no overloading/polymorohism of methods is used. The first method that
181   * has the same name as the one passed, and the same number of arguments, is used.<BR>
182   * And of course,
183   * "first" has no predictable meaning, so please be sure that you don't have ambiguities.
184      * @param name the name of the class
185      * @param method the name of the method to invoke
186      * @param args the arguments to the method of this class of the jar file, as Strings
187      * @return an Object containing th return value or values.
188      */

189
190     public Object JavaDoc simpleInvokeMethod(String JavaDoc className, String JavaDoc method, Object JavaDoc[] args)
191         throws ClassNotFoundException JavaDoc,
192             NoSuchMethodException JavaDoc,
193             InvocationTargetException
194     {
195     Class JavaDoc cl=loadClass(className);
196     return MetaUt.simpleInvokeStaticMethod(cl,method,args);
197   }
198
199     /**
200      * Method that actually reads the class from raw bytes.
201      * This method uses MetaJarResources to read raw bytes, then creates a Class
202      * with the given bytes
203      * @param className the classname (fully qualified with "."). Teh name is then read
204      * friom the jar file substituting "." with "/" and appending ".class"
205      * @return a Class object of representing the given class
206      */

207     protected Class JavaDoc findClass(String JavaDoc className) throws ClassNotFoundException JavaDoc
208     {
209         String JavaDoc urlName=className.replace('.', '/') + ".class";
210         //System.out.println("findClass:"+className);
211

212         // byte[] b1=getClassFromJar(urlName);
213
byte b1[]=metaJarResources.getBytes(urlName);
214         try{
215             return defineClass(className,b1,0,b1.length);
216         }catch(ClassFormatError JavaDoc cfe){
217             Ut.error("'"+className+"':"+cfe);
218         }
219         return null;
220     }
221
222 }
223
224
225
226
227
Popular Tags