KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > oracle > toplink > essentials > platform > server > ServerPlatformBase


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the "License"). You may not use this file except
5  * in compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * glassfish/bootstrap/legal/CDDLv1.0.txt or
9  * https://glassfish.dev.java.net/public/CDDLv1.0.html.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * HEADER in each file and include the License file at
15  * glassfish/bootstrap/legal/CDDLv1.0.txt. If applicable,
16  * add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your
18  * own identifying information: Portions Copyright [yyyy]
19  * [name of copyright owner]
20  */

21 // Copyright (c) 1998, 2006, Oracle. All rights reserved.
22
package oracle.toplink.essentials.platform.server;
23
24 import java.security.AccessController JavaDoc;
25 import java.security.PrivilegedActionException JavaDoc;
26
27 import oracle.toplink.essentials.exceptions.ValidationException;
28 import oracle.toplink.essentials.internal.sessions.DatabaseSessionImpl;
29 import oracle.toplink.essentials.sessions.ExternalTransactionController;
30 import oracle.toplink.essentials.internal.localization.ToStringLocalization;
31 import oracle.toplink.essentials.logging.AbstractSessionLog;
32 import oracle.toplink.essentials.logging.SessionLog;
33 import oracle.toplink.essentials.internal.security.PrivilegedAccessHelper;
34 import oracle.toplink.essentials.internal.security.PrivilegedNewInstanceFromClass;
35 import oracle.toplink.essentials.internal.databaseaccess.Platform;
36
37 /**
38  * Implementation of oracle.toplink.essentials.platform.server.ServerPlatform
39  *
40  * PUBLIC:
41  *
42  * This is the abstract superclass of all platforms for all servers. Each DatabaseSession
43  * contains an instance of the receiver, to help the DatabaseSession determine:
44  *
45  * - Which external transaction controller to use
46  * - Whether or not to enable JTA (external transaction control)
47  * - How to register/unregister for runtime services (JMX/MBean)
48  * - Whether or not to enable runtime services
49  * - How to launch container Threads
50  *
51  * Subclasses already exist to provide configurations for Oc4J, WebLogic, and WebSphere.
52  *
53  * If the user wants a different external transaction controller class or
54  * to provide some different behaviour than the provided ServerPlatform(s), we recommend
55  * subclassing oracle.toplink.essentials.platform.server.ServerPlatformBase (or a subclass),
56  * and overriding:
57  *
58  * ServerPlatformBase.getExternalTransactionControllerClass()
59  * ServerPlatformBase.registerMBean()
60  * ServerPlatformBase.unregisterMBean()
61  *
62  * for the desired behaviour.
63  *
64  * @see oracle.toplink.essentials.platform.server.ServerPlatformBase
65  *
66  * public API:
67  *
68  * String getServerNameAndVersion()
69  */

70 public abstract class ServerPlatformBase implements ServerPlatform {
71
72     /**
73      * externalTransactionControllerClass: This is a user-specifiable class defining the class
74      * of external transaction controller to be set into the DatabaseSession
75      */

76     protected Class JavaDoc externalTransactionControllerClass;
77     
78     /**
79      * INTERNAL:
80      * isRuntimeServicesEnabled: Determines if the JMX Runtime Services will be deployed at runtime
81      */

82     private boolean isRuntimeServicesEnabled;
83
84     /**
85      * INTERNAL:
86      * isJTAEnabled: Determines if the external transaction controller will be populated into the DatabaseSession
87      * at runtime
88      */

89     private boolean isJTAEnabled;
90
91     /**
92      * INTERNAL:
93      * isCMP: true if the container created the server platform, because we're configured
94      * for CMP.
95      */

96     private boolean isCMP;
97     
98     /**
99      * INTERNAL:
100      * databaseSession: The instance of DatabaseSession that I am helping.
101      */

102     private DatabaseSessionImpl databaseSession;
103
104     /**
105      * INTERNAL:
106      * Default Constructor: Initialize so that runtime services and JTA are enabled. Set the DatabaseSession that I
107      * will be helping.
108      */

109     public ServerPlatformBase(DatabaseSessionImpl newDatabaseSession) {
110         this.isRuntimeServicesEnabled = true;
111         this.isJTAEnabled = true;
112         this.databaseSession = newDatabaseSession;
113         this.setIsCMP(false);
114     }
115
116     /**
117      * INTERNAL: getDatabaseSession(): Answer the instance of DatabaseSession the receiver is helping.
118      *
119      * @return DatabaseSession databaseSession
120      */

121     public DatabaseSessionImpl getDatabaseSession() {
122         return this.databaseSession;
123     }
124
125     /**
126      * PUBLIC: getServerNameAndVersion(): Talk to the relevant server class library, and get the server name
127      * and version
128      *
129      * Default is "unknown"
130      *
131      * @return String serverNameAndVersion
132      */

133     public String JavaDoc getServerNameAndVersion() {
134         return ToStringLocalization.buildMessage("unknown");
135     }
136
137     /**
138      * INTERNAL: getModuleName(): Answer the name of the module (jar name) that my session
139        * is associated with.
140        * Answer "unknown" if there is no module name available.
141        *
142        * Default behaviour is to return "unknown".
143      *
144      * @return String moduleName
145      */

146     public String JavaDoc getModuleName() {
147         return "unknown";
148     }
149
150     /**
151      * INTERNAL: getExternalTransactionControllerClass(): Answer the class of external transaction controller to use
152      * For this server platform. This is read-only.
153      *
154        * If the user wants a different external transaction controller class than the provided ServerPlatform(s),
155        * we recommend subclassing oracle.toplink.essentials.platform.server.ServerPlatformBase (or a subclass),
156        * and overriding:
157        *
158        * ServerPlatformBase.getExternalTransactionControllerClass()
159        *
160        * for the desired behaviour.
161      *
162      * @return Class externalTransactionControllerClass
163      *
164      * @see oracle.toplink.essentials.transaction.JTATransactionController
165      * @see #isJTAEnabled()
166      * @see #disableJTA()
167      */

168     public abstract Class JavaDoc getExternalTransactionControllerClass();
169
170     /**
171      * INTERNAL: setExternalTransactionControllerClass(Class newClass): Set the class of external
172      * transaction controller to use in the DatabaseSession.
173      * This is defined by the user via the sessions.xml.
174      *
175      * @see oracle.toplink.essentials.transaction.JTATransactionController
176      * @see #isJTAEnabled()
177      * @see #disableJTA()
178      * @see #initializeExternalTransactionController()
179      */

180     public void setExternalTransactionControllerClass(Class JavaDoc newClass) {
181         this.externalTransactionControllerClass = newClass;
182     }
183     
184     /**
185      * INTERNAL: initializeExternalTransactionController(): Populate the DatabaseSession's
186      * external transaction controller with an instance of my transaction controller class.
187      *
188      * To change the external transaction controller class, we recommend creating a subclass of
189        * ServerPlatformBase, and overriding getExternalTransactionControllerClass().
190        *
191        * @see ServerPlatformBase
192      *
193      * @return void
194      *
195      */

196     public void initializeExternalTransactionController() {
197         this.ensureNotLoggedIn();
198
199         //BUG 3975114: Even if JTA is disabled, override if we're in CMP
200
//JTA must never be disable during CMP (WLS/Oc4j)
201
if (!isJTAEnabled() && !isCMP()) {
202             return;
203         }
204         //BUG 3975114: display a warning if JTA is disabled and we're in CMP
205
if (!isJTAEnabled() && isCMP()) {
206             AbstractSessionLog.getLog().warning("jta_cannot_be_disabled_in_cmp");
207         }
208
209         //check if the transaction controller class is overridden by a preLogin or equivalent,
210
//or if the transaction controller was already defined, in which case they should have written
211
//a subclass. Show a warning
212
try {
213             if (getDatabaseSession().getExternalTransactionController() != null) {
214                 this.externalTransactionControllerNotNullWarning();
215                 return;
216             }
217             ExternalTransactionController controller = null;
218             if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
219                 try {
220                     controller = (ExternalTransactionController)AccessController.doPrivileged(new PrivilegedNewInstanceFromClass(this.getExternalTransactionControllerClass()));
221                 } catch (PrivilegedActionException JavaDoc exception) {
222                     Exception JavaDoc throwableException = exception.getException();
223                     if (throwableException instanceof InstantiationException JavaDoc) {
224                         throw ValidationException.cannotCreateExternalTransactionController(getExternalTransactionControllerClass().getName());
225                     } else {
226                         throw ValidationException.cannotCreateExternalTransactionController(getExternalTransactionControllerClass().getName());
227                     }
228                 }
229             } else {
230                 controller = (ExternalTransactionController)PrivilegedAccessHelper.newInstanceFromClass(this.getExternalTransactionControllerClass());
231             }
232             getDatabaseSession().setExternalTransactionController(controller);
233         } catch (InstantiationException JavaDoc instantiationException) {
234             throw ValidationException.cannotCreateExternalTransactionController(getExternalTransactionControllerClass().getName());
235         } catch (IllegalAccessException JavaDoc illegalAccessException) {
236             throw ValidationException.cannotCreateExternalTransactionController(getExternalTransactionControllerClass().getName());
237         }
238     }
239
240     /**
241      * INTERNAL: externalTransactionControllerNotNullWarning():
242      * When the external transaction controller is being initialized, we warn the developer
243      * if they have already defined the external transaction controller in some way other
244      * than subclassing ServerPlatformBase.
245      *
246      * @see #getExternalTransactionControllerClass()
247      */

248     protected void externalTransactionControllerNotNullWarning() {
249         getDatabaseSession().warning("External_transaction_controller_not_defined_by_server_platform", SessionLog.EJB);
250     }
251
252     /**
253      * INTERNAL: isJTAEnabled(): Answer true if the DatabaseSession's external transaction controller class will
254      * be populated with my transaction controller class at runtime. If the transaction controller class is
255      * overridden in the DatabaseSession, my transaction controller class will be ignored.
256      *
257      * Answer true if TopLink will be configured to register for callbacks for beforeCompletion and afterCompletion.
258      *
259      * @return boolean isJTAEnabled
260      * @see #getExternalTransactionControllerClass()
261      * @see #disableJTA()
262      */

263     public boolean isJTAEnabled() {
264         return this.isJTAEnabled;
265     }
266
267     /**
268      * INTERNAL: disableJTA(): Configure the receiver such that my external transaction controller class will
269      * be ignored, and will NOT be used to populate DatabaseSession's external transaction controller class
270      * at runtime.
271        *
272        * TopLink will NOT be configured to register for callbacks for beforeCompletion and afterCompletion.
273      *
274      * @return void
275      * @see #getExternalTransactionControllerClass()
276      * @see #isJTAEnabled()
277      */

278     public void disableJTA() {
279         this.ensureNotLoggedIn();
280         this.isJTAEnabled = false;
281     }
282
283     /**
284      * INTERNAL: isRuntimeServicesEnabled(): Answer true if the JMX/MBean providing runtime services for
285      * the receiver's DatabaseSession will be deployed at runtime.
286      *
287      * @return boolean isRuntimeServicesEnabled
288      * @see #disableRuntimeServices()
289      */

290     public boolean isRuntimeServicesEnabled() {
291         return this.isRuntimeServicesEnabled;
292     }
293
294     /**
295      * INTERNAL: disableRuntimeServices(): Configure the receiver such that no JMX/MBean will be registered
296      * to provide runtime services for my DatabaseSession at runtime.
297      *
298      * @return void
299      * @see #isRuntimeServicesEnabled()
300      */

301     public void disableRuntimeServices() {
302         this.ensureNotLoggedIn();
303         this.isRuntimeServicesEnabled = false;
304     }
305
306     /**
307      * INTERNAL: registerMBean(): Create and deploy the JMX MBean to provide runtime services for my
308      * databaseSession.
309        *
310        * Default is to do nothing.
311      *
312      * @return void
313      * @see #isRuntimeServicesEnabled()
314      * @see #disableRuntimeServices()
315      * @see #unregisterMBean()
316      */

317     public void registerMBean() {
318         if (!this.isRuntimeServicesEnabled()) {
319             return;
320         }
321         this.serverSpecificRegisterMBean();
322     }
323
324     /**
325      * INTERNAL: serverSpecificRegisterMBean(): Server specific implementation of the
326      * creation and deployment of the JMX MBean to provide runtime services for my
327      * databaseSession.
328      *
329      * Default is to do nothing. This should be subclassed if required.
330      *
331      * @return void
332      * @see #isRuntimeServicesEnabled()
333      * @see #disableRuntimeServices()
334      * @see #registerMBean()
335      */

336     public void serverSpecificRegisterMBean() {
337     }
338
339     /**
340      * INTERNAL: unregisterMBean(): Unregister the JMX MBean that was providing runtime services for my
341      * databaseSession.
342      *
343      * @return void
344      * @see #isRuntimeServicesEnabled()
345      * @see #disableRuntimeServices()
346      * @see #registerMBean()
347      */

348     public void unregisterMBean() {
349         if (!this.isRuntimeServicesEnabled()) {
350             return;
351         }
352         this.serverSpecificUnregisterMBean();
353     }
354
355     /**
356      * INTERNAL: This method is used to unwrap the oracle connection wrapped by
357      * the application server. TopLink needs this unwrapped connection for certain
358      * Oracle Specific support. (ie TIMESTAMPTZ)
359      * This is added as a workaround for bug 4460996
360      */

361     public java.sql.Connection JavaDoc unwrapOracleConnection(Platform platform, java.sql.Connection JavaDoc connection){
362         try {
363             return connection.getMetaData().getConnection();
364         } catch (java.sql.SQLException JavaDoc e){
365             ((DatabaseSessionImpl)getDatabaseSession()).log(SessionLog.WARNING, SessionLog.CONNECTION, "cannot_unwrap_connection", e);
366             return connection;
367         }
368     }
369     
370
371     /**
372      * INTERNAL: serverSpecificUnregisterMBean(): Server specific implementation of the
373      * unregistration of the JMX MBean from its server.
374      *
375      * Default is to do nothing. This should be subclassed if required.
376      *
377      * @return void
378      * @see #isRuntimeServicesEnabled()
379      * @see #disableRuntimeServices()
380      */

381     public void serverSpecificUnregisterMBean() {
382     }
383
384     /**
385      * INTERNAL: launchContainerRunnable(Runnable runnable): Use the container library to
386      * start the provided Runnable.
387      *
388      * Default behaviour is to use Thread(runnable).start()
389      *
390      * @param Runnable runnable: the instance of runnable to be "started"
391      * @return void
392      */

393     public void launchContainerRunnable(Runnable JavaDoc runnable) {
394         new Thread JavaDoc(runnable).start();
395     }
396
397     /**
398      * INTERNAL: Make sure that the DatabaseSession has not logged in yet.
399        * Throw a ValidationException if we have.
400      *
401      */

402     protected void ensureNotLoggedIn() {
403         //RCM: Allow for a null database session
404
if (getDatabaseSession() == null) {
405             return;
406         }
407         if (getDatabaseSession().isConnected()) {
408             throw ValidationException.serverPlatformIsReadOnlyAfterLogin(this.getClass().getName());
409         }
410     }
411
412     /**
413      * INTERNAL: getServerLog(): Return the ServerLog for this platform
414      *
415      * Return the default ServerLog in the base
416      *
417      * @return oracle.toplink.essentials.logging.SessionLog
418      */

419     public oracle.toplink.essentials.logging.SessionLog getServerLog() {
420         return new ServerLog();
421     }
422     
423     /**
424      * INTERNAL: isCMP(): Answer true if we're in the context of CMP (i.e. the container created me)
425      *
426      * @return boolean
427      */

428     public boolean isCMP() {
429         return isCMP;
430     }
431
432     /**
433      * INTERNAL: setIsCMP(boolean): Define whether or not we're in the context of CMP (i.e. the container created me)
434      *
435      * @return void
436      */

437     public void setIsCMP(boolean isThisCMP) {
438         isCMP = isThisCMP;
439     }
440
441 }
442
Popular Tags