KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > orm > toplink > AbstractSessionFactory


1 /*
2  * Copyright 2002-2005 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.springframework.orm.toplink;
18
19 import java.lang.reflect.InvocationHandler JavaDoc;
20 import java.lang.reflect.InvocationTargetException JavaDoc;
21 import java.lang.reflect.Method JavaDoc;
22 import java.lang.reflect.Proxy JavaDoc;
23
24 import oracle.toplink.exceptions.TopLinkException;
25 import oracle.toplink.sessions.Session;
26 import oracle.toplink.sessions.UnitOfWork;
27 import org.apache.commons.logging.Log;
28 import org.apache.commons.logging.LogFactory;
29
30 /**
31  * Abstract SessionFactory implementation that creates proxies for
32  * "managed" client Sessions and transaction-aware Session references.
33  *
34  * <p>Delegates to two template methods:
35  *
36  * @author Juergen Hoeller
37  * @since 1.2.6
38  * @see #getMasterSession()
39  * @see #createClientSession()
40  */

41 public abstract class AbstractSessionFactory implements SessionFactory {
42
43     /** Logger available to subclasses */
44     protected final Log logger = LogFactory.getLog(getClass());
45
46
47     /**
48      * Create a plain client Session for this factory's master Session.
49      * @see #createClientSession()
50      */

51     public Session createSession() throws TopLinkException {
52         logger.debug("Creating TopLink client Session");
53         return createClientSession();
54     }
55
56     /**
57      * Create a "managed" client Session reference for an underlying
58      * client Session created for this factory.
59      * @see #createClientSession()
60      */

61     public Session createManagedClientSession() throws TopLinkException {
62         logger.debug("Creating managed TopLink client Session");
63         return (Session) Proxy.newProxyInstance(
64                 getClass().getClassLoader(), new Class JavaDoc[] {Session.class},
65                 new ManagedClientInvocationHandler(createClientSession()));
66     }
67
68     /**
69      * Create a transaction-aware Session reference for this factory's master Session,
70      * expecting transactions to be registered for this SessionFactory.
71      * @see #getMasterSession()
72      * @see oracle.toplink.sessions.Session#getActiveSession()
73      * @see oracle.toplink.sessions.Session#getActiveUnitOfWork()
74      */

75     public Session createTransactionAwareSession() throws TopLinkException {
76         logger.debug("Creating transaction-aware TopLink Session");
77         return createTransactionAwareSession(this);
78     }
79
80     /**
81      * Create a transaction-aware Session reference for this factory's master Session,
82      * expecting transactions to be registered for the given SessionFactory.
83      * <p>This method is public to allow custom SessionFactory facades to access
84      * it directly, if necessary.
85      * @param sessionFactory the SessionFactory that transactions
86      * are expected to be registered for
87      * @see #getMasterSession()
88      * @see oracle.toplink.sessions.Session#getActiveSession()
89      * @see oracle.toplink.sessions.Session#getActiveUnitOfWork()
90      */

91     public Session createTransactionAwareSession(SessionFactory sessionFactory) throws TopLinkException {
92         return (Session) Proxy.newProxyInstance(
93                 getClass().getClassLoader(), new Class JavaDoc[] {Session.class},
94                 new TransactionAwareInvocationHandler(sessionFactory, getMasterSession()));
95     }
96
97
98     /**
99      * Return this factory's "master" Session.
100      * For example, a TopLink ServerSession.
101      * <p>Used for creating transaction-aware Session reference.
102      */

103     protected abstract Session getMasterSession();
104
105     /**
106      * Create a new client Session for this factory's master Session.
107      * For example, a TopLink ClientSession.
108      * <p>Used for creating plain Sessions and "managed" client Sessions.
109      * @throws TopLinkException if creation of a client Session failed
110      */

111     protected abstract Session createClientSession() throws TopLinkException;
112
113
114     /**
115      * Invocation handler that decorates a client Session with an "active"
116      * UnitOfWork. For use in situations where Spring's TopLinkTransactionManager
117      * requires a "managed" thread-safe TopLink Session.
118      */

119     private static class ManagedClientInvocationHandler implements InvocationHandler JavaDoc {
120
121         private final Session target;
122
123         private final UnitOfWork uow;
124
125         public ManagedClientInvocationHandler(Session target) {
126             this.target = target;
127             this.uow = this.target.acquireUnitOfWork();
128         }
129
130         public Object JavaDoc invoke(Object JavaDoc proxy, Method JavaDoc method, Object JavaDoc[] args) throws Throwable JavaDoc {
131             if (method.getName().equals("getActiveSession")) {
132                 return this.target;
133             }
134             else if (method.getName().equals("getActiveUnitOfWork")) {
135                 return this.uow;
136             }
137             else if (method.getName().equals("release")) {
138                 this.uow.release();
139                 this.target.release();
140             }
141             else if (method.getName().equals("equals")) {
142                 // Only consider equal when proxies are identical.
143
return (proxy == args[0] ? Boolean.TRUE : Boolean.FALSE);
144             }
145             else if (method.getName().equals("hashCode")) {
146                 // Use hashCode of SessionFactory proxy.
147
return new Integer JavaDoc(hashCode());
148             }
149
150             // Invoke method on target Session.
151
try {
152                 return method.invoke(this.target, args);
153             }
154             catch (InvocationTargetException JavaDoc ex) {
155                 throw ex.getTargetException();
156             }
157         }
158     }
159
160
161     /**
162      * Invocation handler that delegates <code>getActiveSession</code> calls
163      * to SessionFactoryUtils, for being aware of thread-bound transactions.
164      */

165     private static class TransactionAwareInvocationHandler implements InvocationHandler JavaDoc {
166
167         private final SessionFactory sessionFactory;
168
169         private final Session target;
170
171         public TransactionAwareInvocationHandler(SessionFactory sessionFactory, Session target) {
172             this.sessionFactory = sessionFactory;
173             this.target = target;
174         }
175
176         public Object JavaDoc invoke(Object JavaDoc proxy, Method JavaDoc method, Object JavaDoc[] args) throws Throwable JavaDoc {
177             // Invocation on Session interface coming in...
178

179             if (method.getName().equals("getActiveSession")) {
180                 // Handle getActiveSession method: return transactional Session, if any.
181
try {
182                     return SessionFactoryUtils.doGetSession(this.sessionFactory, false);
183                 }
184                 catch (IllegalStateException JavaDoc ex) {
185                     // getActiveSession is supposed to return the Session itself if no active one found.
186
return this.target;
187                 }
188             }
189             else if (method.getName().equals("getActiveUnitOfWork")) {
190                 // Handle getActiveUnitOfWork method: return transactional UnitOfWork, if any.
191
try {
192                     return SessionFactoryUtils.doGetSession(this.sessionFactory, false).getActiveUnitOfWork();
193                 }
194                 catch (IllegalStateException JavaDoc ex) {
195                     // getActiveUnitOfWork is supposed to return null if no active one found.
196
return null;
197                 }
198             }
199             else if (method.getName().equals("equals")) {
200                 // Only consider equal when proxies are identical.
201
return (proxy == args[0] ? Boolean.TRUE : Boolean.FALSE);
202             }
203             else if (method.getName().equals("hashCode")) {
204                 // Use hashCode of SessionFactory proxy.
205
return new Integer JavaDoc(hashCode());
206             }
207
208             // Invoke method on target Session.
209
try {
210                 return method.invoke(this.target, args);
211             }
212             catch (InvocationTargetException JavaDoc ex) {
213                 throw ex.getTargetException();
214             }
215         }
216     }
217
218 }
219
Popular Tags