org.kohsuke.asm5.xml.Processor Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of asm5 Show documentation
Show all versions of asm5 Show documentation
ObjectWeb ASM package-renamed to isolate incompatibilities between major versions
The newest version!
/***
* ASM XML Adapter
* Copyright (c) 2004-2011, Eugene Kuleshov
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.objectweb.asm.xml;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
import javax.xml.transform.Source;
import javax.xml.transform.Templates;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.sax.TransformerHandler;
import javax.xml.transform.stream.StreamSource;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.ext.LexicalHandler;
import org.xml.sax.helpers.AttributesImpl;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;
/**
* Processor is a command line tool that can be used for bytecode waving
* directed by XSL transformation.
*
* In order to use a concrete XSLT engine, system property
* javax.xml.transform.TransformerFactory must be set to one of the
* following values.
*
*
*
*
* jd.xslt
* jd.xml.xslt.trax.TransformerFactoryImpl
*
*
*
* Saxon
* net.sf.saxon.TransformerFactoryImpl
*
*
*
* Caucho
* com.caucho.xsl.Xsl
*
*
*
* Xalan interpeter
* org.apache.xalan.processor.TransformerFactory
*
*
*
* Xalan xsltc
* org.apache.xalan.xsltc.trax.TransformerFactoryImpl
*
*
*
*
* @author Eugene Kuleshov
*/
public class Processor {
public static final int BYTECODE = 1;
public static final int MULTI_XML = 2;
public static final int SINGLE_XML = 3;
private static final String SINGLE_XML_NAME = "classes.xml";
private final int inRepresentation;
private final int outRepresentation;
private final InputStream input;
private final OutputStream output;
private final Source xslt;
private int n = 0;
public Processor(final int inRepresenation, final int outRepresentation,
final InputStream input, final OutputStream output,
final Source xslt) {
this.inRepresentation = inRepresenation;
this.outRepresentation = outRepresentation;
this.input = input;
this.output = output;
this.xslt = xslt;
}
public int process() throws TransformerException, IOException, SAXException {
ZipInputStream zis = new ZipInputStream(input);
final ZipOutputStream zos = new ZipOutputStream(output);
final OutputStreamWriter osw = new OutputStreamWriter(zos);
Thread.currentThread().setContextClassLoader(
getClass().getClassLoader());
TransformerFactory tf = TransformerFactory.newInstance();
if (!tf.getFeature(SAXSource.FEATURE)
|| !tf.getFeature(SAXResult.FEATURE)) {
return 0;
}
SAXTransformerFactory saxtf = (SAXTransformerFactory) tf;
Templates templates = null;
if (xslt != null) {
templates = saxtf.newTemplates(xslt);
}
// configuring outHandlerFactory
// ///////////////////////////////////////////////////////
EntryElement entryElement = getEntryElement(zos);
ContentHandler outDocHandler = null;
switch (outRepresentation) {
case BYTECODE:
outDocHandler = new OutputSlicingHandler(
new ASMContentHandlerFactory(zos), entryElement, false);
break;
case MULTI_XML:
outDocHandler = new OutputSlicingHandler(new SAXWriterFactory(osw,
true), entryElement, true);
break;
case SINGLE_XML:
ZipEntry outputEntry = new ZipEntry(SINGLE_XML_NAME);
zos.putNextEntry(outputEntry);
outDocHandler = new SAXWriter(osw, false);
break;
}
// configuring inputDocHandlerFactory
// /////////////////////////////////////////////////
ContentHandler inDocHandler;
if (templates == null) {
inDocHandler = outDocHandler;
} else {
inDocHandler = new InputSlicingHandler("class", outDocHandler,
new TransformerHandlerFactory(saxtf, templates,
outDocHandler));
}
ContentHandlerFactory inDocHandlerFactory = new SubdocumentHandlerFactory(
inDocHandler);
if (inDocHandler != null && inRepresentation != SINGLE_XML) {
inDocHandler.startDocument();
inDocHandler.startElement("", "classes", "classes",
new AttributesImpl());
}
int i = 0;
ZipEntry ze;
while ((ze = zis.getNextEntry()) != null) {
update(ze.getName(), n++);
if (isClassEntry(ze)) {
processEntry(zis, ze, inDocHandlerFactory);
} else {
OutputStream os = entryElement.openEntry(getName(ze));
copyEntry(zis, os);
entryElement.closeEntry();
}
i++;
}
if (inDocHandler != null && inRepresentation != SINGLE_XML) {
inDocHandler.endElement("", "classes", "classes");
inDocHandler.endDocument();
}
if (outRepresentation == SINGLE_XML) {
zos.closeEntry();
}
zos.flush();
zos.close();
return i;
}
private void copyEntry(final InputStream is, final OutputStream os)
throws IOException {
if (outRepresentation == SINGLE_XML) {
return;
}
byte[] buff = new byte[2048];
int i;
while ((i = is.read(buff)) != -1) {
os.write(buff, 0, i);
}
}
private boolean isClassEntry(final ZipEntry ze) {
String name = ze.getName();
return inRepresentation == SINGLE_XML && name.equals(SINGLE_XML_NAME)
|| name.endsWith(".class") || name.endsWith(".class.xml");
}
private void processEntry(final ZipInputStream zis, final ZipEntry ze,
final ContentHandlerFactory handlerFactory) {
ContentHandler handler = handlerFactory.createContentHandler();
try {
// if (CODE2ASM.equals(command)) { // read bytecode and process it
// // with TraceClassVisitor
// ClassReader cr = new ClassReader(readEntry(zis, ze));
// cr.accept(new TraceClassVisitor(null, new PrintWriter(os)),
// false);
// }
boolean singleInputDocument = inRepresentation == SINGLE_XML;
if (inRepresentation == BYTECODE) { // read bytecode and process it
// with handler
ClassReader cr = new ClassReader(readEntry(zis, ze));
cr.accept(new SAXClassAdapter(handler, singleInputDocument), 0);
} else { // read XML and process it with handler
XMLReader reader = XMLReaderFactory.createXMLReader();
reader.setContentHandler(handler);
reader.parse(new InputSource(
singleInputDocument ? (InputStream) new ProtectedInputStream(
zis) : new ByteArrayInputStream(readEntry(zis,
ze))));
}
} catch (Exception ex) {
update(ze.getName(), 0);
update(ex, 0);
}
}
private EntryElement getEntryElement(final ZipOutputStream zos) {
if (outRepresentation == SINGLE_XML) {
return new SingleDocElement(zos);
}
return new ZipEntryElement(zos);
}
// private ContentHandlerFactory getHandlerFactory(
// OutputStream os,
// SAXTransformerFactory saxtf,
// Templates templates)
// {
// ContentHandlerFactory factory = null;
// if (templates == null) {
// if (outputRepresentation == BYTECODE) { // factory used to write
// // bytecode
// factory = new ASMContentHandlerFactory(os, computeMax);
// } else { // factory used to write XML
// factory = new SAXWriterFactory(os, true);
// }
// } else {
// if (outputRepresentation == BYTECODE) { // factory used to transform
// // and then write bytecode
// factory = new ASMTransformerHandlerFactory(saxtf,
// templates,
// os,
// computeMax);
// } else { // factory used to transformand then write XML
// factory = new TransformerHandlerFactory(saxtf,
// templates,
// os,
// outputRepresentation == SINGLE_XML);
// }
// }
// return factory;
// }
private String getName(final ZipEntry ze) {
String name = ze.getName();
if (isClassEntry(ze)) {
if (inRepresentation != BYTECODE && outRepresentation == BYTECODE) {
name = name.substring(0, name.length() - 4); // .class.xml to
// .class
} else if (inRepresentation == BYTECODE
&& outRepresentation != BYTECODE) {
name += ".xml"; // .class to .class.xml
}
// } else if( CODE2ASM.equals( command)) {
// name = name.substring( 0, name.length()-6).concat( ".asm");
}
return name;
}
private static byte[] readEntry(final InputStream zis, final ZipEntry ze)
throws IOException {
long size = ze.getSize();
if (size > -1) {
byte[] buff = new byte[(int) size];
int k = 0;
int n;
while ((n = zis.read(buff, k, buff.length - k)) > 0) {
k += n;
}
return buff;
}
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] buff = new byte[4096];
int i;
while ((i = zis.read(buff)) != -1) {
bos.write(buff, 0, i);
}
return bos.toByteArray();
}
/*
* (non-Javadoc)
*
* @see java.util.Observer#update(java.util.Observable, java.lang.Object)
*/
protected void update(final Object arg, final int n) {
if (arg instanceof Throwable) {
((Throwable) arg).printStackTrace();
} else {
if (n % 100 == 0) {
System.err.println(n + " " + arg);
}
}
}
public static void main(final String[] args) throws Exception {
if (args.length < 2) {
showUsage();
return;
}
int inRepresentation = getRepresentation(args[0]);
int outRepresentation = getRepresentation(args[1]);
InputStream is = System.in;
OutputStream os = new BufferedOutputStream(System.out);
Source xslt = null;
// boolean computeMax = true;
for (int i = 2; i < args.length; i++) {
if ("-in".equals(args[i])) {
is = new FileInputStream(args[++i]);
} else if ("-out".equals(args[i])) {
os = new BufferedOutputStream(new FileOutputStream(args[++i]));
} else if ("-xslt".equals(args[i])) {
xslt = new StreamSource(new FileInputStream(args[++i]));
// } else if( "-computemax".equals( args[ i].toLowerCase())) {
// computeMax = true;
} else {
showUsage();
return;
}
}
if (inRepresentation == 0 || outRepresentation == 0) {
showUsage();
return;
}
Processor m = new Processor(inRepresentation, outRepresentation, is,
os, xslt);
long l1 = System.currentTimeMillis();
int n = m.process();
long l2 = System.currentTimeMillis();
System.err.println(n);
System.err.println((l2 - l1) + "ms " + 1000f * n / (l2 - l1)
+ " resources/sec");
}
private static int getRepresentation(final String s) {
if ("code".equals(s)) {
return BYTECODE;
} else if ("xml".equals(s)) {
return MULTI_XML;
} else if ("singlexml".equals(s)) {
return SINGLE_XML;
}
return 0;
}
private static void showUsage() {
System.err
.println("Usage: Main [-in ] [-out