/** Copyright (c) Oracle Corporation 1998. All Rights Reserved. */ package oracle.jbo.html.jsp; import java.io.PrintWriter; import java.io.OutputStream; import java.io.FileInputStream; import java.io.InputStream; import java.util.Vector; import java.util.Enumeration; import java.util.StringTokenizer; import java.util.Properties; import java.util.Hashtable; import com.sun.java.util.collections.HashMap; import oracle.jbo.ApplicationModule; import oracle.jbo.domain.TypeFactory; import oracle.jdeveloper.html.WebBeanImpl; import oracle.jdeveloper.cm.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.Cookie; import javax.servlet.http.HttpSession; import javax.servlet.jsp.PageContext; import oracle.jbo.common.ampool.PoolMgr; import oracle.jbo.common.ampool.ApplicationPool; import oracle.jbo.common.ampool.SessionCookie; import oracle.jbo.common.ampool.SessionCookieFactory; import oracle.jbo.common.ampool.ApplicationPoolException; import oracle.jbo.common.ampool.AMPoolMessageBundle; import oracle.jbo.common.Diagnostic; import oracle.jbo.common.PropertyMetadata; import oracle.jbo.common.PropertyConstants; import oracle.jbo.common.JBOClass; import oracle.jbo.http.HttpContainer; import oracle.jbo.http.ApplicationBindingListener; import oracle.jbo.http.HttpSessionCookieFactory; import oracle.jbo.http.HttpSessionCookieHelper; import oracle.jbo.http.HttpSessionCookieHelperManager; import oracle.jbo.html.HtmlServices; import oracle.jbo.html.jsp.datatags.ReleasePageResourcesTag; /** ** This class provides the main interface for DataWebBeans to use the Application Module Pool. ** ** View implementation of JSPApplicationRegistry ** ** @author Juan Oropeza ** @version PUBLIC ** **/ public class JSPApplicationRegistry extends WebBeanImpl { static JSPApplicationRegistry mInstance = new JSPApplicationRegistry(); static PoolMgr mPoolManager = PoolMgr.getInstance(); private static final String TIMEOUT_HANDLER_SUFFIX = "_TimeoutHandler"; public static final String RESERVED = PropertyConstants.AM_RELEASE_RESERVED; public static final String STATEFUL = PropertyConstants.AM_RELEASE_STATEFUL; public static final String STATELESS = PropertyConstants.AM_RELEASE_STATELESS; private static final String SESSION_INITIALIZED = "SessionInitialized"; private static Hashtable mLoadedProperties = new Hashtable(); /** ** Constructor, this should not be called directly **/ public JSPApplicationRegistry() { } /** ** Returns the singleton instance of the registry class. **/ static public JSPApplicationRegistry getInstance() { return mInstance; } /** ** Returns the user data associated with the named pool. The user data is a convenient palce for storing ** and retrieving application-specific information shared by all application instances that are part of the ** named pool. **/ static synchronized public Hashtable getAppSettings(String poolName) { ApplicationPool pool = mPoolManager.getPool(poolName); return (Hashtable)pool.getUserData(); } /** * Release the specified application module instance. This method is * intended for use by servlet clients in order to release an application * module resource to the application module pool.
** The specified release mode will determine how the application module is * returned to the pool. The following release modes are currently * supported:
** RESERVED: Do not allow the application module instance to be * shared with other client requests. The reserved lock will be released * when the application module is checked in by a latter request in the * application life cycle or when the http session times out.
** STATEFUL: Only available if a HttpServletResponse has been * specified. The implementation will check the application module * instance into the pool in a stateful manner which will allow the pool * to maintain the application module state between session requests. * This may involve passivating the session's application module state so * that the application may be reused by other session requests. Using * this option will cause a servlet cookie to be generated and written * to the HttpServletResponse.
** STATELESS: Check the application module instance into the pool * without retaining application module state.
* * @see oracle.jbo.common.ampool.ApplicationPool ApplicationPool * * @deprecated * @since 5.0 * @see oracle.jbo.http.HttpContainer * @see oracle.jbo.http.HttpSessionCookie */ public void releaseAppModuleInstance( String applicationId , ApplicationModule appModule , ApplicationPool pool , HttpSession session , HttpServletResponse response , String releaseMode) { // Only proceed if the application is not available. Otherwise, // the application module has been successfully checked in already. // This check is necessary to prevent redundant check-ins to the pool. // The check is implemented here because the JSPApplicationRegistry // may potentially register two application module references in the // HTTP contexts (page and session). if (pool == null || !pool.isAvailable(appModule)) { releaseAppModuleInstance(applicationId, session, response, releaseMode); } } /** * @deprecated * @since 5.0 * @see oracle.jbo.http.HttpContainer * @see oracle.jbo.http.HttpSessionCookie */ public void releaseAppModuleInstance( String applicationId , HttpSession session , HttpServletResponse response , String releaseMode) { HttpContainer container = HttpContainer.getInstanceFromSession(session); SessionCookie cookie = container.getSessionCookie(applicationId); // If the application release mode has been specified as reserved // then promote the application module to the session level context. // The application module will be checked in if it is used in a page // again with a release mode other than reserved or if the session // times out. if (JSPApplicationRegistry.RESERVED.equals(releaseMode)) { Diagnostic.println("ApplicationModule release mode is: Reserved"); cookie.releaseApplicationModule( false // checkin , true); // manageState } // If a stateful release mode has been specified then passivate // the application module and return it to the application pool. This // mode is not supported if a response object has not been specified. else if ((response != null) && (JSPApplicationRegistry.STATEFUL.equals(releaseMode))) { Diagnostic.println("ApplicationModule release mode is: Stateful"); cookie.releaseApplicationModule( true // checkin , true); // manageState cookie.writeValue(response); } // If the release mode is stateless then simply return the application // module to the pool. else { Diagnostic.println("ApplicationModule release mode is: Stateless"); cookie.releaseApplicationModule( true // checkin , false); // manageState cookie.writeValue(response); } } /** * @see #public void releaseAppModuleInstance(String, ApplicationModule, ApplicationPool, HttpSession, HttpServletResponse, String releaseMode) * * @deprecated * @since 5.0 * @see oracle.jbo.http.HttpContainer * @see oracle.jbo.http.HttpSessionCookie */ public void releaseAppModuleInstance( ApplicationModule appModule , ApplicationPool pool , HttpSession session , HttpServletResponse response , String releaseMode) { String applicationId = (String)session.getValue(appModule.toString()); releaseAppModuleInstance(applicationId, session, response, releaseMode); } /** * @see #public void releaseAppModuleInstance(String, ApplicationModule, ApplicationPool, HttpSession, HttpServletResponse, String releaseMode) * * @deprecated * @since 5.0 * @see oracle.jbo.http.HttpContainer * @see oracle.jbo.http.HttpSessionCookie */ public void releaseAppModuleInstance( ApplicationModule appModule , ApplicationPool pool , PageContext pageContext , String releaseMode) { HttpSession session = pageContext.getSession(); String applicationId = (String)session.getValue(appModule.toString()); HttpServletResponse response = (HttpServletResponse)pageContext.getResponse(); releaseAppModuleInstance(applicationId, session, response, releaseMode); } /** * Get an application module instance for the specified application pool. * This method is intended for servlet clients that require an application * module. ** The implementation will attempt to locate an application module in the * session context before asking the application pool for an application * module. *
* If an application module is not found in the session or page contexts * the implementation will check the http request for a session cookie value. * If a session cookie value exists the method will instantiate a new * (@link oracle.jbo.common.ampool.SessionCookie SessionCookie} instance * using that cookie value. If a session cookie value is not found in the * request then the method will invoke (@link #getSessionId getSessionId}. * to obtain a unique session identifier. The returned session id will be * used to instantiate a new * (@link oracle.jbo.common.ampool.SessionCookie SessionCookie} instance. *
* The SessionCookie instance generated above is passed to the application * pool during checkout. The application pool will use the session cookie * to identify the client session and to activate any application state * which may have been passivated at the end of a previous request from this * session. *
* @param applicationId the id of the requesting session application * The applicationId should match the name of the pool that was used to * generate the requested instance * * @see oracle.jdeveloper.html.DataWebBeanImpl#internalInitialize() * * @deprecated * @since 5.0 * @see oracle.jbo.http.HttpContainer * @see oracle.jbo.http.HttpSessionCookie */ public ApplicationModule getAppModuleInstance( String applicationId , HttpServletRequest request , HttpSession session) { return getAppModuleInstance( applicationId // applicationId , applicationId // poolId , null , request , null // response , session); } /** * @deprecated * @since 5.0 * @see oracle.jbo.http.HttpContainer * @see oracle.jbo.http.HttpSessionCookie */ public ApplicationModule getAppModuleInstance( String applicationId , HttpServletRequest request , HttpServletResponse response , HttpSession session) { return getAppModuleInstance( applicationId // applicationId , applicationId // poolId , null , request , response , session); } /** * @see #getAppModuleInstance(String, HttpServletRequest, HttpSession) * * @deprecated * @since 5.0 * @see oracle.jbo.http.HttpContainer * @see oracle.jbo.http.HttpSessionCookie */ public ApplicationModule getAppModuleInstance( String applicationId, PageContext pageContext) { return getAppModuleInstance( applicationId // applicationId , applicationId // poolId , pageContext , (HttpServletRequest) pageContext.getRequest() , (HttpServletResponse) pageContext.getResponse() , pageContext.getSession()); } /** * @see #getAppModuleInstance(String, HttpServletRequest, HttpSession) * * @deprecated * @since 5.0 * @see oracle.jbo.http.HttpContainer * @see oracle.jbo.http.HttpSessionCookie */ public ApplicationModule getAppModuleInstance( String applicationId, String poolName, PageContext pageContext) { return getAppModuleInstance( applicationId , poolName , pageContext , (HttpServletRequest) pageContext.getRequest() , (HttpServletResponse) pageContext.getResponse() , pageContext.getSession()); } /** * This is the where all the getAppModuleInstance comes to */ private ApplicationModule getAppModuleInstance( String applicationId , String poolName , PageContext pageContext , HttpServletRequest request , HttpServletResponse response , HttpSession session ) { ApplicationModule appModule = null; Properties cookieProps = new Properties(); cookieProps.put(HttpSessionCookieFactory.HTTP_SERVLET_REQUEST, request); SessionCookie cookie = HttpContainer.findSessionCookie( session , applicationId , poolName , (String)null , (String)null , null , cookieProps); appModule = cookie.useApplicationModule(); // Temporary fix. Necessary so that the datawebbeans may determine // the applicationId of an application module instance. Redundant. request.getSession(true).putValue(appModule.toString(), applicationId); // Place the appModule in the pageContext for backwards compatibility // purposes. We should not access this value internally. if (pageContext != null) { addAppModuleToPageContext(applicationId, appModule, pageContext); } return appModule; } /** * Check the relevant http contexts for the named application module * instance. *
* If the page context is not null then first check the page context * for a Bc4jPageContext container. If one is found then check for * the specified application module instance. Otherwise check if the * specified application module instance has been placed in the session * context.
* * @param applicationId the application module id of the requested application module * The applicationId should match the name of the pool that was used to generate * the requested instance * @param session the HttpSession context that should be checked for the * named application module instance * @param pageContext if a JSP client the name of the pageContext that * should be checked for the named application module instance. Null * otherwise. * * @deprecated * @since 5.0 * @see oracle.jbo.http.HttpContainer * @see oracle.jbo.http.HttpSessionCookie */ public ApplicationModule getAppModuleFromContexts( String applicationId , HttpSession session , PageContext pageContext) { ApplicationModule appModule = null; // Correction logic to handle a null session parameter. HttpSession httpSession = (session == null ? pageContext.getSession() : session); synchronized(httpSession) { appModule = getAppModuleFromPageContext(applicationId, applicationId, pageContext); // If the appModule was not located in the page context if (appModule == null) { appModule = getAppModuleFromSession(applicationId, session); } } return appModule; } /** * Check the http session for the named application module * instance. * * @param applicationId the id of the requested application module instance * The applicationId should match the name of the pool that was used to generate * the requested instance * @param session the HttpSession context that should be checked for the * named application module instance * * @deprecated * @since 5.0 * @see oracle.jbo.http.HttpContainer * @see oracle.jbo.http.HttpSessionCookie */ public ApplicationModule getAppModuleFromSession( String applicationId, HttpSession session) { return getAppModuleFromSession(applicationId, applicationId, session); } /** * Check the http session for the named application module * instance. * * @param applicationId the id of the requested application module instance * @param poolName the application name of the requesting thread * @param session the HttpSession context that should be checked for the * named application module instance * * @deprecated * @since 5.0 * @see oracle.jbo.http.HttpContainer * @see oracle.jbo.http.HttpSessionCookie */ public ApplicationModule getAppModuleFromSession( String applicationId , String poolName , HttpSession session) { ApplicationModule appModule = null; HttpContainer container = HttpContainer.getInstanceFromSession(session); SessionCookie cookie = container.getSessionCookie(applicationId); appModule = cookie.useApplicationModule(false); // lock return appModule; } private ApplicationModule getAppModuleFromPageContext(String applicationId, String poolName, PageContext pageContext) { ApplicationModule appModule = null; if (pageContext != null) { // Use getAttribute instead of findAttribute. findAttribute will locate // the container in the session context if not located in the pageContext. HttpContainer container = (HttpContainer)pageContext.getAttribute(HttpContainer.PAGE_CONTEXT_CONTAINER_NAME, PageContext.REQUEST_SCOPE); if (container == null) { container = new HttpContainer(pageContext); pageContext.setAttribute(HttpContainer.PAGE_CONTEXT_CONTAINER_NAME, container, PageContext.REQUEST_SCOPE); } appModule = (ApplicationModule)container.getValue(HttpContainer.APPLICATION_PREFIX + applicationId); } return appModule; } /** ** Convenience method for defining a new application pool from a property file. This also transfers some system ** specific variables to the JSP Session object. **/ static public void registerApplicationFromPropertyFile(HttpSession session, String sPropFileName) { registerApplicationFromPropertyFile(sPropFileName); synchronized(session) { if (!PropertyConstants.TRUE.equals((String)session.getValue(SESSION_INITIALIZED))) { Hashtable settings = getAppSettings(sPropFileName); int nTimeOut = 300; if (settings != null) { // see if we have a setting for the session timeout String sTimeOut; if(settings.get("HttpSessionTimeOut") != null) { sTimeOut = (String)settings.get("HttpSessionTimeOut"); if(sTimeOut != null) { nTimeOut = Integer.parseInt(sTimeOut); } } if(settings.get("ImageBase") != null) { session.putValue("ImageBase", settings.get("ImageBase")); } else { settings.put("ImageBase", "/webapp/images"); session.putValue("ImageBase", "/webapp/images"); } if(settings.get("CSSURL") != null) { session.putValue("CSSURL",settings.get("CSSURL")); } else { settings.put("CSSURL", "/webapp/css/oracle.css"); session.putValue("CSSURL", "/webapp/css/oracle.css"); } } // place default renderers into session, these will not be // exposed via config file HtmlServices.registerORDrenderer(session); session.putValue(SESSION_INITIALIZED, PropertyConstants.TRUE); } } } /** ** Creates a new application pool from the contents of a property file. Please look at the ConnectionInfo class ** for documentation of what should be contained in the property file. **/ static public void registerApplicationFromPropertyFile(String sPropFileName) { try { Properties properties = (Properties)mLoadedProperties.get(sPropFileName); ConnectionInfo connectInfo = null; boolean usingConfig = true; if (properties == null) { // open up the property file String sConfigPath = sPropFileName + ".properties"; // find the property file in the classpath System.out.println("Loading from CLASSPATH " + sConfigPath); InputStream in = JBOClass.getResourceAsStream(sConfigPath); if(in == null) { throw new RuntimeException("JSP Registry could not locate runtime property file:" + sConfigPath); } // load up the properties file properties = new Properties(); properties.load(in); in.close(); mLoadedProperties.put(sPropFileName, properties); // Backwards compatibility since 3.1 usingConfig = (properties.get("ConfigName") != null); if (!usingConfig) { // this handles backward compatibility connectInfo = new ConnectionInfo(properties); properties.put("UserName", connectInfo.sUserName); properties.put("Password", connectInfo.sPassword); } } else { // Backwards compatibility since 3.1 usingConfig = (properties.get("ConfigName") != null); if (!usingConfig) { // this handles backward compatibility connectInfo = new ConnectionInfo(properties); } } // check if we are using a configuration (this started in 3.2) ApplicationPool pool = null; if(usingConfig) { String sConfigName = properties.get("ConfigName").toString(); int index = sConfigName.lastIndexOf('.'); String sConfigPackage = sConfigName.substring(0, index); String sConfigSection = sConfigName.substring(index + 1); // strip out the am class sConfigPackage = sConfigPackage.substring(0, sConfigPackage.lastIndexOf('.')); pool = PoolMgr.getInstance().findPool( sPropFileName , sConfigPackage , sConfigSection , properties); } else { pool = PoolMgr.getInstance().findPool( sPropFileName , connectInfo.getPoolClass() , connectInfo.getAppModuleClass() , connectInfo.getConnectionUrl() , connectInfo.getConnectionSettings()); Hashtable userData = pool.getUserData(); if (userData != null && userData.isEmpty()) { pool.setUserData(properties); } } // If the user has not specified a custom session cookie factory // then make sure that the pool is setup to use the HttpSessionCookieFactory SessionCookieFactory factory = pool.getSessionCookieFactory(); if (PropertyMetadata.ENV_AMPOOL_COOKIE_FACTORY_CLASS_NAME.pDefault.equals(factory.getClass().getName())) { pool.setSessionCookieFactory(new HttpSessionCookieFactory()); } } catch (Exception ex) { ex.printStackTrace(); throw new RuntimeException(ex.toString()); } } /** * Helper method to obtain the specified application's release mode. */ public String getReleaseMode(String applicationId) { Hashtable appProps = getAppSettings(applicationId); String releaseMode = ((appProps != null) && (appProps.get(PropertyMetadata.AM_RELEASE_MODE.pName) != null)) ? (String)appProps.get(PropertyMetadata.AM_RELEASE_MODE.pName) : null; // If the stateless runtime application property value is true then set // the release mode to be stateful. Otherwise set the release mode to be // reserved. // Required for backwards compatibility with 3.1 if ((releaseMode == null) && (appProps != null) && (appProps.get(PropertyConstants.IS_STATELESS_RUNTIME) != null)) { releaseMode = ((String)appProps.get(PropertyConstants.IS_STATELESS_RUNTIME)) .equals(PropertyConstants.TRUE) ? STATEFUL : RESERVED; } // Finally, if the release mode is still null set it to be reserved. if (releaseMode == null) { releaseMode = RESERVED; } return releaseMode; } /** * @deprecated * @since 5.0 * @see oracle.jbo.http.HttpSessionCookieHelper#readCookieValue(HttpServletRequest, String) */ protected String readSessionId( HttpServletRequest request , String applicationId) { HttpContainer container = HttpContainer.getInstanceFromSession(request.getSession(true)); SessionCookie cookie = container.getSessionCookie(applicationId); String value = null; if (cookie != null) { value = cookie.readValue(request); } return value; } /** * @deprecated * @since 5.0 * @see oracle.jbo.http.HttpSessionCookieHelper#writeCookieValue(HttpServletResponse, String, String) */ protected void writeSessionId( HttpServletResponse response , String applicationId , String sessionId) { HttpSessionCookieHelper helper = HttpSessionCookieHelperManager.getHttpSessionCookieHelper(); helper.writeCookieValue(response, applicationId, sessionId); } private void addAppModuleToPageContext( String applicationId , ApplicationModule appModule , PageContext pageContext) { // Use getAttribute instead of findAttribute. findAttribute will locate // the container in the session context if not located in the pageContext. HttpContainer container = (HttpContainer)pageContext.getAttribute(HttpContainer.PAGE_CONTEXT_CONTAINER_NAME, PageContext.REQUEST_SCOPE); if (container == null) { container = new HttpContainer(pageContext); pageContext.setAttribute(HttpContainer.PAGE_CONTEXT_CONTAINER_NAME, container, PageContext.REQUEST_SCOPE); } String amKey = HttpContainer.APPLICATION_PREFIX + applicationId; if (container.getValue(amKey) == null) { container.putValue(amKey, appModule, null); } } /** * @deprecated * @since 5.0 * @see oracle.jbo.http.HttpContainer * @see oracle.jbo.http.HttpSessionCookie */ public static HttpContainer getHttpContainer(HttpSession session) { return HttpContainer.getInstanceFromSession(session); } }