001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.harmony.lang.reflect.support;
018:
019: import java.lang.reflect.Type;
020: import java.lang.TypeNotPresentException;
021: import java.lang.reflect.ParameterizedType;
022: import java.lang.reflect.WildcardType;
023: import java.lang.reflect.TypeVariable;
024:
025: import org.apache.harmony.lang.reflect.parser.InterimParameterizedType;
026: import org.apache.harmony.lang.reflect.parser.InterimTypeVariable;
027: import org.apache.harmony.lang.reflect.parser.InterimGenericArrayType;
028: import org.apache.harmony.lang.reflect.support.AuxiliaryChecker;
029: import org.apache.harmony.lang.reflect.support.AuxiliaryFinder;
030: import org.apache.harmony.lang.reflect.repository.*;
031:
032: import org.apache.harmony.lang.reflect.parser.*;
033: import org.apache.harmony.lang.reflect.implementation.*;
034:
035: /**
036: * @author Serguei S. Zapreyev
037: * @version $Revision: 1.1.2.1 $
038: */
039:
040: /**
041: * Finder provides kinds of finding.
042: */
043: public final class AuxiliaryCreator {
044:
045: /**
046: * This method creates generic array type.
047: *
048: * @param ppType a parsered information produced from a generic array type signature.
049: * @param startPoint an instance of the Class, Method, Constructor or Field type to start the search
050: * of a type variable declaration place.
051: * @return a Type object representing a generic array type.
052: */
053: public static Type createGenericArrayType(
054: InterimGenericArrayType ppType, Object startPoint) {
055: InterimType nextLayer = ppType.nextLayer;
056: if (nextLayer instanceof InterimParameterizedType) {
057: ParameterizedType pType = ParameterizedTypeRepository
058: .findParameterizedType(
059: (InterimParameterizedType) nextLayer,
060: startPoint);
061: if (pType == null) {
062: try {
063: AuxiliaryFinder
064: .findGenericClassDeclarationForParameterizedType(
065: (InterimParameterizedType) nextLayer,
066: startPoint);
067: } catch (Throwable e) {
068: throw new TypeNotPresentException(
069: ((InterimParameterizedType) nextLayer).rawType.classTypeName
070: .substring(1).replace('/', '.'), e);
071: }
072: // check the correspondence of the formal parameter number and the actual argument number:
073: AuxiliaryChecker.checkArgsNumber(
074: (InterimParameterizedType) nextLayer,
075: startPoint); //the MalformedParameterizedTypeException may raise here
076: try {
077: pType = new ParameterizedTypeImpl(
078: AuxiliaryCreator
079: .createTypeArgs(
080: (InterimParameterizedType) nextLayer,
081: startPoint),
082: AuxiliaryCreator
083: .createRawType(
084: (InterimParameterizedType) nextLayer,
085: startPoint),
086: AuxiliaryCreator
087: .createOwnerType(
088: (InterimParameterizedType) nextLayer,
089: startPoint));
090: } catch (ClassNotFoundException e) {
091: throw new TypeNotPresentException(e.getMessage(), e);
092: }
093: ParameterizedTypeRepository
094: .registerParameterizedType(
095: pType,
096: (InterimParameterizedType) nextLayer,
097: ((InterimParameterizedType) nextLayer).signature,
098: startPoint);
099: }
100: return new GenericArrayTypeImpl((Type) pType);
101: } else if (nextLayer instanceof InterimTypeVariable) {
102: String tvName = ((InterimTypeVariable) nextLayer).typeVariableName;
103: TypeVariable variable = TypeVariableRepository
104: .findTypeVariable(tvName, startPoint);
105: if (variable == null) {
106: variable = AuxiliaryFinder.findTypeVariable(tvName,
107: startPoint);
108: if (variable == null) {
109: return (Type) null; // compatible behaviour
110: }
111: }
112: return new GenericArrayTypeImpl((Type) variable);
113: } else if (nextLayer instanceof InterimClassType) {
114: Type cType;
115: try {
116: cType = (Type) AuxiliaryLoader
117: .findClass(
118: ((InterimClassType) nextLayer).classTypeName
119: .substring(
120: (((InterimClassType) nextLayer).classTypeName
121: .charAt(0) == 'L' ? 1
122: : 0)).replace(
123: '/', '.'), startPoint);
124: } catch (ClassNotFoundException e) {
125: throw new TypeNotPresentException(
126: ((InterimClassType) nextLayer).classTypeName
127: .substring(
128: (((InterimClassType) nextLayer).classTypeName
129: .charAt(0) == 'L' ? 1
130: : 0)).replace('/', '.'),
131: e);
132: }
133: return new GenericArrayTypeImpl(cType);
134: } else { // GenericArrayType again
135: return new GenericArrayTypeImpl(AuxiliaryCreator
136: .createGenericArrayType(
137: (InterimGenericArrayType) nextLayer,
138: startPoint));
139: }
140: }
141:
142: /**
143: * This method creates the owner's type for a parameterized type.
144: *
145: * @param ppType a parsered information produced from a parameterized type signature.
146: * @param startPoint an instance of the Class, Method, Constructor or Field type to start the search
147: * of a type variable declaration place.
148: * @return a created owner's type.
149: */
150: public static Type createOwnerType(InterimParameterizedType ppType,
151: Object startPoint) throws ClassNotFoundException {
152: // raise to owner level:
153: InterimType nextppType = ppType.ownerType; // XXX:???Can it be of InterimTypeVariable/InterimClassType type
154: if (nextppType == null) {
155: return null;
156: }
157: // create owner type
158: if (nextppType instanceof InterimParameterizedType) {
159: ParameterizedType pType = ParameterizedTypeRepository
160: .findParameterizedType(
161: (InterimParameterizedType) nextppType,
162: startPoint);
163: if (pType == null) {
164: try {
165: AuxiliaryFinder
166: .findGenericClassDeclarationForParameterizedType(
167: (InterimParameterizedType) nextppType,
168: startPoint);
169: } catch (Throwable e) {
170: throw new TypeNotPresentException(
171: ((InterimParameterizedType) nextppType).rawType.classTypeName
172: .substring(1).replace('/', '.'), e);
173: }
174: // check the correspondence of the formal parameter number and the actual argument number:
175: AuxiliaryChecker.checkArgsNumber(
176: (InterimParameterizedType) nextppType,
177: startPoint); // the MalformedParameterizedTypeException may raise here
178: try {
179: pType = new ParameterizedTypeImpl(
180: AuxiliaryCreator
181: .createTypeArgs(
182: (InterimParameterizedType) nextppType,
183: startPoint),
184: AuxiliaryCreator
185: .createRawType(
186: (InterimParameterizedType) nextppType,
187: startPoint),
188: AuxiliaryCreator
189: .createOwnerType(
190: (InterimParameterizedType) nextppType,
191: startPoint));
192: } catch (ClassNotFoundException e) {
193: throw new TypeNotPresentException(e.getMessage(), e);
194: }
195: ParameterizedTypeRepository
196: .registerParameterizedType(
197: pType,
198: (InterimParameterizedType) nextppType,
199: ((InterimParameterizedType) nextppType).signature,
200: startPoint);
201: }
202: return (Type) pType;
203: } else { //ClassType
204: return AuxiliaryLoader
205: .findClass(
206: ((InterimClassType) nextppType).classTypeName
207: .substring(1).replace('/', '.'),
208: startPoint); // XXX: should we propagate the class loader of initial user's request (Field.getGenericType()) or use this one?
209: }
210: }
211:
212: /**
213: * This method creates the raw type for a parameterized type.
214: *
215: * @param ppType a parsered information produced from a parameterized type signature.
216: * @param startPoint an instance of the Class, Method, Constructor or Field type to start the search
217: * of a type variable declaration place.
218: * @return a created raw type.
219: */
220: public static Type createRawType(InterimParameterizedType ppType,
221: Object startPoint) throws ClassNotFoundException {
222: return (Type) AuxiliaryFinder
223: .findGenericClassDeclarationForParameterizedType(
224: ppType, startPoint); // it may be null
225: }
226:
227: /**
228: * This method creates Type object representing the actual type argument.
229: *
230: * @param pType a parsered information of actual parameter.
231: * @param startPoint an instance of the Class, Method, Constructor or Field type to start the search
232: * of a type variable declaration place.
233: * @return a Type object representing the actual type argument.
234: */
235: public static Type createTypeArg(InterimType pType,
236: Object startPoint) throws ClassNotFoundException {
237: Type res;
238: if (pType instanceof InterimParameterizedType) {
239: ParameterizedType cType = ParameterizedTypeRepository
240: .findParameterizedType(
241: (InterimParameterizedType) pType,
242: startPoint);
243: if (cType == null) {
244: try {
245: AuxiliaryFinder
246: .findGenericClassDeclarationForParameterizedType(
247: (InterimParameterizedType) pType,
248: startPoint);
249: } catch (Throwable e) {
250: throw new TypeNotPresentException(
251: ((InterimParameterizedType) pType).rawType.classTypeName
252: .substring(1).replace('/', '.'), e);
253: }
254: // check the correspondence of the formal parameter number and the actual argument number:
255: AuxiliaryChecker.checkArgsNumber(
256: (InterimParameterizedType) pType, startPoint); // the MalformedParameterizedTypeException may raise here
257: cType = new ParameterizedTypeImpl(AuxiliaryCreator
258: .createTypeArgs(
259: (InterimParameterizedType) pType,
260: startPoint), AuxiliaryCreator
261: .createRawType(
262: (InterimParameterizedType) pType,
263: startPoint), AuxiliaryCreator
264: .createOwnerType(
265: (InterimParameterizedType) pType,
266: startPoint));
267: ParameterizedTypeRepository.registerParameterizedType(
268: cType, (InterimParameterizedType) pType,
269: ((InterimParameterizedType) pType).signature,
270: startPoint);
271: }
272: res = (Type) cType;
273: } else if (pType instanceof InterimTypeVariable) {
274: String tvName = ((InterimTypeVariable) pType).typeVariableName;
275: TypeVariable variable = TypeVariableRepository
276: .findTypeVariable(tvName, startPoint);
277: if (variable == null) {
278: variable = AuxiliaryFinder.findTypeVariable(tvName,
279: startPoint);
280: if (variable == null) {
281: return (Type) null;
282: }
283: }
284: res = (Type) variable;
285: } else if (pType instanceof InterimWildcardType) {
286: WildcardType wType = WildcardTypeRepository
287: .findWildcardType(
288: (InterimWildcardType) pType,
289: WildcardTypeRepository
290: .recoverWildcardSignature((InterimWildcardType) pType),
291: startPoint);
292: if (wType == null) {
293: // The MalformedParameterizedTypeException and TypeNotPresentException should not be raised yet.
294: // These ones can be produced only via WildcardType.getUpperBounds() or WildcardType.getLowerBounds.
295: wType = new WildcardTypeImpl(
296: (InterimWildcardType) pType, startPoint);
297: WildcardTypeRepository
298: .registerWildcardType(
299: wType,
300: (InterimWildcardType) pType,
301: WildcardTypeRepository
302: .recoverWildcardSignature((InterimWildcardType) pType),
303: startPoint);
304: }
305: res = (Type) wType;
306: } else if (pType instanceof InterimGenericArrayType) {
307: res = AuxiliaryCreator.createGenericArrayType(
308: (InterimGenericArrayType) pType, startPoint);
309: } else { // ClassType
310: String className = ((InterimClassType) pType).classTypeName
311: .substring(1).replace('/', '.');
312: res = (Type) AuxiliaryLoader.findClass(className,
313: startPoint); // XXX: should we propagate the class loader of initial user's request (Field.getGenericType()) or use this one?
314: }
315: return res;
316: }
317:
318: /**
319: * This method creates an array of Type objects representing the actual type arguments to this type.
320: *
321: * @param ppType a parsered information produced from a parameterized type signature.
322: * @param startPoint an instance of the Class, Method, Constructor or Field type to start the search
323: * of a type variable declaration place.
324: * @return an array of Type objects representing the actual type arguments to this type.
325: */
326: public static Type[] createTypeArgs(
327: InterimParameterizedType ppType, Object startPoint) {
328: InterimType args[] = ppType.parameters;
329: if (args == null) {
330: return new Type[0];
331: }
332: int len = args.length;
333: Type res[] = new Type[len];
334: for (int i = 0; i < len; i++) {
335: try {
336: res[i] = createTypeArg(args[i], startPoint);
337: } catch (ClassNotFoundException e) {
338: throw new TypeNotPresentException(
339: ((InterimClassType) args[i]).classTypeName
340: .substring(1).replace('/', '.'), e); // ClassNotFoundException may appear here only for InterimClassType, see AuxiliaryCreator.createTypeArg.
341: }
342: }
343: return res;
344: }
345: }
|