/* This file is part of the db4o object database http://www.db4o.com
Copyright (C) 2004 - 2011 Versant Corporation http://www.versant.com
db4o is free software; you can redistribute it and/or modify it under
the terms of version 3 of the GNU General Public License as published
by the Free Software Foundation.
db4o 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.db4o.instrumentation.main;
import java.io.*;
import java.net.*;
import java.util.*;
import EDU.purdue.cs.bloat.editor.*;
import EDU.purdue.cs.bloat.file.*;
import com.db4o.instrumentation.core.*;
import com.db4o.instrumentation.file.*;
/**
* @exclude
*/
public class Db4oFileInstrumentor {
private final BloatClassEdit _classEdit;
private final Set<Db4oInstrumentationListener> _listeners = new HashSet<Db4oInstrumentationListener>();
public Db4oFileInstrumentor(BloatClassEdit classEdit) {
_classEdit = classEdit;
}
public Db4oFileInstrumentor(BloatClassEdit[] classEdits) {
this(new CompositeBloatClassEdit(classEdits));
}
public void addInstrumentationListener(Db4oInstrumentationListener listener) {
_listeners.add(listener);
}
public void removeInstrumentationListener(Db4oInstrumentationListener listener) {
_listeners.remove(listener);
}
public void enhance(File sourceDir, File targetDir, String[] classpath) throws Exception {
enhance(new DefaultFilePathRoot(new String[]{ sourceDir.getAbsolutePath() }, ".class"), targetDir, classpath);
}
public void enhance(FilePathRoot sources, File targetDir, String[] classpath) throws Exception {
enhance(new DefaultClassSource(), sources, targetDir, classpath);
}
public void enhance(ClassSource classSource, FilePathRoot sources,File targetDir,String[] classpath) throws Exception {
enhance(classSource, sources, targetDir, classpath, ClassLoader.getSystemClassLoader());
}
public void enhance(ClassSource classSource, FilePathRoot sources,File targetDir,String[] classpath, ClassLoader parentClassLoader) throws Exception {
ClassFileLoader fileLoader=new ClassFileLoader(classSource);
String[] fullClasspath = fullClasspath(sources, classpath);
setOutputDir(fileLoader, targetDir);
setClasspath(fileLoader, fullClasspath);
URL[] urls = classpathToURLs(fullClasspath);
URLClassLoader classLoader=new URLClassLoader(urls,parentClassLoader);
enhance(sources,targetDir,classLoader,new BloatLoaderContext(fileLoader));
fileLoader.done();
}
private void enhance(
FilePathRoot sources,
File target,
ClassLoader classLoader,
BloatLoaderContext bloatUtil) throws Exception {
for (Db4oInstrumentationListener listener : _listeners) {
listener.notifyStartProcessing(sources);
}
for (InstrumentationClassSource file : sources) {
enhanceFile(file, target, classLoader, bloatUtil);
}
for (Db4oInstrumentationListener listener : _listeners) {
listener.notifyEndProcessing(sources);
}
}
private void enhanceFile(
InstrumentationClassSource source,
File target,
ClassLoader classLoader,
BloatLoaderContext bloatUtil) throws IOException, ClassNotFoundException {
ClassEditor classEditor = bloatUtil.classEditor(source.className());
InstrumentationStatus status = _classEdit.enhance(classEditor, classLoader, bloatUtil);
notifyListeners(source, status);
if (!status.isInstrumented()) {
File targetFile = source.targetPath(target);
targetFile.getParentFile().mkdirs();
copy(source, targetFile);
}
}
private void notifyListeners(InstrumentationClassSource source, InstrumentationStatus status) {
for (Db4oInstrumentationListener listener : _listeners) {
listener.notifyProcessed(source, status);
}
}
private void copy(InstrumentationClassSource source, File targetFile) throws IOException {
if(targetFile.equals(source.sourceFile())){
return;
}
final int bufSize = 4096;
BufferedInputStream bufIn = new BufferedInputStream(source.inputStream(), bufSize);
try {
BufferedOutputStream bufOut = new BufferedOutputStream(new FileOutputStream(targetFile));
try {
copy(bufSize, bufIn, bufOut);
}
finally {
bufOut.close();
}
}
finally {
bufIn.close();
}
}
private void copy(final int bufSize, BufferedInputStream bufIn,
BufferedOutputStream bufOut) throws IOException {
byte[] buf = new byte[bufSize];
int bytesRead = -1;
while((bytesRead = bufIn.read(buf)) >= 0) {
bufOut.write(buf, 0, bytesRead);
}
}
private String[] fullClasspath(FilePathRoot sources, String[] classpath) throws IOException {
String[] sourceRoots = sources.rootDirs();
String [] fullClasspath = new String[sourceRoots.length + classpath.length];
System.arraycopy(sourceRoots, 0, fullClasspath, 0, sourceRoots.length);
System.arraycopy(classpath, 0, fullClasspath, sourceRoots.length, classpath.length);
return fullClasspath;
}
private void setOutputDir(ClassFileLoader fileLoader, File fTargetDir) {
fileLoader.setOutputDir(fTargetDir);
}
private void setClasspath(ClassFileLoader fileLoader, String[] classPath) {
for (int pathIdx = 0; pathIdx < classPath.length; pathIdx++) {
fileLoader.appendClassPath(classPath[pathIdx]);
}
}
private URL[] classpathToURLs(String[] classPath) throws MalformedURLException {
URL[] urls=new URL[classPath.length];
for (int pathIdx = 0; pathIdx < classPath.length; pathIdx++) {
urls[pathIdx]=toURL(classPath[pathIdx]);
}
return urls;
}
/**
* @deprecated
*
* @throws MalformedURLException
*/
private URL toURL(final String classPathItem) throws MalformedURLException {
return new File(classPathItem).toURL();
}
}