com.sun.xml.bind.v2.bytecode.ClassTailor Maven / Gradle / Ivy
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 1997-2011 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can
* obtain a copy of the License at
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
* or packager/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package com.sun.xml.bind.v2.bytecode;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.sun.xml.bind.Util;
/**
* Replaces a few constant pool tokens from a class "template" and then loads it into the VM.
*
* @author Kohsuke Kawaguchi
*/
public final class ClassTailor {
private ClassTailor() {} // no instanciation please
private static final Logger logger = Util.getClassLogger();
/**
* Returns the class name in the JVM format (such as "java/lang/String")
*/
public static String toVMClassName( Class c ) {
assert !c.isPrimitive();
if(c.isArray())
// I have no idea why it is designed like this, but javap says so.
return toVMTypeName(c);
return c.getName().replace('.','/');
}
public static String toVMTypeName( Class c ) {
if(c.isArray()) {
// TODO: study how an array type is encoded.
return '['+toVMTypeName(c.getComponentType());
}
if(c.isPrimitive()) {
if(c==Boolean.TYPE) return "Z";
if(c==Character.TYPE) return "C";
if(c==Byte.TYPE) return "B";
if(c==Double.TYPE) return "D";
if(c==Float.TYPE) return "F";
if(c==Integer.TYPE) return "I";
if(c==Long.TYPE) return "J";
if(c==Short.TYPE) return "S";
throw new IllegalArgumentException(c.getName());
}
return 'L'+c.getName().replace('.','/')+';';
}
public static byte[] tailor( Class templateClass, String newClassName, String... replacements ) {
String vmname = toVMClassName(templateClass);
return tailor(
SecureLoader.getClassClassLoader(templateClass).getResourceAsStream(vmname+".class"),
vmname, newClassName, replacements );
}
/**
* Customizes a class file by replacing constant pools.
*
* @param image
* The image of the template class.
* @param replacements
* A list of pair of strings that specify the substitution
* {@code String[]{search_0, replace_0, search_1, replace_1, ..., search_n, replace_n }}
*
* The search strings found in the constant pool will be replaced by the corresponding
* replacement string.
*/
public static byte[] tailor( InputStream image, String templateClassName, String newClassName, String... replacements ) {
DataInputStream in = new DataInputStream(image);
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
DataOutputStream out = new DataOutputStream(baos);
// skip until the constant pool count
long l = in.readLong();
out.writeLong(l);
// read the constant pool size
short count = in.readShort();
out.writeShort(count);
// replace constant pools
for( int i=0; i0)
out.write(buf,0,len);
in.close();
out.close();
// by now we got the properly tailored class file image
return baos.toByteArray();
} catch( IOException e ) {
// never happen
logger.log(Level.WARNING,"failed to tailor",e);
return null;
}
}
}