001
014
015 package com.liferay.portal.bean;
016
017 import com.liferay.portal.kernel.bean.ConstantsBeanFactory;
018 import com.liferay.portal.kernel.concurrent.ConcurrentReferenceKeyHashMap;
019 import com.liferay.portal.kernel.concurrent.ConcurrentReferenceValueHashMap;
020 import com.liferay.portal.kernel.memory.FinalizeManager;
021 import com.liferay.portal.kernel.util.ReflectionUtil;
022
023 import java.lang.ref.Reference;
024 import java.lang.reflect.Field;
025 import java.lang.reflect.Method;
026 import java.lang.reflect.Modifier;
027
028 import java.util.concurrent.ConcurrentMap;
029
030 import org.objectweb.asm.ClassWriter;
031 import org.objectweb.asm.MethodVisitor;
032 import org.objectweb.asm.Opcodes;
033 import org.objectweb.asm.Type;
034
035
038 public class ConstantsBeanFactoryImpl implements ConstantsBeanFactory {
039
040 @Override
041 public Object getConstantsBean(Class<?> constantsClass) {
042 Object constantsBean = constantsBeans.get(constantsClass);
043
044 if (constantsBean == null) {
045 constantsBean = createConstantsBean(constantsClass);
046
047 constantsBeans.put(constantsClass, constantsBean);
048 }
049
050 return constantsBean;
051 }
052
053 protected static Object createConstantsBean(Class<?> constantsClass) {
054 ClassLoader classLoader = constantsClass.getClassLoader();
055
056 String constantsBeanClassName = constantsClass.getName() + "Bean";
057
058 Class<?> constantsBeanClass = null;
059
060 synchronized (classLoader) {
061 try {
062 constantsBeanClass = classLoader.loadClass(
063 constantsBeanClassName);
064 }
065 catch (ClassNotFoundException cnfe) {
066 }
067
068 try {
069 if (constantsBeanClass == null) {
070 Method defineClassMethod = ReflectionUtil.getDeclaredMethod(
071 ClassLoader.class, "defineClass", String.class,
072 byte[].class, int.class, int.class);
073
074 byte[] classData = generateConstantsBeanClassData(
075 constantsClass);
076
077 constantsBeanClass = (Class<?>)defineClassMethod.invoke(
078 classLoader, constantsBeanClassName, classData, 0,
079 classData.length);
080 }
081
082 return constantsBeanClass.newInstance();
083 }
084 catch (Throwable t) {
085 throw new RuntimeException(t);
086 }
087 }
088 }
089
090 protected static byte[] generateConstantsBeanClassData(
091 Class<?> constantsClass) {
092
093 String constantsClassBinaryName = getClassBinaryName(constantsClass);
094
095 String constantsBeanClassBinaryName = constantsClassBinaryName + "Bean";
096
097 String objectClassBinaryName = getClassBinaryName(Object.class);
098
099 ClassWriter classWriter = new ClassWriter(0);
100
101 classWriter.visit(
102 Opcodes.V1_6, Opcodes.ACC_PUBLIC | Opcodes.ACC_SUPER,
103 constantsBeanClassBinaryName, null, objectClassBinaryName, null);
104
105 MethodVisitor methodVisitor = classWriter.visitMethod(
106 Opcodes.ACC_PUBLIC, "<init>", "()V", null, null);
107
108 methodVisitor.visitCode();
109 methodVisitor.visitVarInsn(Opcodes.ALOAD, 0);
110 methodVisitor.visitMethodInsn(
111 Opcodes.INVOKESPECIAL, objectClassBinaryName, "<init>", "()V",
112 false);
113 methodVisitor.visitInsn(Opcodes.RETURN);
114 methodVisitor.visitMaxs(1, 1);
115 methodVisitor.visitEnd();
116
117 Field[] fields = constantsClass.getFields();
118
119 for (Field field :fields) {
120 if (Modifier.isStatic(field.getModifiers())) {
121 Type fieldType = Type.getType(field.getType());
122
123 methodVisitor = classWriter.visitMethod(
124 Opcodes.ACC_PUBLIC, "get" + field.getName(),
125 "()" + fieldType.getDescriptor(), null, null);
126
127 methodVisitor.visitCode();
128 methodVisitor.visitFieldInsn(
129 Opcodes.GETSTATIC, constantsClassBinaryName,
130 field.getName(), fieldType.getDescriptor());
131
132 methodVisitor.visitInsn(fieldType.getOpcode(Opcodes.IRETURN));
133
134 methodVisitor.visitMaxs(fieldType.getSize(), 1);
135 methodVisitor.visitEnd();
136 }
137 }
138
139 classWriter.visitEnd();
140
141 return classWriter.toByteArray();
142 }
143
144 protected static String getClassBinaryName(Class<?> clazz) {
145 String className = clazz.getName();
146
147 return className.replace('.', '/');
148 }
149
150 protected static ConcurrentMap<Class<?>, Object> constantsBeans =
151 new ConcurrentReferenceKeyHashMap<Class<?>, Object>(
152 new ConcurrentReferenceValueHashMap<Reference<Class<?>>, Object>(
153 FinalizeManager.WEAK_REFERENCE_FACTORY),
154 FinalizeManager.WEAK_REFERENCE_FACTORY);
155
156 }