/*
This file is part of JOP, the Java Optimized Processor
see <http://www.jopdesign.com/>
Copyright (C) 2005-2008, Martin Schoeberl (martin@jopdesign.com)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jopdesign.build;
import java.io.IOException;
import java.io.Serializable;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.bcel.Repository;
import org.apache.bcel.classfile.DescendingVisitor;
import org.apache.bcel.classfile.JavaClass;
import org.apache.bcel.classfile.Visitor;
import org.apache.bcel.util.ClassPath;
import org.apache.bcel.util.SyntheticRepository;
/**
* Helper class for BCEL based class analysis and manipulation.
* Used by JOPizer and should be used by WCETAnalyser and
* merged with libgraph
*
* TODO: split JOP specific and general MethodInfo
* TODO: make all general usable visitors AppVisitor instead of JOPizerVisitor
* TODO: How do we handle the update when manipulating methods and classes?
* There is this gen* in BCEL, but don't we also need to update the info
* in XClassInfo and XMethodInfo?
*
* @author Martin
* @deprecated
*/
public class OldAppInfo implements Serializable {
private static final long serialVersionUID = 1L;
protected String outFile;
protected String srcPath;
/**
* The class that contains the main method.
*/
protected String mainClass = "unknown";
protected String mainMethodName = "main";
// we usually provide the classpath, so this is redundant.
public ClassPath classpath = new ClassPath(".");
/**
* class list from the arguments
*/
private Set<String> clsArgs = new HashSet<String>();
/**
* Excluded classes (e.g. JOP Native.java)
*/
private Set<String> exclude = new HashSet<String>();
/**
* A template of the specific cli type to create
* the specific cli map (some form of factory pattern)
*/
private OldClassInfo template;
/**
* Map of ClassInfo that represents the application.
*
* It's public for the debugger.
*/
public Map<String, ? extends OldClassInfo> cliMap;
// protected Map<String, ClassInfo> cliMap;
public final static String clinitSig = "<clinit>()V";
/**
*
* @param cliTemplate a template to create the correct ClassInfo type
*/
public OldAppInfo(OldClassInfo cliTemplate) {
template = cliTemplate;
template.appInfo = this;
}
public String[] parseOptions(String args[]) {
List<String> retList = new LinkedList<String>();
System.out.println(args);
// if(args.length == 0) {
// System.err.println("arguments: [-cp classpath] [-o file] class [class]*");
try {
for (int i = 0; i<args.length; i++) {
if (args[i].equals("-cp")) {
i++;
classpath = new ClassPath(args[i]);
continue;
}
if (args[i].equals("-o")) {
i++;
outFile = args[i];
continue;
}
if (args[i].equals("-sp")) {
i++;
srcPath = args[i];
continue;
}
if (args[i].equals("-mm")) {
i++;
mainMethodName = args[i];
continue;
}
if (args[i].charAt(0)=='-') {
// an option we don't know
retList.add(args[i]);
i++;
while (i<args.length) {
if (args[i].charAt(0)!='-') {
retList.add(args[i]);
} else {
break;
}
}
} else {
// it's a class
clsArgs.add(args[i]);
}
// The last class contains the main method
// We also allow / notation as used with JCC
mainClass = args[i].replace('/', '.');
}
} catch(Exception e) { e.printStackTrace();}
String[] sa = new String[retList.size()];
return retList.toArray(sa);
}
/**
* Add an application known class (e.g. JOP system classes)
* @param name
*/
public void addClass(String name) {
clsArgs.add(name);
}
/**
* Exclude that class.
* @param name
*/
public void excludeClass(String name) {
exclude.add(name);
}
/**
* Load all classes that belong to the application.
* @throws ClassNotFoundException
*/
public void load() throws IOException, ClassNotFoundException {
JavaClass[] jcl = new JavaClass[clsArgs.size()];
Repository.setRepository(SyntheticRepository.getInstance(classpath));
Iterator<String> i = clsArgs.iterator();
for (int nr=0; i.hasNext(); ++nr) {
String clname = i.next();
jcl[nr] = Repository.lookupClass(clname);
if(jcl[nr] == null) throw new IOException("lookupClass("+clname+") failed");
System.out.println(jcl[nr].getClassName());
}
TransitiveHull hull = new TransitiveHull(classpath, jcl);
String[] excl = new String[exclude.size()];
hull.setExcluded(exclude.toArray(excl));
hull.start();
System.out.println(Arrays.asList(hull.getClassNames()));
JavaClass[] jclazz = hull.getClasses();
// jclazz now contains the closure of the application
cliMap = template.genClassInfoMap(jclazz, this);
}
public String toString() {
return cliMap.toString();
}
/**
* Iterate over all classes and run the visitor.
*
* @param v
*/
public void iterate(Visitor v) {
Iterator<? extends OldClassInfo> it = cliMap.values().iterator();
while (it.hasNext()) {
JavaClass clz = it.next().clazz;
new DescendingVisitor(clz, v).visit();
}
}
/**
* A simple example main that prints the Map of ClassInfo
*
* @param args
*/
public static void main(String[] args) {
OldAppInfo ai = new OldAppInfo(OldClassInfo.getTemplate());
ai.parseOptions(args);
System.out.println("CLASSPATH="+ai.classpath+"\tmain class="+ai.mainClass);
try {
ai.load();
} catch (Exception e) {
e.printStackTrace();
System.exit(-1);
}
System.out.println("Provide your own main!");
System.out.println("Ok here comes a BCEL dump of the loaded classes:");
System.out.println(ai);
}
/** Configure the application (classpath, sourcepath, entry point) */
public void configure(String classpath, String sourcepath,String entryClass) {
this.classpath = new ClassPath(classpath);
this.srcPath = sourcepath;
addClass(entryClass);
this.mainClass = entryClass;
}
}