001: /*
002: * Enhydra Java Application Server Project
003: *
004: * The contents of this file are subject to the Enhydra Public License
005: * Version 1.1 (the "License"); you may not use this file except in
006: * compliance with the License. You may obtain a copy of the License on
007: * the Enhydra web site ( http://www.enhydra.org/ ).
008: *
009: * Software distributed under the License is distributed on an "AS IS"
010: * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
011: * the License for the specific terms governing rights and limitations
012: * under the License.
013: *
014: * The Initial Developer of the Enhydra Application Server is Lutris
015: * Technologies, Inc. The Enhydra Application Server and portions created
016: * by Lutris Technologies, Inc. are Copyright Lutris Technologies, Inc.
017: * All Rights Reserved.
018: *
019: * Contributor(s):
020: *
021: * $Id: Enhydra.java,v 1.3 2007-10-19 10:05:39 sinisa Exp $
022: *
023: * formatted with JxBeauty (c) johann.langhofer@nextra.at
024: */
025:
026: package com.lutris.appserver.server;
027:
028: import java.lang.reflect.Method;
029: import java.util.Hashtable;
030:
031: import com.lutris.appserver.server.session.SessionManager;
032: import com.lutris.appserver.server.sql.DatabaseManager;
033: import com.lutris.logging.LogChannel;
034: import com.lutris.logging.Logger;
035:
036: //import org.enhydra.dods.DODS;
037: //import org.enhydra.dods.DODSException;
038:
039: /**
040: * The Enhydra class provides static methods that allow each application
041: * to conviently get at their application object. It also provides
042: * access <P>
043: *
044: * This class implements dynamically scoped global variables, accessed
045: * via static methods. Which variable is accessed (and thus which
046: * Application object is returned) depends on the flow of control of
047: * the program before the access (the call stack). <P>
048: *
049: * Currently a hashtable keyed on the threads themselves is used to
050: * store the different Application, in Java 1.2 threads will have a field
051: * already available for storing client data. <P>
052: *
053: * Normal usage of this class is to call <CODE>register()</CODE> when
054: * a thread enters your application, then <CODE>unRegister()</CODE>
055: * when it leaves. It is very important that every <CODE>register()</CODE>
056: * is matched with an <CODE>unRegister()</CODE>, or else it will be
057: * a memory leak, threads that re-enter the application will have
058: * a stale Application (until the first <CODE>register()</CODE>), and
059: * an extra pointer to the Application will be left around, preventing
060: * garbage collection. <P>
061: *
062: * If no thread is passed in (the normal usage), the current thread is
063: * used. If your application creates new threads, these will not initially be
064: * associated with any Application. These new threads can be passed in to
065: * <CODE>register()</CODE>, to assocaiate them with an Application.
066: * You may call <CODE>register()</CODE> before calling <CODE>start()</CODE>
067: * on the thread. <P>
068: *
069: * To ensure that every <CODE>register()</CODE> is balanced with an
070: * <CODE>unRegister()</CODE>, the following code is recommended:
071: * <PRE>
072: * Enhydra.register(application);
073: * try {
074: * doSomeWork();
075: * } finally {
076: * Enhydra.unRegister();
077: * }
078: * </PRE>
079: * This will ensure that the <CODE>unRegister()</CODE> is called even if
080: * an exception is thrown, but it will not interfere with the exception
081: * processing.
082: *
083: * @version $Revision: 1.3 $
084: * @author Paul Morgan
085: * @author Andy John
086: * @since LBS1.8
087: */
088: public class Enhydra {
089: private static String DODS_CLASS_NAME_STRING = "org.enhydra.dods.DODS";
090: private static Class DodsClass;
091: private static boolean dodsThreadingIsSet = false;
092: private static boolean dodsIsSet = false;
093:
094: private static Class getDodsClass() {
095: try {
096: if (!dodsIsSet) {
097: DodsClass = Class.forName(DODS_CLASS_NAME_STRING);
098: dodsIsSet = true;
099: }
100: return DodsClass;
101: } catch (Exception e) {
102: e.printStackTrace();
103: throw new RuntimeException(e.getMessage());
104: }
105: }
106:
107: private static void InitDodsThreading() {
108: if (!dodsThreadingIsSet) {
109: DODS_setThreading(true);
110: dodsThreadingIsSet = true;
111: }
112: }
113:
114: private static void DODS_setThreading(boolean value) {
115: try {
116: Class[] ArgClassArray = new Class[] { boolean.class };
117: Object[] ArgObject = new Object[] { Boolean.valueOf("true") };
118: Method DODSMethod = getDodsClass().getDeclaredMethod(
119: "setThreading", ArgClassArray);
120: DODSMethod.invoke(getDodsClass(), ArgObject);
121: } catch (Exception e) {
122: throw new RuntimeException(e.getMessage());
123: }
124: }
125:
126: private static void DODS_register(Thread currentThread,
127: DatabaseManager dbm) {
128: try {
129: InitDodsThreading();
130: Class[] ArgClassArray = new Class[] { Thread.class,
131: DatabaseManager.class };
132: Object[] ArgObject = new Object[] { currentThread, dbm };
133: Method DODSMethod = getDodsClass().getDeclaredMethod(
134: "register", ArgClassArray);
135: DODSMethod.invoke(getDodsClass(), ArgObject);
136: } catch (Exception e) {
137: e.printStackTrace();
138: throw new RuntimeException(e.getMessage());
139: }
140: }
141:
142: private static void DODS_registerLogChannel(Thread currentThread,
143: LogChannel lc) {
144: try {
145: InitDodsThreading();
146: Class[] ArgClassArray = new Class[] { Thread.class,
147: LogChannel.class };
148: Object[] ArgObject = new Object[] { currentThread, lc };
149: Method DODSMethod = getDodsClass().getDeclaredMethod(
150: "registerLogChannel", ArgClassArray);
151: DODSMethod.invoke(getDodsClass(), ArgObject);
152: } catch (Exception e) {
153: throw new RuntimeException(e.getMessage());
154: }
155: }
156:
157: private static void DODS_unregister(Thread currentThread) {
158: try {
159: InitDodsThreading();
160:
161: Class[] ArgClassArray = new Class[] { Thread.class };
162: Object[] ArgObject = new Object[] { currentThread };
163:
164: Method DODSMethod = getDodsClass().getDeclaredMethod(
165: "unregister", ArgClassArray);
166: DODSMethod.invoke(getDodsClass(), ArgObject);
167:
168: Method DODSunregisterLogChannel = getDodsClass()
169: .getDeclaredMethod("unregisterLogChannel",
170: ArgClassArray);
171: DODSunregisterLogChannel.invoke(getDodsClass(), ArgObject);
172:
173: } catch (Exception e) {
174: throw new RuntimeException(e.getMessage());
175: }
176: }
177:
178: // dp 13.10.03 end
179:
180: // One application per thread.
181: private static Hashtable applications = new Hashtable();
182: // compliance with WEBDOCWF begin
183: private static Hashtable htAppCount = new Hashtable();
184:
185: // original line
186: //
187: // compliance with WEBDOCWF end
188:
189: // static {
190: // DODS.setThreading(true);
191: // }
192: /**
193: * Prevent instantiation
194: */
195: protected Enhydra() {
196: }
197:
198: /**
199: * Associate the given application with the current thread.
200: * After this call, calls to <CODE>getApplication()</CODE>
201: * made by this thread will return <CODE>app</CODE>.
202: * Be sure to call <CODE>unRegister()</CODE> when you are done
203: * with the thread. This must be called before the any calls to
204: * <CODE>getApplication()</CODE>.
205: *
206: * @param app The Application object to associate with the
207: * current thread. This Application will be returned by calls made
208: * by this thread to <CODE>getApplication()</CODE>.
209: */
210: public static void register(Application app) {
211: applications.put(Thread.currentThread(), app);
212: DatabaseManager databaseManager = app.getDatabaseManager();
213: if (databaseManager != null) {
214: DODS_register(Thread.currentThread(), databaseManager);
215: LogChannel channel = app.getLogChannel();
216: if (channel == null) {
217: try {
218: //DODS.configureStandardLogerChannel();
219: InitDodsThreading();
220: Method DODSMethod = getDodsClass()
221: .getDeclaredMethod(
222: "configureStandardLogerChannel",
223: new Class[] {});
224: DODSMethod.invoke(getDodsClass(), new Object[] {});
225: } catch (Exception e) {
226: throw new RuntimeException(e.getMessage());
227: }
228: }
229: DODS_registerLogChannel(Thread.currentThread(), channel);
230: }
231: }
232:
233: /**
234: * Associate the given application with the given thread.
235: * After this call, calls to <CODE>getApplication()</CODE>
236: * made by the specified thread thread will return <CODE>app</CODE>.
237: * Be sure to call <CODE>unRegister()</CODE> when you are done
238: * with the thread. This must be called before the thread calls
239: * <CODE>getApplication()</CODE>.
240: *
241: * @param thread
242: * the thread to associate with <CODE>app</CODE>.
243: * @param app
244: * the Application object to associate with the
245: * specified thread. This Application will be returned by calls made
246: * by this thread to <CODE>getApplication()</CODE>.
247: */
248: // compliance with WEBDOCWF begin
249: public static synchronized void register(Thread thread,
250: Application app) {
251: Integer intRefCount = (Integer) htAppCount.get(thread);
252: if (intRefCount != null && intRefCount.intValue() > 0) {
253: // increase the reference counter
254: htAppCount.put(thread, new Integer(
255: intRefCount.intValue() + 1));
256: } else {
257: // set the AppCounter to the initial value of 1
258: htAppCount.put(thread, new Integer(1));
259: applications.put(thread, app);
260: }
261: DatabaseManager databaseManager = app.getDatabaseManager();
262: if (databaseManager != null) {
263: DODS_register(thread, databaseManager);
264: LogChannel channel = app.getLogChannel();
265: if (channel != null) {
266: DODS_registerLogChannel(Thread.currentThread(), channel);
267: }
268: }
269: // original line
270: /*
271: public static void register(Thread thread, Application app) {
272: applications.put(thread, app);
273: */
274: // compliance with WEBDOCWF end
275: }
276:
277: /**
278: * Remove the association between the current thread and it's Application.
279: * This must be called when the thread is done using this Enhydra class.
280: * The current thread should not call <CODE>getApplication()</CODE>
281: * after this.
282: */
283: public static void unRegister() {
284: unRegister(Thread.currentThread());
285: }
286:
287: /**
288: * Remove the association between the specified thread and it's Application.
289: * This must be called when the thread is done using this Enhydra class.
290: * The thread should not call <CODE>getApplication()</CODE>
291: * after this.
292: *
293: * @param thread
294: * the thread to operate on.
295: */
296: // compliance with WEBDOCWF begin
297: public static synchronized void unRegister(Thread thread) {
298: Integer intAppCount = (Integer) htAppCount.get(thread);
299: if (intAppCount != null && intAppCount.intValue() > 1) {
300: // decrease the reference counter
301: htAppCount.put(thread, new Integer(
302: intAppCount.intValue() - 1));
303: } else {
304: htAppCount.remove(thread);
305: try {
306: if (dodsIsSet) {
307: DODS_unregister(thread);
308: }
309: } catch (Exception e) {
310: }
311: }
312: }
313:
314: /**
315: * Return the application object for current application.
316: * Returns null if there is no Application currently associated
317: * with the current thread.
318: *
319: * @return The application object.
320: */
321: public static Application getApplication() {
322: // return (Application)applications.get(Thread.currentThread());
323: return (applications != null) ? (Application) applications
324: .get(Thread.currentThread()) : null;
325:
326: }
327:
328: /**
329: * Return the database manager object for current application.
330: * Returns null if there is no database manager associated
331: * with the application or there is no application associated
332: * with the current thread.
333: *
334: * @return The database manager object if available else null.
335: */
336: public static DatabaseManager getDatabaseManager() {
337: Application app = getApplication();
338: if (app != null) {
339: return app.getDatabaseManager();
340: } else {
341: return null;
342: }
343: }
344:
345: /**
346: * Return the session manager object for current application.
347: * Returns null if there is no session manager associated
348: * with the application or there is no application associated
349: * with the current thread.
350: *
351: * @return The session manager object if available else null.
352: */
353: public static SessionManager getSessionManager() {
354: Application app = getApplication();
355: if (app != null) {
356: return app.getSessionManager();
357: } else {
358: return null;
359: }
360: }
361:
362: /**
363: * Return the LogChannel in the current Application object, or
364: * a log channel to the facility "Enhydra" if there is no current
365: * Application set.
366: *
367: * @return The LogChannel for the current application, or a
368: * generic LogChannel.
369: */
370: public static LogChannel getLogChannel() {
371: Application app = getApplication();
372: LogChannel chan = null;
373: if (app != null)
374: chan = app.getLogChannel();
375: if (chan != null)
376: return chan;
377: Logger logger = Logger.getCentralLogger();
378: if (logger == null)
379: return null; // This should never happen.
380: return logger.getChannel("Enhydra");
381: }
382: }
|