1 9 package org.ozoneDB.core; 10 11 import java.io.*; 12 import java.util.*; 13 import java.lang.reflect.*; 14 import org.ozoneDB.*; 15 import org.ozoneDB.io.stream.ResolvingObjectInputStream; 16 import org.ozoneDB.DxLib.*; 17 import org.ozoneDB.core.*; 18 import org.ozoneDB.core.helper.ReflectionHelper; 19 import org.ozoneDB.util.*; 20 21 22 26 public abstract class AbstractObjectContainer implements ObjectContainer { 27 28 private static transient DxMap methodTable = new DxHashMap( 128 ); 29 30 private static transient DxMap classTable = new DxHashMap( 128 ); 31 32 private transient OzoneProxy theProxy; 33 34 protected int state; 35 36 protected transient boolean shouldCallOnActivate = true; 37 protected transient boolean shouldCallOnPassivate = true; 38 39 public int state() { 40 return state; 41 } 42 43 44 public synchronized void raiseState( int newState ) { 45 state = newState > state ? newState : state; 46 } 47 48 49 public synchronized void clearState() { 50 state = STATE_CLEAN; 51 } 52 53 54 public OzoneInterface database() { 55 return Env.currentEnv().database; 57 } 58 59 60 public OzoneProxy ozoneProxy() { 61 try { 62 if (theProxy == null) { 63 synchronized (this) { 64 if (theProxy == null) { 65 String implName = targetClass().getName(); 66 String proxyName; 67 if (implName.endsWith( ObjectContainer.IMPLNAME_POSTFIX )) { 68 proxyName = implName.substring( 0, implName.length() - 5 ); 69 } 70 else { 71 proxyName = implName + PROXYNAME_POSTFIX; 72 } 73 74 MethodKey key = new MethodKey( proxyName, "_ctor_", "(default)" ); 75 Constructor ctor = (Constructor)methodTable.elementForKey( key ); 76 if (ctor == null) { 77 Class cl = Env.currentEnv().classManager.classForName( proxyName ); 78 Class [] argTypes = {ObjectID.class, OzoneInterface.class}; 79 ctor = cl.getConstructor( argTypes ); 80 methodTable.addForKey( ctor, key ); 81 } 82 83 Object [] args = {id(), database()}; 85 theProxy = (OzoneProxy)ctor.newInstance( args ); 86 Env.currentEnv().logWriter.newEntry (this, "proxy added to cache - " + theProxy, LogWriter.DEBUG2); 87 } 88 } 89 } 90 return theProxy; 91 } catch (Exception e) { 92 Env.currentEnv().logWriter.newEntry( this, "ozoneProxy(): unable to create proper proxy object.", e, LogWriter.WARN ); 93 throw new RuntimeException ( e.toString() ); 94 } 95 } 96 97 98 public OzoneCompatible targetClone() throws Exception { 99 ByteArrayOutputStream bout = new ByteArrayOutputStream( 2048 ); 100 ObjectOutputStream out = new ObjectOutputStream( bout ); 101 out.writeObject( target() ); 102 out.close(); 103 ObjectInputStream in = new ResolvingObjectInputStream( new ByteArrayInputStream( bout.toByteArray() ) ); 104 Object targetClone = in.readObject(); 105 in.close(); 106 return (OzoneCompatible)targetClone; 107 } 108 109 110 120 protected final Method methodFor( Env env, Object obj, String methodName, String sig, Object [] args ) 121 throws Exception { 122 123 MethodKey key = new MethodKey( targetClass().getName(), methodName, sig ); 124 125 Method method = (Method)methodTable.elementForKey( key ); 126 if (method == null) { 127 Class [] classes; 128 StringTokenizer st = new StringTokenizer( sig, ReflectionHelper.SIGNATURE_DELIMITER ); 129 classes = new Class [args.length]; 130 for (int i = 0; st.hasMoreTokens(); ++i) { 131 classes[i] = env.classManager.classForName( st.nextToken() ); 132 } 133 134 method = obj.getClass().getMethod( methodName, classes ); 135 methodTable.addForKey( method, key ); 136 env.logWriter.newEntry( this, "method added to cache - " + key, LogWriter.DEBUG ); 137 } 138 return method; 139 } 140 141 142 151 protected Constructor constructorFor( Env env, Class cl, String sig ) throws Exception ,NoSuchMethodException { 152 153 MethodKey key = new MethodKey( cl.getName(), "_ctor_", sig ); 154 Constructor constructor = (Constructor)methodTable.elementForKey( key ); 155 if (constructor == null) { 156 Class [] classes; 157 if (sig == null) { 158 classes = new Class [0]; 159 } else { 160 StringTokenizer st = new StringTokenizer( sig, ReflectionHelper.SIGNATURE_DELIMITER ); 161 classes = new Class [st.countTokens()]; 162 for (int i = 0; st.hasMoreTokens(); ++i) { 163 classes[i] = env.classManager.classForName( st.nextToken() ); 164 } 165 } 166 try { 167 constructor = cl.getConstructor( classes ); 168 } catch (NoSuchMethodException e) { 169 StringBuffer b = new StringBuffer (200); 170 171 b.append("caught NoSuchMethodException for "+cl+" constructor signature \""+sig+"\" ("); 172 for (int i = 0;i<classes.length;i++) { 173 if (i!=0) 174 b.append(','); 175 b.append(classes[i]); 176 } 177 b.append(")\n"); 178 179 b.append("available constructors are:\n"); 180 181 Constructor[] constructors = cl.getConstructors(); 182 183 for (int i = 0;i<constructors.length;i++) { 184 b.append(" "+constructors[i]+"\n"); 185 } 186 187 env.logWriter.newEntry( this, b.toString(), LogWriter.ERROR ); 188 throw e; 189 } 190 methodTable.addForKey( constructor, key ); 191 env.logWriter.newEntry( this, "constructor added to cache - " + key, LogWriter.DEBUG ); 192 } 193 return constructor; 194 } 195 196 197 public static void flushMethodCache() { 198 methodTable = new DxHashMap( 128 ); 199 } 200 201 202 public Object invokeTarget( Env env, String methodName, String sig, Object [] args ) throws Exception ,InvocationTargetException { 203 204 Method method = methodFor( env, target(), methodName, sig, args ); 205 if (method == null) { 206 throw new MethodNotFoundException( methodName ); 207 } 208 209 try { 210 return method.invoke( target(), args ); 211 } catch (InvocationTargetException e) { 212 throw e; 213 } 214 } 215 216 217 public Object invokeTarget( Env env, int methodIndex, Object [] args ) throws Exception ,InvocationTargetException { 218 219 Class cl = targetClass(); 220 221 Method[] methods = (Method[])classTable.elementForKey( cl ); 222 if (methods == null) { 223 methods = ReflectionHelper.methodsOfClass( cl ); 224 classTable.addForKey( methods, cl ); 225 } 226 227 Method method = methods[methodIndex]; 228 if (method == null) { 229 throw new MethodNotFoundException( "Method index: " + methodIndex ); 230 } 231 232 if (env.logWriter.hasTarget( LogWriter.DEBUG3 )) { 233 env.logWriter.newEntry( this, "invoke(): calling method " + method.getName() + " with arguments " + Arrays.asList(args), LogWriter.DEBUG3 ); 234 } 235 236 try { 237 return method.invoke(target(),args); 238 } catch (InvocationTargetException e) { 239 throw e; 240 } 241 } 242 243 public void invokeOnPassivate() { 244 try { 245 target().onPassivate(); 246 setShouldCallOnPassivate(false); 247 setShouldCallOnActivate(true); 248 } catch (Throwable e) { 249 Env.currentEnv().logWriter.newEntry( this, "Runtime exception during onPassivate", e, LogWriter.WARN); 250 } 252 } 253 254 public void invokeOnActivate() { 255 try { 256 target().onActivate(); 257 setShouldCallOnActivate(false); 260 setShouldCallOnPassivate(true); 261 } catch (Throwable e) { 262 Env.currentEnv().logWriter.newEntry( this, "Runtime exception during onActivate", e, LogWriter.WARN); 263 } 265 } 266 267 public boolean shouldOnActivateBeCalled() { 268 return shouldCallOnActivate; 269 } 270 271 public boolean shouldOnPassivateBeCalled() { 272 return shouldCallOnPassivate; 273 } 274 275 public void setShouldCallOnActivate(boolean shouldOnActivateBeCalled) { 276 shouldCallOnActivate = shouldOnActivateBeCalled; 277 } 278 279 public void setShouldCallOnPassivate(boolean shouldOnPassivateBeCalled) { 280 shouldCallOnPassivate = shouldOnPassivateBeCalled; 281 } 282 283 public void createTarget( Env env, Class cl, String sig, Object [] args ) throws Exception { 284 OzoneCompatible result; 285 if (sig != null) { 286 Constructor ctor = constructorFor( env, cl, sig ); 287 result = (OzoneCompatible) ctor.newInstance( args ); 288 } else { 289 result = (OzoneCompatible) cl.newInstance(); 290 } 291 setTarget( result ); 292 } 293 294 public void requireWriteLocking() { 295 getCurrrentTransaction().requireWriteLockingCallByUser(this); 296 } 297 298 protected Env getEnv() { 299 return getCurrentDatabase().getEnv(); 300 } 301 302 protected static Database getCurrentDatabase() { 303 return (Database) CurrentDatabase.get(); 304 } 305 306 protected Transaction getCurrrentTransaction() { 307 return getCurrentDatabase().getCurrentTransaction(); 308 } 309 } 310 311 | Popular Tags |