001: /***
002: * Retrotranslator: a Java bytecode transformer that translates Java classes
003: * compiled with JDK 5.0 into classes that can be run on JVM 1.4.
004: *
005: * Copyright (c) 2005 - 2008 Taras Puchko
006: * All rights reserved.
007: *
008: * Redistribution and use in source and binary forms, with or without
009: * modification, are permitted provided that the following conditions
010: * are met:
011: * 1. Redistributions of source code must retain the above copyright
012: * notice, this list of conditions and the following disclaimer.
013: * 2. Redistributions in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in the
015: * documentation and/or other materials provided with the distribution.
016: * 3. Neither the name of the copyright holders nor the names of its
017: * contributors may be used to endorse or promote products derived from
018: * this software without specific prior written permission.
019: *
020: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
021: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
022: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
023: * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
024: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
025: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
026: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
027: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
028: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
029: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
030: * THE POSSIBILITY OF SUCH DAMAGE.
031: */package net.sf.retrotranslator.runtime.java.lang;
032:
033: import java.io.*;
034: import java.lang.ref.WeakReference;
035: import java.lang.reflect.*;
036: import java.security.*;
037: import java.util.Map;
038: import java.util.concurrent.*;
039: import net.sf.retrotranslator.runtime.impl.WeakIdentityTable;
040:
041: /**
042: * @author Taras Puchko
043: */
044: public abstract class Enum_<E extends Enum_<E>> implements
045: Comparable<E>, Serializable {
046:
047: private static final WeakIdentityTable<Class, ConcurrentMap<String, WeakReference<Enum_>>> table = new WeakIdentityTable<Class, ConcurrentMap<String, WeakReference<Enum_>>>() {
048: protected ConcurrentMap<String, WeakReference<Enum_>> initialValue() {
049: return new ConcurrentHashMap<String, WeakReference<Enum_>>();
050: }
051: };
052:
053: private String name;
054:
055: private int ordinal;
056:
057: protected Enum_(String name, int ordinal) {
058: this .name = name;
059: this .ordinal = ordinal;
060: if (name != null) {
061: table.obtain(getDeclaringClass()).putIfAbsent(name,
062: new WeakReference<Enum_>(this ));
063: }
064: }
065:
066: public final String name() {
067: return name;
068: }
069:
070: public final int ordinal() {
071: return ordinal;
072: }
073:
074: public String toString() {
075: return name;
076: }
077:
078: public final boolean equals(Object other) {
079: return this == other;
080: }
081:
082: public final int hashCode() {
083: return super .hashCode();
084: }
085:
086: protected final Object clone() throws CloneNotSupportedException {
087: throw new CloneNotSupportedException();
088: }
089:
090: public final int compareTo(E other) {
091: if (this .getClass() != other.getClass()
092: && this .getDeclaringClass() != other
093: .getDeclaringClass()) {
094: throw new ClassCastException();
095: }
096: return this .ordinal - other.ordinal;
097: }
098:
099: public final Class<E> getDeclaringClass() {
100: Class clazz = getClass();
101: Class zuper = clazz.getSuperclass();
102: return (zuper == Enum_.class) ? clazz : zuper;
103: }
104:
105: public static <T extends Enum_<T>> T valueOf(Class<T> enumType,
106: String name) {
107: if (name == null) {
108: throw new NullPointerException("Name is null");
109: }
110: Map<String, WeakReference<Enum_>> map = getMap(enumType);
111: if (map == null) {
112: throw new IllegalArgumentException(enumType.getName()
113: + " is not an enum type");
114: }
115: WeakReference<Enum_> reference = map.get(name);
116: if (reference == null) {
117: throw new IllegalArgumentException("No enum const "
118: + enumType + "." + name);
119: }
120: return (T) reference.get();
121: }
122:
123: protected Object readResolve() throws InvalidObjectException {
124: try {
125: return valueOf(getDeclaringClass(), name);
126: } catch (IllegalArgumentException e) {
127: InvalidObjectException exception = new InvalidObjectException(
128: e.getMessage());
129: exception.initCause(e);
130: throw exception;
131: }
132: }
133:
134: protected static Enum_[] getEnumConstants(Class aClass) {
135: Map<String, WeakReference<Enum_>> map = getMap(aClass);
136: if (map == null) {
137: return null;
138: }
139: Enum_[] result = (Enum_[]) Array
140: .newInstance(aClass, map.size());
141: for (WeakReference<Enum_> reference : map.values()) {
142: Enum_ constant = reference.get();
143: result[constant.ordinal] = constant;
144: }
145: return result;
146: }
147:
148: protected static void setEnumConstants(Class enumType,
149: Enum_[] enumConstants) {
150: // for backward compatibility with 1.2.1
151: }
152:
153: private static Map<String, WeakReference<Enum_>> getMap(
154: final Class enumType) {
155: initFast(enumType);
156: Map<String, WeakReference<Enum_>> map = table.lookup(enumType);
157: if (map != null) {
158: return map;
159: }
160: if (enumType.getSuperclass() != Enum_.class) {
161: return null;
162: }
163: initPrivileged(enumType);
164: return table.lookup(enumType);
165: }
166:
167: private static void initFast(Class enumType) {
168: try {
169: Class.forName(enumType.getName(), true, enumType
170: .getClassLoader());
171: } catch (ClassNotFoundException e) {
172: // ignore
173: }
174: }
175:
176: private static void initPrivileged(final Class enumType) {
177: AccessController.doPrivileged(new PrivilegedAction<Void>() {
178: public Void run() {
179: initFast(enumType);
180: initEnum(enumType);
181: return null;
182: }
183: });
184: }
185:
186: private static void initEnum(Class enumType) {
187: try {
188: Method method = enumType.getMethod("values");
189: method.setAccessible(true);
190: method.invoke(null);
191: } catch (Exception e) {
192: //ignore
193: }
194: }
195:
196: }
|