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