/*
* Copyright (C) 2001 Mika Riekkinen, Joni Suominen
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package alt.jiapi.reflect;
import java.io.InputStream;
import java.io.IOException;
import java.lang.reflect.Modifier;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.List;
import java.util.Iterator;
import org.apache.log4j.Category;
import alt.jiapi.Runtime; // Dependency in wrong direction!
import alt.jiapi.file.ClassFile;
/*
*
* NOTE: Change this javadoc to relevant place !!!!
*
* This class modifies class loading so, that classes to be loaded
* are first checked wheteher or not they need to be instrumented.
* The algorithm, that decides the need for instrumentation,
* prefers exclusion. That is, a class is not to be instrumented.
* In other words, if you want a class to be instrumented, you will
* have to say so.<p>
*
* If there is a set of rules, that would apply both to inclusion and
* exclusion, more specific rule will apply.<p>
*
* That said, if have the following rules : <br>
* <blockquote>
* exclude : org.opensource<br>
* include : org.opensource.coolstuff<br>
* </blockquote>
* Then, <br>
* <blockquote>
* <b>org.opensource.coolstuff.Utility</b> class would be instrumented<br>
* <b>org.opensource.Thing</b> class would <b>not</b> be instrumented<br>
* <b>org.opensource.other.Thing</b> class would <b>not</b> be instrumented<br>
* </blockquote>
*
* There are two levels of rules : Package level and Class rules.
* Following describes each of the types of rules.
* <ul>
* <li>package level rules
* <blockquote>
* One specifies a package that is to be included or excluded with
* instrumentation. Package rules may be given so, that any part of
* the package name may be given in a rule. For example, one may
* give a package rule "org", or "org.opensource".
* All of the subpackages will be covered with this rule.
* </blockquote>
* <li>class level rules
* <blockquote>
* One specifies a class that is to be included or excluded with
* instrumentation. All of the methods of that class are covered
* by this rule.
* </blockquote>
* </ul>
*
* @author Mika Riekkinen
* @author Joni Suominen
* @version $Revision: 1.5 $ $Date: 2004/02/28 21:40:23 $
*/
/**
* Loads a JiapiClass. This class slightly looks like java.lang.ClassLoader.
*
* @author Mika Riekkinen
* @author Joni Suominen
* @version $Revision: 1.5 $ $Date: 2004/02/28 21:40:23 $
*/
public class Loader {
/**
* Creates new Loader.
*/
public Loader() {
}
/**
* Loads a JiapiCass from CLASSPATH. CLASSPATH is searched and if
* a class with given name is found, a JiapiClass is created to
* represent that class. When JiapiClass is created, it does not
* indicate, that corresponding class has been loaded/linked into
* Virtual Machine. An in-memory object representation for a given
* class is just created.
*
* @param className name of a class
* @return JiapiClass which is an in-memory representation for a class
* @exception ClassNotFoundException, if the class with given name can't
* be found
* @exception IOException, if the loading of class failed.
* @see #loadClass(String, URL)
*/
public JiapiClass loadClass(InputStream is) throws ClassNotFoundException, IOException {
ClassFile clazz = ClassFile.parse(is);
JiapiClass jiapiClass = new JiapiClass(clazz);
jiapiClass.setLoader(this);
return jiapiClass;
}
/**
* Loads a JiapiCass from CLASSPATH. CLASSPATH is searched and if
* a class with given name is found, a JiapiClass is created to
* represent that class. When JiapiClass is created, it does not
* indicate, that corresponding class has been loaded/linked into
* Virtual Machine. An in-memory object representation for a given
* class is just created.
*
* @param className name of a class
* @return JiapiClass which is an in-memory representation for a class
* @exception ClassNotFoundException, if the class with given name can't
* be found
* @exception IOException, if the loading of class failed.
* @see #loadClass(String, URL)
*/
public JiapiClass loadClass(String className) throws ClassNotFoundException, IOException {
return loadClass(className, null);
}
/**
* Loads a JiapiCass from a given URL. CLASSPATH is searched and if
* a class with given name is found, a JiapiClass is created to
* represent that class. When JiapiClass is created, it does not
* indicate, that corresponding class has been loaded/linked into
* Virtual Machine. An in-memory object representation for a given
* class is just created.
*
* @param className name of a class
* @param location an URL where the class should be loaded, if null
* then CLASSPATH is used to locate the class
* @return JiapiClass which is an in-memory representation for a class
* @exception ClassNotFoundException, if the class with given name can't
* be found
* @exception IOException, if the loading of class failed.
*/
public JiapiClass loadClass(String className, URL location) throws ClassNotFoundException, IOException {
JiapiClass jiapiClass = null;
InputStream is = getInputStream(className, location);
if (is == null) {
throw new ClassNotFoundException(className);
}
ClassFile clazz = ClassFile.parse(is);
jiapiClass = new JiapiClass(clazz);
jiapiClass.setLoader(this);
return jiapiClass;
}
private InputStream getInputStream(String name, URL location) throws IOException {
if (location == null) {
String resource = "/" + name.replace('.', '/') + ".class";
return getClass().getResourceAsStream(resource);
}
return location.openStream();
//throw new RuntimeException("NOT IMPLEMENTED: " + location);
}
// For testing purposes. args[0] is fully qualified classname
// args[1], if given, is the filename, that JiapiClass
// gets dumped to.
// > java alt.jiapi.reflect.Loader alt.jiapi.reflect.Loader
// Would read alt.jiapi.reflect.Loader
//
// > java alt.jiapi.reflect.Loader alt.jiapi.reflect.Loader test.class
// Would read Loader and dump that class into test.class.
// test.class should be exactly the same as Loader.class
//
// > java alt.jiapi.reflect.Loader test
// Would read test created above
public static void main(String[] args) throws Exception {
Loader l = new Loader();
JiapiClass clazz = l.loadClass(args[0]);
System.out.println(clazz);
if (args.length > 2) {
clazz.addInterface(args[2]);
}
// if (args.length > 3) {
// clazz.addField(args[3]);
// }
clazz.addField("jiapi_generated");
if (args.length > 1) {
clazz.dump(new java.io.FileOutputStream(args[1]));
}
}
}