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.repository;
018:
019: import java.lang.reflect.ParameterizedType;
020:
021: import org.apache.harmony.lang.reflect.parser.*;
022: import org.apache.harmony.lang.reflect.support.AuxiliaryFinder;
023:
024: /**
025: * @author Serguei S. Zapreyev
026: * @version $Revision: 1.1.2.1 $
027: */
028:
029: /**
030: * (This all should be considered as an experimental approach which could be changed on
031: * java.lang.ref using)
032: *
033: * ParameterizedTypeRepository provides the keeping iformation about a parameterized types.
034: *
035: * For now the following approach for keeping is realized.
036: * A concreet PT instance is included into repository if somebody do the *first* request for
037: * the reflect's method like Class.getGenericSuperclass()->Class.ReflectionData.initGenericSuperclass()
038: * (Field.getGenericType()->Field.FieldData.initGenericType()
039: * Method.getGenericReturnType()->Class.MethodData.initGenericReturnType()
040: * ...
041: * Constructor.getGenericParameterTypes()->Class.ConstructorData.initGenericParameterTypes()
042: * ...
043: * ). If the identical PT is accessed anyhow then the pointer from repository is used. However,
044: * further it can be removed from the repository if the cache is full under the new instance including.
045: * Then if reflect's request for such PT using the earlier used interface methods then the pointers
046: * to such instance kept within the Method/Constructor/Field/Class instances are returned just if it is
047: * absent within repository. But if we use other Method/Constructor/Field/Class instances to access
048: * to some instance of the same PT type which has been removed from repository then the new
049: * exemplar of instance is included into repository and the pointer to it is replicated if it needs
050: * into the new Method/Constructor/Field/Class instances.
051: *
052: * Maybe, it would be more convinient to realize another repository implementation
053: * where the accumulative approach will be used.
054: * It might be realized using just java.lang.ref.
055: *
056: * Note1. The inserted on 01.26.06 cache3 may significantly slow the algorithm but
057: * it needs to provide the functional completeness of repository because we should distinguish
058: * the entries with equals signatures if there are TVARs which are only homonym ones, i.e.
059: * they are parameters of different generic declarations.
060: */
061: public final class ParameterizedTypeRepository {
062:
063: static final class ParameterizedTypeCache {
064:
065: /**
066: * This class realizes the ParameterizedType repository which
067: * is just a cache. When the cache is exceeded at that time this experimental original cache algorithm (which, if
068: * it will justify hopes, should be combined in one for all type repositories here) rewrites the worst entity
069: * which can't be copied any more only recreated (as equal, of course). If the cache has an entity which
070: * the reflect supporting algorithm supposes to include there than the cache's algorithm copies the existing entity.
071: * If the cache is not full and an entity does not exist than there the cache's algorithm
072: * creates preliminary an entity and inserts it there.
073: * So, an earlier created type variable exists while the cache's algorithm has pointer[s] of it
074: * within the cache (entity has not removed yet during cleanings)
075: * or user's java code keeps pointer[s] of this type variable.
076: */
077:
078: private static class TVSSynchro {
079: };
080:
081: private static int cacheLenght = 2048;
082: private static String cache[] = new String[cacheLenght];
083: private static ParameterizedType cache2[] = new ParameterizedType[cacheLenght];
084: private static InterimParameterizedType cache3[] = new InterimParameterizedType[cacheLenght];
085: private static Object cache4[] = new Object[cacheLenght];
086: private static int counter = 0;
087: private static int worth[] = new int[cacheLenght];
088:
089: /**
090: * To delete the worst entry.
091: */
092: static int deleteParameterizedType() {
093: int min = -1;
094: int min2 = -1;
095:
096: synchronized (TVSSynchro.class) {
097: float minWorth = ((worth[0] >> 16) > 0 ? (worth[0] & 0xFFFF)
098: / worth[0] >> 16
099: : worth[0]);
100: int minWorth2 = worth[0];
101: float tmp;
102: int i = 0;
103: for (; i < cacheLenght; i++) {
104: try {
105: if ((tmp = (worth[i] & 0xFFFF) / worth[i] >> 16) <= minWorth) {
106: min = i;
107: minWorth = tmp;
108: }
109: } catch (ArithmeticException _) {
110: if ((tmp = worth[i]) <= minWorth2) {
111: min2 = i;
112: minWorth2 = (int) tmp;
113: }
114: }
115: }
116: if (i == cacheLenght && min == -1) {
117: min = min2;
118: }
119: cache[min] = null;
120: cache2[min] = null;
121: cache3[min] = null;
122: cache4[min] = null;
123: worth[min] = 0;
124: }
125: return min;
126: }
127:
128: /**
129: * To create new cache entry
130: */
131: static int insertParameterizedType(
132: ParameterizedType parameterizedType,
133: InterimParameterizedType prsrdParameterizedType,
134: String signature, Object startPoint, int ip) {
135: synchronized (TVSSynchro.class) {
136: if (ip < 0) {
137: for (int ind = 0; ind < cacheLenght; ind++) {
138: if (null == cache[ind]) {
139: cache[ind] = signature;
140: cache2[ind] = parameterizedType;
141: cache3[ind] = prsrdParameterizedType;
142: cache4[ind] = startPoint;
143: worth[ind] = 1;
144: return ind;
145: }
146: }
147: return insertParameterizedType(parameterizedType,
148: prsrdParameterizedType, signature,
149: startPoint, deleteParameterizedType());
150: } else {
151: cache[ip] = signature;
152: cache2[ip] = parameterizedType;
153: cache3[ip] = prsrdParameterizedType;
154: cache4[ip] = startPoint;
155:
156: boolean flg = false;
157: short sv = (short) (worth[ip] & 0xFFFF);
158: if (sv == Short.MAX_VALUE - 1) {
159: flg = true; // to reduce
160: }
161: worth[ip] = (sv + 1) | (worth[ip] & 0xFFFF0000);
162: if (flg) {
163: try {
164: for (int ind = 0; ind < cacheLenght; ind++) { // reducing
165: short sv1 = (short) (worth[ind] >> 16);
166: short sv2 = (short) (worth[ind] & 0xFFFF);
167: worth[ind] = (sv2 == 1 ? 1 : sv2 >> 2)
168: | (((sv1 == 1 ? 1 : sv1 >> 2) + 1) << 16);
169: }
170: } catch (NullPointerException _) {
171: }
172: }
173: }
174: }
175: return ip;
176: }
177:
178: /**
179: * To return ParameterizedType of cache.
180: */
181: static ParameterizedType valueParameterizedType(
182: InterimParameterizedType parameterizedType,
183: String signature, Object startPoint) {
184: synchronized (TVSSynchro.class) {
185: boolean flg = false;
186: if (counter == cacheLenght) { // Do smoke, it's time for reordering
187: try {
188: for (int ind = 0; ind < cacheLenght; ind++) {
189: short sv1 = (short) (worth[ind] >> 16);
190: if (sv1 == Short.MAX_VALUE - 1) {
191: flg = true; // to reduce
192: }
193: worth[ind] = worth[ind] & 0xFFFF
194: | ((sv1 + 1) << 16);
195: }
196: } catch (NullPointerException _) {
197: }
198: if (flg) {
199: try {
200: for (int ind = 0; ind < cacheLenght; ind++) { // reducing
201: short sv1 = (short) (worth[ind] >> 16);
202: short sv2 = (short) (worth[ind] & 0xFFFF);
203: worth[ind] = (sv2 == 1 ? 1 : sv2 >> 2)
204: | (((sv1 == 1 ? 1 : sv1 >> 2) + 1) << 16);
205: }
206: } catch (NullPointerException _) {
207: }
208: }
209: counter = 0;
210: } else {
211: counter++;
212: }
213: try {
214: for (int ind = 0; ind < cacheLenght; ind++) {
215: if (signature.equals(cache[ind])
216: && arePTEqual(cache3[ind], cache4[ind],
217: parameterizedType, startPoint)) {
218: return cache2[ind];
219: }
220: }
221: } catch (NullPointerException _) {
222: }
223: }
224: return null;
225: }
226: }
227:
228: /**
229: * This method provides the comparing of two InterimParameterizedType entities.
230: *
231: * @param parameterizedType1 a InterimParameterizedType entity.
232: * @param startPoint1 a generic declaration which the seeking of any type variable definition used within parameterizedType1 should be started from.
233: * @param parameterizedType2 another InterimParameterizedType entity.
234: * @param startPoint2 a generic declaration which the seeking of any type variable definition used within parameterizedType2 should be started from.
235: */
236: static boolean arePTEqual(
237: InterimParameterizedType parameterizedType1,
238: Object startPoint1,
239: InterimParameterizedType parameterizedType2,
240: Object startPoint2) {
241: // Remember that the signatures for being compared InterimParameterizedType-s are equal!
242:
243: // So, we need to compare only the rests:
244: InterimType params1[] = parameterizedType1.parameters;
245: InterimType params2[] = parameterizedType2.parameters;
246: for (int i = 0; i < params1.length; i++) {
247: if (params1[i] instanceof InterimTypeVariable
248: && !areTVEqual((InterimTypeVariable) params1[i],
249: startPoint1,
250: (InterimTypeVariable) params2[i],
251: startPoint2)) {
252: return false;
253: }
254: if (params1[i] instanceof InterimParameterizedType
255: && !arePTEqual(
256: (InterimParameterizedType) params1[i],
257: startPoint1,
258: (InterimParameterizedType) params2[i],
259: startPoint2)) {
260: return false;
261: }
262: if (params1[i] instanceof InterimWildcardType
263: && !WildcardTypeRepository.areWCEqual(
264: (InterimWildcardType) params1[i],
265: startPoint1,
266: (InterimWildcardType) params2[i],
267: startPoint2)) {
268: return false;
269: }
270: }
271: if (parameterizedType1.ownerType != null
272: && parameterizedType1.ownerType instanceof InterimParameterizedType) {
273: return arePTEqual(
274: (InterimParameterizedType) parameterizedType1.ownerType,
275: startPoint1,
276: (InterimParameterizedType) parameterizedType2.ownerType,
277: startPoint2);
278: }
279: return true;
280: }
281:
282: /**
283: * This method provides the comparing of two InterimTypeVariable entities.
284: *
285: * @param typeVariable1 a InterimTypeVariable entity.
286: * @param startPoint1 a generic declaration which the seeking of typeVariable1 type variable definition should be started from.
287: * @param typeVariable2 another InterimTypeVariable entity.
288: * @param startPoint2 a generic declaration which the seeking of typeVariable2 type variable definition should be started from.
289: */
290: static boolean areTVEqual(InterimTypeVariable typeVariable1,
291: Object startPoint1, InterimTypeVariable typeVariable2,
292: Object startPoint2) {
293: if (AuxiliaryFinder.findTypeVariable(
294: typeVariable1.typeVariableName, startPoint1) == AuxiliaryFinder
295: .findTypeVariable(typeVariable2.typeVariableName,
296: startPoint2)) {
297: return true;
298: }
299: return false;
300: }
301:
302: /**
303: * This method returns a registered type variable if it exists within the repository.
304: *
305: * @param ParameterizedTypeName a parameterized type.
306: * @param startPoint an instance of the Class, Method, Constructor or Field type to start the search
307: * of a type variable declaration place.
308: * @return the found type variable or null if it does not exist within repository.
309: */
310: public static ParameterizedType findParameterizedType(
311: InterimParameterizedType parameterizedType,
312: Object startPoint) {
313: return ParameterizedTypeCache.valueParameterizedType(
314: parameterizedType, parameterizedType.signature,
315: startPoint);
316: }
317:
318: /**
319: * This method returns a registered type variable if it exists within the repository.
320: *
321: * @param ParameterizedTypeName a parameterized type.
322: * @param signature a signature of a parameterized type.
323: * @param startPoint an instance of the Class, Method, Constructor or Field type to start the search
324: * of a type variable declaration place.
325: * @return the found type variable or null if it does not exist within repository.
326: */
327: public static ParameterizedType findParameterizedType(
328: InterimParameterizedType parameterizedType,
329: String signature, Object startPoint) {
330: return ParameterizedTypeCache.valueParameterizedType(
331: parameterizedType, signature, startPoint);
332: }
333:
334: /**
335: * This method registers a parameterized type within the repository.
336: *
337: * @param ParameterizedType a type variable.
338: * @param ParameterizedTypeName a name of a type variable.
339: * @param startPoint an instance of the Class, Method, Constructor or Field type to start the search
340: * of a type variable declaration place.
341: */
342: public static void registerParameterizedType(
343: ParameterizedType parameterizedType,
344: InterimParameterizedType prsrdParameterizedType,
345: String signature, Object startPoint) {
346: ParameterizedTypeCache.insertParameterizedType(
347: parameterizedType, prsrdParameterizedType, signature,
348: startPoint, -1);
349: }
350: }
|