/* See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * Esri Inc. licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.esri.gpt.framework.context; import java.sql.Timestamp; import java.util.HashMap; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import javax.servlet.ServletRequest; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import com.esri.gpt.catalog.context.CatalogConfiguration; import com.esri.gpt.framework.collection.StringAttributeMap; import com.esri.gpt.framework.mail.MailConfiguration; import com.esri.gpt.framework.security.credentials.UsernameCredential; import com.esri.gpt.framework.security.identity.IdentityAdapter; import com.esri.gpt.framework.security.identity.IdentityConfiguration; import com.esri.gpt.framework.security.principal.User; import com.esri.gpt.framework.sql.ConnectionBroker; import com.esri.gpt.framework.util.LogUtil; import com.esri.gpt.framework.util.Val; /** * Context for a request. * <p> * This class is intended for use by a single execution thread. */ public class RequestContext { // class variables ============================================================= /** The key used to store the instance within the ServletRequest. */ public static final String REFERENCEKEY = "com.esri.gpt.framework.context.RequestContext"; /** user key */ private static final String USERKEY = "com.esri.gpt.user"; // instance variables ========================================================== private ApplicationContext _applicationContext; private ConnectionBroker _connectionBroker; private Map<String,Object> _objectMap = new HashMap<String,Object>(); private ServletRequest _servletRequest; private Timestamp _timeCompleted; private Timestamp _timeStarted; private User _user; private boolean _viewerExecutedJavascript; // constructors ================================================================ /** Default constructor. */ protected RequestContext() { this(null); } /** * Constructs with an associated servlet request. * @param request the current servlet request */ protected RequestContext(ServletRequest request) { _servletRequest = request; _timeStarted = new Timestamp(System.currentTimeMillis()); _timeCompleted = null; setApplicationContext(ApplicationContext.getInstance()); ApplicationConfiguration config = getApplicationContext().getConfiguration(); setConnectionBroker(new ConnectionBroker(config.getDatabaseReferences())); setUser(new User()); boolean bWasUserInSession = false; if (request instanceof HttpServletRequest) { HttpServletRequest httpReq = (HttpServletRequest)request; HttpSession sn = httpReq.getSession(true); User user = (User)sn.getAttribute(USERKEY); if (user == null) { sn.setAttribute(USERKEY,getUser()); } else { bWasUserInSession = true; setUser(user); } user = getUser(); // check for single sign-on if (getIdentityConfiguration().getSingleSignOnMechanism().getActive()) { if (Val.chkStr(user.getKey()).startsWith("urn:openid:")) return; String sPrevious = user.getName(); String sUsername = getIdentityConfiguration().getSingleSignOnMechanism().determineUsername(httpReq); if (!sPrevious.equals(sUsername)) { if (bWasUserInSession) { setUser(new User()); sn.setAttribute(USERKEY,getUser()); user = getUser(); } if (sUsername.length() > 0) { user.setCredentials(new UsernameCredential(sUsername)); try { newIdentityAdapter().authenticate(user); } catch (Exception e) { String sMsg = "An error occured while evaluating single sign-on credentials for: "+sUsername; setUser(new User()); sn.setAttribute(USERKEY,getUser()); getLogger().log(Level.SEVERE,sMsg,e); } finally { this.getConnectionBroker().closeAll(); } } } } } } // properties ================================================================== /** * Gets the application configuration. * @return the application configuration */ public ApplicationConfiguration getApplicationConfiguration() { return getApplicationContext().getConfiguration(); } /** * Gets the context for this application. * @return the ApplicationContext */ public ApplicationContext getApplicationContext() { return _applicationContext; } /** * Sets the context for this application. * @param context the ApplicationContext */ private void setApplicationContext(ApplicationContext context) { _applicationContext = context; if (_applicationContext == null) { _applicationContext = ApplicationContext.getInstance(); } } /** * Gets the metadata catalog configuration associated with this application. * @return the catalog configuration */ public CatalogConfiguration getCatalogConfiguration() { return getApplicationConfiguration().getCatalogConfiguration(); } /** * Gets the broker for database access. * @return the database connection broker */ public ConnectionBroker getConnectionBroker() { return _connectionBroker; } /** * Sets the broker for database access. * @param broker the database connection broker */ private void setConnectionBroker(ConnectionBroker broker) { _connectionBroker = broker; } /** * Gets the identity configuration associated with this application. * @return the identity configuration */ public IdentityConfiguration getIdentityConfiguration() { return getApplicationConfiguration().getIdentityConfiguration(); } /** * Gets the logger. * @return the logger */ public Logger getLogger() { return LogUtil.getLogger(); } /** * Gets the mail configuration associated with this application. * @return the mail configuration */ public MailConfiguration getMailConfiguration() { return getApplicationConfiguration().getMailConfiguration(); } /** * Gets underlying servlet request. * <br/>This is only available if it was passed on the coonstructor. * @return the underlying servlet request (can be null) */ public ServletRequest getServletRequest() { return _servletRequest; } /** * Gets the free form object map associated with this request. * <br/>This map can be used in a manner similar to the attributes * of a ServletRequest. * @return the free form object map */ public Map<String,Object> getObjectMap() { return _objectMap; } /** * Gets the user associated with this request. * @return the user */ public User getUser() { return _user; } /** * Sets the user associated with this request. * @param user the user */ protected void setUser(User user) { _user = user; } /** * Gets the viewer executes javascript. * * @return the viewer executed javascript */ public boolean getViewerExecutesJavascript() { return _viewerExecutedJavascript; } /** * Sets the viewer executes javascript. * * @param viewerExecutedJavascript the new viewer executed javascript */ public void setViewerExecutesJavascript(boolean viewerExecutedJavascript) { this._viewerExecutedJavascript = viewerExecutedJavascript; } // methods ===================================================================== /** * Extracts the request context from the current servlet request. * @param request the current servlet request * @return the request context */ public static RequestContext extract(ServletRequest request) { String sKey = REFERENCEKEY; RequestContext requestContext = null; if (request == null) { requestContext = new RequestContext(); } else { requestContext = (RequestContext)request.getAttribute(sKey); if (requestContext == null) { requestContext = new RequestContext(request); request.setAttribute(sKey,requestContext); } } return requestContext; } /** * Resolves the base context path associated with an HTTP request. * <br/>(<i>http://<host:port>/<Context></i>) * <p/> * If a reverse proxy base URL hase been configured, it will be returned: * <br/> * /gptConfig/catalog/parameter@key="reverseProxy.baseContextPath" * @return the base context path */ public static String resolveBaseContextPath(HttpServletRequest request) { if (request == null) return ""; StringAttributeMap params = null; RequestContext ctx = (RequestContext)request.getAttribute(REFERENCEKEY); if (ctx != null) { params = ctx.getCatalogConfiguration().getParameters(); } else { params = ApplicationContext.getInstance().getConfiguration().getCatalogConfiguration().getParameters(); } String basePath = Val.chkStr(params.getValue("reverseProxy.baseContextPath")); if (basePath.length() == 0) { StringBuffer requestURL = request.getRequestURL(); String ctxPath = request.getContextPath(); basePath = requestURL.substring(0,requestURL.indexOf(ctxPath)+ctxPath.length()); } return basePath; } /** * Instantiates a new Identity adapter. * @return the new identity adapter */ public IdentityAdapter newIdentityAdapter() { IdentityAdapter idAdapter = getApplicationConfiguration().newIdentityAdapter(); idAdapter.setRequestContext(this); return idAdapter; } /** * Flags the end of the execution phase of a request. * <br/>Database connections accessed during the request are freed by this method. * <br/>This method must be triggered by the controller managing this request context. */ public void onExecutionPhaseCompleted() { getConnectionBroker().closeAll(); if (_timeCompleted == null) { _timeCompleted = new Timestamp(System.currentTimeMillis()); } } /** * Flags the end of the execution phase of a request. * <br/>Database connections accessed during the request are freed by this method. * <br/>This method must be triggered by the controller if the previewView * event has been invoked. */ public void onPrepareViewCompleted() { getConnectionBroker().closeAll(); } /** * Adds the to session. Placed in central class so that inner * classes do not have to work with the http session object. * * @param key the key * @param obj the obj */ public void addToSession(String key, Object obj) { ServletRequest request = this.getServletRequest(); if(!(request instanceof HttpServletRequest)) { return; } HttpServletRequest hRequest = (HttpServletRequest) request; HttpSession session = hRequest.getSession(true); session.setAttribute(key, obj); } /** * Extract an object from session. * * @param key the key * * @return the object (possibly null) */ public Object extractFromSession(String key) { ServletRequest request = this.getServletRequest(); if(!(request instanceof HttpServletRequest)) { return null; } HttpServletRequest hRequest = (HttpServletRequest) request; HttpSession session = hRequest.getSession(true); return session.getAttribute(key); } }