KickJava   Java API By Example, From Geeks To Geeks.

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


1 ///////////////////////////////////////////////////////////////////////////////
2
//
3
// Copyright (C) 2003-@year@ by Thomas M. Hazel, MyOODB (www.myoodb.org)
4
//
5
// All Rights Reserved
6
//
7
// This program is free software; you can redistribute it and/or modify
8
// it under the terms of the GNU General Public License and GNU Library
9
// General Public License as published by the Free Software Foundation;
10
// either version 2, or (at your option) any later version.
11
//
12
// This program is distributed in the hope that it will be useful,
13
// but WITHOUT ANY WARRANTY; without even the implied warranty of
14
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
// GNU General Public License and GNU Library General Public License
16
// for more details.
17
//
18
// You should have received a copy of the GNU General Public License
19
// and GNU Library General Public License along with this program; if
20
// not, write to the Free Software Foundation, 675 Mass Ave, Cambridge,
21
// MA 02139, USA.
22
//
23
///////////////////////////////////////////////////////////////////////////////
24
package org.myoodb.core;
25
26 import java.io.*;
27 import java.util.*;
28 import java.lang.reflect.*;
29
30 import org.myoodb.*;
31 import org.myoodb.exception.*;
32
33 public abstract class AbstractObjectContainer implements Externalizable
34 {
35     private static transient HashMap m_classTable = new HashMap(128);
36     private static transient HashMap m_methodTable = new HashMap(128);
37
38     public transient static String JavaDoc IMPL_NAME_SUFFIX = "@implExtension@";
39     public transient static String JavaDoc BEAN_NAME_SUFFIX = "@beanExtension@";
40     public transient static String JavaDoc PROXY_NAME_SUFFIX = "@proxyExtension@";
41
42     public final transient static int STATE_UNKNOWN = 0;
43     public final transient static int STATE_CREATED = 1;
44     public final transient static int STATE_ACTIVE = 2;
45     public final transient static int STATE_DELETED = 3;
46
47     private int m_state;
48     private Identifier m_objectId;
49     private MyOodbLocal[] m_targets;
50     private boolean m_deactivationFlag;
51     protected AbstractCluster m_cluster;
52
53     private transient MyOodbBean m_myBean;
54     private transient MyOodbProxy m_myProxy;
55
56     public static Method ifThisIsAJavaBeanSetMethodThenReturnItsGetMethod(Method method, Method[] methods)
57     {
58         String JavaDoc name = method.getName();
59
60         if ((name.length() <= 3) ||
61             (name.equals("setXML") == true) || (name.equals("getXML") == true) ||
62             (name.equals("setBean") == true) || (name.equals("getBean") == true))
63         {
64             return null;
65         }
66
67         String JavaDoc suffix = name.substring(0, 3);
68
69         if ((suffix.equals("set") == true) && (method.getParameterTypes().length == 1))
70         {
71             String JavaDoc setMethod = "get" + name.substring(3);
72    
73             for (int methodIndex = 0; methodIndex < methods.length; methodIndex++)
74             {
75                 method = methods[methodIndex];
76     
77                 if ((method.getName().equals(setMethod) == true) && (method.getParameterTypes().length == 0))
78                 {
79                     return method;
80                 }
81             }
82         }
83
84         return null;
85     }
86
87     public AbstractObjectContainer()
88     {
89         // XXX: let the JVM initialize our attributes
90
}
91
92     public AbstractObjectContainer(int state, Identifier objectId)
93     {
94         m_state = state;
95         m_objectId = objectId;
96
97         // XXX: let the JVM initialize the rest of our attributes
98
}
99
100     protected Method[] getMethods(Class JavaDoc classType)
101     {
102         Method[] methods = (Method[]) m_classTable.get(classType);
103
104         if (methods == null)
105         {
106             synchronized(m_classTable)
107             {
108                 methods = (Method[]) m_classTable.get(classType);
109
110                 if (methods == null)
111                 {
112                     Class JavaDoc interfaceType = null;
113
114                     try
115                     {
116                         String JavaDoc className = classType.getName();
117                         className = className.substring(0, className.length() - IMPL_NAME_SUFFIX.length());
118                         interfaceType = Class.forName(className);
119                     }
120                     catch (java.lang.ClassNotFoundException JavaDoc e)
121                     {
122                         // XXX: this should never happen
123
e.printStackTrace();
124                     }
125
126                     methods = MethodHelper.getMethods(classType, interfaceType);
127                     m_classTable.put(classType, methods);
128                 }
129             }
130         }
131
132         return methods;
133     }
134
135     protected final Constructor getConstructor(Class JavaDoc classType, String JavaDoc sig) throws ClassNotFoundException JavaDoc, NoSuchMethodException JavaDoc
136     {
137         MethodSignature def = new MethodSignature(classType.getName(), "CONSTRUCTOR", sig);
138         Constructor constructor = (Constructor) m_methodTable.get(def);
139
140         if (constructor == null)
141         {
142             synchronized(m_methodTable)
143             {
144                 constructor = (Constructor) m_methodTable.get(def);
145
146                 if (constructor == null)
147                 {
148                     Class JavaDoc[] classes;
149                     if (sig == null)
150                     {
151                         classes = new Class JavaDoc[0];
152                     }
153                     else
154                     {
155                         StringTokenizer st = new StringTokenizer(sig, MethodHelper.SIGNATURE_DELIMITER);
156                         classes = new Class JavaDoc[st.countTokens()];
157                         for (int i = 0; st.hasMoreTokens(); ++i)
158                         {
159                             classes[i] = MyOodbManager.getTheManager().getClassManager().getClass(st.nextToken());
160                         }
161                     }
162
163                     constructor = classType.getConstructor(classes);
164
165                     m_methodTable.put(def, constructor);
166                 }
167             }
168         }
169
170         return constructor;
171     }
172
173     protected final Method getMethod(Object JavaDoc obj, String JavaDoc methodName, String JavaDoc sig, Object JavaDoc[] args) throws Exception JavaDoc
174     {
175         Method method = null;
176
177         for (int i = 0; i < m_targets.length; i++)
178         {
179             MethodSignature def = new MethodSignature(m_targets[i].getClass().getName(), methodName, sig);
180             method = (Method) m_methodTable.get(def);
181
182             if (method == null)
183             {
184                 synchronized(m_methodTable)
185                 {
186                     if (method == null)
187                     {
188                         Class JavaDoc[] classes = new Class JavaDoc[args.length];
189                         StringTokenizer st = new StringTokenizer(sig, MethodHelper.SIGNATURE_DELIMITER);
190                         for (int j = 0; st.hasMoreTokens(); ++j)
191                         {
192                             classes[j] = MyOodbManager.getTheManager().getClassManager().getClass(st.nextToken());
193                         }
194
195                         try
196                         {
197                             method = obj.getClass().getMethod(methodName, classes);
198
199                             m_methodTable.put(def, method);
200                         }
201                         catch (java.lang.NoSuchMethodException JavaDoc e)
202                         {
203                             // nothing to do
204
}
205                    }
206                 }
207             }
208
209             if (method != null)
210             {
211                 break;
212             }
213         }
214
215         return method;
216     }
217
218     public int getState()
219     {
220         return m_state;
221     }
222
223     public void raiseState(int newState)
224     {
225         m_state = newState > m_state ? newState : m_state;
226     }
227
228     public AbstractLock getLock()
229     {
230         return (m_cluster != null) ? m_cluster.getLock() : null;
231     }
232
233     public void setCluster(AbstractCluster cluster)
234     {
235         m_cluster = cluster;
236     }
237
238     public AbstractCluster getCluster()
239     {
240         return m_cluster;
241     }
242
243     public boolean isDeleted()
244     {
245         return (getState() == STATE_DELETED);
246     }
247
248     public boolean isCreated()
249     {
250         return (getState() == STATE_CREATED);
251     }
252
253     public void setObjectId(Identifier objectId)
254     {
255         m_objectId = objectId;
256     }
257
258     public Identifier getObjectId()
259     {
260         return m_objectId;
261     }
262
263     public void setDeactivationFlag(boolean flag) throws Exception JavaDoc
264     {
265         m_deactivationFlag = flag;
266     }
267
268     public boolean getDeactivationFlag()
269     {
270         return m_deactivationFlag;
271     }
272
273     public MyOodbLocal getTarget()
274     {
275         return m_targets[0];
276     }
277
278     public MyOodbLocal getTarget(int index)
279     {
280         return m_targets[index];
281     }
282
283     public MyOodbLocal[] getTargets()
284     {
285         return m_targets;
286     }
287
288     public void createTarget(Class JavaDoc[] classTypes, String JavaDoc sig, Object JavaDoc[] args) throws Exception JavaDoc
289     {
290         m_targets = new MyOodbLocal[classTypes.length];
291
292         if (sig != null)
293         {
294             Constructor constructor = getConstructor(classTypes[0], sig);
295             m_targets[0] = (MyOodbLocal) constructor.newInstance(args);
296         }
297         else
298         {
299             m_targets[0] = (MyOodbLocal) classTypes[0].newInstance();
300         }
301
302         m_targets[0].setContainer(this);
303
304         for (int i = 1; i < m_targets.length; i++)
305         {
306             // TODO: handle more than just primary signatures
307
try
308             {
309                 Constructor constructor = getConstructor(classTypes[i], sig);
310                 m_targets[i] = (MyOodbLocal) constructor.newInstance(args);
311             }
312             catch (NoSuchMethodException JavaDoc e)
313             {
314                 m_targets[i] = (MyOodbLocal) classTypes[i].newInstance();
315             }
316
317             m_targets[i].setContainer(this);
318         }
319
320         if (MyOodbManager.getTheManager().m_postObjectMethodCallback != null)
321         {
322             MyOodbManager.getTheManager().m_postObjectMethodCallback.invoke(null, new Object JavaDoc[] {m_targets[0], "CONSTRUCTOR", new Object JavaDoc[]{}});
323         }
324
325         for (int i = 0; i < m_targets.length; i++)
326         {
327             m_targets[i].onCreate();
328         }
329
330         raiseState(STATE_CREATED);
331     }
332
333     public Object JavaDoc invokeTarget(String JavaDoc methodName, String JavaDoc sig, Object JavaDoc[] args, int accessLevel) throws Exception JavaDoc
334     {
335         Method primaryMethod = getMethod(m_targets[0], methodName, sig, args);
336
337         if (primaryMethod == null)
338         {
339             throw new NoSuchMethodException JavaDoc("Target( " + m_objectId + " ) Method Name: " + methodName);
340         }
341
342         if ((accessLevel > Lock.ACCESS_READ) && (MyOodbManager.getTheManager().m_preObjectMethodCallback != null))
343         {
344             MyOodbManager.getTheManager().m_preObjectMethodCallback.invoke(null, new Object JavaDoc[] {m_targets[0], primaryMethod.getName(), args});
345         }
346
347         Object JavaDoc result = primaryMethod.invoke(m_targets[0], args);
348
349         if ((accessLevel > Lock.ACCESS_READ) && (MyOodbManager.getTheManager().m_postObjectMethodCallback != null))
350         {
351             MyOodbManager.getTheManager().m_postObjectMethodCallback.invoke(null, new Object JavaDoc[] {m_targets[0], primaryMethod.getName(), args});
352         }
353
354         if ((m_targets.length != 1) && (accessLevel > Lock.ACCESS_READ))
355         {
356             try
357             {
358                 m_targets[0].getClass().getDeclaredMethod(primaryMethod.getName(), primaryMethod.getParameterTypes());
359             }
360             catch (java.lang.NoSuchMethodException JavaDoc e1)
361             {
362                 for (int i = 1; i < m_targets.length; i++)
363                 {
364                     Method secondaryMethod = getMethod(m_targets[i], methodName, sig, args);
365
366                     if (secondaryMethod == null)
367                     {
368                         continue;
369                     }
370
371                     try
372                     {
373                         secondaryMethod.invoke(m_targets[i], args);
374                     }
375                     catch (java.lang.IllegalArgumentException JavaDoc e2)
376                     {
377                         // nothing to do
378
}
379                 }
380             }
381         }
382
383         return result;
384     }
385
386     public Object JavaDoc invokeTarget(int methodIndex, Object JavaDoc[] args, int accessLevel) throws Exception JavaDoc
387     {
388         Class JavaDoc classType = m_targets[0].getClass();
389
390         Method[] primaryMethods = getMethods(classType);
391         Method primaryMethod = primaryMethods[methodIndex];
392
393         if (primaryMethod == null)
394         {
395             throw new NoSuchMethodException JavaDoc("Target( " + m_objectId + " ) Method index: " + methodIndex);
396         }
397
398         if ((accessLevel > Lock.ACCESS_READ) && (MyOodbManager.getTheManager().m_preObjectMethodCallback != null))
399         {
400             MyOodbManager.getTheManager().m_preObjectMethodCallback.invoke(null, new Object JavaDoc[] {m_targets[0], primaryMethod.getName(), args});
401         }
402
403         Object JavaDoc result = primaryMethod.invoke(m_targets[0],args);
404
405         if ((accessLevel > Lock.ACCESS_READ) && (MyOodbManager.getTheManager().m_postObjectMethodCallback != null))
406         {
407             MyOodbManager.getTheManager().m_postObjectMethodCallback.invoke(null, new Object JavaDoc[] {m_targets[0], primaryMethod.getName(), args});
408         }
409
410         if ((m_targets.length != 1) && (accessLevel > Lock.ACCESS_READ))
411         {
412             try
413             {
414                 m_targets[0].getClass().getDeclaredMethod(primaryMethod.getName(), primaryMethod.getParameterTypes());
415             }
416             catch (java.lang.NoSuchMethodException JavaDoc e1)
417             {
418                 for (int i = 1; i < m_targets.length; i++)
419                 {
420                     classType = m_targets[i].getClass();
421
422                     try
423                     {
424                         Method secondaryMethod = classType.getMethod(primaryMethod.getName(), primaryMethod.getParameterTypes());
425
426                         secondaryMethod.invoke(m_targets[i], args);
427                     }
428                     catch (java.lang.NoSuchMethodException JavaDoc e2)
429                     {
430                         // nothing to do
431
}
432                     catch (java.lang.IllegalArgumentException JavaDoc e3)
433                     {
434                         // nothing to do
435
}
436                 }
437             }
438         }
439
440         return result;
441     }
442
443     public void deleteTarget() throws Exception JavaDoc
444     {
445         if (getDeactivationFlag() == true)
446         {
447             throw new PermissionException("Target( " + m_objectId + " ) Invalid delete (deactived): " + m_targets[0]);
448         }
449
450         if (MyOodbManager.getTheManager().m_preObjectMethodCallback != null)
451         {
452             MyOodbManager.getTheManager().m_preObjectMethodCallback.invoke(null, new Object JavaDoc[] {m_targets[0], "DESTRUCTOR", new Object JavaDoc[]{}});
453         }
454
455         for (int i = 0; i < m_targets.length; i++)
456         {
457             m_targets[i].onDelete();
458         }
459
460         raiseState(STATE_DELETED);
461     }
462
463     public void setBean(MyOodbBean bean)
464     {
465         if (m_myBean == null)
466         {
467             getBean();
468         }
469
470         if (m_myBean.getClass().equals(bean.getClass()) == false)
471         {
472             throw new PermissionException("Target( " + m_objectId + " ) Invalid set (bean mismatch): " + bean.getClass());
473         }
474
475         try
476         {
477             // TODO: notify begin/end of bean sets?
478
// TODO: cache get/set methods for peformance
479

480             synchronized(this)
481             {
482                 Method[] methods = getMethods(m_targets[0].getClass());
483                 for (int methodIndex = 0; methodIndex < methods.length; methodIndex++)
484                 {
485                     Method setMethod = methods[methodIndex];
486                     Method getMethod = ifThisIsAJavaBeanSetMethodThenReturnItsGetMethod(setMethod, methods);
487
488                     if (getMethod == null)
489                     {
490                         continue;
491                     }
492
493                     try
494                     {
495                         getMethod = bean.getClass().getDeclaredMethod(getMethod.getName(), getMethod.getParameterTypes());
496                         Object JavaDoc retval = getMethod.invoke(bean, new Object JavaDoc[]{});
497                         setMethod.invoke(m_targets[0], new Object JavaDoc[]{retval});
498                     }
499                     catch (java.lang.NoSuchMethodException JavaDoc e)
500                     {
501                         // not all sets are beanified
502
}
503                 }
504             }
505         }
506         catch (Exception JavaDoc e)
507         {
508             throw new InternalException("Target( " + m_objectId + " ) Caught during set bean: " + e, e);
509         }
510     }
511
512     public MyOodbBean getBean()
513     {
514         try
515         {
516             if (m_myBean == null)
517             {
518                 synchronized(m_classTable)
519                 {
520                     if (m_myBean == null)
521                     {
522                         String JavaDoc beanName = m_targets[0].getClass().getName();
523                         beanName = beanName.substring(0, beanName.length() - IMPL_NAME_SUFFIX.length()) + BEAN_NAME_SUFFIX;
524
525                         MethodSignature def = new MethodSignature(beanName, "CONSTRUCTOR", "org.myoodb.core.Identifier");
526                         Constructor constructor = (Constructor) m_methodTable.get(def);
527
528                         if (constructor == null)
529                         {
530                             synchronized(m_methodTable)
531                             {
532                                 constructor = (Constructor) m_methodTable.get(def);
533
534                                 if (constructor == null)
535                                 {
536                                     Class JavaDoc classType = MyOodbManager.getTheManager().getClassManager().getClass(beanName);
537                                     constructor = classType.getConstructor(new Class JavaDoc[]{Identifier.class});
538
539                                     m_methodTable.put(def, constructor);
540                                 }
541                             }
542                         }
543
544                         m_myBean = (MyOodbBean)constructor.newInstance(new Object JavaDoc[]{getObjectId()});
545                     }
546                 }
547             }
548
549             // TODO: notify begin/end of bean gets?
550
// TODO: cache get/set methods for peformance
551

552             synchronized(this)
553             {
554                 Method[] methods = getMethods(m_targets[0].getClass());
555                 for (int methodIndex = 0; methodIndex < methods.length; methodIndex++)
556                 {
557                     Method setMethod = methods[methodIndex];
558                     Method getMethod = ifThisIsAJavaBeanSetMethodThenReturnItsGetMethod(setMethod, methods);
559
560                     if (getMethod == null)
561                     {
562                         continue;
563                     }
564
565                     try
566                     {
567                         setMethod = m_myBean.getClass().getDeclaredMethod(setMethod.getName(), setMethod.getParameterTypes());
568                         Object JavaDoc retval = getMethod.invoke(m_targets[0], new Object JavaDoc[]{});
569                         setMethod.invoke(m_myBean, new Object JavaDoc[]{retval});
570                     }
571                     catch (java.lang.NoSuchMethodException JavaDoc e)
572                     {
573                         // not all sets are beanified
574
}
575                 }
576             }
577
578             return m_myBean;
579         }
580         catch (Exception JavaDoc e)
581         {
582             throw new InternalException("Target( " + m_objectId + " ) Caught during get bean: " + e, e);
583         }
584     }
585
586     public void setXML(String JavaDoc xml)
587     {
588         org.myoodb.MyOodbLocal[] targets = m_targets;
589
590         try
591         {
592             // TODO: notify begin/end of xml sets?
593

594             synchronized(this)
595             {
596                 com.thoughtworks.xstream.XStream xstream = new com.thoughtworks.xstream.XStream();
597                 m_targets = (org.myoodb.MyOodbLocal[]) xstream.fromXML(xml);
598
599                 for (int i = 0; i < m_targets.length; i++)
600                 {
601                     m_targets[i].setContainer(this);
602                 }
603
604                 m_cluster.write();
605             }
606         }
607         catch (Exception JavaDoc e)
608         {
609             m_targets = targets;
610
611             throw new InternalException("Target( " + m_objectId + " ) Caught during set xml: " + e, e);
612         }
613     }
614
615     public String JavaDoc getXML()
616     {
617         try
618         {
619             // TODO: notify begin/end of xml gets?
620

621             synchronized(this)
622             {
623                 com.thoughtworks.xstream.XStream xstream = new com.thoughtworks.xstream.XStream();
624                 return xstream.toXML(m_targets);
625             }
626         }
627         catch (Exception JavaDoc e)
628         {
629             throw new InternalException("Target( " + m_objectId + " ) Caught during get xml: " + e, e);
630         }
631     }
632
633     public MyOodbProxy getProxy()
634     {
635         try
636         {
637             if (m_myProxy == null)
638             {
639                 synchronized(m_classTable)
640                 {
641                     if (m_myProxy == null)
642                     {
643                         String JavaDoc proxyName = m_targets[0].getClass().getName();
644                         proxyName = proxyName.substring(0, proxyName.length() - IMPL_NAME_SUFFIX.length()) + PROXY_NAME_SUFFIX;
645
646                         Class JavaDoc classType = MyOodbManager.getTheManager().getClassManager().getClass(proxyName);
647                         Constructor constructor = (Constructor) classType.getConstructor(new Class JavaDoc[]{Identifier.class, AbstractDatabase.class});
648
649                         m_myProxy = (MyOodbProxy) constructor.newInstance(new Object JavaDoc[]{getObjectId(), MyOodbManager.getTheManager().getDatabase()});
650                     }
651                 }
652             }
653
654             return m_myProxy;
655         }
656         catch (Exception JavaDoc e)
657         {
658             throw new InternalException("Target( " + m_objectId + " ) Caught during set proxy: " + e, e);
659         }
660     }
661
662     public int hashCode()
663     {
664         return getObjectId().hashCode();
665     }
666
667     public boolean equals(Object JavaDoc obj)
668     {
669         if (this == obj)
670         {
671             return true;
672         }
673         else if (obj instanceof AbstractObjectContainer)
674         {
675             return getObjectId().equals(((AbstractObjectContainer) obj).getObjectId());
676         }
677         else
678         {
679             return false;
680         }
681     }
682
683     public String JavaDoc toString()
684     {
685         return "ObjectContainer [target="+getTarget()+", objectId="+getObjectId()+", cluster="+getCluster()+"]";
686     }
687
688     public void writeExternal(ObjectOutput out) throws IOException
689     {
690         out.writeByte((byte) m_state);
691         out.writeBoolean(m_deactivationFlag);
692         out.writeObject(m_objectId);
693
694         if (m_targets != null)
695         {
696             for (int i = 0; i < m_targets.length; i++)
697             {
698                 ((MyOodbLocal) m_targets[i]).setConvertFlag(false);
699             }
700         }
701
702         // TODO: synchronize on this since java object streaming is not atomic (see invokeMethod)
703
out.writeObject(m_targets);
704     }
705
706     public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException JavaDoc
707     {
708         m_state = (int) in.readByte();
709         m_deactivationFlag = in.readBoolean();
710         m_objectId = (Identifier) in.readObject();
711         m_targets = (MyOodbLocal[]) in.readObject();
712
713         // XXX: null m_targets is valid for transaction rollback ( clean up on verify )
714
MyOodbManager manager = MyOodbManager.getTheManager();
715         if ((m_targets == null) && ((manager == null) || (manager.getStoreManager().isVerifyingDatabase() == false)))
716         {
717             return;
718         }
719
720         for (int i = 0; i < m_targets.length; i++)
721         {
722             m_targets[i].setContainer(this);
723         }
724     }
725 }
726
Popular Tags