KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > ozoneDB > core > AbstractObjectContainer


1 // You can redistribute this software and/or modify it under the terms of
2
// the Ozone Core License version 1 published by ozone-db.org.
3
//
4
// The original code and portions created by SMB are
5
// Copyright (C) 1997-@year@ by SMB GmbH. All rights reserved.
6
//
7
// $Id: AbstractObjectContainer.java,v 1.15 2003/12/07 18:20:37 per_nyfelt Exp $
8

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 /**
23  * @author <a HREF="http://www.softwarebuero.de/">SMB</a>
24  * @version $Revision: 1.15 $Date: 2003/12/07 18:20:37 $
25  */

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         // We should change this to CurrentDatabase.get(), shouldn't we?
56
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 JavaDoc implName = targetClass().getName();
66                         String JavaDoc 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 JavaDoc cl = Env.currentEnv().classManager.classForName( proxyName );
78                             Class JavaDoc[] argTypes = {ObjectID.class, OzoneInterface.class};
79                             ctor = cl.getConstructor( argTypes );
80                             methodTable.addForKey( ctor, key );
81                         }
82
83                         //creating proxy: cl.getName()
84
Object JavaDoc[] 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 JavaDoc e) {
92             Env.currentEnv().logWriter.newEntry( this, "ozoneProxy(): unable to create proper proxy object.", e, LogWriter.WARN );
93             throw new RuntimeException JavaDoc( e.toString() );
94         }
95     }
96
97
98     public OzoneCompatible targetClone() throws Exception JavaDoc {
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 JavaDoc targetClone = in.readObject();
105         in.close();
106         return (OzoneCompatible)targetClone;
107     }
108
109
110     /**
111      * Search the method with the specified name and signature. Once
112      * a method has been invoked it is stored in a global cache that holds
113      * the method objects of all database classes.
114      *
115      *
116      * @param methodName
117      * @param sig
118      * @param args
119      */

120     protected final Method methodFor( Env env, Object JavaDoc obj, String JavaDoc methodName, String JavaDoc sig, Object JavaDoc[] args )
121             throws Exception JavaDoc {
122
123         MethodKey key = new MethodKey( targetClass().getName(), methodName, sig );
124
125         Method method = (Method)methodTable.elementForKey( key );
126         if (method == null) {
127             Class JavaDoc[] classes;
128             StringTokenizer st = new StringTokenizer( sig, ReflectionHelper.SIGNATURE_DELIMITER );
129             classes = new Class JavaDoc[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     /**
143      * Search the constructor with the specified signature.
144      * Once a constructor has been invoked it is stored in a global cache that
145      * holds the method and constructor objects of all database classes.
146      *
147      * @param env
148      * @param cl
149      * @param sig
150      */

151     protected Constructor constructorFor( Env env, Class JavaDoc cl, String JavaDoc sig ) throws Exception JavaDoc,NoSuchMethodException JavaDoc {
152
153         MethodKey key = new MethodKey( cl.getName(), "_ctor_", sig );
154         Constructor constructor = (Constructor)methodTable.elementForKey( key );
155         if (constructor == null) {
156             Class JavaDoc[] classes;
157             if (sig == null) {
158                 classes = new Class JavaDoc[0];
159             } else {
160                 StringTokenizer st = new StringTokenizer( sig, ReflectionHelper.SIGNATURE_DELIMITER );
161                 classes = new Class JavaDoc[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 JavaDoc e) {
169                 StringBuffer JavaDoc b = new StringBuffer JavaDoc(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 JavaDoc invokeTarget( Env env, String JavaDoc methodName, String JavaDoc sig, Object JavaDoc[] args ) throws Exception JavaDoc,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 JavaDoc invokeTarget( Env env, int methodIndex, Object JavaDoc[] args ) throws Exception JavaDoc,InvocationTargetException {
218
219         Class JavaDoc 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 JavaDoc e) {
249             Env.currentEnv().logWriter.newEntry( this, "Runtime exception during onPassivate", e, LogWriter.WARN);
250             // todo: Do something
251
}
252     }
253
254     public void invokeOnActivate() {
255         try {
256             target().onActivate();
257             // Note that we set this _after_ the method was called. If we set this before,
258
// the method may fail due to a deadlock TransactionException and might not be re-tried.
259
setShouldCallOnActivate(false);
260             setShouldCallOnPassivate(true);
261         } catch (Throwable JavaDoc e) {
262             Env.currentEnv().logWriter.newEntry( this, "Runtime exception during onActivate", e, LogWriter.WARN);
263             // todo: Do something
264
}
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 JavaDoc cl, String JavaDoc sig, Object JavaDoc[] args ) throws Exception JavaDoc {
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 // :indentSize=4:tabSize=4:noTabs=true:
312
Popular Tags