001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: *
023: * Free Software Foundation, Inc.
024: * 59 Temple Place, Suite 330
025: * Boston, MA 02111-1307 USA
026: *
027: * @author Scott Ferguson
028: */
029:
030: package com.caucho.ejb.cfg;
031:
032: import java.util.*;
033: import java.lang.reflect.*;
034: import java.lang.annotation.*;
035:
036: import com.caucho.ejb.cfg.*;
037: import com.caucho.util.*;
038:
039: /**
040: * Represents an interface class, either Local or Remote
041: */
042: public class ApiClass {
043: private static final L10N L = new L10N(ApiClass.class);
044:
045: public static final ApiClass OBJECT = new ApiClass(Object.class);
046: public static final ApiClass ENTITY_BEAN = new ApiClass(
047: javax.ejb.EntityBean.class);
048:
049: private Class _apiClass;
050: private ArrayList<ApiMethod> _methods = new ArrayList<ApiMethod>();
051:
052: /**
053: * Creates a new api class
054: *
055: * @param topClass the api class
056: */
057: public ApiClass(Class apiClass) {
058: if (apiClass == null)
059: throw new NullPointerException();
060:
061: _apiClass = apiClass;
062:
063: HashMap<String, Type> typeMap = new HashMap<String, Type>();
064: introspectClass(apiClass, typeMap);
065: }
066:
067: /**
068: * Returns the classname.
069: */
070: public String getName() {
071: return _apiClass.getName();
072: }
073:
074: /**
075: * Returns the short classname.
076: */
077: public String getSimpleName() {
078: return _apiClass.getSimpleName();
079: }
080:
081: public Class getJavaClass() {
082: return _apiClass;
083: }
084:
085: /**
086: * Returns true for a public class.
087: */
088: public boolean isPublic() {
089: return Modifier.isPublic(_apiClass.getModifiers());
090: }
091:
092: /**
093: * Returns true for an interface
094: */
095: public boolean isInterface() {
096: return Modifier.isInterface(_apiClass.getModifiers());
097: }
098:
099: /**
100: * Returns true for an abstract class
101: */
102: public boolean isAbstract() {
103: return Modifier.isAbstract(_apiClass.getModifiers());
104: }
105:
106: /**
107: * Returns true for a final class
108: */
109: public boolean isFinal() {
110: return Modifier.isFinal(_apiClass.getModifiers());
111: }
112:
113: /**
114: * Returns true for a primitive class
115: */
116: public boolean isPrimitive() {
117: return _apiClass.isPrimitive();
118: }
119:
120: /**
121: * Returns the fields.
122: */
123: public Field[] getFields() {
124: return _apiClass.getFields();
125: }
126:
127: /**
128: * Returns the interfaces (should be ApiClass?)
129: */
130: public Class[] getInterfaces() {
131: return _apiClass.getInterfaces();
132: }
133:
134: public Constructor getConstructor(Class[] param)
135: throws NoSuchMethodException {
136: return _apiClass.getConstructor(param);
137: }
138:
139: /**
140: * Returns the methods.
141: */
142: public ArrayList<ApiMethod> getMethods() {
143: return _methods;
144: }
145:
146: /**
147: * Returns the matching method.
148: */
149: public ApiMethod getMethod(Method method) {
150: return getMethod(method.getName(), method.getParameterTypes());
151: }
152:
153: /**
154: * Returns the matching method.
155: */
156: public ApiMethod getMethod(ApiMethod method) {
157: return getMethod(method.getName(), method.getParameterTypes());
158: }
159:
160: /**
161: * Returns true if the method exists
162: */
163: public boolean hasMethod(String name, Class[] args) {
164: return getMethod(name, args) != null;
165: }
166:
167: /**
168: * Returns the matching method.
169: */
170: public ApiMethod getMethod(String name, Class[] param) {
171: for (int i = 0; i < _methods.size(); i++) {
172: ApiMethod method = _methods.get(i);
173:
174: if (method.isMatch(name, param))
175: return method;
176: }
177:
178: return null;
179: }
180:
181: /**
182: * Returns true if the annotation exists.
183: */
184: public boolean isAnnotationPresent(Class annType) {
185: return _apiClass.isAnnotationPresent(annType);
186: }
187:
188: /**
189: * Returns true if the annotation exists.
190: */
191: public <A extends Annotation> A getAnnotation(Class<A> annType) {
192: return (A) _apiClass.getAnnotation(annType);
193: }
194:
195: private void introspectClass(Class cl, HashMap<String, Type> typeMap) {
196: if (cl == null)
197: return;
198:
199: for (Method method : cl.getDeclaredMethods()) {
200: ApiMethod apiMethod = new ApiMethod(this , method, typeMap);
201:
202: if (!_methods.contains(apiMethod)) {
203: _methods.add(apiMethod);
204: }
205: }
206:
207: introspectGenericClass(cl.getGenericSuperclass(), typeMap);
208:
209: for (Type subClass : cl.getGenericInterfaces()) {
210: introspectGenericClass(subClass, typeMap);
211: }
212: }
213:
214: private void introspectGenericClass(Type type,
215: HashMap<String, Type> typeMap) {
216: if (type == null)
217: return;
218:
219: if (type instanceof Class) {
220: introspectClass((Class) type, typeMap);
221: } else if (type instanceof ParameterizedType) {
222: ParameterizedType pType = (ParameterizedType) type;
223: Type[] args = pType.getActualTypeArguments();
224:
225: Class rawType = (Class) pType.getRawType();
226: TypeVariable[] params = rawType.getTypeParameters();
227:
228: HashMap<String, Type> subMap = new HashMap<String, Type>(
229: typeMap);
230:
231: for (int i = 0; i < params.length; i++) {
232: TypeVariable param = params[i];
233: Type arg = args[i];
234:
235: if (arg instanceof TypeVariable) {
236: TypeVariable argVar = (TypeVariable) arg;
237:
238: if (typeMap.get(argVar.getName()) != null)
239: arg = typeMap.get(argVar.getName());
240: }
241:
242: subMap.put(param.getName(), arg);
243: }
244:
245: introspectClass(rawType, subMap);
246: }
247: }
248:
249: public String toString() {
250: return "ApiClass[" + _apiClass.getName() + "]";
251: }
252: }
|