KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > speedo > mim > lib > SpeedoMemoryInstanceManager


1 /**
2  * Copyright (C) 2001-2004 France Telecom R&D
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  */

18 package org.objectweb.speedo.mim.lib;
19
20 import org.objectweb.fractal.api.control.BindingController;
21 import org.objectweb.jorm.api.PClassMapping;
22 import org.objectweb.jorm.api.PException;
23 import org.objectweb.jorm.lib.JormPathHelper;
24 import org.objectweb.jorm.naming.api.PBinder;
25 import org.objectweb.jorm.naming.api.PName;
26 import org.objectweb.jorm.type.api.PType;
27 import org.objectweb.jorm.util.api.Loggable;
28 import org.objectweb.perseus.cache.api.CacheEntry;
29 import org.objectweb.perseus.cache.api.CacheEntryFactory;
30 import org.objectweb.perseus.cache.api.CacheEvent;
31 import org.objectweb.perseus.cache.api.FixableCacheEntry;
32 import org.objectweb.perseus.persistence.api.ConnectionHolder;
33 import org.objectweb.perseus.persistence.api.MemoryInstanceManager;
34 import org.objectweb.perseus.persistence.api.PersistenceException;
35 import org.objectweb.perseus.persistence.api.State;
36 import org.objectweb.perseus.persistence.api.StateManager;
37 import org.objectweb.speedo.api.ExceptionHelper;
38 import org.objectweb.speedo.genclass.SpeedoGenClassHome;
39 import org.objectweb.speedo.genclass.SupportedGenClass;
40 import org.objectweb.speedo.genclass.api.SpeedoGenClassProxy;
41 import org.objectweb.speedo.mapper.api.JormFactory;
42 import org.objectweb.speedo.mim.api.LifeCycle;
43 import org.objectweb.speedo.mim.api.MemoryInstanceManagerAttribute;
44 import org.objectweb.speedo.mim.api.SpeedoAccessor;
45 import org.objectweb.speedo.mim.api.SpeedoHome;
46 import org.objectweb.speedo.mim.api.SpeedoProxy;
47 import org.objectweb.speedo.pm.api.ProxyManagerFactory;
48 import org.objectweb.util.monolog.api.BasicLevel;
49 import org.objectweb.util.monolog.api.Logger;
50
51 import java.util.Collections JavaDoc;
52 import java.util.HashMap JavaDoc;
53 import java.util.Iterator JavaDoc;
54 import java.util.Map JavaDoc;
55 import java.util.StringTokenizer JavaDoc;
56
57 import javax.jdo.JDOException;
58 import javax.jdo.listener.InstanceLifecycleEvent;
59
60 /**
61  * This class is an implementation of the MemoryInstanceManager provided by the
62  * persistence framwork availlable in perseus. This implementation depends on
63  * the identifier used, and the way to instanciate user objects. This
64  * implementation supports only the jorm object identifier: PName.
65  * This implementation supports also the instanciation of the Jorm generic
66  * class. To do this it is needed to specify for each jorm generic class used
67  * the name of the class which must be instanciated. This configuration is done
68  * via the GenClassNames attribute.
69  * This implementation does not used a pool, then the instance are created at
70  * each newInstance call.
71  *
72  * @author S.Chassande-Barrioz
73  */

74 public class SpeedoMemoryInstanceManager
75         implements MemoryInstanceManager,
76         MemoryInstanceManagerAttribute,
77         StateManager,
78         CacheEntryFactory,
79         BindingController {
80
81     public final static String JavaDoc JORM_FACTORY_BINDING = "jorm-factory";
82     public final static String JavaDoc PMS_BINDING = "proxy-manager-factory";
83
84     /**
85      * This fields maintains the association between the name of the Jorm
86      * generic class and the class name which must be implemented.
87      */

88     private Map JavaDoc name2gcimpl = null;
89
90     protected JormFactory jf = null;
91     protected ProxyManagerFactory pmf = null;
92
93     protected Logger logger = null;
94
95     public SpeedoMemoryInstanceManager() {
96         name2gcimpl = Collections.EMPTY_MAP;
97     }
98
99     private String JavaDoc getGCClassName(String JavaDoc cn) {
100         String JavaDoc res = (String JavaDoc) name2gcimpl.get(cn);
101         if (res != null) {
102             return res;
103         }
104         for (int i = 0; i < SupportedGenClass.GC_IMPL.length; i++) {
105             if (SupportedGenClass.GC_IMPL[i][0].equals(cn)) {
106                 return SupportedGenClass.GC_IMPL[i][1];
107             }
108         }
109         return null;
110     }
111
112     /**
113      * Active a persistent object :
114      * - assign the PClassMapping
115      * - assign a Pbinding for the SpeedoGenClassProxy
116      *
117      * @param sp is SpeedoProxy or a SpeedoGenClassProxy instance, the
118      * persistent object
119      * @param pn the identifier of the object
120      */

121     private void activeProxy(SpeedoProxy sp, PName pn) {
122         //fetch the PClassMapping
123
PClassMapping pcm = null;
124         if (pn != null && (pn.getPNameManager() instanceof PBinder)) {
125             pcm = ((PBinder) pn.getPNameManager()).getBinderClassMapping();
126         }
127         if (sp instanceof SpeedoGenClassProxy) {
128             if (((SpeedoGenClassProxy) sp).jdoGetPBinding() == null) {
129                 if (pcm == null) {
130                     pcm = jf.getGenClassMapping(
131                             ((SpeedoGenClassProxy) sp).jdoGetGenClassId());
132                 }
133                 //Assign the PBinding
134
try {
135                     ((SpeedoGenClassProxy) sp).jdoSetPBinding(pcm.createPBinding());
136                 } catch (PException e) {
137                     throw new JDOException("Impossible to initialize the delegate PBinding of the genclass", e);
138                 }
139                 if (sp instanceof Loggable) {
140                     ((Loggable) sp).setLogger(logger);
141                 }
142             }
143         } else {
144             if (pcm == null) {
145                 try {
146                     pcm = jf.getPClassMapping(sp.getClass());
147                 } catch (PException e) {
148                     throw new JDOException("Impossible to initialize a class", e);
149                 }
150             }
151             if (sp.getPClassMapping() == null) {
152                 //Assign the PClassMapping
153
try {
154                     sp.init(pcm);
155                 } catch (PException e) {
156                     Exception JavaDoc ie = ExceptionHelper.getNested(e);
157                     if (logger != null)
158                         logger.log(BasicLevel.ERROR,
159                                 "Impossible to init the persistent class: "
160                                 + sp.getClass().getName(), ie);
161                     throw new JDOException("Impossible to init the persistent class:" +
162                             ie.getMessage());
163                 }
164             }
165         }
166         //Mark as active
167
sp.jdoIsActive(true);
168         if (logger != null && logger.isLoggable(BasicLevel.DEBUG))
169             logger.log(BasicLevel.DEBUG, "Proxy activated: " + sp.getClass().getName());
170     }
171
172     // IMPLEMENTATION OF THE MemoryInstanceManagerAttribute INTERFACE //
173
//----------------------------------------------------------------------//
174
public String JavaDoc[] listFc() {
175         return new String JavaDoc[]{JORM_FACTORY_BINDING, PMS_BINDING};
176     }
177
178     public Object JavaDoc lookupFc(String JavaDoc s) {
179         if (JORM_FACTORY_BINDING.equals(s)) {
180             return jf;
181         } else if (PMS_BINDING.equals(s)) {
182             return pmf;
183         } else {
184             return null;
185         }
186     }
187
188     public void bindFc(String JavaDoc s, Object JavaDoc o) {
189         if (JORM_FACTORY_BINDING.equals(s)) {
190             jf = (JormFactory) o;
191         } else if (PMS_BINDING.equals(s)) {
192             pmf =(ProxyManagerFactory) o;
193         } else if ("logger".equals(s)) {
194             logger = (Logger) o;
195         }
196     }
197
198     public void unbindFc(String JavaDoc s) {
199         if (JORM_FACTORY_BINDING.equals(s)) {
200             jf = null;
201         } else if (PMS_BINDING.equals(s)) {
202             pmf = null;
203         }
204     }
205
206
207     // IMPLEMENTATION OF THE MemoryInstanceManagerAttribute INTERFACE //
208
//----------------------------------------------------------------------//
209

210     /**
211      * @return a String describing the genclass names with the following format:
212      * "(jorm_name,java_name),(jorm_name,java_name),(jorm_name,java_name)}"
213      */

214     public String JavaDoc getGenClassNames() {
215         if (name2gcimpl == null || name2gcimpl.size() == 0)
216             return "{}";
217         StringBuffer JavaDoc res = new StringBuffer JavaDoc("");
218         boolean first = true;
219         for (Iterator JavaDoc it = name2gcimpl.entrySet().iterator(); it.hasNext();) {
220             if (first) {
221                 res.append("{");
222                 first = false;
223             } else
224                 res.append(",");
225             res.append("(");
226             Map.Entry JavaDoc me = (Map.Entry JavaDoc) it.next();
227             res.append(me.getKey());
228             res.append(",");
229             res.append(me.getValue());
230             res.append(")");
231         }
232         res.append("}");
233         return res.toString();
234     }
235
236     /**
237      * It assignes a description of the gen class names.
238      * @param gcname is the desciption which must follow this format:
239      * "(jorm_name,java_name),(jorm_name,java_name),(jorm_name,java_name)}"
240      */

241     public void setGenClassNames(String JavaDoc gcname) {
242         if (gcname == null || gcname.length() == 0)
243             name2gcimpl = Collections.EMPTY_MAP;
244         name2gcimpl = new HashMap JavaDoc(5);
245         StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(gcname, "{,()}:;[]", false);
246         String JavaDoc key = null;
247         while (st.hasMoreTokens()) {
248             if (key == null) {
249                 key = st.nextToken().trim();
250             } else {
251                 name2gcimpl.put(key, st.nextToken().trim());
252             }
253         }
254     }
255
256
257     // IMPLEMENTATION OF THE MemoryInstanceManager INTERFACE //
258
//-------------------------------------------------------//
259

260     /**
261      * It creates an instance since an identifier
262      * @param oid is the identifier of the futur object
263      * @return a memory instance
264      */

265     public Object JavaDoc newInstance(Object JavaDoc oid, ConnectionHolder context) throws PersistenceException {
266         if (!(oid instanceof PName))
267             throw new PersistenceException("Unmanaged object identifier: " + oid);
268         PName pn = (PName) oid;
269         String JavaDoc className = null;
270         try {
271             pn = pn.resolve(context);
272             if (logger.isLoggable(BasicLevel.DEBUG)) {
273                 logger.log(BasicLevel.DEBUG, "newInstance(" + oid + "): pn.resolve=" + pn);
274                 logger.log(BasicLevel.DEBUG, "newInstance(" + oid + "): pn.type=" + pn.getPType());
275             }
276             PType type = pn.getPType();
277             if (type == null) {
278                 //Error detected by Roland Hedayat
279
throw new PersistenceException("newInstance() "
280                     + "\n\toid=" + oid
281                     + "\n\tpn=" + pn
282                     + "\n\tpn.pnc=" + (pn.getPNameManager() != null ? pn.getPNameManager() : null));
283             }
284             className = type.getJormName();
285             int idx = className.indexOf(JormPathHelper.SEP);
286             PClassMapping pcm = ((PBinder) pn.getPNameManager())
287                     .getBinderClassMapping();
288             SpeedoProxy sp = null;
289             if ((pcm instanceof SpeedoGenClassHome) && idx != -1) {
290                 // This is a Generic class
291
className = getGCClassName(className.substring(0, idx));
292                 sp = (SpeedoProxy) Class.forName(className).newInstance();
293             } else {
294                 if (pcm != null) {
295                     className = pcm.getClassName();
296                 }
297                 ClassLoader JavaDoc cl = jf.getClassLoader(className);
298                 if (cl == null) {
299                     cl = oid.getClass().getClassLoader();
300                     if (cl == null) {
301                         cl = ClassLoader.getSystemClassLoader();
302                     }
303                 }
304                 sp = (SpeedoProxy)
305                         cl.loadClass(className).newInstance();
306             }
307             return sp;
308         } catch (PException e) {
309             throw new PersistenceException(
310                     "Impossible to analyze the object identifier" + oid, e);
311         } catch (Exception JavaDoc e) {
312             throw new PersistenceException(
313                     "Impossible to instanciate the class " + className
314                     + "Be careful to the generic class (Collection, ...), oid class:"
315                     + oid.getClass(), e);
316         }
317     }
318
319
320     // IMPLEMENTATION OF THE StateManager INTERFACE //
321
//----------------------------------------------//
322
public State createState(CacheEntry ce) {
323         return ((SpeedoProxy) ce).createAccessor();
324     }
325
326     public State createState(State s) {
327         SpeedoProxy sp = (SpeedoProxy) s.getCacheEntry();
328         SpeedoAccessor sa = sp.createAccessor();
329         sp.copyAccessor(((SpeedoAccessor) s), sa);
330         return sa;
331     }
332
333     public State getReferenceState(CacheEntry ce) {
334         return ((SpeedoProxy) ce).getReferenceAccessor();
335     }
336
337     public void destroyState(State state) {
338         //nothing to do
339
}
340
341     public void makeUnexported(State state) {
342         ((SpeedoAccessor) state).jdoChangeStatus(LifeCycle.ACTION_DELETEPERSISTENT);
343     }
344
345     public boolean isUnexported(State state) {
346         return LifeCycle.isDeleted(((SpeedoAccessor) state).jdoGetStatus());
347     }
348
349     public void makeExported(State state) {
350         ((SpeedoAccessor) state).jdoChangeStatus(LifeCycle.ACTION_MAKEPERSISTENT);
351     }
352
353     public boolean isExported(State state) {
354         return LifeCycle.isNew(((SpeedoAccessor) state).jdoGetStatus());
355     }
356
357     public void makeDirty(State state) {
358         ((SpeedoAccessor) state).jdoChangeStatus(LifeCycle.ACTION_WRITEFIELD_ACTIVEDATASTORETRANSACTION);
359         ((SpeedoAccessor) state).setFlushed(false);
360     }
361
362     public boolean isDirty(State state) {
363         return LifeCycle.isDirty(((SpeedoAccessor) state).jdoGetStatus());
364     }
365
366     public void setReferenceState(CacheEntry ce, State state) {
367         if (state == ((SpeedoProxy) ce).getReferenceAccessor()) {
368             return;
369         }
370         SpeedoProxy sp = (SpeedoProxy) ce;
371         if (sp.jdoIsActive() && state != null) {
372             sp.getSpeedoHome().sendEvent(InstanceLifecycleEvent.CLEAR, sp, null, false);
373         }
374         if (state == null || !sp.jdoIsActive() || sp.getSpeedoHome().isCacheable()) {
375             sp.setReferenceAccessor((SpeedoAccessor) state);
376         } else {
377             sp.setReferenceAccessor(null);
378         }
379     }
380
381     public void makeClean(State state) {
382         SpeedoAccessor sa = (SpeedoAccessor) state;
383         sa.jdoSetStatus(LifeCycle.PERSISTENT_CLEAN);
384     }
385
386     public void makeFlushed(State state) {
387         ((SpeedoAccessor) state).setFlushed(true);
388     }
389
390     public boolean isFlushed(State state) {
391         return ((SpeedoAccessor) state).hasBeenFlush();
392     }
393
394     public void makeUnbound(CacheEntry ce) {
395         SpeedoProxy sp = (SpeedoProxy) ce;
396         sp.jdoIsActive(false);
397         try {
398             sp.init(null);
399         } catch (PException e) {
400             logger.log(BasicLevel.WARN, "Error during the unbinding: ", e);
401         }
402     }
403
404     public void makeBound(CacheEntry ce, Object JavaDoc oid) {
405         PName pname = (PName) oid;
406         SpeedoProxy sp = (SpeedoProxy) ce;
407         try {
408             sp.bind(pname);
409         } catch (PException e) {
410             logger.log(BasicLevel.WARN, "Error during the binding: ", e);
411         }
412     }
413     
414     public boolean isBound(CacheEntry ce) {
415         return ((SpeedoProxy) ce).jdoIsActive();
416     }
417
418     public boolean isToMerge(State state) {
419         return ((SpeedoAccessor) state).isToMerge();
420     }
421     public void makeToMerge(State state, Object JavaDoc thinLock) {
422         ((SpeedoAccessor) state).makeToMerge(thinLock);
423     }
424     public State merge(State oldState, State newState) {
425         return ((SpeedoAccessor) newState).merge(oldState);
426     }
427
428     public void stateNoMoreUsed(State state) {
429         ((SpeedoAccessor) state).unSwizzle();
430     }
431     
432     // IMPLEMENTATION OF THE CacheEventListener INTERFACE //
433
//----------------------------------------------------//
434

435     /**
436      * @param event
437      */

438     public void entryBound(CacheEvent event) {
439     }
440
441     /**
442      * @param event
443      */

444     public void entryUnbound(CacheEvent event) {
445         if (logger.isLoggable(BasicLevel.DEBUG)) {
446             logger.log(BasicLevel.DEBUG, "Entry unbound from the cache: \n\tid: "
447                 + event.getCeIdentifier());
448         }
449         PName pn = (PName) event.getCeIdentifier();
450         SpeedoHome sh = (SpeedoHome)
451                 ((PBinder) pn.getPNameManager()).getBinderClassMapping();
452         sh.userCacheEntryUnbound(pn);
453     }
454
455
456     // IMPLEMENTATION OF THE CacheEntryFactory INTERFACE //
457
//---------------------------------------------------//
458

459     /**
460      * binds the SpeedoProxy to its identifier (PName) if it does not have
461      * already one.
462      * @param id is the PName of the SpeedoProxy
463      * @param obj is the SpeedoProxy instance added into the cache
464      * @return the SpeedoProxy instance
465      */

466     public FixableCacheEntry create(Object JavaDoc id, Object JavaDoc obj) {
467         SpeedoProxy sp = (SpeedoProxy) obj;
468         PName pn = (PName) id;
469         activeProxy(sp, pn);
470         if (sp.getPName() == null || sp.getPName().isNull()) {
471             try {
472                 pn.resolve(null);
473                 sp.bind(pn);
474             } catch (PException e) {
475                 throw new JDOException(
476                         "Impossible to bind the proxy to its persistent name: ", e);
477             }
478         }
479         /**
480          * else the entry is a new persistent object, the export created an
481          * identifier
482          */

483         return (FixableCacheEntry) obj;
484     }
485 }
486
Popular Tags