001: /**
002: * Copyright (C) 2001-2005 France Telecom R&D
003: *
004: * This library is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU Lesser General Public
006: * License as published by the Free Software Foundation; either
007: * version 2 of the License, or (at your option) any later version.
008: *
009: * This library is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012: * Lesser General Public License for more details.
013: *
014: * You should have received a copy of the GNU Lesser General Public
015: * License along with this library; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
017: */package org.objectweb.speedo.generation.enhancer.common;
018:
019: import org.objectweb.asm.CodeVisitor;
020: import org.objectweb.asm.Constants;
021: import org.objectweb.asm.Type;
022: import org.objectweb.speedo.generation.lib.NamingRules;
023: import org.objectweb.speedo.metadata.SpeedoClass;
024: import org.objectweb.speedo.metadata.SpeedoPackage;
025: import org.objectweb.speedo.metadata.SpeedoXMLDescriptor;
026:
027: import java.util.Collection;
028: import java.util.HashSet;
029: import java.util.Iterator;
030: import java.util.Set;
031:
032: /**
033: * Utility class.
034: *
035: * Adapted from isPersistentType and isPersitentCapable in EnhancerTool.
036: */
037: public class Util {
038:
039: private static Set PERSISTENT_CLASSES;
040: private static Set AUTO_PERSISTENT_CLASSES;
041:
042: static {
043: PERSISTENT_CLASSES = new HashSet();
044: AUTO_PERSISTENT_CLASSES = new HashSet();
045:
046: AUTO_PERSISTENT_CLASSES.add("java.lang.String");
047: AUTO_PERSISTENT_CLASSES.add("java.lang.Character");
048: AUTO_PERSISTENT_CLASSES.add("java.lang.Boolean");
049: AUTO_PERSISTENT_CLASSES.add("java.lang.Number");
050: AUTO_PERSISTENT_CLASSES.add("java.lang.Byte");
051: AUTO_PERSISTENT_CLASSES.add("java.lang.Integer");
052: AUTO_PERSISTENT_CLASSES.add("java.lang.Long");
053: AUTO_PERSISTENT_CLASSES.add("java.lang.Double");
054: AUTO_PERSISTENT_CLASSES.add("java.lang.Float");
055: AUTO_PERSISTENT_CLASSES.add("java.lang.Short");
056:
057: AUTO_PERSISTENT_CLASSES.add("java.math.BigInteger");
058: AUTO_PERSISTENT_CLASSES.add("java.math.BigDecimal");
059:
060: PERSISTENT_CLASSES.add("java.util.Collection");
061: PERSISTENT_CLASSES.add("java.util.Map");
062: PERSISTENT_CLASSES.add("java.util.Set");
063: PERSISTENT_CLASSES.add("java.util.List");
064: PERSISTENT_CLASSES.add("java.util.LinkedList");
065: PERSISTENT_CLASSES.add("java.util.ArrayList");
066: PERSISTENT_CLASSES.add("java.util.HashMap");
067: PERSISTENT_CLASSES.add("java.util.TreeMap");
068: PERSISTENT_CLASSES.add("java.util.WeakHashMap");
069: PERSISTENT_CLASSES.add("java.util.Properties");
070:
071: PERSISTENT_CLASSES.add("java.util.Vector");
072: PERSISTENT_CLASSES.add("java.util.HashTable");
073: PERSISTENT_CLASSES.add("java.util.Stack");
074:
075: PERSISTENT_CLASSES.add("java.util.Date");
076: PERSISTENT_CLASSES.add("java.util.Locale");
077:
078: AUTO_PERSISTENT_CLASSES.add("java.sql.Date");
079: AUTO_PERSISTENT_CLASSES.add("java.sql.Time");
080: AUTO_PERSISTENT_CLASSES.add("java.sql.Timestamp");
081:
082: PERSISTENT_CLASSES.addAll(AUTO_PERSISTENT_CLASSES);
083: }
084:
085: /**
086: * Tests whether a specific Type can be defined persistent.
087: *
088: * @see #isPersistentCapable
089: * @param desc the descriptor of the type that is tested
090: * @param xml a collection of SpeedoXMLDescriptor
091: * @return true is the type can be defaulted as persistent, false either
092: */
093: public static boolean isPersistentType(final String desc,
094: final Collection xml) {
095: Type type = Type.getType(desc);
096: if (type.getSort() == Type.ARRAY) {
097: // an array can be defaulted as persistent if its elements can
098: return isPersistentType(type.getElementType()
099: .getDescriptor(), xml);
100: } else if (type.getSort() == Type.OBJECT) {
101: // for the class types it depends on the package and the class
102: String className = type.getClassName();
103: return PERSISTENT_CLASSES.contains(className)
104: || isPersistentCapable(className, xml) != null;
105: } else {
106: // a basic type can always be defaulted as persistent
107: return true;
108: }
109: }
110:
111: public static boolean isAutomaticPersistentType(final String desc,
112: final Collection xml) {
113: Type type = Type.getType(desc);
114: if (type.getSort() == Type.ARRAY) {
115: return false;
116: } else if (type.getSort() == Type.OBJECT) {
117: // for the class types it depends on the package and the class
118: String className = type.getClassName();
119: return AUTO_PERSISTENT_CLASSES.contains(className)
120: || isPersistentCapable(className, xml) != null;
121: } else {
122: // a basic type can always be defaulted as persistent
123: return true;
124: }
125: }
126:
127: /**
128: * Tests whether a class exists in the object model.
129: *
130: * @param className the complete name of the class
131: * @param xml a collection of SpeedoXMLDescriptor
132: * @return null if the class is not known as a persistent capable class
133: */
134: public static SpeedoClass isPersistentCapable(
135: final String className, final Collection xml) {
136: Iterator i = xml.iterator();
137: while (i.hasNext()) {
138: SpeedoXMLDescriptor xmlDesc = (SpeedoXMLDescriptor) i
139: .next();
140: String fieldPackage = NamingRules.packageName(className);
141: String fieldClass = NamingRules.className(className);
142: SpeedoPackage pkg = (SpeedoPackage) xmlDesc.packages
143: .get(fieldPackage);
144: if (pkg != null) {
145: SpeedoClass c = (SpeedoClass) pkg.classes
146: .get(fieldClass);
147: if (c != null) {
148: return c;
149: }
150: }
151: }
152: return null;
153: }
154:
155: // ASM TOOLS //
156: //-----------//
157:
158: public static void visitIntConstant(CodeVisitor cv, int value) {
159: if (value == 0) {
160: cv.visitInsn(Constants.ICONST_0);
161: } else if (value == 1) {
162: cv.visitInsn(Constants.ICONST_1);
163: } else if (value == 2) {
164: cv.visitInsn(Constants.ICONST_2);
165: } else if (value == 3) {
166: cv.visitInsn(Constants.ICONST_3);
167: } else if (value == 4) {
168: cv.visitInsn(Constants.ICONST_4);
169: } else if (value == 5) {
170: cv.visitInsn(Constants.ICONST_5);
171: } else if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE) {
172: cv.visitIntInsn(Constants.BIPUSH, value);
173: } else if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE) {
174: cv.visitIntInsn(Constants.SIPUSH, value);
175: } else {
176: cv.visitLdcInsn(new Integer(value));
177: }
178: }
179:
180: public static void visitLongConstant(CodeVisitor cv, long value) {
181: if (value == 0) {
182: cv.visitInsn(Constants.LCONST_0);
183: } else if (value == 1) {
184: cv.visitInsn(Constants.LCONST_1);
185: } else {
186: cv.visitLdcInsn(new Long(value));
187: }
188: }
189:
190: // CONVERSIONS FROM ASM TO JAVA SOURCE CODE //
191: //------------------------------------------//
192:
193: public static String modifier(int access) {
194: StringBuffer buf = new StringBuffer();
195: if ((access & Constants.ACC_PUBLIC) != 0) {
196: buf.append("public ");
197: }
198: if ((access & Constants.ACC_PRIVATE) != 0) {
199: buf.append("private ");
200: }
201: if ((access & Constants.ACC_PROTECTED) != 0) {
202: buf.append("protected ");
203: }
204: if ((access & Constants.ACC_FINAL) != 0) {
205: buf.append("final ");
206: }
207: if ((access & Constants.ACC_STATIC) != 0) {
208: buf.append("static ");
209: }
210: if ((access & Constants.ACC_SYNCHRONIZED) != 0) {
211: buf.append("synchronized ");
212: }
213: if ((access & Constants.ACC_VOLATILE) != 0) {
214: buf.append("volatile ");
215: }
216: if ((access & Constants.ACC_TRANSIENT) != 0) {
217: buf.append("transient ");
218: }
219: if ((access & Constants.ACC_NATIVE) != 0) {
220: buf.append("native ");
221: }
222: if ((access & Constants.ACC_ABSTRACT) != 0) {
223: buf.append("abstract ");
224: }
225: if ((access & Constants.ACC_STRICT) != 0) {
226: buf.append("strictfp ");
227: }
228: return buf.toString();
229: }
230:
231: public static String type(Type type) {
232: switch (type.getSort()) {
233: case Type.BOOLEAN:
234: return "boolean";
235: case Type.CHAR:
236: return "char";
237: case Type.BYTE:
238: return "byte";
239: case Type.SHORT:
240: return "short";
241: case Type.INT:
242: return "int";
243: case Type.FLOAT:
244: return "float";
245: case Type.LONG:
246: return "long";
247: case Type.DOUBLE:
248: return "double";
249: case Type.ARRAY:
250: String result = type(type.getElementType());
251: for (int i = 0; i < type.getDimensions(); ++i) {
252: result += "[]";
253: }
254: return result;
255: default:
256: result = type.getClassName();
257: if (result.startsWith("java.lang.")) {
258: return result.substring("java.lang.".length());
259: }
260: return result;
261: }
262: }
263:
264: public static Class getClass(Type type, ClassLoader cl)
265: throws Exception {
266: switch (type.getSort()) {
267: case Type.BOOLEAN:
268: return Boolean.TYPE;
269: case Type.CHAR:
270: return Character.TYPE;
271: case Type.BYTE:
272: return Byte.TYPE;
273: case Type.SHORT:
274: return Short.TYPE;
275: case Type.INT:
276: return Integer.TYPE;
277: case Type.FLOAT:
278: return Float.TYPE;
279: case Type.LONG:
280: return Long.TYPE;
281: case Type.DOUBLE:
282: return Double.TYPE;
283: default:
284: return Class.forName(type.getClassName(), false, cl);
285: }
286: }
287:
288: public static String getClassName(Type type) {
289: switch (type.getSort()) {
290: case Type.BOOLEAN:
291: return "Boolean.TYPE";
292: case Type.CHAR:
293: return "Character.TYPE";
294: case Type.BYTE:
295: return "Byte.TYPE";
296: case Type.SHORT:
297: return "Short.TYPE";
298: case Type.INT:
299: return "Integer.TYPE";
300: case Type.FLOAT:
301: return "Float.TYPE";
302: case Type.LONG:
303: return "Long.TYPE";
304: case Type.DOUBLE:
305: return "Double.TYPE";
306: case Type.ARRAY:
307: StringBuffer result = new StringBuffer(type(type
308: .getElementType()));
309: for (int i = 0; i < type.getDimensions(); ++i) {
310: result.append("[]");
311: }
312: return result.append(".class").toString();
313: default:
314: return type.getClassName() + ".class";
315: }
316: }
317: }
|