001 package net.sourceforge.retroweaver.runtime.java.lang; 002 003 import java.io.InvalidObjectException; 004 import java.io.ObjectStreamException; 005 import java.io.Serializable; 006 import java.util.HashMap; 007 import java.util.Map; 008 009 /** 010 * A version of the 1.5 java.lang.Enum class for the 1.4 VM. 011 */ 012 public class Enum<E extends Enum<E>> implements Comparable<E>, Serializable { 013 014 private static final long serialVersionUID = -1689726118486609581L; 015 016 private final transient int ordinal_; 017 018 private final String name_; 019 020 private static final Map<Class, Object[]> enumValues = new HashMap<Class, Object[]>(); 021 022 protected Enum(final String name, final int ordinal) { 023 this.name_ = name; 024 this.ordinal_ = ordinal; 025 } 026 027 protected static final void setEnumValues(final Object[] values, final Class c) { 028 synchronized(enumValues) { 029 enumValues.put(c, values); 030 } 031 } 032 033 protected static final <T> T[] getEnumValues(final Class<T> class_) { 034 synchronized(enumValues) { 035 final T[] values = (T[]) enumValues.get(class_); 036 if (values != null) { 037 return values; 038 } 039 } 040 041 if (!class_.isEnum()) { 042 return null; 043 } 044 045 // force initialization of class_ as 046 // class loader may not have called static initializers yet 047 try { 048 Class.forName(class_.getName(), true, class_.getClassLoader()); 049 } catch (ClassNotFoundException e) { 050 // can not happen: class_ has already been resolved. 051 } 052 053 synchronized(enumValues) { 054 return (T[]) enumValues.get(class_); 055 } 056 } 057 058 /** 059 * Implement serialization so we can get the singleton behavior we're 060 * looking for in enums. 061 */ 062 protected Object readResolve() throws ObjectStreamException { 063 /* 064 * The implementation is based on "Java Object Serialization Specification", 065 * revision 1.5.0: 066 * 067 * only the name_ is saved, serialVersionUID is 0L for all enum types 068 * InvalidObjectException is raised if valueOf() raises IllegalArgumentException. 069 * 070 */ 071 072 final Class<E> clazz = getDeclaringClass(); 073 /* 074 * Note: getClass() would not work for enum inner classes 075 * such as CMYK.Cyan in the test suite. 076 */ 077 try { 078 return valueOf(clazz, name_); 079 } catch (IllegalArgumentException iae) { 080 final InvalidObjectException ioe = new InvalidObjectException(name_ + " is not a valid enum for " + clazz.getName()); 081 try { 082 ioe.initCause(iae); 083 } catch (NoSuchMethodError nsm) { 084 // cause should be set according to the spec but it's only available in 1.4 085 } 086 087 throw ioe; 088 } 089 } 090 091 public static <T extends Enum<T>> T valueOf(final Class<T> enumType, final String name) { 092 093 if (enumType == null) { 094 throw new NullPointerException("enumType is null"); // NOPMD by xlv 095 } 096 097 if (name == null) { 098 throw new NullPointerException("name_ is null"); // NOPMD by xlv 099 } 100 101 final T[] enums = getEnumValues(enumType); 102 103 if (enums != null) { 104 for (T enum_ : enums) { 105 if (enum_.name_.equals(name)) { 106 return enum_; 107 } 108 } 109 } 110 111 throw new IllegalArgumentException("No enum const " + enumType + "." 112 + name); 113 } 114 115 public final boolean equals(final Object other) { 116 return other == this; 117 } 118 119 public final int hashCode() { 120 return System.identityHashCode(this); 121 } 122 123 public String toString() { 124 return name_; 125 } 126 127 public final int compareTo(final E e) { 128 final Class c1 = getDeclaringClass(); 129 final Class c2 = e.getDeclaringClass(); 130 131 if (c1 == c2) { // NOPMD by xlv 132 return ordinal_ - e.ordinal_; 133 } 134 135 throw new ClassCastException(); 136 } 137 138 protected final Object clone() throws CloneNotSupportedException { 139 throw new CloneNotSupportedException(); 140 } 141 142 public final String name() { 143 return name_; 144 } 145 146 public final int ordinal() { 147 return ordinal_; 148 } 149 150 public final Class<E> getDeclaringClass() { 151 final Class clazz = getClass(); 152 final Class superClass = clazz.getSuperclass(); 153 if (superClass == Enum.class) { 154 return clazz; 155 } else { 156 return superClass; 157 } 158 } 159 160 }