Source Code Cross Referenced for AbstractIndirectionHandler.java in  » Database-ORM » db-ojb » org » apache » ojb » broker » core » proxy » 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.core.proxy 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        package org.apache.ojb.broker.core.proxy;
002:
003:        /* Copyright 2002-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.lang.reflect.Method;
019:        import java.util.ArrayList;
020:
021:        import org.apache.ojb.broker.Identity;
022:        import org.apache.ojb.broker.OJBRuntimeException;
023:        import org.apache.ojb.broker.PBFactoryException;
024:        import org.apache.ojb.broker.PBKey;
025:        import org.apache.ojb.broker.PersistenceBrokerException;
026:        import org.apache.ojb.broker.PersistenceBrokerFactory;
027:        import org.apache.ojb.broker.PersistenceBrokerInternal;
028:        import org.apache.ojb.broker.core.PersistenceBrokerThreadMapping;
029:        import org.apache.ojb.broker.util.logging.LoggerFactory;
030:
031:        /**
032:         * Abstract implementation for the indirection handler used by ojb's proxies.
033:         *
034:         * @version $Id$
035:         */
036:        public abstract class AbstractIndirectionHandler implements 
037:                IndirectionHandler {
038:            static final long serialVersionUID = -1993879565033755826L;
039:
040:            /** The key for acquiring the above broker */
041:            private PBKey _brokerKey;
042:            /** The real subject which this is hidden by the proxy */
043:            private Object _realSubject = null;
044:            /** Represents the identity of the real subject. When the real subject is not
045:             *  yet materialized, it can be loaded from the underlying db by this identity object */
046:            private Identity _id = null;
047:            /** The materialization listeners */
048:            private transient ArrayList _listeners;
049:
050:            /**
051:             * Creates a new indirection handler for the indicated object.
052:             *
053:             * @param brokerKey
054:             *            The key of the persistence broker
055:             * @param id
056:             *            The identity of the subject
057:             */
058:            public AbstractIndirectionHandler(PBKey brokerKey, Identity id) {
059:                setBrokerKey(brokerKey);
060:                setIdentity(id);
061:            }
062:
063:            /**
064:             * Returns the identity of the subject.
065:             *
066:             * @return The identity
067:             */
068:            public Identity getIdentity() {
069:                return _id;
070:            }
071:
072:            /**
073:             * Sets the identity of the subject of this indirection handler.
074:             *
075:             * @param identity
076:             */
077:            protected void setIdentity(Identity identity) {
078:                _id = identity;
079:            }
080:
081:            /**
082:             * Returns the key of the persistence broker used by this indirection
083:             * handler.
084:             *
085:             * @return The broker key
086:             */
087:            public PBKey getBrokerKey() {
088:                return _brokerKey;
089:            }
090:
091:            /**
092:             * Sets the key of the persistence broker used by this indirection handler.
093:             *
094:             * @param brokerKey
095:             *            The broker key
096:             */
097:            protected void setBrokerKey(PBKey brokerKey) {
098:                _brokerKey = brokerKey;
099:            }
100:
101:            /**
102:             * Adds a materialization listener.
103:             *
104:             * @param listener
105:             *            The listener to add
106:             */
107:            public synchronized void addListener(
108:                    MaterializationListener listener) {
109:                if (_listeners == null) {
110:                    _listeners = new ArrayList();
111:                }
112:                // add listener only once
113:                if (!_listeners.contains(listener)) {
114:                    _listeners.add(listener);
115:                }
116:            }
117:
118:            /**
119:             * Removes a materialization listener.
120:             *
121:             * @param listener
122:             *            The listener to remove
123:             */
124:            public synchronized void removeListener(
125:                    MaterializationListener listener) {
126:                if (_listeners != null) {
127:                    _listeners.remove(listener);
128:                }
129:            }
130:
131:            /**
132:             * Calls beforeMaterialization on all registered listeners in the reverse
133:             * order of registration.
134:             */
135:            protected void beforeMaterialization() {
136:                if (_listeners != null) {
137:                    MaterializationListener listener;
138:
139:                    for (int idx = _listeners.size() - 1; idx >= 0; idx--) {
140:                        listener = (MaterializationListener) _listeners
141:                                .get(idx);
142:                        listener.beforeMaterialization(this , _id);
143:                    }
144:                }
145:            }
146:
147:            /**
148:             * Calls afterMaterialization on all registered listeners in the reverse
149:             * order of registration.
150:             */
151:            protected void afterMaterialization() {
152:                if (_listeners != null) {
153:                    MaterializationListener listener;
154:
155:                    // listeners may remove themselves during the afterMaterialization
156:                    // callback.
157:                    // thus we must iterate through the listeners vector from back to
158:                    // front
159:                    // to avoid index problems.
160:                    for (int idx = _listeners.size() - 1; idx >= 0; idx--) {
161:                        listener = (MaterializationListener) _listeners
162:                                .get(idx);
163:                        listener.afterMaterialization(this , _realSubject);
164:                    }
165:                }
166:            }
167:
168:            /**
169:             * Gets the persistence broker used by this indirection handler.
170:             * If no PBKey is available a runtime exception will be thrown.
171:             *
172:             * @return a PersistenceBroker
173:             */
174:            protected TemporaryBrokerWrapper getBroker()
175:                    throws PBFactoryException {
176:                PersistenceBrokerInternal broker;
177:                boolean needsClose = false;
178:
179:                if (getBrokerKey() == null) {
180:                    /*
181:                    arminw:
182:                    if no PBKey is set we throw an exception, because we don't
183:                    know which PB (connection) should be used.
184:                     */
185:                    throw new OJBRuntimeException(
186:                            "Can't find associated PBKey. Need PBKey to obtain a valid"
187:                                    + "PersistenceBroker instance from intern resources.");
188:                }
189:                // first try to use the current threaded broker to avoid blocking
190:                broker = PersistenceBrokerThreadMapping
191:                        .currentPersistenceBroker(getBrokerKey());
192:                // current broker not found, create a intern new one
193:                if ((broker == null) || broker.isClosed()) {
194:                    broker = (PersistenceBrokerInternal) PersistenceBrokerFactory
195:                            .createPersistenceBroker(getBrokerKey());
196:                    /** Specifies whether we obtained a fresh broker which we have to close after we used it */
197:                    needsClose = true;
198:                }
199:                return new TemporaryBrokerWrapper(broker, needsClose);
200:            }
201:
202:            /**
203:             * [Copied from {@link java.lang.reflect.InvocationHandler}]:<br/>
204:             * Processes a method invocation on a proxy instance and returns the result.
205:             * This method will be invoked on an invocation handler when a method is
206:             * invoked on a proxy instance that it is associated with.
207:             *
208:             * @param proxy
209:             *            The proxy instance that the method was invoked on
210:             *
211:             * @param method
212:             *            The <code>Method</code> instance corresponding to the
213:             *            interface method invoked on the proxy instance. The declaring
214:             *            class of the <code>Method</code> object will be the
215:             *            interface that the method was declared in, which may be a
216:             *            superinterface of the proxy interface that the proxy class
217:             *            inherits the method through.
218:             *
219:             * @param args
220:             *            An array of objects containing the values of the arguments
221:             *            passed in the method invocation on the proxy instance, or
222:             *            <code>null</code> if interface method takes no arguments.
223:             *            Arguments of primitive types are wrapped in instances of the
224:             *            appropriate primitive wrapper class, such as
225:             *            <code>java.lang.Integer</code> or
226:             *            <code>java.lang.Boolean</code>.
227:             *
228:             * @return The value to return from the method invocation on the proxy
229:             *         instance. If the declared return type of the interface method is
230:             *         a primitive type, then the value returned by this method must be
231:             *         an instance of the corresponding primitive wrapper class;
232:             *         otherwise, it must be a type assignable to the declared return
233:             *         type. If the value returned by this method is <code>null</code>
234:             *         and the interface method's return type is primitive, then a
235:             *         <code>NullPointerException</code> will be thrown by the method
236:             *         invocation on the proxy instance. If the value returned by this
237:             *         method is otherwise not compatible with the interface method's
238:             *         declared return type as described above, a
239:             *         <code>ClassCastException</code> will be thrown by the method
240:             *         invocation on the proxy instance.
241:             *
242:             * @throws PersistenceBrokerException
243:             *             The exception to throw from the method invocation on the
244:             *             proxy instance. The exception's type must be assignable
245:             *             either to any of the exception types declared in the
246:             *             <code>throws</code> clause of the interface method or to
247:             *             the unchecked exception types
248:             *             <code>java.lang.RuntimeException</code> or
249:             *             <code>java.lang.Error</code>. If a checked exception is
250:             *             thrown by this method that is not assignable to any of the
251:             *             exception types declared in the <code>throws</code> clause
252:             *             of the interface method, then an
253:             *             {@link java.lang.reflect.UndeclaredThrowableException}
254:             *             containing the exception that was thrown by this method will
255:             *             be thrown by the method invocation on the proxy instance.
256:             *
257:             * @see java.lang.reflect.UndeclaredThrowableException
258:             */
259:            public Object invoke(Object proxy, Method method, Object[] args) {
260:                Object subject;
261:                String methodName = method.getName();
262:
263:                try {
264:                    // [andrew clute]
265:                    // short-circuit any calls to a finalize methjod if the subject
266:                    // has not been retrieved yet
267:                    if ("finalize".equals(methodName) && _realSubject == null) {
268:                        return null;
269:                    }
270:
271:                    // [andrew clute]
272:                    // When trying to serialize a proxy, we need to determine how to
273:                    // handle it
274:                    if ("writeReplace".equals(methodName)) {
275:                        if (_realSubject == null) {
276:                            // Unmaterialized proxies are replaced by simple
277:                            // serializable
278:                            // objects that can be unserialized without classloader
279:                            // issues
280:                            return generateSerializableProxy();
281:                        } else {
282:                            // Materiliazed objects should be passed back as they might
283:                            // have
284:                            // been mutated
285:                            return getRealSubject();
286:                        }
287:                    }
288:
289:                    // [tomdz]
290:                    // Previously the hashcode of the identity would have been used
291:                    // but this requires a compatible hashCode implementation in the
292:                    // proxied object (which is somewhat unlikely, even the default
293:                    // hashCode implementation does not fulfill this requirement)
294:                    // for those that require this behavior, a custom indirection
295:                    // handler can be used, or the hashCode of the identity
296:                    /*
297:                     * if ("hashCode".equals(methodName)) { return new
298:                     * Integer(_id.hashCode()); }
299:                     */
300:
301:                    // [tomdz]
302:                    // this would handle toString differently for non-materialized
303:                    // proxies
304:                    // (to avoid materialization due to logging)
305:                    // however toString should be a normal business method which
306:                    // materializes the proxy
307:                    // if this is not desired, then the ProxyHandler.toString(Object)
308:                    // method
309:                    // should be used instead (e.g. for logging within OJB)
310:                    /*
311:                     * if ((realSubject == null) && "toString".equals(methodName)) {
312:                     * return "unmaterialized proxy for " + id; }
313:                     */
314:
315:                    // BRJ: make sure that the object to be compared is a real object
316:                    // otherwise equals may return false.
317:                    if ("equals".equals(methodName) && args[0] != null) {
318:                        TemporaryBrokerWrapper tmp = getBroker();
319:                        try {
320:                            args[0] = tmp.broker.getProxyFactory()
321:                                    .getRealObject(args[0]);
322:                        } finally {
323:                            tmp.close();
324:                        }
325:                    }
326:
327:                    if ("getIndirectionHandler".equals(methodName)
328:                            && args[0] != null) {
329:                        return this ;
330:                    }
331:
332:                    subject = getRealSubject();
333:                    return method.invoke(subject, args);
334:                    // [olegnitz] I've changed the following strange lines
335:                    // to the above one. Why was this done in such complicated way?
336:                    // Is it possible that subject doesn't implement the method's
337:                    // interface?
338:                    // Method m = subject.getClass().getMethod(method.getName(),
339:                    // method.getParameterTypes());
340:                    // return m.invoke(subject, args);
341:                } catch (Exception ex) {
342:                    throw new PersistenceBrokerException(
343:                            "Error invoking method " + method.getName(), ex);
344:                }
345:            }
346:
347:            /**
348:             * Returns the proxies real subject. The subject will be materialized if
349:             * necessary.
350:             *
351:             * @return The subject
352:             */
353:            public Object getRealSubject() throws PersistenceBrokerException {
354:                if (_realSubject == null) {
355:                    beforeMaterialization();
356:                    _realSubject = materializeSubject();
357:                    afterMaterialization();
358:                }
359:                return _realSubject;
360:            }
361:
362:            /**
363:             * [olegnitz] This looks stupid, but is really necessary for OTM: the
364:             * materialization listener replaces the real subject by its clone to ensure
365:             * transaction isolation. Is there a better way to do this?
366:             */
367:            public void setRealSubject(Object object) {
368:                _realSubject = object;
369:            }
370:
371:            /**
372:             * Retrieves the real subject from the underlying RDBMS. Override this
373:             * method if the object is to be materialized in a specific way.
374:             *
375:             * @return The real subject of the proxy
376:             */
377:            protected synchronized Object materializeSubject()
378:                    throws PersistenceBrokerException {
379:                TemporaryBrokerWrapper tmp = getBroker();
380:                try {
381:                    Object realSubject = tmp.broker.getObjectByIdentity(_id);
382:                    if (realSubject == null) {
383:                        LoggerFactory.getLogger(IndirectionHandler.class).warn(
384:                                "Can not materialize object for Identity "
385:                                        + _id + " - using PBKey "
386:                                        + getBrokerKey());
387:                    }
388:                    return realSubject;
389:                } catch (Exception ex) {
390:                    throw new PersistenceBrokerException(ex);
391:                } finally {
392:                    tmp.close();
393:                }
394:            }
395:
396:            /**
397:             * Determines whether the real subject already has been materialized.
398:             *
399:             * @return <code>true</code> if the real subject has already been loaded
400:             */
401:            public boolean alreadyMaterialized() {
402:                return _realSubject != null;
403:            }
404:
405:            /**
406:             * Generate a simple object that is serializable and placeholder for
407:             * proxies.
408:             *
409:             */
410:            private Object generateSerializableProxy() {
411:                return new OJBSerializableProxy(getIdentity()
412:                        .getObjectsRealClass(), this );
413:            }
414:
415:            //===================================================================
416:            // inner class
417:            //===================================================================
418:            /**
419:             * wrapper class for temporary used broker instances.
420:             */
421:            static final class TemporaryBrokerWrapper {
422:                /** Specifies whether we obtained a fresh broker which we have to close after we used it */
423:                boolean needsClose;
424:                PersistenceBrokerInternal broker;
425:
426:                public TemporaryBrokerWrapper(PersistenceBrokerInternal broker,
427:                        boolean needsClose) {
428:                    this .broker = broker;
429:                    this .needsClose = needsClose;
430:                }
431:
432:                /**
433:                 * Cleanup the used broker instance, it's mandatory to call
434:                 * this method after use.
435:                 */
436:                public void close() {
437:                    if (needsClose) {
438:                        broker.close();
439:                    }
440:                }
441:            }
442:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.