Torsten,
I saw that you are interested in having an Ant task that instruments
class files statically, but the code is only half complete.
I took it little further and attached it, although it's still not tested
yet.
Would it be OK to commit this change?
--
Kohsuke Kawaguchi
/*
* Copyright 1999-2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.javaflow.ant;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
import java.util.zip.ZipEntry;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.MatchingTask;
import org.apache.commons.javaflow.bytecode.ClassTransformer;
import org.apache.commons.javaflow.bytecode.bcel.BcelClassTransformer;
import org.apache.commons.io.IOUtils;
/**
* Ant task that enhances class files with javaflow instrumentation.
*
* @author tcurdt
*/
public class AntRewriteTask extends MatchingTask {
private ClassTransformer transformer = new BcelClassTransformer();
private File destDir;
public void setDestDir(File file) {
destDir = file;
}
public File getDestDir() {
return destDir;
}
/**
* Check that all required attributes have been set and nothing
* silly has been entered.
*
* @since Ant 1.5
*/
protected void checkParameters() throws BuildException {
if (destDir==null) {
throw new BuildException("no destination directory is specified",getLocation());
}
if (!destDir.exists()) {
throw new BuildException(
"destination directory \""
+ destDir
+ "\" does not exist ",
getLocation());
}
if (!destDir.isDirectory()) {
throw new BuildException(
"destination directory \""
+ destDir
+ "\" is not a directory",
getLocation());
}
}
public void execute() throws BuildException {
super.execute();
checkParameters();
DirectoryScanner ds = fileset.getDirectoryScanner(getProject());
String[] files = ds.getIncludedFiles();
File srcDir = ds.getBasedir();
try {
for (int i = 0; i < files.length; i++) {
String one = files[i];
File source = new File(srcDir, one);
File destination = new File(getDestDir(), one);
if (!destination.getParentFile().exists()) {
log("Making dir: "+destination.getParentFile(), Project.MSG_VERBOSE);
destination.getParentFile().mkdirs();
}
if (source.lastModified() <= destination.lastModified()) {
log(source+" omitted as "+destination+" is up to date", Project.MSG_VERBOSE);
continue;
}
if (one.endsWith(".class")) {
log("source: "+source + " to "+destination, Project.MSG_VERBOSE);
// source might be the same as destination, so be careful
long origSize = source.length();
InputStream in = new FileInputStream(source);
byte[] bytes = IOUtils.toByteArray(in);
in.close();
bytes = transformer.transform(bytes);
FileOutputStream out = new FileOutputStream(destination);
out.write(bytes);
out.close();
log("Payload: " + 100*(destination.length()-origSize)/origSize+ '%');
}
if (one.endsWith(".jar")
|| one.endsWith(".ear")
|| one.endsWith(".zip")
|| one.endsWith(".war")) {
log("source: "+source + " to "+destination, Project.MSG_VERBOSE);
// write to a temporary file first because
// source might be the same as destination
File tmp = File.createTempFile("javaflow","tmp",destination.getParentFile());
ZipInputStream in = new ZipInputStream(new FileInputStream(source));
ZipOutputStream out = new ZipOutputStream(new FileOutputStream(tmp));
boolean changed;
try {
changed = processArchive(in,out,1);
} finally {
in.close();
out.close();
}
if(changed) {
if(destination.exists()) {
destination.delete();
}
tmp.renameTo(destination);
}
}
}
} catch (IOException e) {
throw new BuildException(e);
}
}
/**
* Recursively proecss all the files (including zip/jar files).
*
* @return nestLevel
* for a zip file, 1. for a zip file inside a zip file, 2. And so on.
* Used for indentation.
* @return
* true if at least one file has been modified. false
* if otherwise (meaning input and output are identical.)
*/
private boolean processArchive(ZipInputStream in, ZipOutputStream out, int nestLevel) throws IOException {
boolean changed = false;
ZipEntry e;
while((e=in.getNextEntry())!=null) {
// log the entry
StringBuffer buf = new StringBuffer();
for( int i=0; i<nestLevel; i++ )
buf.append(" ");
buf.append("processing "+e.getName());
log(buf.toString(), Project.MSG_VERBOSE);
String one = e.getName();
if (one.endsWith(".class")) {
// source might be the same as destination, so be careful
long origSize = e.getSize();
byte[] bytes = IOUtils.toByteArray(in);
in.close();
bytes = transformer.transform(bytes);
out.putNextEntry(e);
out.write(bytes);
out.closeEntry();
log("Payload: " + 100*(bytes.length-origSize)/origSize+ '%');
}
else
if (one.endsWith(".jar")
|| one.endsWith(".ear")
|| one.endsWith(".zip")
|| one.endsWith(".war")) {
out.putNextEntry(e);
changed |= processArchive(new ZipInputStream(in),new ZipOutputStream(out),nestLevel++);
out.closeEntry();
// TODO: compute the size increase
} else {
// just copy the file as-is.
out.putNextEntry(e);
IOUtils.copy(in,out);
out.closeEntry();
}
}
return changed;
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]