001: // Copyright 2006, 2007 The Apache Software Foundation
002: //
003: // Licensed under the Apache License, Version 2.0 (the "License");
004: // you may not use this file except in compliance with the License.
005: // You may obtain a copy of the License at
006: //
007: // http://www.apache.org/licenses/LICENSE-2.0
008: //
009: // Unless required by applicable law or agreed to in writing, software
010: // distributed under the License is distributed on an "AS IS" BASIS,
011: // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012: // See the License for the specific language governing permissions and
013: // limitations under the License.
014:
015: package org.apache.tapestry.ioc.services;
016:
017: import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newMap;
018:
019: import java.lang.reflect.Method;
020: import java.util.Map;
021:
022: /**
023: * Handy method useful when creating new classes using
024: * {@link org.apache.tapestry.ioc.services.ClassFab}.
025: */
026: public class ClassFabUtils {
027: private static long _uid = System.currentTimeMillis();
028:
029: private ClassFabUtils() {
030: }
031:
032: /**
033: * Generates a unique class name, which will be in the default package.
034: */
035:
036: public static synchronized String generateClassName(String baseName) {
037: return "$" + baseName + "_" + Long.toHexString(_uid++);
038: }
039:
040: /**
041: * Returns a class name derived from the provided interfaceClass. The package part of the
042: * interface name is stripped out, and the result passed to {@link #generateClassName(String)}.
043: */
044:
045: public static String generateClassName(Class interfaceClass) {
046: String name = interfaceClass.getName();
047:
048: int dotx = name.lastIndexOf('.');
049:
050: return generateClassName(name.substring(dotx + 1));
051: }
052:
053: /**
054: * Javassist needs the class name to be as it appears in source code, even for arrays. Invoking
055: * getName() on a Class instance representing an array returns the internal format (i.e, "[...;"
056: * or something). This returns it as it would appear in Java code.
057: */
058: public static String toJavaClassName(Class inputClass) {
059: if (inputClass.isArray())
060: return toJavaClassName(inputClass.getComponentType())
061: + "[]";
062:
063: return inputClass.getName();
064: }
065:
066: /**
067: * Returns true if the method is the standard toString() method. Very few interfaces will ever
068: * include this method as part of the interface, but we have to be sure.
069: */
070: public static boolean isToString(Method method) {
071: if (!method.getName().equals("toString"))
072: return false;
073:
074: if (method.getParameterTypes().length > 0)
075: return false;
076:
077: return method.getReturnType().equals(String.class);
078: }
079:
080: private static class PrimitiveInfo {
081: private final String _typeCode;
082:
083: private final Class _wrapperType;
084:
085: private final String _unwrapMethod;
086:
087: public PrimitiveInfo(String typeCode, Class wrapperType,
088: String unwrapMethod) {
089: _typeCode = typeCode;
090: _wrapperType = wrapperType;
091: _unwrapMethod = unwrapMethod;
092: }
093:
094: public String getTypeCode() {
095: return _typeCode;
096: }
097:
098: public String getUnwrapMethod() {
099: return _unwrapMethod;
100: }
101:
102: public Class getWrapperType() {
103: return _wrapperType;
104: }
105: }
106:
107: private static final Map<String, PrimitiveInfo> PRIMITIVE_INFO = newMap();
108:
109: static {
110: add("boolean", "Z", Boolean.class, "booleanValue");
111: add("short", "S", Short.class, "shortValue");
112: add("int", "I", Integer.class, "intValue");
113: add("long", "J", Long.class, "longValue");
114: add("float", "F", Float.class, "floatValue");
115: add("double", "D", Double.class, "doubleValue");
116: add("char", "C", Character.class, "charValue");
117: add("byte", "B", Byte.class, "byteValue");
118: }
119:
120: private static void add(String primitiveType, String typeCode,
121: Class wrapperType, String unwrapMethod) {
122: PRIMITIVE_INFO.put(primitiveType, new PrimitiveInfo(typeCode,
123: wrapperType, unwrapMethod));
124: }
125:
126: /**
127: * Translates types from standard Java format to Java VM format. For example, java.util.Locale
128: * remains java.util.Locale, but int[][] is translated to [[I and java.lang.Object[] to
129: * [Ljava.lang.Object;
130: */
131: public static String toJVMBinaryName(String type) {
132: // if it is not an array, just return the type itself
133: if (!type.endsWith("[]"))
134: return type;
135:
136: // if it is an array, convert it to JavaVM-style format
137: StringBuilder buffer = new StringBuilder();
138:
139: while (type.endsWith("[]")) {
140: buffer.append("[");
141: type = type.substring(0, type.length() - 2);
142: }
143:
144: PrimitiveInfo pi = PRIMITIVE_INFO.get(type);
145:
146: if (pi != null)
147: buffer.append(pi.getTypeCode());
148: else {
149: buffer.append("L");
150: buffer.append(type);
151: buffer.append(";");
152: }
153:
154: return buffer.toString();
155: }
156:
157: /**
158: * Given one of the primitive types, returns the name of the method that will unwrap the wrapped
159: * type to the primitive type.
160: */
161: public static String getUnwrapMethodName(String primitiveTypeName) {
162: return PRIMITIVE_INFO.get(primitiveTypeName).getUnwrapMethod();
163: }
164:
165: /** Given the name of a primitive type, returns the name of the corresponding wrapper class. */
166:
167: public static String getWrapperTypeName(String primitiveType) {
168: return PRIMITIVE_INFO.get(primitiveType).getWrapperType()
169: .getName();
170: }
171:
172: /**
173: * Given some type (possibly a primitive) returns the corresponding primitive type. For
174: * non-primitives, the provided type is returned.
175: */
176: public static Class getWrapperType(Class primitiveType) {
177: if (primitiveType.isPrimitive())
178: return PRIMITIVE_INFO.get(primitiveType.getName())
179: .getWrapperType();
180:
181: return primitiveType; // Not a primitive!
182: }
183:
184: public static String getTypeCode(Class type) {
185: if (type.equals(void.class))
186: return "V";
187:
188: if (type.isPrimitive())
189: return PRIMITIVE_INFO.get(type.getName()).getTypeCode();
190:
191: if (type.isArray())
192: return "[" + getTypeCode(type.getComponentType());
193:
194: return "L" + type.getName().replace('.', '/') + ";";
195: }
196: }
|