WALA/com.ibm.wala.cast.java.poly.../source/com/ibm/wala/cast/java/translator/polyglot/PolyglotSourceModuleTransla...

150 lines
5.0 KiB
Java

/******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
/*
* Created on Oct 6, 2005
*/
package com.ibm.wala.cast.java.translator.polyglot;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import polyglot.frontend.Compiler;
import polyglot.frontend.ExtensionInfo;
import polyglot.main.Options;
import polyglot.main.UsageError;
import polyglot.util.ErrorInfo;
import polyglot.util.Position;
import com.ibm.wala.cast.java.translator.SourceModuleTranslator;
import com.ibm.wala.classLoader.DirectoryTreeModule;
import com.ibm.wala.classLoader.FileModule;
import com.ibm.wala.classLoader.JarFileModule;
import com.ibm.wala.classLoader.Module;
import com.ibm.wala.classLoader.SourceFileModule;
import com.ibm.wala.ipa.callgraph.AnalysisScope;
import com.ibm.wala.types.ClassLoaderReference;
import com.ibm.wala.util.debug.Assertions;
/**
* A SourceModuleTranslator whose implementation of loadAllSources() uses the PolyglotFrontEnd pseudo-compiler to generate DOMO IR
* for the sources in the compile-time classpath.
*
* @author rfuhrer
*/
public class PolyglotSourceModuleTranslator implements SourceModuleTranslator {
private final ExtensionInfo fExtInfo;
private String fClassPath;
public PolyglotSourceModuleTranslator(AnalysisScope scope, IRTranslatorExtension extInfo, PolyglotSourceLoaderImpl sourceLoader) {
fExtInfo = (ExtensionInfo) extInfo;
computeClassPath(scope);
extInfo.setSourceLoader(sourceLoader);
}
private void computeClassPath(AnalysisScope scope) {
StringBuffer buf = new StringBuffer();
ClassLoaderReference cl = findInnermostClassLoader(scope);
while (cl != null) {
List<Module> modules = scope.getModules(cl);
for (Iterator<Module> iter = modules.iterator(); iter.hasNext();) {
Module m = (Module) iter.next();
if (buf.length() > 0)
buf.append(File.pathSeparator);
if (m instanceof JarFileModule) {
JarFileModule jarFileModule = (JarFileModule) m;
buf.append(jarFileModule.getAbsolutePath());
} else if (m instanceof DirectoryTreeModule) {
DirectoryTreeModule directoryTreeModule = (DirectoryTreeModule) m;
buf.append(directoryTreeModule.getPath());
} else if (m instanceof FileModule) {
// do nothing
} else
Assertions.UNREACHABLE("Module entry is neither jar file nor directory: " + m);
}
cl = cl.getParent();
}
fClassPath = buf.toString();
}
private ClassLoaderReference findInnermostClassLoader(AnalysisScope scope) {
Set<ClassLoaderReference> parentLoaders = new HashSet<ClassLoaderReference>();
for (ClassLoaderReference loader : scope.getLoaders()) {
parentLoaders.add(loader.getParent());
}
for (ClassLoaderReference child : scope.getLoaders()) {
if (!parentLoaders.contains(child)) {
return child;
}
}
throw new IllegalStateException("No innermost class loader???");
}
@SuppressWarnings("unchecked")
public void loadAllSources(Set modules) {
Options opts = fExtInfo.getOptions();
opts.assertions = true;
Options.global = opts;
try {
opts.parseCommandLine(new String[] { "-cp", fClassPath }, new HashSet());
} catch (UsageError e) {
// Assertions.UNREACHABLE("Error parsing classpath spec???");
}
Compiler compiler = new PolyglotFrontEnd(fExtInfo);
List<StreamSource> streams = new ArrayList<StreamSource>();
// N.B.: 'modules' is a flat set of source file ModuleEntry's.
for (Iterator it = modules.iterator(); it.hasNext();) {
SourceFileModule entry = (SourceFileModule) it.next();
assert entry.isSourceFile();
if (skipSourceFile(entry)) {
continue;
}
String filePath = entry.getAbsolutePath();
try {
StreamSource srcStream = new StreamSource(entry.getInputStream(), filePath);
streams.add(srcStream);
} catch (IOException e) {
compiler.errorQueue().enqueue(
new ErrorInfo(ErrorInfo.IO_ERROR, "Unable to open source file '" + entry.getName() + "'", Position.COMPILER_GENERATED));
}
}
compiler.compile(streams);
// At this point, DOMO now "knows" about all the source-originated stuff
}
/**
* @return true if the given source file module should not be processed, e.g. because it is generated on behalf of some upstream
* source.
*/
protected boolean skipSourceFile(SourceFileModule entry) {
return false;
}
}