Source Code Cross Referenced for ObjectCacheTwoLevelImpl.java in  » Database-ORM » db-ojb » org » apache » ojb » broker » cache » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Database ORM » db ojb » org.apache.ojb.broker.cache 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        package org.apache.ojb.broker.cache;
002:
003:        /* Copyright 2004-2005 The Apache Software Foundation
004:         *
005:         * Licensed under the Apache License, Version 2.0 (the "License");
006:         * you may not use this file except in compliance with the License.
007:         * You may obtain a copy of the License at
008:         *
009:         *     http://www.apache.org/licenses/LICENSE-2.0
010:         *
011:         * Unless required by applicable law or agreed to in writing, software
012:         * distributed under the License is distributed on an "AS IS" BASIS,
013:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014:         * See the License for the specific language governing permissions and
015:         * limitations under the License.
016:         */
017:
018:        import java.io.Serializable;
019:        import java.lang.ref.ReferenceQueue;
020:        import java.lang.ref.SoftReference;
021:        import java.util.HashMap;
022:        import java.util.Iterator;
023:        import java.util.Properties;
024:
025:        import org.apache.ojb.broker.Identity;
026:        import org.apache.ojb.broker.PBStateEvent;
027:        import org.apache.ojb.broker.PBStateListener;
028:        import org.apache.ojb.broker.PersistenceBroker;
029:        import org.apache.ojb.broker.core.DelegatingPersistenceBroker;
030:        import org.apache.ojb.broker.core.PersistenceBrokerImpl;
031:        import org.apache.ojb.broker.core.proxy.ProxyHelper;
032:        import org.apache.ojb.broker.metadata.ClassDescriptor;
033:        import org.apache.ojb.broker.metadata.FieldDescriptor;
034:        import org.apache.ojb.broker.metadata.MetadataException;
035:        import org.apache.ojb.broker.util.ClassHelper;
036:        import org.apache.ojb.broker.util.logging.Logger;
037:        import org.apache.ojb.broker.util.logging.LoggerFactory;
038:        import org.apache.commons.lang.builder.ToStringBuilder;
039:
040:        /**
041:         * A two-level {@link ObjectCache} implementation with a session- and an application cache. The application
042:         * cache could be specified by the property <code>applicationCache</code>.
043:         * <p/>
044:         * The first level is a transactional session
045:         * cache which cache objects till {@link org.apache.ojb.broker.PersistenceBroker#close()} or if
046:         * a PB-tx is running till {@link org.apache.ojb.broker.PersistenceBroker#abortTransaction()} or
047:         * {@link org.apache.ojb.broker.PersistenceBroker#commitTransaction()}. On commit all objects written to
048:         * database will be pushed to the application cache.
049:         * </p>
050:         * <p/>
051:         * The session cache act as a temporary storage for all read/store operations of persistent objects
052:         * and only on commit or close of the used PB instance the buffered objects of type
053:         * {@link #TYPE_WRITE} will be written to the application cache. Except objects of type
054:         * {@link #TYPE_NEW_MATERIALIZED} these objects will be immediatly pushed to application cache.
055:         * </p>
056:         * <p/>
057:         * <p/>
058:         * </p>
059:         * <p/>
060:         * The application cache
061:         * </p>
062:         * <p/>
063:         * <table cellspacing="2" cellpadding="2" border="3" frame="box">
064:         * <tr>
065:         * <td><strong>Property Key</strong></td>
066:         * <td><strong>Property Values</strong></td>
067:         * </tr>
068:         * <p/>
069:         * <tr>
070:         * <td>applicationCache</td>
071:         * <td>
072:         * Specifies the {@link ObjectCache} implementation used as application cache (second level cache).
073:         * By default {@link ObjectCacheDefaultImpl} was used. It's recommended to use a shared cache implementation
074:         * (all used PB instances should access the same pool of objects - e.g. by using a static Map in cache
075:         * implementation).
076:         * </td>
077:         * </tr>
078:         * <p/>
079:         * <tr>
080:         * <td>copyStrategy</td>
081:         * <td>
082:         * Specifies the implementation class of the {@link ObjectCacheTwoLevelImpl.CopyStrategy}
083:         * interface, which was used to copy objects on read and write to application cache. If not
084:         * specified a default implementation based was used ({@link ObjectCacheTwoLevelImpl.CopyStrategyImpl}
085:         * make field-descriptor based copies of the cached objects).
086:         * </td>
087:         * </tr>
088:         * <p/>
089:         * <tr>
090:         * <td>forceProxies</td>
091:         * <td>
092:         * If <em>true</em> on materialization of cached objects, all referenced objects will
093:         * be represented by proxy objects (independent from the proxy settings in reference- or
094:         * collection-descriptor).
095:         * <br/>
096:         * <strong>Note:</strong> To use this feature all persistence capable objects have to be
097:         * interface based <strong>or</strong> the <em>ProxyFactory</em> and
098:         * <em>IndirectionHandler</em> implementation classes supporting dynamic proxy enhancement
099:         * for all classes (see OJB.properties file).
100:         * </td>
101:         * </tr>
102:         * </table>
103:         * <p/>
104:         *
105:         * @version $Id: ObjectCacheTwoLevelImpl.java,v 1.1.2.16 2005/12/21 22:24:15 tomdz Exp $
106:         */
107:        public class ObjectCacheTwoLevelImpl implements  ObjectCacheInternal,
108:                PBStateListener {
109:            private Logger log = LoggerFactory
110:                    .getLogger(ObjectCacheTwoLevelImpl.class);
111:
112:            public static final String APPLICATION_CACHE_PROP = "applicationCache";
113:            public static final String COPY_STRATEGY_PROP = "copyStrategy";
114:            public static final String FORCE_PROXIES = "forceProxies";
115:            private static final String DEF_COPY_STRATEGY = ObjectCacheTwoLevelImpl.CopyStrategyImpl.class
116:                    .getName();
117:            private static final String DEF_APP_CACHE = ObjectCacheDefaultImpl.class
118:                    .getName();
119:
120:            private HashMap sessionCache;
121:            // private boolean enabledReadCache;
122:            private int invokeCounter;
123:            private ReferenceQueue queue = new ReferenceQueue();
124:            private ObjectCacheInternal applicationCache;
125:            private CopyStrategy copyStrategy;
126:            private PersistenceBrokerImpl broker;
127:            private boolean forceProxies = false;
128:
129:            public ObjectCacheTwoLevelImpl(final PersistenceBroker broker,
130:                    Properties prop) {
131:                // TODO: Fix cast. Cast is needed to get access to ReferenceBroker class in PBImpl, see method #lookup
132:                if (broker instanceof  PersistenceBrokerImpl) {
133:                    this .broker = (PersistenceBrokerImpl) broker;
134:                } else if (broker instanceof  DelegatingPersistenceBroker) {
135:                    this .broker = (PersistenceBrokerImpl) ((DelegatingPersistenceBroker) broker)
136:                            .getInnermostDelegate();
137:                } else {
138:                    throw new RuntimeCacheException(
139:                            "Can't initialize two level cache, expect instance of"
140:                                    + PersistenceBrokerImpl.class + " or of "
141:                                    + DelegatingPersistenceBroker.class
142:                                    + " to setup application cache, but was "
143:                                    + broker);
144:                }
145:                this .sessionCache = new HashMap(100);
146:                // this.enabledReadCache = false;
147:                setupApplicationCache(this .broker, prop);
148:                // we add this instance as a permanent PBStateListener
149:                broker.addListener(this , true);
150:            }
151:
152:            /**
153:             * Returns the {@link org.apache.ojb.broker.PersistenceBroker} instance associated with
154:             * this cache instance.
155:             */
156:            public PersistenceBrokerImpl getBroker() {
157:                return broker;
158:            }
159:
160:            private void setupApplicationCache(PersistenceBrokerImpl broker,
161:                    Properties prop) {
162:                if (log.isDebugEnabled())
163:                    log.debug("Start setup application cache for broker "
164:                            + broker);
165:                if (prop == null) {
166:                    prop = new Properties();
167:                }
168:                String copyStrategyName = prop.getProperty(COPY_STRATEGY_PROP,
169:                        DEF_COPY_STRATEGY).trim();
170:                if (copyStrategyName.length() == 0) {
171:                    copyStrategyName = DEF_COPY_STRATEGY;
172:                }
173:                String applicationCacheName = prop.getProperty(
174:                        APPLICATION_CACHE_PROP, DEF_APP_CACHE).trim();
175:                if (applicationCacheName.length() == 0) {
176:                    applicationCacheName = DEF_APP_CACHE;
177:                }
178:
179:                String forceProxyValue = prop.getProperty(FORCE_PROXIES,
180:                        "false").trim();
181:                forceProxies = Boolean.valueOf(forceProxyValue).booleanValue();
182:
183:                if (forceProxies
184:                        && broker.getProxyFactory()
185:                                .interfaceRequiredForProxyGeneration()) {
186:                    log
187:                            .warn("'"
188:                                    + FORCE_PROXIES
189:                                    + "' is set to true, however a ProxyFactory implementation "
190:                                    + "["
191:                                    + broker.getProxyFactory().getClass()
192:                                            .getName()
193:                                    + "] "
194:                                    + " that requires persistent objects to implement an inteface is being used. Please ensure "
195:                                    + "that all persistent objects implement an interface, or change the ProxyFactory setting to a dynamic "
196:                                    + "proxy generator (like ProxyFactoryCGLIBImpl).");
197:                }
198:
199:                Class[] type = new Class[] { PersistenceBroker.class,
200:                        Properties.class };
201:                Object[] objects = new Object[] { broker, prop };
202:                try {
203:                    this .copyStrategy = (CopyStrategy) ClassHelper
204:                            .newInstance(copyStrategyName);
205:                    Class target = ClassHelper.getClass(applicationCacheName);
206:                    if (target.equals(ObjectCacheDefaultImpl.class)) {
207:                        // this property doesn't make sense in context of two-level cache
208:                        prop.setProperty(ObjectCacheDefaultImpl.AUTOSYNC_PROP,
209:                                "false");
210:                    }
211:                    ObjectCache temp = (ObjectCache) ClassHelper.newInstance(
212:                            target, type, objects);
213:                    if (!(temp instanceof  ObjectCacheInternal)) {
214:                        log
215:                                .warn("Specified application cache class doesn't implement '"
216:                                        + ObjectCacheInternal.class.getName()
217:                                        + "'. For best interaction only specify caches implementing the internal object cache interface.");
218:                        temp = new CacheDistributor.ObjectCacheInternalWrapper(
219:                                temp);
220:                    }
221:                    this .applicationCache = (ObjectCacheInternal) temp;
222:                } catch (Exception e) {
223:                    throw new MetadataException(
224:                            "Can't setup application cache. Specified application cache was '"
225:                                    + applicationCacheName
226:                                    + "', copy strategy was '"
227:                                    + copyStrategyName + "'", e);
228:                }
229:                if (log.isEnabledFor(Logger.INFO)) {
230:                    ToStringBuilder buf = new ToStringBuilder(this );
231:                    buf.append("copyStrategy", copyStrategyName).append(
232:                            "applicationCache", applicationCacheName);
233:                    log.info("Setup cache: " + buf.toString());
234:                }
235:            }
236:
237:            /**
238:             * Returns the application cache that this 2-level cache uses.
239:             * 
240:             * @return The application cache
241:             */
242:            public ObjectCacheInternal getApplicationCache() {
243:                return applicationCache;
244:            }
245:
246:            private Object lookupFromApplicationCache(Identity oid) {
247:                Object result = null;
248:                Object obj = getApplicationCache().lookup(oid);
249:                if (obj != null) {
250:                    result = copyStrategy.read(broker, obj);
251:                }
252:                return result;
253:            }
254:
255:            private boolean putToApplicationCache(Identity oid, Object obj,
256:                    boolean cacheIfNew) {
257:                /*
258:                we allow to reuse cached objects, so lookup the old cache object
259:                and forward it to the CopyStrategy
260:                 */
261:                Object oldTarget = null;
262:                if (!cacheIfNew) {
263:                    oldTarget = getApplicationCache().lookup(oid);
264:                }
265:                Object target = copyStrategy.write(broker, obj, oldTarget);
266:                if (cacheIfNew) {
267:                    return getApplicationCache().cacheIfNew(oid, target);
268:                } else {
269:                    getApplicationCache().cache(oid, target);
270:                    return false;
271:                }
272:            }
273:
274:            /**
275:             * Discard all session cached objects and reset the state of
276:             * this class for further usage.
277:             */
278:            public void resetSessionCache() {
279:                sessionCache.clear();
280:                invokeCounter = 0;
281:            }
282:
283:            /**
284:             * Push all cached objects of the specified type, e.g. like {@link #TYPE_WRITE} to
285:             * the application cache and reset type to the specified one.
286:             */
287:            private void pushToApplicationCache(int typeToProcess,
288:                    int typeAfterProcess) {
289:                for (Iterator iter = sessionCache.values().iterator(); iter
290:                        .hasNext();) {
291:                    CacheEntry entry = (CacheEntry) iter.next();
292:                    // if the cached object was garbage collected, nothing to do
293:                    Object result = entry.get();
294:                    if (result == null) {
295:                        if (log.isDebugEnabled())
296:                            log
297:                                    .debug("Object in session cache was gc, nothing to push to application cache");
298:                    } else {
299:                        // push all objects of the specified type to application cache
300:                        if (entry.type == typeToProcess) {
301:                            if (log.isDebugEnabled()) {
302:                                log
303:                                        .debug("Move obj from session cache --> application cache : "
304:                                                + entry.oid);
305:                            }
306:                            /*
307:                            arminw:
308:                            only cache non-proxy or real subject of materialized proxy objects
309:                             */
310:                            if (ProxyHelper.isMaterialized(result)) {
311:                                putToApplicationCache(entry.oid, ProxyHelper
312:                                        .getRealObject(result), false);
313:                                // set the new type after the object was pushed to application cache
314:                                entry.type = typeAfterProcess;
315:                            }
316:                        }
317:                    }
318:                }
319:            }
320:
321:            /**
322:             * Cache the given object. Creates a
323:             * {@link org.apache.ojb.broker.cache.ObjectCacheTwoLevelImpl.CacheEntry} and put it
324:             * to session cache. If the specified object to cache is of type {@link #TYPE_NEW_MATERIALIZED}
325:             * it will be immediately pushed to the application cache.
326:             */
327:            public void doInternalCache(Identity oid, Object obj, int type) {
328:                processQueue();
329:                // pass new materialized objects immediately to application cache
330:                if (type == TYPE_NEW_MATERIALIZED) {
331:                    boolean result = putToApplicationCache(oid, obj, true);
332:                    CacheEntry entry = new CacheEntry(oid, obj,
333:                            TYPE_CACHED_READ, queue);
334:                    if (result) {
335:                        // as current session says this object is new, put it
336:                        // in session cache
337:                        putToSessionCache(oid, entry, false);
338:                    } else {
339:                        // object is not new, but if not in session cache
340:                        // put it in
341:                        putToSessionCache(oid, entry, true);
342:                        if (log.isDebugEnabled()) {
343:                            log
344:                                    .debug("The 'new' materialized object was already in cache,"
345:                                            + " will not push it to application cache: "
346:                                            + oid);
347:                        }
348:                    }
349:                } else {
350:                    // other types of cached objects will only be put to the session
351:                    // cache.
352:                    CacheEntry entry = new CacheEntry(oid, obj, type, queue);
353:                    putToSessionCache(oid, entry, false);
354:                }
355:            }
356:
357:            /**
358:             * Lookup corresponding object from session cache or if not found from
359:             * the underlying real {@link ObjectCache} - Return <em>null</em> if no
360:             * object was found.
361:             */
362:            public Object lookup(Identity oid) {
363:                Object result = null;
364:                // 1. lookup an instance in session cache
365:                CacheEntry entry = (CacheEntry) sessionCache.get(oid);
366:                if (entry != null) {
367:                    result = entry.get();
368:                }
369:                if (result == null) {
370:                    result = lookupFromApplicationCache(oid);
371:                    // 4. if we have a match
372:                    // put object in session cache
373:                    if (result != null) {
374:                        doInternalCache(oid, result, TYPE_CACHED_READ);
375:                        materializeFullObject(result);
376:                        if (log.isDebugEnabled())
377:                            log
378:                                    .debug("Materialized object from second level cache: "
379:                                            + oid);
380:                    }
381:                }
382:                if (result != null && log.isDebugEnabled()) {
383:                    log.debug("Match for: " + oid);
384:                }
385:                return result;
386:            }
387:
388:            /**
389:             * This cache implementation cache only "flat" objects (persistent objects without any
390:             * references), so when {@link #lookup(org.apache.ojb.broker.Identity)} a cache object
391:             * it needs full materialization (assign all referenced objects) before the cache returns
392:             * the object. The materialization of the referenced objects based on the auto-XXX settings
393:             * specified in the metadata mapping.
394:             * <br/>
395:             * Override this method if needed in conjunction with a user-defined
396:             * {@link org.apache.ojb.broker.cache.ObjectCacheTwoLevelImpl.CopyStrategy}.
397:             *
398:             * @param target The "flat" object for full materialization
399:             */
400:            public void materializeFullObject(Object target) {
401:                ClassDescriptor cld = broker.getClassDescriptor(target
402:                        .getClass());
403:                // don't force, let OJB use the user settings
404:                final boolean forced = false;
405:                if (forceProxies) {
406:                    broker.getReferenceBroker().retrieveProxyReferences(target,
407:                            cld, forced);
408:                    broker.getReferenceBroker().retrieveProxyCollections(
409:                            target, cld, forced);
410:                } else {
411:                    broker.getReferenceBroker().retrieveReferences(target, cld,
412:                            forced);
413:                    broker.getReferenceBroker().retrieveCollections(target,
414:                            cld, forced);
415:                }
416:            }
417:
418:            /**
419:             * Remove the corresponding object from session AND application cache.
420:             */
421:            public void remove(Identity oid) {
422:                if (log.isDebugEnabled())
423:                    log.debug("Remove object " + oid);
424:                sessionCache.remove(oid);
425:                getApplicationCache().remove(oid);
426:            }
427:
428:            /**
429:             * Clear session cache and application cache.
430:             */
431:            public void clear() {
432:                sessionCache.clear();
433:                getApplicationCache().clear();
434:            }
435:
436:            /**
437:             * Put the specified object to session cache.
438:             */
439:            public void cache(Identity oid, Object obj) {
440:                doInternalCache(oid, obj, TYPE_UNKNOWN);
441:            }
442:
443:            public boolean cacheIfNew(Identity oid, Object obj) {
444:                boolean result = putToApplicationCache(oid, obj, true);
445:                if (result) {
446:                    CacheEntry entry = new CacheEntry(oid, obj,
447:                            TYPE_CACHED_READ, queue);
448:                    putToSessionCache(oid, entry, true);
449:                }
450:                return result;
451:            }
452:
453:            /**
454:             * Put object to session cache.
455:             *
456:             * @param oid The {@link org.apache.ojb.broker.Identity} of the object to cache
457:             * @param entry The {@link org.apache.ojb.broker.cache.ObjectCacheTwoLevelImpl.CacheEntry} of the object
458:             * @param onlyIfNew Flag, if set <em>true</em> only new objects (not already in session cache) be cached.
459:             */
460:            private void putToSessionCache(Identity oid, CacheEntry entry,
461:                    boolean onlyIfNew) {
462:                if (onlyIfNew) {
463:                    // no synchronization needed, because session cache was used per broker instance
464:                    if (!sessionCache.containsKey(oid))
465:                        sessionCache.put(oid, entry);
466:                } else {
467:                    sessionCache.put(oid, entry);
468:                }
469:            }
470:
471:            /**
472:             * Make sure that the Identity objects of garbage collected cached
473:             * objects are removed too.
474:             */
475:            private void processQueue() {
476:                CacheEntry sv;
477:                while ((sv = (CacheEntry) queue.poll()) != null) {
478:                    sessionCache.remove(sv.oid);
479:                }
480:            }
481:
482:            //------------------------------------------------------------
483:            // PBStateListener methods
484:            //------------------------------------------------------------
485:            /**
486:             * After committing the transaction push the object
487:             * from session cache ( 1st level cache) to the application cache
488:             * (2d level cache). Finally, clear the session cache.
489:             */
490:            public void afterCommit(PBStateEvent event) {
491:                if (log.isDebugEnabled())
492:                    log
493:                            .debug("afterCommit() call, push objects to application cache");
494:                if (invokeCounter != 0) {
495:                    log
496:                            .error("** Please check method calls of ObjectCacheTwoLevelImpl#enableMaterialization and"
497:                                    + " ObjectCacheTwoLevelImpl#disableMaterialization, number of calls have to be equals **");
498:                }
499:                try {
500:                    // we only push "really modified objects" to the application cache
501:                    pushToApplicationCache(TYPE_WRITE, TYPE_CACHED_READ);
502:                } finally {
503:                    resetSessionCache();
504:                }
505:            }
506:
507:            /**
508:             * Before closing the PersistenceBroker ensure that the session
509:             * cache is cleared
510:             */
511:            public void beforeClose(PBStateEvent event) {
512:                /*
513:                arminw:
514:                this is a workaround for use in managed environments. When a PB instance is used
515:                within a container a PB.close call is done when leave the container method. This close
516:                the PB handle (but the real instance is still in use) and the PB listener are notified.
517:                But the JTA tx was not committed at
518:                this point in time and the session cache should not be cleared, because the updated/new
519:                objects will be pushed to the real cache on commit call (if we clear, nothing to push).
520:                So we check if the real broker is in a local tx (in this case we are in a JTA tx and the handle
521:                is closed), if true we don't reset the session cache.
522:                 */
523:                if (!broker.isInTransaction()) {
524:                    if (log.isDebugEnabled())
525:                        log.debug("Clearing the session cache");
526:                    resetSessionCache();
527:                }
528:            }
529:
530:            /**
531:             * Before rollbacking clear the session cache (first level cache)
532:             */
533:            public void beforeRollback(PBStateEvent event) {
534:                if (log.isDebugEnabled())
535:                    log.debug("beforeRollback()");
536:                resetSessionCache();
537:            }
538:
539:            public void afterOpen(PBStateEvent event) {
540:            }
541:
542:            public void beforeBegin(PBStateEvent event) {
543:            }
544:
545:            public void afterBegin(PBStateEvent event) {
546:            }
547:
548:            public void beforeCommit(PBStateEvent event) {
549:            }
550:
551:            public void afterRollback(PBStateEvent event) {
552:            }
553:
554:            //------------------------------------------------------------
555:
556:            //-----------------------------------------------------------
557:            // inner class
558:            //-----------------------------------------------------------
559:
560:            /**
561:             * Helper class to wrap cached objects using {@link java.lang.ref.SoftReference}, which
562:             * allows to release objects when they no longer referenced within the PB session.
563:             */
564:            static final class CacheEntry extends SoftReference implements 
565:                    Serializable {
566:                private int type;
567:                private Identity oid;
568:
569:                public CacheEntry(Identity oid, Object obj, int type,
570:                        final ReferenceQueue q) {
571:                    super (obj, q);
572:                    this .oid = oid;
573:                    this .type = type;
574:                }
575:            }
576:
577:            public interface CopyStrategy {
578:                /**
579:                 * Called when an object is read from the application cache (second level cache)
580:                 * before the object is full materialized, see {@link ObjectCacheTwoLevelImpl#materializeFullObject(Object)}.
581:                 *
582:                 * @param broker The current used {@link org.apache.ojb.broker.PersistenceBroker} instance.
583:                 * @param obj The object read from the application cache.
584:                 * @return A copy of the object.
585:                 */
586:                public Object read(PersistenceBroker broker, Object obj);
587:
588:                /**
589:                 * Called before an object is written to the application cache (second level cache).
590:                 *
591:                 * @param broker The current used {@link org.apache.ojb.broker.PersistenceBroker} instance.
592:                 * @param obj The object to cache in application cache.
593:                 * @param oldObject The old cache object or <em>null</em>
594:                 * @return A copy of the object to write to application cache.
595:                 */
596:                public Object write(PersistenceBroker broker, Object obj,
597:                        Object oldObject);
598:            }
599:
600:            public static class CopyStrategyImpl implements  CopyStrategy {
601:                static final String CLASS_NAME_STR = "ojbClassName11";
602:
603:                public CopyStrategyImpl() {
604:                }
605:
606:                public Object read(PersistenceBroker broker, Object obj) {
607:                    HashMap source = (HashMap) obj;
608:                    String className = (String) source.get(CLASS_NAME_STR);
609:                    ClassDescriptor cld = broker.getDescriptorRepository()
610:                            .getDescriptorFor(className);
611:                    Object target = ClassHelper.buildNewObjectInstance(cld);
612:                    // perform main object values
613:                    FieldDescriptor[] flds = cld.getFieldDescriptor(true);
614:                    FieldDescriptor fld;
615:                    int length = flds.length;
616:                    for (int i = 0; i < length; i++) {
617:                        fld = flds[i];
618:                        // read the field value
619:                        Object value = source.get(fld.getPersistentField()
620:                                .getName());
621:                        // copy the field value
622:                        if (value != null)
623:                            value = fld.getJdbcType().getFieldType()
624:                                    .copy(value);
625:                        // now make a field-conversion to java-type, because we only
626:                        // the sql type of the field
627:                        value = fld.getFieldConversion().sqlToJava(value);
628:                        // set the copied field value in new object
629:                        fld.getPersistentField().set(target, value);
630:                    }
631:                    return target;
632:                }
633:
634:                public Object write(PersistenceBroker broker, Object obj,
635:                        Object oldObject) {
636:                    ClassDescriptor cld = broker.getClassDescriptor(obj
637:                            .getClass());
638:                    // we store field values by name in a Map
639:                    HashMap target = oldObject != null ? (HashMap) oldObject
640:                            : new HashMap();
641:                    // perform main object values
642:                    FieldDescriptor[] flds = cld.getFieldDescriptor(true);
643:                    FieldDescriptor fld;
644:                    int length = flds.length;
645:                    for (int i = 0; i < length; i++) {
646:                        fld = flds[i];
647:                        // get the value
648:                        Object value = fld.getPersistentField().get(obj);
649:                        // convert value to a supported sql type
650:                        value = fld.getFieldConversion().javaToSql(value);
651:                        // copy the sql type
652:                        value = fld.getJdbcType().getFieldType().copy(value);
653:                        target.put(fld.getPersistentField().getName(), value);
654:                    }
655:                    target.put(CLASS_NAME_STR, obj.getClass().getName());
656:                    return target;
657:                }
658:            }
659:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.