javassist.util.proxy.FactoryHelper Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jersey-all Show documentation
Show all versions of jersey-all Show documentation
jersey-all is a rebundled verison of Jersey as one OSGi bundle.
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package javassist.util.proxy;
import java.lang.reflect.Method;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.ProtectionDomain;
import javassist.CannotCompileException;
import javassist.bytecode.ClassFile;
/**
* A helper class for implementing ProxyFactory
.
* The users of ProxyFactory
do not have to see this class.
*
* @see ProxyFactory
*/
public class FactoryHelper {
private static java.lang.reflect.Method defineClass1, defineClass2;
static {
try {
Class cl = Class.forName("java.lang.ClassLoader");
defineClass1 = SecurityActions.getDeclaredMethod(
cl,
"defineClass",
new Class[] { String.class, byte[].class,
int.class, int.class });
defineClass2 = SecurityActions.getDeclaredMethod(
cl,
"defineClass",
new Class[] { String.class, byte[].class,
int.class, int.class, ProtectionDomain.class });
}
catch (Exception e) {
throw new RuntimeException("cannot initialize");
}
}
/**
* Returns an index for accessing arrays in this class.
*
* @throws RuntimeException if a given type is not a primitive type.
*/
public static final int typeIndex(Class type) {
Class[] list = primitiveTypes;
int n = list.length;
for (int i = 0; i < n; i++)
if (list[i] == type)
return i;
throw new RuntimeException("bad type:" + type.getName());
}
/**
* Class
objects representing primitive types.
*/
public static final Class[] primitiveTypes = {
Boolean.TYPE, Byte.TYPE, Character.TYPE, Short.TYPE, Integer.TYPE,
Long.TYPE, Float.TYPE, Double.TYPE, Void.TYPE
};
/**
* The fully-qualified names of wrapper classes for primitive types.
*/
public static final String[] wrapperTypes = {
"java.lang.Boolean", "java.lang.Byte", "java.lang.Character",
"java.lang.Short", "java.lang.Integer", "java.lang.Long",
"java.lang.Float", "java.lang.Double", "java.lang.Void"
};
/**
* The descriptors of the constructors of wrapper classes.
*/
public static final String[] wrapperDesc = {
"(Z)V", "(B)V", "(C)V", "(S)V", "(I)V", "(J)V",
"(F)V", "(D)V"
};
/**
* The names of methods for obtaining a primitive value
* from a wrapper object. For example, intValue()
* is such a method for obtaining an integer value from a
* java.lang.Integer
object.
*/
public static final String[] unwarpMethods = {
"booleanValue", "byteValue", "charValue", "shortValue",
"intValue", "longValue", "floatValue", "doubleValue"
};
/**
* The descriptors of the unwrapping methods contained
* in unwrapMethods
.
*/
public static final String[] unwrapDesc = {
"()Z", "()B", "()C", "()S", "()I", "()J", "()F", "()D"
};
/**
* The data size of primitive types. long
* and double
are 2; the others are 1.
*/
public static final int[] dataSize = {
1, 1, 1, 1, 1, 2, 1, 2
};
/**
* Loads a class file by a given class loader.
* This method uses a default protection domain for the class
* but it may not work with a security manager or a sigend jar file.
*
* @see #toClass(ClassFile,ClassLoader,ProtectionDomain)
*/
public static Class toClass(ClassFile cf, ClassLoader loader)
throws CannotCompileException
{
return toClass(cf, loader, null);
}
/**
* Loads a class file by a given class loader.
*
* @param domain if it is null, a default domain is used.
* @since 3.3
*/
public static Class toClass(ClassFile cf, ClassLoader loader, ProtectionDomain domain)
throws CannotCompileException
{
try {
byte[] b = toBytecode(cf);
Method method;
Object[] args;
if (domain == null) {
method = defineClass1;
args = new Object[] { cf.getName(), b, new Integer(0),
new Integer(b.length) };
}
else {
method = defineClass2;
args = new Object[] { cf.getName(), b, new Integer(0),
new Integer(b.length), domain };
}
return toClass2(method, loader, args);
}
catch (RuntimeException e) {
throw e;
}
catch (java.lang.reflect.InvocationTargetException e) {
throw new CannotCompileException(e.getTargetException());
}
catch (Exception e) {
throw new CannotCompileException(e);
}
}
private static synchronized Class toClass2(Method method,
ClassLoader loader, Object[] args)
throws Exception
{
SecurityActions.setAccessible(method, true);
Class clazz = (Class)method.invoke(loader, args);
SecurityActions.setAccessible(method, false);
return clazz;
}
private static byte[] toBytecode(ClassFile cf) throws IOException {
ByteArrayOutputStream barray = new ByteArrayOutputStream();
DataOutputStream out = new DataOutputStream(barray);
try {
cf.write(out);
}
finally {
out.close();
}
return barray.toByteArray();
}
/**
* Writes a class file.
*/
public static void writeFile(ClassFile cf, String directoryName)
throws CannotCompileException {
try {
writeFile0(cf, directoryName);
}
catch (IOException e) {
throw new CannotCompileException(e);
}
}
private static void writeFile0(ClassFile cf, String directoryName)
throws CannotCompileException, IOException {
String classname = cf.getName();
String filename = directoryName + File.separatorChar
+ classname.replace('.', File.separatorChar) + ".class";
int pos = filename.lastIndexOf(File.separatorChar);
if (pos > 0) {
String dir = filename.substring(0, pos);
if (!dir.equals("."))
new File(dir).mkdirs();
}
DataOutputStream out = new DataOutputStream(new BufferedOutputStream(
new FileOutputStream(filename)));
try {
cf.write(out);
}
catch (IOException e) {
throw e;
}
finally {
out.close();
}
}
}