0001: /*
0002: * Enhydra Java Application Server Project
0003: *
0004: * The contents of this file are subject to the Enhydra Public License
0005: * Version 1.1 (the "License"); you may not use this file except in
0006: * compliance with the License. You may obtain a copy of the License on
0007: * the Enhydra web site ( http://www.enhydra.org/ ).
0008: *
0009: * Software distributed under the License is distributed on an "AS IS"
0010: * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
0011: * the License for the specific terms governing rights and limitations
0012: * under the License.
0013: *
0014: * The Initial Developer of the Enhydra Application Server is Lutris
0015: * Technologies, Inc. The Enhydra Application Server and portions created
0016: * by Lutris Technologies, Inc. are Copyright Lutris Technologies, Inc.
0017: * All Rights Reserved.
0018: *
0019: * Contributor(s):
0020: *
0021: * $Id: StandardApplication.java,v 1.5 2007-10-19 10:05:39 sinisa Exp $
0022: *
0023: *
0024: *
0025: */
0026: package com.lutris.appserver.server;
0027:
0028: import java.io.IOException;
0029: import java.lang.reflect.Constructor;
0030: import java.lang.reflect.Method;
0031: import java.util.Enumeration;
0032: import java.util.Hashtable;
0033: import java.util.List;
0034: import java.util.ListIterator;
0035:
0036: import javax.management.Attribute;
0037: import javax.management.AttributeList;
0038: import javax.management.AttributeNotFoundException;
0039: import javax.management.DynamicMBean;
0040: import javax.management.InvalidAttributeValueException;
0041: import javax.management.MBeanAttributeInfo;
0042: import javax.management.MBeanConstructorInfo;
0043: import javax.management.MBeanException;
0044: import javax.management.MBeanInfo;
0045: import javax.management.MBeanNotificationInfo;
0046: import javax.management.MBeanOperationInfo;
0047: import javax.management.MBeanParameterInfo;
0048: import javax.management.MBeanServer;
0049: import javax.management.MBeanServerFactory;
0050: import javax.management.ObjectName;
0051: import javax.management.ReflectionException;
0052: import javax.management.RuntimeOperationsException;
0053: import javax.servlet.Servlet;
0054: import javax.servlet.ServletContext;
0055: import javax.servlet.ServletException;
0056: import javax.servlet.http.HttpServletRequest;
0057: import javax.servlet.http.HttpServletResponse;
0058:
0059: import org.enhydra.util.DOTable;
0060: import org.enhydra.util.Utils;
0061: import org.enhydra.util.EafConfigMBean;
0062: import org.enhydra.util.jivan.JivanFactory;
0063: import org.enhydra.xml.xmlc.XMLCFactory;
0064: import org.enhydra.xml.xmlc.XMLCStdFactory;
0065: import org.enhydra.xml.xmlc.deferredparsing.DocumentLoaderImpl;
0066: import org.enhydra.xml.xmlc.deferredparsing.StandardDocumentLoader;
0067: import org.enhydra.xml.xmlc.deferredparsing.XMLCDeferredParsingFactory;
0068:
0069: import com.lutris.appserver.server.httpPresentation.ClientPageRedirectException;
0070: import com.lutris.appserver.server.httpPresentation.HttpPresentationComms;
0071: import com.lutris.appserver.server.httpPresentation.HttpPresentationException;
0072: import com.lutris.appserver.server.httpPresentation.HttpPresentationManager;
0073: import com.lutris.appserver.server.session.MemoryPersistence;
0074: import com.lutris.appserver.server.session.Session;
0075: import com.lutris.appserver.server.session.SessionException;
0076: import com.lutris.appserver.server.session.SessionManager;
0077: import com.lutris.appserver.server.sessionEnhydra.StandardSessionManager;
0078: import com.lutris.appserver.server.sql.DatabaseManager;
0079: import com.lutris.classloader.MultiClassLoader;
0080: import com.lutris.logging.EnhydraXMLCLogger;
0081: import com.lutris.logging.LogChannel;
0082: import com.lutris.logging.Logger;
0083: import com.lutris.util.Config;
0084: import com.lutris.util.KeywordValueException;
0085:
0086: /**
0087: * Default application implementation. This class provides standard start/stop
0088: * services. This can be used as a base class to derive Application objects.
0089: *
0090: * @version $Revision: 1.5 $
0091: * @author Mark Diekhans
0092: */
0093: public abstract class StandardApplication implements Application {
0094: /*
0095: * Category of logger that logs on System.out.
0096: */
0097: // private static final String sysConLoggerName = "SysOut";
0098: private static final String STANDARD_DATABASE_MANAGER_CLASS_NAME = "com.lutris.appserver.server.sql.StandardDatabaseManager";
0099: /**
0100: * Determines if a cookie with the session id is sent to the client.
0101: */
0102: protected boolean sendCookieForNewSession = true;
0103: /**
0104: * The name of the application; defaults to the unqualified
0105: * class name.
0106: */
0107: protected String appName = null;
0108: /**
0109: * Current state of the application. Only modified by the derived
0110: * application.
0111: */
0112: protected int state = STOPPED;
0113: /**
0114: * Session manager for all application sessions. A session manager
0115: * manages the creation, deletion and assocation of sessions with
0116: * a user.
0117: */
0118: protected SessionManager sessionManager;
0119: /**
0120: * Presentation manager instance for application. The presentation
0121: * manager handles incomming http requests.
0122: */
0123: protected HttpPresentationManager presentationManager;
0124:
0125: /**
0126: * Request Pre Processing Manager instance for application. It handles additional
0127: * http request processing.
0128: */
0129: protected RequestPreProcessingManager preProcessingManager;
0130:
0131: /**
0132: * Response Post Processing Manager instance for application. It handles additional
0133: * http response processing.
0134: */
0135: protected ResponsePostProcessingManager postProcessingManager;
0136:
0137: /**
0138: * Database manager instance for application. The database manager
0139: * manages logical database and is responsible for allocating
0140: * connection, create transactions, etc.
0141: */
0142: protected DatabaseManager databaseManager;
0143: /**
0144: * This applications config object. Every application has a configuration
0145: * object that is created from the application configuration file.
0146: *
0147: * @see Config
0148: */
0149: protected Config config;
0150: /**
0151: * Default URL used for application if defined in Config file. This
0152: * is used to redirect the user to the preferred start page if a
0153: * URL equal to the root of this application is given. By setting
0154: * this to index.html, it behaves in the same way as a http server.
0155: */
0156: protected String defaultUrl;
0157: /**
0158: * The log channel for this application to write to.
0159: */
0160: protected LogChannel logChannel;
0161: protected Logger logger;
0162: /**
0163: * The logger that logs on System.out.
0164: */
0165: protected static LogChannel loggerSys;
0166: /**
0167: * Application Data accessable through Jolt Fields.
0168: */
0169: protected ApplicationData data = new ApplicationData();
0170: /**
0171: * XMLC Factory.
0172: */
0173: protected XMLCFactory xmlcFactory;
0174:
0175: /**
0176: * Jivan Factory.
0177: */
0178: protected JivanFactory jivanFactory;
0179:
0180: protected MBeanServer server = null;
0181: protected ApplicationConfigMBean appConfigMBean;
0182: protected PresentationManagerMBean presentationManagerMBean;
0183: protected SessionManagerMBean sessionManagerMBean;
0184: protected ContextMBean contextMBean;
0185:
0186: /** DACHA & TUFA
0187: * Variable which determine should we keep
0188: * SessionManager in memory.
0189: */
0190: private boolean isMemoryPersistence = false;
0191:
0192: /**
0193: * A constructor with no arguments is required.
0194: */
0195: public StandardApplication() {
0196: }
0197:
0198: /**
0199: * Get the application state.
0200: * N.B. Purposely not syncronized for speed.
0201: *
0202: * @return
0203: * The application's state code.
0204: */
0205: public int getState() {
0206: return state;
0207: }
0208:
0209: /**
0210: * Tells the application if a cookie is used to bind new sessions
0211: * to a client. If no cookie is set, session ID's must be
0212: * communicated by means of URL rewriting.
0213: * @param flag indicates whether to send a cookie or not.
0214: */
0215: public void setCookieForNewSession(boolean flag) {
0216: sendCookieForNewSession = flag;
0217: }
0218:
0219: /**
0220: * Get the application's config object.
0221: *
0222: * @return
0223: * The application's config object.
0224: */
0225: public Config getConfig() {
0226: return config;
0227: }
0228:
0229: /**
0230: * Set the application name.
0231: *
0232: * @param name The new name for the application.
0233: */
0234: public void setName(String applName) {
0235: appName = applName;
0236: }
0237:
0238: /**
0239: * Get the application symbolic name. This is normally the
0240: * package name of this application class. <P>
0241: * N.B. Purposely not syncronized for speed.
0242: *
0243: * @return
0244: * The symbolic name.
0245: */
0246: public String getName() {
0247: return appName;
0248: }
0249:
0250: /**
0251: * Set the <CODE>LogChannel</CODE> associated with this application.
0252: *
0253: * @param The <CODE>LogChannel</CODE> to write to.
0254: */
0255: public void setLogChannel(LogChannel chan) {
0256: logChannel = chan;
0257: }
0258:
0259: /**
0260: * Get the <CODE>LogChannel</CODE> associated with this application.
0261: *
0262: * @return The log channel or <CODE>null</CODE> if this application
0263: * does not have one.
0264: */
0265: public LogChannel getLogChannel() {
0266: return logChannel;
0267: }
0268:
0269: /**
0270: * Start the application. The default method sets the state to
0271: * <CODE>RUNNING</CODE>.
0272: *
0273: * @param appConfig
0274: * Application configuration object.
0275: * @exception ApplicationException
0276: * If an error occurs starting the application.
0277: */
0278: public synchronized void startup(Config appConfig)
0279: throws ApplicationException {
0280: if (state == RUNNING) {
0281: return; // Handle multiple threads doing a startup.
0282: }
0283: printCopyrightHeader();
0284: /**
0285: * Read config object.
0286: */
0287: Config sessionConfig, databaseConfig = null;
0288: try {
0289: if (appConfig.containsKey("Application")) {
0290: defaultUrl = appConfig
0291: .getString("Application.DefaultUrl");
0292: }
0293: sessionConfig = (Config) appConfig
0294: .getSection("SessionManager");
0295: //DACHA 12.05.2003
0296: // databaseConfig = (Config)appConfig.getSection("DatabaseManager");
0297: } catch (KeywordValueException except) {
0298: throw new ApplicationException(except);
0299: }
0300: //DACHA 12.05.2003 do not throw exception if databaseConfig is null
0301: try {
0302: databaseConfig = (Config) appConfig
0303: .getSection("DatabaseManager");
0304: if (databaseConfig != null && appName != null) {
0305: databaseConfig.set("AppName", (Object) appName);
0306: }
0307: } catch (KeywordValueException except) {
0308: logChannel.write(Logger.DEBUG,
0309: "Application configured without DatabaseManager.");
0310: }
0311:
0312: /**
0313: * Create session manager...
0314: */
0315: sessionManager = createSessionManager(sessionConfig);
0316:
0317: /**
0318: * Create database manager if required...
0319: */
0320: boolean hasDatabaseConfig = databaseConfig != null;
0321:
0322: if (hasDatabaseConfig) {
0323: // TODO this might be a bit nicer
0324: // prevents creation of "DatabaseManager.log" file in working directory
0325: // because inside constractor StandardDatabaseManager has things to log :-)
0326: try {
0327: Class dodsClass = Class
0328: .forName("org.enhydra.dods.DODS");
0329: Method DODSMethod = dodsClass.getDeclaredMethod(
0330: "registerLogChannel", new Class[] {
0331: Thread.class, LogChannel.class });
0332: DODSMethod.invoke(dodsClass, new Object[] {
0333: Thread.currentThread(), logChannel });
0334: } catch (Exception e) {
0335: throw new RuntimeException(e.getMessage());
0336: }
0337: databaseManager = createDatabaseManager(databaseConfig);
0338: }
0339:
0340: // SV
0341: Config preProcessinfConfig, postProcessinfConfig = null;
0342: try {
0343: preProcessinfConfig = (Config) appConfig
0344: .getSection(RequestPreProcessingManager.CONFIG_PREFIX);
0345: if (appConfig.getConfigFile() != null
0346: && preProcessinfConfig != null)
0347: preProcessinfConfig.setConfigFile(appConfig
0348: .getConfigFile());
0349: preProcessingManager = createPreProcessingManager(preProcessinfConfig);
0350: } catch (KeywordValueException except) {
0351: // No Pre Processor
0352: }
0353: try {
0354: postProcessinfConfig = (Config) appConfig
0355: .getSection(ResponsePostProcessingManager.CONFIG_PREFIX);
0356: if (appConfig.getConfigFile() != null
0357: && postProcessinfConfig != null)
0358: postProcessinfConfig.setConfigFile(appConfig
0359: .getConfigFile());
0360: postProcessingManager = createPostProcessingManager(postProcessinfConfig);
0361: } catch (KeywordValueException except) {
0362: // No Post Processor
0363: }
0364: // SV
0365:
0366: /**
0367: * Remember config object...
0368: */
0369: config = appConfig;
0370:
0371: /**
0372: * register Application Coinfiguration MBean
0373: */
0374:
0375: registerApplicationMBean();
0376: registerSessionManagerMBean();
0377: registerPresentationManagerMBean();
0378: registerContextMBean();
0379:
0380: if (hasDatabaseConfig) {
0381: databaseManager.registerMBeans("DatabaseManager",
0382: appConfig, this .getClass().getClassLoader()); // tj 08.2007.
0383: /* tj 08.2007.
0384: registerDatabaseManagerMBean();
0385: registerTableMBeans();
0386: String [] dbNames = databaseManager.getLogicalDatabaseNames();
0387: for (int i=0;i<dbNames.length;i++){
0388: registerDatabaseMBean(dbNames[i]);
0389: }
0390: */
0391: }
0392:
0393: state = RUNNING;
0394: }
0395:
0396: /**
0397: * Initialize Asynchronous DODS Caches!
0398: *
0399: * @throws ApplicationException
0400: * If an error occurs restart the application.
0401: */
0402: public void initDodsAsyncCaches() throws ApplicationException {
0403: if (databaseManager != null) {
0404: try {
0405: databaseManager.getClass().getMethod("initCaches",
0406: new Class[] { ClassLoader.class })
0407: .invoke(
0408: databaseManager,
0409: new Object[] { this .getClass()
0410: .getClassLoader() });
0411: } catch (Exception e) {
0412: if (logChannel != null)
0413: logChannel
0414: .write(
0415: Logger.WARNING,
0416: "Problem occurred during initialization of asynchronous DODS caches load for the application "
0417: + getName());
0418: throw new ApplicationException(e);
0419: }
0420: }
0421: }
0422:
0423: /**
0424: *
0425: * Initialize Asynchronous DODS Caches!
0426: *
0427: * @param threadNumber
0428: * Number of parallel cache loading threads
0429: * @throws ApplicationException
0430: * If an error occurs restart the application.
0431: */
0432: public void initDodsAsyncCaches(int threadNumber)
0433: throws ApplicationException {
0434: if (databaseManager != null) {
0435: try {
0436: databaseManager.getClass().getMethod(
0437: "asynchInitCaches",
0438: new Class[] { Integer.TYPE }).invoke(
0439: databaseManager,
0440: new Object[] { new Integer(threadNumber) });
0441: } catch (Exception e) {
0442: if (logChannel != null)
0443: logChannel.write(Logger.WARNING,
0444: "Problem occurred during initialization of asynchronous "
0445: + "DODS caches load ("
0446: + threadNumber
0447: + ") for the application "
0448: + getName());
0449: throw new ApplicationException(e);
0450: }
0451: }
0452: }
0453:
0454: public void printCopyrightHeader() {
0455: /**
0456: * Print out a copyright notice. In most cases this will
0457: * fulfill a third party's copyright obligations when using Enhydra.
0458: */
0459: }
0460:
0461: /**
0462: * Continue the startup up process with the application is in the
0463: * <CODE>INCOMPLETE</CODE> state. The default method generates an
0464: * error, as the application should never be in the <CODE>INCOMPLETE</CODE>
0465: * state if it doesn't implment this method.
0466: *
0467: * @param appConfig
0468: * The same <CODE>appConfig</CODE> object that was passed to
0469: * <CODE>startup</CODE>.
0470: * @exception ApplicationException
0471: * If an error occurs restarting the application.
0472: */
0473: public synchronized void restartup(Config appConfig)
0474: throws ApplicationException {
0475: throw new ApplicationException(
0476: "no support for INCOMPLETE state");
0477: }
0478:
0479: /**
0480: * Shutdown the application. The default method sets the state to
0481: * <CODE>STOPPED</CODE>.
0482: */
0483: public synchronized void shutdown() {
0484: if (state == STOPPED) {
0485: return; // Handle multiple threads doing a shutdown.
0486: }
0487:
0488: // Unregister previously registered application MBeans
0489: try {
0490: unRegisterApplicationMBean();
0491: unRegisterSessionManagerMBean();
0492: unRegisterPresentationManagerMBean();
0493: unRegisterContextMBean();
0494:
0495: if (databaseManager != null) {
0496: databaseManager.unregisterMBeans(); // tj 08.2007.
0497: /* tj 08.2007.
0498: unRegisterTableMBeans();
0499: unRegisterDatabaseManagerMBean();
0500: String [] dbNames = databaseManager.getLogicalDatabaseNames();
0501: for (int i=0;i<dbNames.length;i++){
0502: unRegisterDatabaseMBean(dbNames[i]);
0503: }
0504: */
0505: }
0506:
0507: } catch (Exception e) {
0508: logChannel.write(Logger.DEBUG, e.toString());
0509: }
0510:
0511: if (sessionManager != null) {
0512: sessionManager.shutdown();
0513: sessionManager = null;
0514: }
0515: if (databaseManager != null) {
0516: databaseManager.shutdown();
0517: databaseManager = null;
0518: }
0519:
0520: state = STOPPED;
0521: }
0522:
0523: /**
0524: * Shutdown the application. The default method sets the state to
0525: * <CODE>STOPPED</CODE>.
0526: */
0527: public synchronized void shutdownWithoutMBeanUnRegistration() {
0528: if (state == STOPPED) {
0529: return; // Handle multiple threads doing a shutdown.
0530: }
0531:
0532: if (sessionManager != null) {
0533: sessionManager.shutdown();
0534: sessionManager = null;
0535: }
0536: if (databaseManager != null) {
0537: databaseManager.shutdown();
0538: databaseManager = null;
0539: }
0540:
0541: state = STOPPED;
0542: }
0543:
0544: /**
0545: * Create the session manager to be used by this application. By
0546: * default this will return the <EM>Lutris</EM> standard session manager.
0547: * This method can be overwritten to create a custom session
0548: * manager.
0549: *
0550: * @param sessionMgrConfig
0551: * Configuration object containing "SessionManager" keys.
0552: * This can be <CODE>null</CODE> to use defaults.
0553: * @exception ApplicationException
0554: * If an error occurs in creating a session manager.
0555: * @return
0556: * The session manager.
0557: */
0558: protected SessionManager createSessionManager(
0559: Config sessionMgrConfig) throws ApplicationException {
0560: if (sessionMgrConfig == null) {
0561: sessionMgrConfig = new Config();
0562: }
0563: try {
0564: /*DACHA & TUFA
0565: * Config file specified should we keep
0566: * SessionManager in memory.
0567: */
0568: String sessionMgr;
0569: if (sessionMgrConfig.containsKey("Class")) {
0570: sessionMgr = sessionMgrConfig.getString("Class");
0571: } else {
0572: sessionMgr = "com.lutris.appserver.server.sessionEnhydra.StandardSessionManager";
0573: }
0574: Class sessionMgrClass = Class.forName(sessionMgr);
0575: Class[] constructorParameterTypes = new Class[3];
0576: constructorParameterTypes[0] = Class
0577: .forName("com.lutris.appserver.server.Application");
0578: constructorParameterTypes[1] = Class
0579: .forName("com.lutris.util.Config");
0580: constructorParameterTypes[2] = Class
0581: .forName("com.lutris.logging.LogChannel");
0582: Constructor sessionMgrConstructor = sessionMgrClass
0583: .getConstructor(constructorParameterTypes);
0584: if (sessionMgrConfig.containsKey("MemoryPersistence")) {
0585: String mp = sessionMgrConfig
0586: .getString("MemoryPersistence");
0587: if (mp.equals("true")) {
0588: isMemoryPersistence = true;
0589: }
0590: }
0591: SessionManager sm = null;
0592: if (this .appName != null) {
0593: sm = MemoryPersistence.getSessionManager(this .appName);
0594: }
0595: if (isMemoryPersistence && (sm != null)) {
0596: return sm;
0597: } else {
0598: // v. strahinja, 26 sep 2002 return new StandardSessionManager(this, sessionMgrConfig, logChannel);
0599: Object[] parameters = new Object[3];
0600: parameters[0] = this ;
0601: parameters[1] = sessionMgrConfig;
0602: parameters[2] = logChannel;
0603: SessionManager sessionManager = (SessionManager) sessionMgrConstructor
0604: .newInstance(parameters);
0605: return sessionManager;
0606: }
0607: } catch (Exception except) {
0608: throw new ApplicationException(except);
0609: }
0610: }
0611:
0612: /**
0613: * Create the request pre-processing manager to be used by this application.
0614: * This method can be overwritten to create a custom request pre-processing
0615: * manager.
0616: *
0617: * @param ppConfig
0618: * Configuration object containing "RequestPreProcessor" keys.
0619: * This can be <CODE>null</CODE> to use none.
0620: * @return
0621: * The request pre-processor.
0622: */
0623: protected RequestPreProcessingManager createPreProcessingManager(
0624: Config ppConfig) {
0625: if (ppConfig != null) {
0626: return new RequestPreProcessingManager(ppConfig, logChannel);
0627: }
0628: return null;
0629: }
0630:
0631: /**
0632: * Create the response post-processing manager to be used by this application.
0633: * This method can be overwritten to create a custom response post-processing
0634: * manager.
0635: *
0636: * @param ppConfig
0637: * Configuration object containing "ResponsePostProcessor" keys.
0638: * This can be <CODE>null</CODE> to use none.
0639: * @return
0640: * The response post-processor.
0641: */
0642: protected ResponsePostProcessingManager createPostProcessingManager(
0643: Config ppConfig) {
0644: if (ppConfig != null) {
0645: return new ResponsePostProcessingManager(ppConfig,
0646: logChannel);
0647: }
0648: return null;
0649: }
0650:
0651: /**
0652: * Create the database manager to be used by this application. By
0653: * default this will return the <EM>Lutris</EM>
0654: * <CODE>StandardDatabaseManager</CODE>.
0655: * This method can be overwritten to create a custom session
0656: * manager.
0657: *
0658: * @param databaseMgrConfig
0659: * Configuration object containing "DatabaseManager" keys.
0660: * @exception ApplicationException
0661: * If an error occurs in creating a database manager.
0662: */
0663: protected DatabaseManager createDatabaseManager(
0664: Config databaseMgrConfig) throws ApplicationException {
0665: try {
0666: String databaseMgr;
0667: if (databaseMgrConfig.containsKey("Class")) {
0668: databaseMgr = databaseMgrConfig.getString("Class");
0669: } else {
0670: databaseMgr = STANDARD_DATABASE_MANAGER_CLASS_NAME;
0671: }
0672: Class standardDbManagerClass = Class.forName(databaseMgr);
0673: Class[] ArgClassArray = new Class[] { Config.class };
0674: Object[] ArgObject = new Object[] { databaseMgrConfig };
0675: Constructor standardDbManager = standardDbManagerClass
0676: .getDeclaredConstructor(ArgClassArray);
0677: return (DatabaseManager) (standardDbManager
0678: .newInstance(ArgObject));
0679: } catch (Exception except) {
0680: throw new ApplicationException(except);
0681: }
0682: }
0683:
0684: /**
0685: * Create a new session for application. By default this will create
0686: * the <EM>Lutris</EM> <CODE>StandardSession</CODE>.
0687: * This method can be overwritten to create a custom session.
0688: *
0689: * @param comms
0690: * Object containing request, response and redirect objects.
0691: * <I>Warning: comms.session and comms.sessionData will be null.
0692: * they are filled in after this method returns.</I>
0693: * @return
0694: * The session.
0695: * @exception ApplicationException
0696: * If an error occurs in creating the session.
0697: */
0698: protected Session createSession(HttpPresentationComms comms)
0699: throws ApplicationException {
0700: try {
0701: return sessionManager.createSession(comms);
0702: } catch (Exception exception) {
0703: throw new ApplicationException(exception);
0704: }
0705: }
0706:
0707: /**
0708: * Default method used by <CODE>requestPreprocessor</CODE>
0709: * to ensure that a session exists and initialize the
0710: * <CODE>session</CODE> and <CODE>sessionData</CODE> fields
0711: * in the <CODE>HttpPresentationComms</CODE> object.
0712: * New sessions are only created on requests to presentation
0713: * objects, not requests for other types of files (such as gifs).
0714: * This avoids allocating multiple sessions when a browser makes
0715: * multiple requests for HREFs. If the session already exist, it
0716: * is alwasy set in <CODE>comms</CODE><P>
0717: *
0718: * This normally looks up the session using a session key from
0719: * a cookie.
0720: *
0721: * @param comms
0722: * Object containing request, response and redirect objects.
0723: * @exception ApplicationException
0724: * If an error occurs setting up the session.
0725: */
0726: protected void ensureSession(HttpPresentationComms comms)
0727: throws ApplicationException {
0728: try {
0729: if (presentationManager
0730: .isPresentationRequest(comms.request)) {
0731: // FIX - verify OK
0732: comms.session = StandardAppUtil
0733: .getRequestSession(comms);
0734: }
0735: if (comms.session != null
0736: && sessionManager.sessionExists(comms.session
0737: .getSessionKey())) {
0738: /*
0739: * InitializeNewSession() sets up comms.sessionData, so
0740: * that it may be used if an application defines it's own
0741: * version of that method (after calling the super method,
0742: * it has a normal comms object to work with).
0743: * Therefore, if we did not call initializeNewSession(),
0744: * we have to initialize comms.sessionData here.
0745: */
0746: comms.sessionData = comms.session.getSessionData();
0747: } else {
0748: if (presentationManager
0749: .isPresentationRequest(comms.request)) {
0750: initializeNewSession(comms);
0751: }
0752: }
0753: } catch (HttpPresentationException except) {
0754: throw new ApplicationException(except);
0755: } catch (SessionException except) {
0756: throw new ApplicationException(except);
0757: }
0758: }
0759:
0760: /**
0761: * Calls application session manager's <i>passivateSession</i> method
0762: * for the session associated with this request.
0763: *
0764: * @param comms
0765: * Object containing request, response and redirect objects.
0766: * @exception ApplicationException
0767: * If the session manager was unable to "passivate" the session.
0768: * @see com.lutris.appserver.server.session.SessionManager.passivateSession
0769: */
0770: public void requestPostProcessor(HttpPresentationComms comms)
0771: throws ApplicationException {
0772: try {
0773: if (comms.session != null) {
0774: comms.application.getSessionManager().passivateSession(
0775: Thread.currentThread(),
0776: comms.session.getSessionKey());
0777: }
0778: } catch (SessionException e) {
0779: throw new ApplicationException(e);
0780: }
0781: }
0782:
0783: /**
0784: * This is called when no valid session is found in an incoming request.
0785: * A new session is created and added to <CODE>comms</CODE>. If
0786: * sending session cookies is enabled, a cookie is created and
0787: * added to the response, so future requests will be associated
0788: * with the newly created session. If sending session cookies is
0789: * disabled, it is the application's responsibility to include
0790: * the session ID in URLs to associate further requests with the
0791: * session.<P>
0792: *
0793: * <I>Warning:</I> At first <CODE>comms.session</CODE>
0794: * and <CODE>comms.sessionData</CODE> are null. This method initializes
0795: * them both.
0796: *
0797: * @param comms
0798: * Object containing request, response and redirect objects. Session
0799: * and SessionData objects are initialized.
0800: * @exception ApplicationException
0801: * If an error occurs setting up the session.
0802: * @see #setCookieForNewSession
0803: */
0804: protected void initializeNewSession(HttpPresentationComms comms)
0805: throws ApplicationException {
0806: comms.session = createSession(comms);
0807: if (sendCookieForNewSession) {
0808: StandardAppUtil.bindSessionToClient(comms);
0809: }
0810: comms.sessionData = comms.session.getSessionData();
0811: }
0812:
0813: /**
0814: * Returns the specified url rewritten to include the sessionId
0815: *
0816: * @param url String to urlencode
0817: * @return the param url rewritten to contain the sessionId
0818: */
0819: public String encodeUrl(String url, String sessionKey)
0820: throws ApplicationException {
0821: return StandardAppUtil.encodeUrl(url, sessionKey);
0822: }
0823:
0824: /**
0825: * Returns the specified url rewritten to include the sessionId
0826: *
0827: * @param url String to urlencode
0828: * @return the param url rewritten to contain the sessionId
0829: * @deprecated Use encodeUrl(String,String)
0830: */
0831: public String encodeUrl(String url, String sessionKey,
0832: String appName) throws ApplicationException {
0833: return StandardAppUtil.encodeUrl(url, sessionKey);
0834: }
0835:
0836: /**
0837: * Default application request preprocessor. This method sets up
0838: * a session data structure if a cookie is not set for the application.
0839: * It doesn't require a login however. The unauthenticated session is
0840: * useful for persistence in simple applications. It is possible to
0841: * later force a login. If the URL is not a reference to a presentation
0842: * object, then a session will not be allocated if it does not already
0843: * exist. This prevents allocation of multiple sessions when a browser
0844: * is requesting other objects, such as gifs, in parallel. Thus, after
0845: * this function is called, it is possible for session to be null. <P>
0846: *
0847: * N.B. Purposely not syncronized for speed/concurrency.
0848: *
0849: * @param comms
0850: * Object containing request, response and redirect objects.
0851: * @return
0852: * Always returns false, as request handling is not done.
0853: * @exception Exception
0854: * May throw any exception, as with a presentation object;
0855: * including page redirects.
0856: */
0857: public boolean requestPreprocessor(HttpPresentationComms comms)
0858: throws Exception {
0859:
0860: /**
0861: * Remap / ---> "defaultUrl" if defined.
0862: */
0863: if (defaultUrl != null) {
0864: String ap = comms.request.getApplicationPath();
0865: if (!ap.endsWith("/")) {
0866: ap += "/";
0867: }
0868: String page = comms.request.getPresentationObjectPath();
0869: if (!page.endsWith("/")) {
0870: page += "/";
0871: }
0872: if (page.equals(ap)) {
0873: // Don't want two slashes in a row.
0874: String target = comms.request.getHttpServletRequest()
0875: .getContextPath();
0876: if (target.equals("/")) {
0877: target = "";
0878: }
0879: target = "";
0880: if (defaultUrl.startsWith("/")) {
0881: target += ap + defaultUrl.substring(1);
0882: } else {
0883: target += ap + defaultUrl;
0884: }
0885: // get query string and add it to target
0886: String query = comms.request.getQueryString();
0887: if (query != null) {
0888: target += "?" + query;
0889: }
0890:
0891: /**
0892: * Initialize session if one doesn't exist
0893: */
0894: if (StandardAppUtil.getRequestSession(comms) == null) {
0895: initializeNewSession(comms);
0896: }
0897:
0898: /**
0899: * Set URL encoding for the first application page
0900: * to enable further session propagation
0901: */
0902: try {
0903: if (sessionManager.getEncodeFirstUrl()) {
0904: comms.request
0905: .setRequestedSessionIdFromUrl(true);
0906: }
0907: } catch (Throwable trowable) {
0908: }
0909:
0910: throw new ClientPageRedirectException(target);
0911: }
0912: }
0913: // Only need the session if we haven't redirected to a new page.
0914: ensureSession(comms);
0915: boolean returnValue = false;
0916:
0917: comms.response.setPostProcessingManager(postProcessingManager);
0918:
0919: if (preProcessingManager != null) {
0920: returnValue = preProcessingManager.manage(comms);
0921: }
0922: // Proceed depending on returnValue:
0923: // Continue request processing or jump to the response flush!
0924: return returnValue;
0925: }
0926:
0927: /**
0928: * Get the <CODE>SessionManager</CODE> associated with this application.
0929: *
0930: * @return
0931: * The session manager or <CODE>null</CODE> if the application
0932: * doesn't have a <CODE>SessionManager</CODE>.
0933: */
0934: public SessionManager getSessionManager() {
0935: return sessionManager;
0936: }
0937:
0938: /**
0939: * Get the <CODE>DatabaseManager</CODE> associated with this application.
0940: *
0941: * @return
0942: * The database manager or <CODE>null</CODE> if the application
0943: * doesn't have a <CODE>DatabaseManager</CODE>.
0944: */
0945: public DatabaseManager getDatabaseManager() {
0946: return databaseManager;
0947: }
0948:
0949: /**
0950: * Get the <CODE>HttpPresentationManager</CODE> associated with this
0951: * application.
0952: *
0953: * @return The presentation manager.
0954: */
0955: public HttpPresentationManager getHttpPresentationManager() {
0956: return presentationManager;
0957: }
0958:
0959: /**
0960: * Tells the application about the Presentation Manager running it.
0961: * This is necessary because the presentation manager is created
0962: * before the application.
0963: *
0964: * @param pm The HTTP presentation manager running this application.
0965: */
0966: public void setHttpPresentationManager(HttpPresentationManager pm) {
0967: presentationManager = pm;
0968: }
0969:
0970: /**
0971: * This is a hook that allows applications to act on requests before
0972: * they enter the Enhydra framework. This implementation always returns
0973: * false, so the request is processed normally. <B>Do not override this
0974: * unless you absolutly have to.</B> Currently the only application
0975: * that needs to is the debugger, because it needs to hand off requests
0976: * to other non-Enhydra servlets. <P>
0977: *
0978: * In contrast, the method requestPreprocessor() is commonly overridden.
0979: * It provides applications with a centeral place to put code that has
0980: * to be run on every request before it is sent to the presentation
0981: * objects.
0982: *
0983: * @param servlet
0984: * The servlet we are running in.
0985: * @param context
0986: * The ServletContext that was used to initialize our servlet.
0987: * @param request
0988: * The incomming request object.
0989: * @param response
0990: * The incomming response object.
0991: * @return
0992: * True if this method handled the request, in which case no
0993: * further action will be taken. Or false if normal processing
0994: * should continue.
0995: * @exception ServletException
0996: * You are allowed to throw the same exceptions that the servlet's
0997: * service() method throws.
0998: * @exception IOException
0999: * You are allowed to throw the same exceptions that the servlet's
1000: * service() method throws.
1001: */
1002: public boolean servletRequestPreprocessor(Servlet servlet,
1003: ServletContext context, HttpServletRequest request,
1004: HttpServletResponse response) throws ServletException,
1005: IOException {
1006: return false;
1007: }
1008:
1009: /**
1010: * Get the XMLC factory object being used by the application.
1011: */
1012: public XMLCFactory getXMLCFactory() {
1013: return xmlcFactory;
1014: }
1015:
1016: /**
1017: * Set the XMLC factory based on the deferred parsing option.
1018: */
1019: public void setXMLCFactory() {
1020: xmlcFactory = new XMLCDeferredParsingFactory(
1021: StandardDocumentLoader.getInstance(),
1022: (MultiClassLoader) presentationManager
1023: .getAppClassLoader(), new EnhydraXMLCLogger(
1024: logChannel));
1025: }
1026:
1027: /**
1028: * Initializes the Jivan factory object which can be used by application.
1029: * @param reload swich which indicates realoading status of Jivan generated
1030: * pages in presentation layer (true = reload is on, false = reload is off)
1031: */
1032: public void setJivanFactory(boolean reload) {
1033: this .jivanFactory = new JivanFactory(reload, this .logChannel);
1034: }
1035:
1036: /**
1037: * Get the Jivan factory object being used by the application.
1038: */
1039: public JivanFactory getJivanFactory() {
1040: return this .jivanFactory;
1041: }
1042:
1043: /**
1044: * Get the MBeanServer object being used by the application.
1045: */
1046: private MBeanServer findMBeanServer()
1047: throws com.lutris.appserver.server.session.SessionException {
1048: MBeanServer mBeanServer;
1049: try {
1050: java.util.ArrayList server = MBeanServerFactory
1051: .findMBeanServer(null);
1052: if (server == null) {
1053: return null;
1054: } else {
1055: mBeanServer = (MBeanServer) server.get(0);
1056: }
1057: } catch (Exception e) {
1058: throw new com.lutris.appserver.server.session.SessionException(
1059: e);
1060: }
1061: return mBeanServer;
1062: }
1063:
1064: /**
1065: * Get the Application Info HTML presentation.
1066: */
1067: public String toHtml() {
1068: return "No Application Info";
1069: }
1070:
1071: /**
1072: * Application MBean definition section
1073: *
1074: * Definitions of application MBean implementations.
1075: * All present MBean Implementations extend basic
1076: * EafConfigMBean implementation which defines basic
1077: * Config MBean actions.
1078: **/
1079:
1080: private void registerApplicationMBean() {
1081: if (appName == null) {
1082: return;
1083: }
1084:
1085: try {
1086: server = findMBeanServer();
1087: if (server == null) {
1088: return;
1089: }
1090: } catch (Exception e) {
1091: logChannel.write(Logger.DEBUG, e.toString());
1092: }
1093:
1094: try {
1095: String applicationName = appName;
1096:
1097: ObjectName objectName = new ObjectName(
1098: "EnhydraApplications:type=ApplicationConfig,name="
1099: + applicationName);
1100:
1101: if (!server.isRegistered(objectName)) {
1102: String[] includes = null;
1103: String[] excludes = { "SessionManager",
1104: "PresentationManager", "DatabaseManager" };
1105: appConfigMBean = new ApplicationConfigMBean(this ,
1106: objectName, null, includes, excludes);
1107: server.registerMBean(appConfigMBean, objectName);
1108: }
1109:
1110: } catch (Exception e) {
1111: logChannel.write(Logger.DEBUG, e.toString());
1112: return;
1113: }
1114: }
1115:
1116: private void unRegisterApplicationMBean() {
1117: if (appName == null) {
1118: return;
1119: }
1120:
1121: try {
1122: server = findMBeanServer();
1123: if (server == null) {
1124: return;
1125: }
1126: } catch (Exception e) {
1127: logChannel.write(Logger.DEBUG, e.toString());
1128: }
1129:
1130: try {
1131: String applicationName = appName;
1132:
1133: ObjectName objectName = new ObjectName(
1134: "EnhydraApplications:type=ApplicationConfig,name="
1135: + applicationName);
1136:
1137: if (server.isRegistered(objectName)) {
1138: server.unregisterMBean(objectName);
1139: }
1140:
1141: } catch (Exception e) {
1142: logChannel.write(Logger.DEBUG, e.toString());
1143: return;
1144: }
1145: }
1146:
1147: /**
1148: * Application Config MBean
1149: */
1150: private class ApplicationConfigMBean extends EafConfigMBean {
1151: public ApplicationConfigMBean(Application application,
1152: ObjectName objectName, String prefix,
1153: String[] includes, String[] excludes) {
1154: super (application, objectName, prefix, includes, excludes);
1155: buildDynamicMBeanInfo();
1156: }
1157:
1158: /**
1159: * Sets the value of the specified attribute of the Dynamic MBean.
1160: */
1161: public void setAttribute(Attribute attribute)
1162: throws AttributeNotFoundException,
1163: InvalidAttributeValueException, MBeanException,
1164: ReflectionException {
1165:
1166: super .setAttribute(attribute);
1167:
1168: // restart without MBean UnRegistration
1169: shutdownWithoutMBeanUnRegistration();
1170: try {
1171: startup(config);
1172: } catch (Exception e) {
1173: logChannel.write(Logger.DEBUG, e.toString());
1174: }
1175: }
1176:
1177: /**
1178: * Allows an operation to be invoked on the Dynamic MBean.
1179: */
1180: public Object invoke(String operationName, Object params[],
1181: String signature[]) throws MBeanException,
1182: ReflectionException {
1183: // Check operationName is not null to avoid NullPointerException later on
1184: if (operationName == null) {
1185: throw new RuntimeOperationsException(
1186: new IllegalArgumentException(
1187: "Operation name cannot be null"),
1188: "Cannot invoke a null operation in "
1189: + dClassName);
1190: }
1191: // Check for a recognized operation name and call the corresponding operation
1192: if (operationName.equals("getConfig")) {
1193: return config;
1194: } else {
1195: // basic set of operations
1196: return super .invoke(operationName, params, signature);
1197: }
1198: }
1199:
1200: /**
1201: * Method returns MBean's MBeanOperationInfo Array
1202: * @return MBeanOperationInfo[]
1203: */
1204: protected MBeanOperationInfo[] getMBeanOperationsInfo() {
1205: MBeanParameterInfo[] params = null;
1206: MBeanOperationInfo[] dOperations = new MBeanOperationInfo[6];
1207: dOperations[0] = new MBeanOperationInfo(
1208: "reset",
1209: "reset(): reset attributes to their initial values",
1210: params, "void", MBeanOperationInfo.ACTION);
1211: dOperations[1] = new MBeanOperationInfo(
1212: "saveAttributes",
1213: "saveAttributes(): save the attribute values into the configuration file",
1214: params, "void", MBeanOperationInfo.ACTION);
1215: dOperations[2] = new MBeanOperationInfo("getAppInfo",
1216: "getAppInfo(): get application information",
1217: params, "String", MBeanOperationInfo.ACTION);
1218:
1219: params = new MBeanParameterInfo[2];
1220: params[0] = new MBeanParameterInfo(
1221: "attKey",
1222: "java.lang.String",
1223: "Attribute name! Please, "
1224: + "use UNDERLINE (_) as attribute group separator.");
1225: params[1] = new MBeanParameterInfo("attValue",
1226: "java.lang.String", "Attribute value!");
1227:
1228: dOperations[3] = new MBeanOperationInfo(
1229: "addAttribute",
1230: "addAttribute(String key, String value): add new application parameter",
1231: params, "void", MBeanOperationInfo.ACTION);
1232:
1233: params = new MBeanParameterInfo[1];
1234: params[0] = new MBeanParameterInfo(
1235: "attKey",
1236: "java.lang.String",
1237: "Attribute name! Please, "
1238: + "use UNDERLINE (_) as attribute group separator.");
1239:
1240: dOperations[4] = new MBeanOperationInfo(
1241: "removeAttribute",
1242: "removeAttribute(String key): remove application parameter",
1243: params, "void", MBeanOperationInfo.ACTION);
1244:
1245: params = null;
1246:
1247: dOperations[5] = new MBeanOperationInfo(
1248: "getConfig",
1249: "getConfig(): Gets actual application Config object.",
1250: params, "com.lutris.util.Config",
1251: MBeanOperationInfo.ACTION);
1252:
1253: return dOperations;
1254: }
1255:
1256: }
1257:
1258: private void registerSessionManagerMBean() {
1259: if (appName == null) {
1260: return;
1261: }
1262:
1263: try {
1264: server = findMBeanServer();
1265: if (server == null) {
1266: return;
1267: }
1268: } catch (Exception e) {
1269: logChannel.write(Logger.DEBUG, e.toString());
1270: }
1271:
1272: try {
1273: String applicationName = appName;
1274:
1275: ObjectName objectName = new ObjectName(
1276: "EnhydraApplications:type=SessionManager,name="
1277: + applicationName);
1278:
1279: if (!server.isRegistered(objectName)) {
1280: String[] includes = { "SessionManager" };
1281: String[] excludes = null;
1282: sessionManagerMBean = new SessionManagerMBean(this ,
1283: objectName, "SessionManager", includes,
1284: excludes);
1285: server.registerMBean(sessionManagerMBean, objectName);
1286: }
1287:
1288: } catch (Exception e) {
1289: logChannel.write(Logger.DEBUG, e.toString());
1290: return;
1291: }
1292: }
1293:
1294: private void unRegisterSessionManagerMBean() {
1295: if (appName == null) {
1296: return;
1297: }
1298:
1299: try {
1300: server = findMBeanServer();
1301: if (server == null) {
1302: return;
1303: }
1304: } catch (Exception e) {
1305: logChannel.write(Logger.DEBUG, e.toString());
1306: }
1307:
1308: try {
1309: String applicationName = appName;
1310:
1311: ObjectName objectName = new ObjectName(
1312: "EnhydraApplications:type=SessionManager,name="
1313: + applicationName);
1314:
1315: if (server.isRegistered(objectName)) {
1316: server.unregisterMBean(objectName);
1317: }
1318:
1319: } catch (Exception e) {
1320: logChannel.write(Logger.DEBUG, e.toString());
1321: return;
1322: }
1323: }
1324:
1325: /**
1326: * SessionManager MBean
1327: */
1328: private class SessionManagerMBean extends EafConfigMBean {
1329: public SessionManagerMBean(Application application,
1330: ObjectName objectName, String prefix,
1331: String[] includes, String[] excludes) {
1332: super (application, objectName, prefix, includes, excludes);
1333: buildDynamicMBeanInfo();
1334: }
1335:
1336: /**
1337: * Sets the value of the specified attribute of the Dynamic MBean.
1338: */
1339: public void setAttribute(Attribute attribute)
1340: throws AttributeNotFoundException,
1341: InvalidAttributeValueException, MBeanException,
1342: ReflectionException {
1343:
1344: super .setAttribute(attribute);
1345:
1346: // restart without MBean UnRegistration
1347: shutdownWithoutMBeanUnRegistration();
1348: try {
1349: startup(config);
1350: } catch (Exception e) {
1351: logChannel.write(Logger.DEBUG, e.toString());
1352: }
1353: }
1354:
1355: /**
1356: * Allows an operation to be invoked on the Dynamic MBean.
1357: */
1358: public Object invoke(String operationName, Object params[],
1359: String signature[]) throws MBeanException,
1360: ReflectionException {
1361: // SessionManager additional functionalities
1362: if (operationName.equals("sessionExists")) {
1363: boolean temp = false;
1364: try {
1365: if (params != null && params.length == 1) {
1366: temp = sessionManager
1367: .sessionExists((String) params[0]);
1368: }
1369: return Boolean.valueOf(temp);
1370: } catch (Exception e) {
1371: throw new MBeanException(e);
1372: }
1373: } else if (operationName.equals("activeSessionCount")) {
1374: int temp = 0;
1375: try {
1376: temp = sessionManager.activeSessionCount();
1377: return new Integer(temp);
1378: } catch (Exception e) {
1379: throw new MBeanException(e);
1380: }
1381: } else if (operationName.equals("getSessionKeys")) {
1382: Enumeration temp = null;
1383: try {
1384: temp = sessionManager.getSessionKeys();
1385: return temp;
1386: } catch (Exception e) {
1387: throw new MBeanException(e);
1388: }
1389: } else if (operationName.equals("getSession")) {
1390: Session temp = null;
1391: try {
1392: if (params != null && params.length == 1) {
1393: temp = sessionManager
1394: .getSession((String) params[0]);
1395: }
1396: return temp;
1397: } catch (Exception e) {
1398: throw new MBeanException(e);
1399: }
1400: } else if (operationName.equals("getSessionManager")) {
1401: try {
1402: return sessionManager;
1403: } catch (Exception e) {
1404: throw new MBeanException(e);
1405: }
1406: } else if (operationName.equals("getEncodeUrlState")) {
1407: try {
1408: return sessionManager.getEncodeUrlState();
1409: } catch (Exception e) {
1410: throw new MBeanException(e);
1411: }
1412: } else if (operationName.equals("createSession")) {
1413: try {
1414: Session sesion = null;
1415: if (params != null && params.length == 1) {
1416: sesion = sessionManager
1417: .createSession((String) params[0]);
1418: }
1419: return sesion;
1420: } catch (Exception e) {
1421: throw new MBeanException(e);
1422: }
1423: } else if (operationName.equals("deleteSession")) {
1424: try {
1425: if (params != null && params.length == 1) {
1426: sessionManager
1427: .deleteSession((String) params[0]);
1428: }
1429: return null;
1430: } catch (Exception e) {
1431: throw new MBeanException(e);
1432: }
1433: } else {
1434: // basic set of operations
1435: return super .invoke(operationName, params, signature);
1436: }
1437: }
1438:
1439: /**
1440: * Method returns MBean's MBeanOperationInfo Array
1441: * @return MBeanOperationInfo[]
1442: */
1443: protected MBeanOperationInfo[] getMBeanOperationsInfo() {
1444:
1445: boolean includeAdditional = true;
1446: if (hashAttrib.containsKey("Class")) {
1447: String value = (String) hashAttrib.get("Class");
1448: if ("com.lutris.appserver.server.sessionContainerAdapter.ContainerAdapterSessionManager"
1449: .equals(value)
1450: || "com.lutris.appserver.server.sessionContainerAdapter.JmxContainerAdapterSessionManager"
1451: .equals(value)) {
1452: includeAdditional = false;
1453: }
1454: }
1455:
1456: MBeanParameterInfo[] params = null;
1457: MBeanOperationInfo[] dOperations = null;
1458: if (includeAdditional) {
1459: dOperations = new MBeanOperationInfo[13];
1460: } else {
1461: dOperations = new MBeanOperationInfo[7];
1462: }
1463:
1464: dOperations[0] = new MBeanOperationInfo(
1465: "reset",
1466: "reset(): reset attributes to their initial values",
1467: params, "void", MBeanOperationInfo.ACTION);
1468: dOperations[1] = new MBeanOperationInfo(
1469: "saveAttributes",
1470: "saveAttributes(): save the attribute values into the configuration file",
1471: params, "void", MBeanOperationInfo.ACTION);
1472: dOperations[2] = new MBeanOperationInfo("getAppInfo",
1473: "getAppInfo(): get application information",
1474: params, "String", MBeanOperationInfo.ACTION);
1475:
1476: params = new MBeanParameterInfo[2];
1477: params[0] = new MBeanParameterInfo(
1478: "attKey",
1479: "java.lang.String",
1480: "Attribute name! Please, "
1481: + "use UNDERLINE (_) as attribute group separator.");
1482: params[1] = new MBeanParameterInfo("attValue",
1483: "java.lang.String", "Attribute value!");
1484:
1485: dOperations[3] = new MBeanOperationInfo(
1486: "addAttribute",
1487: "addAttribute(String key, String value): add new application parameter",
1488: params, "void", MBeanOperationInfo.ACTION);
1489:
1490: params = new MBeanParameterInfo[1];
1491: params[0] = new MBeanParameterInfo(
1492: "attKey",
1493: "java.lang.String",
1494: "Attribute name! Please, "
1495: + "use UNDERLINE (_) as attribute group separator.");
1496:
1497: dOperations[4] = new MBeanOperationInfo(
1498: "removeAttribute",
1499: "removeAttribute(String key): remove application parameter",
1500: params, "void", MBeanOperationInfo.ACTION);
1501:
1502: params = null;
1503:
1504: dOperations[5] = new MBeanOperationInfo(
1505: "getSessionManager",
1506: "getSessionManager(): "
1507: + "Get an SessionManager object.",
1508: params,
1509: "com.lutris.appserver.server.session.SessionManager",
1510: MBeanOperationInfo.ACTION);
1511:
1512: dOperations[6] = new MBeanOperationInfo(
1513: "getEncodeUrlState",
1514: "getEncodeUrlState(): "
1515: + "Get the value indicating the url encoding status.",
1516: params,
1517: "com.lutris.appserver.server.session.SessionManager",
1518: MBeanOperationInfo.ACTION);
1519:
1520: if (includeAdditional) {
1521: dOperations[7] = new MBeanOperationInfo(
1522: "activeSessionCount",
1523: "activeSessionCount(): "
1524: + "Gets the number of currently active sessions.",
1525: params, "int", MBeanOperationInfo.ACTION);
1526:
1527: dOperations[8] = new MBeanOperationInfo(
1528: "getSessionKeys",
1529: "getSessionKeys(): "
1530: + "Get an enumeration of all session keys. ",
1531: params, "java.util.Enumeration",
1532: MBeanOperationInfo.ACTION);
1533:
1534: params = new MBeanParameterInfo[1];
1535: params[0] = new MBeanParameterInfo("sessionKey",
1536: "java.lang.String",
1537: "The String used to reference a Session object.");
1538:
1539: dOperations[9] = new MBeanOperationInfo(
1540: "sessionExists",
1541: "sessionExists(String sessionKey): "
1542: + "Returns whether the Session object "
1543: + "associated with the specified session key exists",
1544: params, "boolean", MBeanOperationInfo.ACTION);
1545:
1546: dOperations[10] = new MBeanOperationInfo(
1547: "getSession",
1548: "getSession(String sessionKey): "
1549: + "Returns the Session object associated with the "
1550: + "specified session key. The session is put in the "
1551: + "ACTIVE state.", params,
1552: "com.lutris.appserver.server.session.Session",
1553: MBeanOperationInfo.ACTION);
1554:
1555: dOperations[11] = new MBeanOperationInfo(
1556: "createSession",
1557: "createSession(String sessionKey): "
1558: + "Create a new Session object and an associated "
1559: + "unique random key. No <CODE>User</CODE> object is "
1560: + "initially associated with the session",
1561: params,
1562: "com.lutris.appserver.server.session.Session",
1563: MBeanOperationInfo.ACTION);
1564:
1565: dOperations[12] = new MBeanOperationInfo(
1566: "deleteSession",
1567: "deleteSession(String sessionKey): "
1568: + "Removes a session from the manager.",
1569: params,
1570: "com.lutris.appserver.server.session.Session",
1571: MBeanOperationInfo.ACTION);
1572: }
1573: return dOperations;
1574: }
1575:
1576: }
1577:
1578: private void registerPresentationManagerMBean() {
1579: if (appName == null) {
1580: return;
1581: }
1582:
1583: try {
1584: server = findMBeanServer();
1585: if (server == null) {
1586: return;
1587: }
1588: } catch (Exception e) {
1589: logChannel.write(Logger.DEBUG, e.toString());
1590: }
1591:
1592: try {
1593: String applicationName = appName;
1594:
1595: ObjectName objectName = new ObjectName(
1596: "EnhydraApplications:type=PresentationManager,name="
1597: + applicationName);
1598:
1599: if (!server.isRegistered(objectName)) {
1600: String[] includes = { "PresentationManager" };
1601: String[] excludes = null;
1602: presentationManagerMBean = new PresentationManagerMBean(
1603: this , objectName, "PresentationManager",
1604: includes, excludes);
1605: server.registerMBean(presentationManagerMBean,
1606: objectName);
1607: }
1608:
1609: } catch (Exception e) {
1610: logChannel.write(Logger.DEBUG, e.toString());
1611: return;
1612: }
1613: }
1614:
1615: private void unRegisterPresentationManagerMBean() {
1616: if (appName == null) {
1617: return;
1618: }
1619:
1620: try {
1621: server = findMBeanServer();
1622: if (server == null) {
1623: return;
1624: }
1625: } catch (Exception e) {
1626: logChannel.write(Logger.DEBUG, e.toString());
1627: }
1628:
1629: try {
1630: String applicationName = appName;
1631:
1632: ObjectName objectName = new ObjectName(
1633: "EnhydraApplications:type=PresentationManager,name="
1634: + applicationName);
1635:
1636: if (server.isRegistered(objectName)) {
1637: server.unregisterMBean(objectName);
1638: }
1639:
1640: } catch (Exception e) {
1641: logChannel.write(Logger.DEBUG, e.toString());
1642: return;
1643: }
1644: }
1645:
1646: /**
1647: * PresentationManager MBean
1648: */
1649: private class PresentationManagerMBean extends EafConfigMBean {
1650:
1651: /**
1652: * PresentationManager MBean Constructor method
1653: */
1654: public PresentationManagerMBean(Application application,
1655: ObjectName objectName, String prefix,
1656: String[] includes, String[] excludes) {
1657: super (application, objectName, prefix, includes, excludes);
1658: buildDynamicMBeanInfo();
1659: }
1660:
1661: /**
1662: * Sets the value of the specified attribute of the Dynamic MBean.
1663: */
1664: public void setAttribute(Attribute attribute)
1665: throws AttributeNotFoundException,
1666: InvalidAttributeValueException, MBeanException,
1667: ReflectionException {
1668:
1669: super .setAttribute(attribute);
1670:
1671: // restart without MBean UnRegistration
1672: shutdownWithoutMBeanUnRegistration();
1673: try {
1674: startup(config);
1675: } catch (Exception e) {
1676: logChannel.write(Logger.DEBUG, e.toString());
1677: }
1678: }
1679:
1680: /**
1681: * Allows an operation to be invoked on the Dynamic MBean.
1682: */
1683: public Object invoke(String operationName, Object params[],
1684: String signature[]) throws MBeanException,
1685: ReflectionException {
1686: // PresentationManager additional functionalities
1687: if (operationName.equals("flushCache")) {
1688: try {
1689: presentationManager.flushCache();
1690: } catch (Exception e) {
1691: throw new MBeanException(e);
1692: }
1693: return null;
1694: } else if (operationName.equals("sizeofPOCache")) {
1695: int temp = 0;
1696: try {
1697: temp = presentationManager.sizeofPOCache();
1698: } catch (Exception e) {
1699: throw new MBeanException(e);
1700: }
1701: return new Integer(temp);
1702: } else if (operationName.equals("sizeofResourceCache")) {
1703: int temp = 0;
1704: try {
1705: temp = presentationManager.sizeofResourceCache();
1706: } catch (Exception e) {
1707: throw new MBeanException(e);
1708: }
1709: return new Integer(temp);
1710: } else if (operationName.equals("addMimeType")) {
1711: if (params != null && params.length == 2) {
1712: presentationManager.addMimeType((String) params[0],
1713: (String) params[1]);
1714: }
1715: return null;
1716: } else if (operationName.equals("getPresentationManager")) {
1717: try {
1718: return presentationManager;
1719: } catch (Exception e) {
1720: throw new MBeanException(e);
1721: }
1722: } else {
1723: // basic set of operations
1724: return super .invoke(operationName, params, signature);
1725: }
1726: }
1727:
1728: /**
1729: * Method returns MBeanOperationInfo
1730: * @return MBeanOperationInfo[]
1731: */
1732: protected MBeanOperationInfo[] getMBeanOperationsInfo() {
1733: MBeanParameterInfo[] params = null;
1734: MBeanOperationInfo[] dOperations = new MBeanOperationInfo[10];
1735: dOperations[0] = new MBeanOperationInfo(
1736: "reset",
1737: "reset(): reset attributes to their initial values",
1738: params, "void", MBeanOperationInfo.ACTION);
1739: dOperations[1] = new MBeanOperationInfo(
1740: "saveAttributes",
1741: "saveAttributes(): save the attribute values into the configuration file",
1742: params, "void", MBeanOperationInfo.ACTION);
1743: dOperations[2] = new MBeanOperationInfo("getAppInfo",
1744: "getAppInfo(): get application information",
1745: params, "String", MBeanOperationInfo.ACTION);
1746:
1747: params = new MBeanParameterInfo[2];
1748: params[0] = new MBeanParameterInfo(
1749: "attKey",
1750: "java.lang.String",
1751: "Attribute name! Please, "
1752: + "use UNDERLINE (_) as attribute group separator.");
1753: params[1] = new MBeanParameterInfo("attValue",
1754: "java.lang.String", "Attribute value!");
1755:
1756: dOperations[3] = new MBeanOperationInfo(
1757: "addAttribute",
1758: "addAttribute(String key, String value): add new application parameter",
1759: params, "void", MBeanOperationInfo.ACTION);
1760:
1761: params = new MBeanParameterInfo[1];
1762: params[0] = new MBeanParameterInfo(
1763: "attKey",
1764: "java.lang.String",
1765: "Attribute name! Please, "
1766: + "use UNDERLINE (_) as attribute group separator.");
1767:
1768: dOperations[4] = new MBeanOperationInfo(
1769: "removeAttribute",
1770: "removeAttribute(String key): remove application parameter",
1771: params, "void", MBeanOperationInfo.ACTION);
1772:
1773: params = null;
1774:
1775: dOperations[5] = new MBeanOperationInfo(
1776: "getPresentationManager",
1777: "getPresentationManager(): Gets actual PresentationManager object reference.",
1778: params,
1779: "com.lutris.appserver.server.httpPresentation.HttpPresentationManager",
1780: MBeanOperationInfo.ACTION);
1781:
1782: dOperations[6] = new MBeanOperationInfo(
1783: "flushCache",
1784: "flushCache(): Flush the presentation object and resource caches",
1785: params, "void", MBeanOperationInfo.ACTION);
1786:
1787: dOperations[7] = new MBeanOperationInfo(
1788: "sizeofPOCache",
1789: "sizeofPOCache(): the number of entries in the cache or 0 is disabled",
1790: params, "int", MBeanOperationInfo.ACTION);
1791:
1792: dOperations[8] = new MBeanOperationInfo(
1793: "sizeofResourceCache",
1794: "sizeofResourceCache(): number of entries in the cache or 0 is disabled",
1795: params, "int", MBeanOperationInfo.ACTION);
1796:
1797: params = new MBeanParameterInfo[2];
1798: params[0] = new MBeanParameterInfo("mimeType",
1799: "java.lang.String", "Mime Type you want to add!");
1800: params[1] = new MBeanParameterInfo("extension",
1801: "java.lang.String",
1802: "Extension of Mime Type you want to add!");
1803:
1804: dOperations[9] = new MBeanOperationInfo(
1805: "addMimeType",
1806: "addMimeType(String mimeType, String extension): Add a new mime type to extension mapping.",
1807: params, "void", MBeanOperationInfo.ACTION);
1808:
1809: return dOperations;
1810: }
1811:
1812: }
1813:
1814: private void registerContextMBean() {
1815: if (appName == null) {
1816: return;
1817: }
1818:
1819: try {
1820: server = findMBeanServer();
1821: if (server == null) {
1822: return;
1823: }
1824: } catch (Exception e) {
1825: logChannel.write(Logger.DEBUG, e.toString());
1826: }
1827:
1828: try {
1829: String applicationName = appName;
1830: ObjectName objectName = new ObjectName(
1831: "EnhydraApplications:type=Context,name="
1832: + applicationName);
1833: if (!server.isRegistered(objectName)) {
1834:
1835: contextMBean = new ContextMBean(this );
1836: if (contextMBean != null) {
1837: server.registerMBean(contextMBean, objectName);
1838: }
1839: }
1840: } catch (Exception e) {
1841: e.printStackTrace();
1842: logChannel.write(Logger.DEBUG, e.toString());
1843: return;
1844: }
1845: }
1846:
1847: private void unRegisterContextMBean() {
1848: if (appName == null) {
1849: return;
1850: }
1851:
1852: try {
1853: server = findMBeanServer();
1854: if (server == null) {
1855: return;
1856: }
1857: } catch (Exception e) {
1858: logChannel.write(Logger.DEBUG, e.toString());
1859: }
1860:
1861: try {
1862: String applicationName = appName;
1863: ObjectName objectName = new ObjectName(
1864: "EnhydraApplications:type=Context,name="
1865: + applicationName);
1866: if (server.isRegistered(objectName)) {
1867: server.unregisterMBean(objectName);
1868: }
1869: contextMBean = null;
1870: } catch (Exception e) {
1871: logChannel.write(Logger.DEBUG, e.toString());
1872: return;
1873: }
1874: }
1875:
1876: public static class ContextMBean implements DynamicMBean {
1877:
1878: private String appName = null;
1879: private String appContext = null;
1880: private String appRealContext = null;
1881:
1882: protected String dClassName = this .getClass().getName();
1883: protected MBeanInfo dMBeanInfo = null;
1884:
1885: public ContextMBean(Application application) {
1886: appName = application.getName();
1887: try {
1888: appRealContext = application
1889: .getHttpPresentationManager()
1890: .getServletContext().getRealPath("/");
1891: appContext = application.getHttpPresentationManager()
1892: .getServletContext().getServletContextName();
1893: if (appContext == null) {
1894: if (appRealContext.endsWith(java.io.File.separator)) {
1895: appContext = appRealContext.substring(0,
1896: appRealContext.length() - 1);
1897: } else {
1898: appContext = appRealContext;
1899: }
1900: int temp = appContext
1901: .lastIndexOf(java.io.File.separator);
1902: if (temp != -1)
1903: appContext = appContext.substring(temp + 1);
1904: }
1905:
1906: } catch (Exception except) {
1907: except.printStackTrace();
1908: }
1909:
1910: buildDynamicMBeanInfo();
1911: }
1912:
1913: public String getAppContext() {
1914: return appContext;
1915: }
1916:
1917: public String getAppRealContext() {
1918: return appRealContext;
1919: }
1920:
1921: public String getAppName() {
1922: return appName;
1923: }
1924:
1925: public void buildDynamicMBeanInfo() {
1926: // MBeanInfo initialization
1927: dMBeanInfo = new MBeanInfo(dClassName, getDescription(),
1928: getMBeanAttributesInfo(),
1929: getMBeanConstructorInfo(),
1930: getMBeanOperationsInfo(),
1931: getMBeanNotificationInfo());
1932: }
1933:
1934: /**
1935: * -----------------------------------------------------
1936: * ADDITIONALL PROTECTED METHODS
1937: * -----------------------------------------------------
1938: */
1939:
1940: /**
1941: * Method returns MBean's MBeanAttributeInfo Array
1942: * @return MBeanAttributeInfo[]
1943: */
1944: protected MBeanAttributeInfo[] getMBeanAttributesInfo() {
1945: MBeanAttributeInfo[] dAttributes = new MBeanAttributeInfo[0];
1946: return dAttributes;
1947: }
1948:
1949: /**
1950: * Method returns MBean's MBeanOperationInfo Array
1951: * @return MBeanOperationInfo[]
1952: */
1953: protected MBeanOperationInfo[] getMBeanOperationsInfo() {
1954: MBeanParameterInfo[] params = null;
1955: MBeanOperationInfo[] dOperations = new MBeanOperationInfo[3];
1956: dOperations[0] = new MBeanOperationInfo("getAppName",
1957: "getAppName(): returns ApplicationName", params,
1958: "java.lang.String", MBeanOperationInfo.ACTION);
1959: dOperations[1] = new MBeanOperationInfo(
1960: "getAppContext",
1961: "getAppContext(): returns value of appliation context",
1962: params, "java.lang.String",
1963: MBeanOperationInfo.ACTION);
1964: dOperations[2] = new MBeanOperationInfo(
1965: "getAppRealContext",
1966: "getAppRealContext(): returns value of appliation real context",
1967: params, "java.lang.String",
1968: MBeanOperationInfo.ACTION);
1969:
1970: return dOperations;
1971: }
1972:
1973: /**
1974: * Method returns MBean's MBeanNotificationInfo Array
1975: * @return MBeanNotificationInfo[]
1976: */
1977: protected MBeanNotificationInfo[] getMBeanNotificationInfo() {
1978: MBeanNotificationInfo[] dNotifications = new MBeanNotificationInfo[0];
1979: return dNotifications;
1980: }
1981:
1982: /**
1983: * Method returns MBean's MBeanConstructorInfo Array
1984: * @return MBeanConstructorInfo[]
1985: */
1986: protected MBeanConstructorInfo[] getMBeanConstructorInfo() {
1987: MBeanParameterInfo[] dParameters = new MBeanParameterInfo[1];
1988: dParameters[0] = new MBeanParameterInfo("application",
1989: "com.lutris.appserver.server.Application",
1990: "Application Object");
1991:
1992: MBeanConstructorInfo[] dConstructors = new MBeanConstructorInfo[1];
1993: dConstructors[0] = new MBeanConstructorInfo("ContextMBean",
1994: "Context MBean Object Constructor", dParameters);
1995:
1996: return dConstructors;
1997: }
1998:
1999: /**
2000: * Method returns MBean's description
2001: * @return String
2002: */
2003: protected String getDescription() {
2004: String dDescription = "Dynamic MBean offers application base context data";
2005: return dDescription;
2006: }
2007:
2008: /*
2009: * -----------------------------------------------------
2010: * IMPLEMENTATION OF THE DynamicMBean INTERFACE
2011: * -----------------------------------------------------
2012: */
2013:
2014: /**
2015: * Allows the value of the specified attribute of the Dynamic MBean to be obtained.
2016: */
2017: public Object getAttribute(String attribute_name)
2018: throws AttributeNotFoundException, MBeanException,
2019: ReflectionException {
2020: // not implemented
2021: return null;
2022: }
2023:
2024: /**
2025: * Sets the value of the specified attribute of the Dynamic MBean.
2026: */
2027: public void setAttribute(Attribute attribute)
2028: throws AttributeNotFoundException,
2029: InvalidAttributeValueException, MBeanException,
2030: ReflectionException {
2031: //not implemented
2032: }
2033:
2034: /**
2035: * Sets the values of several attributes of the Dynamic MBean, and returns the
2036: * list of attributes that have been set.
2037: */
2038: public AttributeList setAttributes(AttributeList attributes) {
2039: // Check attributes is not null to avoid NullPointerException later on
2040: // not implemented
2041: return null;
2042: }
2043:
2044: /**
2045: * get the values of several attributes of the Dynamic MBean.
2046: */
2047: public AttributeList getAttributes(String[] attributeNames) {
2048:
2049: // Check attributeNames is not null to avoid NullPointerException later on
2050: // not implemented
2051: return null;
2052: }
2053:
2054: /**
2055: * This method provides the exposed attributes and operations of the Dynamic MBean.
2056: * It provides this information using an MBeanInfo object.
2057: */
2058: public MBeanInfo getMBeanInfo() {
2059: // return the information we want to expose for management:
2060: // the dMBeanInfo private field has been built at instanciation time,
2061: return dMBeanInfo;
2062: }
2063:
2064: /**
2065: * -----------------------------------------------------
2066: * ADDITIONALL PUBLIC METHODS
2067: * -----------------------------------------------------
2068: */
2069:
2070: /**
2071: * Allows an operation to be invoked on the Dynamic MBean.
2072: */
2073: public Object invoke(String operationName, Object params[],
2074: String signature[]) throws MBeanException,
2075: ReflectionException {
2076: // Check operationName is not null to avoid NullPointerException later on
2077: if (operationName == null) {
2078: throw new RuntimeOperationsException(
2079: new IllegalArgumentException(
2080: "Operation name cannot be null"),
2081: "Cannot invoke a null operation in "
2082: + dClassName);
2083: }
2084: // Check for a recognized operation name and call the corresponding operation
2085: if (operationName.equals("getAppName")) {
2086: return getAppName();
2087: } else if (operationName.equals("getAppContext")) {
2088: return getAppContext();
2089: } else if (operationName.equals("getAppRealContext")) {
2090: return getAppRealContext();
2091: } else {
2092: // unrecognized operation name:
2093: throw new ReflectionException(
2094: new NoSuchMethodException(operationName),
2095: "Cannot find the operation " + operationName
2096: + " in " + dClassName);
2097: }
2098: }
2099:
2100: }
2101: }
|