1 19 20 package org.openide.util; 21 22 import java.beans.PropertyChangeEvent ; 23 import java.beans.PropertyChangeListener ; 24 import java.io.ByteArrayInputStream ; 25 import java.io.ByteArrayOutputStream ; 26 import java.io.ObjectInputStream ; 27 import java.io.ObjectOutputStream ; 28 import java.io.PrintStream ; 29 import java.lang.ref.Reference ; 30 import java.lang.ref.WeakReference ; 31 import java.lang.reflect.Field ; 32 import java.lang.reflect.Method ; 33 import java.net.URL ; 34 import java.net.URLClassLoader ; 35 import junit.textui.TestRunner; 36 import org.netbeans.junit.NbTestCase; 37 import org.openide.util.SharedClassObject; 38 39 42 public class SharedClassObjectTest extends NbTestCase { 43 44 public SharedClassObjectTest(String name) { 45 super(name); 46 } 47 48 public void testSimpleSCO() throws Exception { 49 Class c = makeClazz("SimpleSCO"); 50 assertTrue(c != SimpleSCO.class); 51 assertNull("No instance created yet", SharedClassObject.findObject(c, false)); 52 SharedClassObject o = SharedClassObject.findObject(c, true); 53 assertNotNull(o); 54 assertEquals("org.openide.util.SharedClassObjectTest$SimpleSCO", o.getClass().getName()); 55 assertEquals(c, o.getClass()); 56 assertEquals("has not been initialized", 0, o.getClass().getField("initcount").getInt(o)); 57 assertNull(o.getProperty("foo")); 58 assertEquals("has been initialized", 1, o.getClass().getField("initcount").getInt(o)); 59 assertNull(o.getProperty("bar")); 60 assertEquals("has been initialized just once", 1, o.getClass().getField("initcount").getInt(null)); 61 Class c2 = makeClazz("SimpleSCO"); 62 assertTrue("Call to makeClazz created a fresh class", c != c2); 63 SharedClassObject o2 = SharedClassObject.findObject(c2, true); 64 o2.getProperty("baz"); 65 assertEquals(1, o2.getClass().getField("initcount").getInt(null)); 66 } 67 68 public void testClearSharedData() throws Exception { 69 Class c = makeClazz("DontClearSharedDataSCO"); 70 SharedClassObject o = SharedClassObject.findObject(c, true); 71 o.putProperty("inited", Boolean.TRUE); 72 assertEquals("DCSD has been initialized", Boolean.TRUE, o.getProperty("inited")); 73 Reference r = new WeakReference (o); 74 o = null; 75 assertGC("collected SCO instance", r); 76 assertNull("findObject(Class,false) gives nothing after running GC + finalization #1", SharedClassObject.findObject(c)); 77 o = SharedClassObject.findObject(c, true); 78 assertEquals("has still been initialized", Boolean.TRUE, o.getProperty("inited")); 79 c = makeClazz("ClearSharedDataSCO"); 80 o = SharedClassObject.findObject(c, true); 81 o.putProperty("inited", Boolean.TRUE); 82 assertEquals("CSD has been initialized", Boolean.TRUE, o.getProperty("inited")); 83 r = new WeakReference (o); 84 o = null; 85 assertGC("collected SCO instance", r); 86 assertNull("findObject(Class,false) gives nothing after running GC + finalization #2", SharedClassObject.findObject(c)); 87 o = SharedClassObject.findObject(c, true); 88 assertEquals("is no longer initialized", null, o.getProperty("inited")); 89 o.putProperty("inited", Boolean.TRUE); 90 assertEquals("has now been initialized again", Boolean.TRUE, o.getProperty("inited")); 91 } 92 93 public void testIllegalState() throws Exception { 94 Class c = makeClazz("InitErrorSCO"); 95 SharedClassObject o = SharedClassObject.findObject(c, true); 96 assertNotNull(o); 97 try { 98 o.getProperty("foo"); 99 fail("should not be able to do anything with it"); 100 } catch (IllegalStateException ise) { 101 } 103 try { 104 o.getProperty("bar"); 105 fail("should still not be able to do anything with it"); 106 } catch (IllegalStateException ise) { 107 } 109 } 110 111 public void testPropertyChanges() throws Exception { 112 Class c = makeClazz("PropFirerSCO"); 113 Method putprop = c.getMethod("putprop", new Class [] {Object .class, Boolean.TYPE}); 114 Method getprop = c.getMethod("getprop", new Class [] {}); 115 Field count = c.getField("addCount"); 116 SharedClassObject o = SharedClassObject.findObject(c, true); 117 assertNull(getprop.invoke(o, null)); 118 assertEquals(0, count.getInt(o)); 119 class Listener implements PropertyChangeListener { 120 public int count = 0; 121 public void propertyChange(PropertyChangeEvent ev) { 122 if ("key".equals(ev.getPropertyName())) { 123 count++; 124 } 125 } 126 } 127 Listener l = new Listener (); 128 o.addPropertyChangeListener(l); 129 assertEquals(1, count.getInt(o)); 130 Listener l2 = new Listener (); 131 o.addPropertyChangeListener(l2); 132 assertEquals(1, count.getInt(o)); 133 o.removePropertyChangeListener(l2); 134 assertEquals(1, count.getInt(o)); 135 putprop.invoke(o, new Object [] {"something", Boolean.FALSE}); 136 assertEquals(0, l.count); 137 assertEquals("something", getprop.invoke(o, null)); 138 putprop.invoke(o, new Object [] {"somethingelse", Boolean.TRUE}); 139 assertEquals(1, l.count); 140 assertEquals("somethingelse", getprop.invoke(o, null)); 141 putprop.invoke(o, new Object [] {"somethingelse", Boolean.TRUE}); 143 assertEquals(1, l.count); 144 assertEquals("somethingelse", getprop.invoke(o, null)); 145 putprop.invoke(o, new Object [] {new String ("somethingelse"), Boolean.TRUE}); 147 assertEquals(1, l.count); 148 assertEquals("somethingelse", getprop.invoke(o, null)); 149 o.removePropertyChangeListener(l); 150 assertEquals(0, count.getInt(o)); 151 o.addPropertyChangeListener(l); 152 assertEquals(1, count.getInt(o)); 153 o.removePropertyChangeListener(l); 154 assertEquals(0, count.getInt(o)); 155 } 156 157 public void testRecursiveInit() throws Exception { 158 Class c = makeClazz("RecursiveInitSCO"); 159 SharedClassObject o = SharedClassObject.findObject(c, true); 160 assertEquals(0, c.getField("count").getInt(null)); 161 o.getProperty("foo"); 162 assertEquals(1, c.getField("count").getInt(null)); 163 assertEquals(o, c.getField("INSTANCE").get(null)); 164 } 165 166 public void testAbilityToReadResolveToAnyObject () throws Exception { 167 SharedClassObject o = SharedClassObject.findObject (SharedClassObjectWithReadResolve.class, true); 168 ByteArrayOutputStream os = new ByteArrayOutputStream (); 169 ObjectOutputStream oos = new ObjectOutputStream (os); 170 oos.writeObject (o); 171 oos.close (); 172 173 ObjectInputStream ois = new ObjectInputStream (new ByteArrayInputStream (os.toByteArray())); 174 Object result = ois.readObject (); 175 ois.close (); 176 177 178 assertEquals ("Result should be the string", String .class, result.getClass()); 179 180 } 181 182 185 private Class makeClazz(String name) throws Exception { 186 return Class.forName("org.openide.util.SharedClassObjectTest$" + name, false, new MaskingURLClassLoader()); 187 } 188 private static final class MaskingURLClassLoader extends URLClassLoader { 189 public MaskingURLClassLoader() { 190 super(new URL [] {SharedClassObjectTest.class.getProtectionDomain().getCodeSource().getLocation()}, 191 SharedClassObject.class.getClassLoader()); 192 } 193 protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { 194 if (name.startsWith("org.openide.util.SharedClassObjectTest")) { 195 Class c = findLoadedClass(name); 197 if (c != null) return c; 198 c = findClass(name); 199 if (resolve) resolveClass(c); 200 return c; 201 } else { 202 return super.loadClass(name, resolve); 203 } 204 } 205 } 206 207 public static class SimpleSCO extends SharedClassObject { 208 public static int initcount = 0; 209 private static String firstinit = null; 210 protected void initialize() { 211 super.initialize(); 212 initcount++; 213 if (initcount > 1) { 214 System.err.println("Multiple initializations of SimpleSCO: see http://www.netbeans.org/issues/show_bug.cgi?id=14700"); 215 System.err.print(firstinit); 216 new Throwable ("Init #" + initcount + " here").printStackTrace(); 217 } else { 218 ByteArrayOutputStream baos = new ByteArrayOutputStream (); 219 new Throwable ("Init #1 here").printStackTrace(new PrintStream (baos)); 220 firstinit = baos.toString(); 221 } 223 } 224 protected boolean clearSharedData() { 226 return false; 227 } 228 } 229 230 public static class ClearSharedDataSCO extends SharedClassObject { 231 protected boolean clearSharedData() { 232 return true; 233 } 234 } 235 236 public static class DontClearSharedDataSCO extends SharedClassObject { 237 protected boolean clearSharedData() { 238 return false; 239 } 240 } 241 242 private static final class QuietException extends NullPointerException { 245 public void printStackTrace() { 246 } 248 } 249 250 public static class InitErrorSCO extends SharedClassObject { 251 protected void initialize() { 252 throw new QuietException(); 253 } 254 } 255 256 public static class PropFirerSCO extends SharedClassObject { 257 public int addCount = 0; 258 protected void addNotify() { 259 super.addNotify(); 260 addCount++; 261 } 262 protected void removeNotify() { 263 addCount--; 264 super.removeNotify(); 265 } 266 public void putprop(Object val, boolean notify) { 267 putProperty("key", val, notify); 268 } 269 public Object getprop() { 270 return getProperty("key"); 271 } 272 } 273 274 public static class RecursiveInitSCO extends SharedClassObject { 275 public static final RecursiveInitSCO INSTANCE = (RecursiveInitSCO)SharedClassObject.findObject(RecursiveInitSCO.class, true); 276 public static int count = 0; 277 protected void initialize() { 278 super.initialize(); 279 count++; 280 } 281 } 282 283 public static final class SharedClassObjectWithReadResolve extends SharedClassObject { 284 public Object readResolve () throws java.io.ObjectStreamException { 285 return "Ahoj"; 286 } 287 } 288 } 289 | Popular Tags |