KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > JSX > magic > MagicClass14


1 /** (c) Brendan Macmillan 2002, licensed under GNU's GPL 2
2         (If your project is not GPL, then a fee is due - see license on website)
3     Website: http://www.csse.monash.edu.au/~bren/JSX
4     Website: http://freshmeat.net/projects/jsx
5     List (can read without subscribing, need to join to post):
6       http://groups.yahoo.com/group/JSX-ideas/messages
7         Commercial licensing enquiries only:
8             bren@objectlight.com */

9
10
11 package JSX.magic;
12 import sun.misc.Unsafe;
13 import java.io.*;
14 import java.lang.reflect.*;
15
16 import sun.reflect.ReflectionFactory;
17 import java.security.AccessController JavaDoc;
18 import java.security.PrivilegedAction JavaDoc;
19
20 class MagicClass14 extends MagicClassI {
21     static ReflectionFactory reflFactory = (ReflectionFactory)
22         AccessController.doPrivileged(
23             new ReflectionFactory.GetReflectionFactoryAction());
24     static Constructor objectConstructor;
25     static Unsafe unsafe;
26     public MagicClass14() {
27         // allocate new instance: init Serialization Constructor
28
try {
29             objectConstructor = Object JavaDoc.class.getDeclaredConstructor(new Class JavaDoc[0]);
30         } catch (NoSuchMethodException JavaDoc noMethod) {
31             throw new InternalError JavaDoc("Object constructor not found");
32         }
33
34         // set final fields: init Unsafe
35
try {
36             Class JavaDoc osc$frClazz = Class.forName("java.io.ObjectStreamClass$FieldReflector");
37             Field unsafeF = osc$frClazz.getDeclaredField("unsafe");
38             unsafeF.setAccessible(true);
39             unsafe = (Unsafe) unsafeF.get(null); //static field
40
} catch (ClassNotFoundException JavaDoc noClass) {
41             throw new InternalError JavaDoc("java.io.ObjectStreamClass$FieldReflector not found");
42         } catch (NoSuchFieldException JavaDoc noField) {
43             throw new InternalError JavaDoc("java.io.ObjectStreamClass$FieldReflector has no field 'unsafe'");
44         } catch (IllegalAccessException JavaDoc noAccess) {
45             throw new InternalError JavaDoc("not able to access java.io.ObjectStreamClass$FieldReflector.unsafe");
46         }
47
48     // set osc (note: different Exceptions from other magics)
49
try {
50             osc = (ObjectStreamClass) newInstance(ObjectStreamClass.class);
51         } catch (IllegalAccessException JavaDoc noAccess) {
52             throw new InternalError JavaDoc(noAccess.toString());
53         } catch (InvocationTargetException e) {
54             e.printStackTrace();
55         } catch (NotSerializableException e) { // Serializable check in newInstance
56
e.printStackTrace();
57         }
58     }
59
60
61
62 //Experiment with demanding classes implement "Serializable" - see similar
63
//code in MagicClass13.newInstance()
64
public Object JavaDoc newInstance(Class JavaDoc currentClass)
65             throws InvocationTargetException,
66                          NotSerializableException,
67                    IllegalAccessException JavaDoc {
68 /*
69         if (!Serializable.class.isAssignableFrom(currentClass))
70             throw new NotSerializableException("'"+currentClass+"' is not Serializable - JSX *can* serialize such classes, despite them not implementing the 'Serializable' interface; but this feature is currently switched off (since version JSX1.0.4.2), as an experiment to see if it makes any difference. If this is an annoyance to you, please post to the mailing list immediately:\n" +
71             " http://groups.yahoo.com/group/JSX-ideas/messages");
72 */

73
74         
75         Constructor clCons = null;
76         // Serializable -> JOS way (inherited non-Serializable different)
77
if (Serializable.class.isAssignableFrom(currentClass)) {
78             clCons = getSerializableConstructor(currentClass);
79             if (clCons==null)
80                 throw new InternalError JavaDoc("Unable to find no-arg constructor of first non-serializable subclass of "+currentClass);
81         } else {
82         // !Serializable -> JSX way (just does it)
83
clCons = reflFactory.newConstructorForSerialization(currentClass, objectConstructor);
84             clCons.setAccessible(true);
85         }
86
87         Object JavaDoc obj = null;
88         try {
89             obj = clCons.newInstance(new Object JavaDoc[0]);
90         } catch (InstantiationException JavaDoc cantMake) {
91             throw new InternalError JavaDoc("serialization constructor for "+currentClass+" not not able to instantiate it");
92         }
93         return obj;
94     }
95
96     /**
97      * Returns subclass-accessible no-arg constructor of first non-serializable
98      * superclass, or null if none found. Access checks are disabled on the
99      * returned constructor (if any).
100      */

101     private static Constructor getSerializableConstructor(Class JavaDoc cl) {
102         Class JavaDoc initCl = cl;
103         while (Serializable.class.isAssignableFrom(initCl)) {
104             if ((initCl = initCl.getSuperclass()) == null) {
105                 return null;
106             }
107         }
108         try {
109             Constructor cons = initCl.getDeclaredConstructor(new Class JavaDoc[0]);
110             int mods = cons.getModifiers();
111             if ((mods & Modifier.PRIVATE) != 0 ||
112                 ((mods & (Modifier.PUBLIC | Modifier.PROTECTED)) == 0 &&
113                 !packageEquals(cl, initCl))) {
114                 return null;
115             }
116             cons = reflFactory.newConstructorForSerialization(cl, cons);
117             cons.setAccessible(true);
118             return cons;
119         } catch (NoSuchMethodException JavaDoc ex) {
120             return null;
121         }
122     }
123
124     /**
125      * Returns true if classes are defined in the same package, false
126      * otherwise.
127      */

128     private static boolean packageEquals(Class JavaDoc cl1, Class JavaDoc cl2) {
129         Package JavaDoc pkg1 = cl1.getPackage(), pkg2 = cl2.getPackage();
130         return ((pkg1 == pkg2) || ((pkg1 != null) && (pkg1.equals(pkg2))));
131     }
132
133
134
135 //Exception back-compatible - good to rewrite JSX, so caller can handle nicer
136
public void setObjectFieldValue(Object JavaDoc parent, Field f, Class JavaDoc type, Object JavaDoc value) {
137             //if (parent==null) throw new NullPointerException();
138
if (value!=null && !f.getType().isInstance(value))//if non-null & incompat
139
throw new ClassCastException JavaDoc("Expected "+f.getType()+" or subclass, got "+value.getClass());
140         unsafe.putObject(parent, unsafe.fieldOffset(f), value);
141     }
142
143     public void setPrimitiveFieldValues(Object JavaDoc parent, Field f, Object JavaDoc value) {
144             //if (parent==null) throw new NullPointerException();
145
int key = unsafe.fieldOffset(f);
146         Class JavaDoc type = f.getType(); //value.getClass() gives Integer.class etc
147
if (type==int.class) //ordered by expected frequency of occurance
148
unsafe.putInt(parent, key, ((Integer JavaDoc)value).intValue());
149         else if (type==double.class)
150             unsafe.putDouble(parent, key, ((Double JavaDoc)value).doubleValue());
151         else if (type==boolean.class)
152             unsafe.putBoolean(parent, key, ((Boolean JavaDoc)value).booleanValue());
153         else if (type==byte.class)
154             unsafe.putByte(parent, key, ((Byte JavaDoc)value).byteValue());
155         else if (type==char.class)
156             unsafe.putChar(parent, key, ((Character JavaDoc)value).charValue());
157         else if (type==short.class)
158             unsafe.putShort(parent, key, ((Short JavaDoc)value).shortValue());
159         else if (type==float.class)
160             unsafe.putFloat(parent, key, ((Float JavaDoc)value).floatValue());
161         else if (type==long.class)
162             unsafe.putLong(parent, key, ((Long JavaDoc)value).longValue());
163         else
164             throw new InternalError JavaDoc(type+" is unknown type, expected primitive");
165     }
166 }
167
Popular Tags