blob: cdcfae2d07f5dee14fc1674e601dfae37e04bc62 [file] [log] [blame]
/*
* Copyright 1999-2004 The Apache Software Foundation.
*
* Licensed 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 org.apache.cocoon.jxpath;
import java.util.Map;
import org.apache.avalon.excalibur.pool.Recyclable;
import org.apache.avalon.framework.component.Component;
import org.apache.avalon.framework.context.Context;
import org.apache.avalon.framework.context.ContextException;
import org.apache.avalon.framework.context.Contextualizable;
import org.apache.cocoon.components.ContextHelper;
import org.apache.cocoon.environment.ObjectModelHelper;
import org.apache.cocoon.environment.Request;
import org.apache.cocoon.environment.Session;
import org.apache.cocoon.environment.http.HttpContext;
import org.apache.cocoon.environment.http.HttpRequest;
import org.apache.cocoon.environment.http.HttpSession;
import org.apache.commons.jxpath.JXPathContext;
import org.apache.commons.jxpath.JXPathContextFactory;
import org.apache.commons.jxpath.JXPathIntrospector;
import org.apache.commons.jxpath.servlet.Constants;
import org.apache.commons.jxpath.servlet.KeywordVariables;
/**
* Component that allocate and cache JXPathContexts bound to VariableContext,
* Cocoon Request, Cocoon Session and Cocoon Context.
* <p>
* If you need to limit the attibute lookup to just one scope, you can use the
* pre-definded variables "request", "session" and "application".
* For example, the expression "$session/foo" extracts the value of the
* session attribute named "foo".
* <p>
* Following are some implementation details.
* There is a separate JXPathContext for each of the four scopes. These contexts are chained
* according to the nesting of the scopes. So, the parent of the "variable"
* JXPathContext is a "request" JXPathContext, whose parent is a "session"
* JXPathContext (that is if there is a session), whose parent is an "application"
* context.
* <p>
* Since JXPath chains lookups for variables and extension functions, variables
* and extension function declared in the outer scopes are also available in
* the inner scopes.
* <p>
* The "session" variable will be undefined if there is no session for this servlet.
* JXPath does not automatically create sessions.
*
* @author <a href="mailto:volker.schmitt@basf-it-services.com">Volker Schmitt</a>
* @version CVS $Id: JXPathCocoonContexts.java,v 1.5 2004/03/05 13:02:24 bdelacretaz Exp $
*/
public final class JXPathCocoonContexts implements Component, Contextualizable, Recyclable {
public static final String ROLE = JXPathCocoonContexts.class.getName();
private static JXPathContextFactory factory;
private JXPathContext variableContext;
private Context context;
static {
factory = JXPathContextFactory.newInstance();
JXPathIntrospector.registerDynamicClass(HttpRequest.class, CocoonRequestHandler.class);
JXPathIntrospector.registerDynamicClass(HttpSession.class, CocoonSessionHandler.class);
JXPathIntrospector.registerDynamicClass(HttpContext.class, CocoonContextHandler.class);
}
/* (non-Javadoc)
* @see org.apache.avalon.framework.context.Contextualizable#contextualize(org.apache.avalon.framework.context.Context)
*/
public void contextualize(Context context)
throws ContextException {
this.context = context;
}
public final JXPathContext getVariableContext() {
if (variableContext == null) {
JXPathContext parentContext = getRequestContext();
variableContext = factory.newContext(parentContext, null);
}
return variableContext;
}
/**
* Returns a JXPathContext bound to the "request" scope. Caches that context
* within the request itself.
*/
public final JXPathContext getRequestContext() {
Map objectModel = ContextHelper.getObjectModel(this.context);
Request request = ObjectModelHelper.getRequest(objectModel);
JXPathContext context = (JXPathContext) request.getAttribute(Constants.JXPATH_CONTEXT);
if (context == null) {
org.apache.cocoon.environment.Context cocoonContext = ObjectModelHelper.getContext(objectModel);
JXPathContext parentContext = null;
Session session = request.getSession(false);
if (session != null) {
parentContext = getSessionContext(session, cocoonContext);
} else {
parentContext = getApplicationContext(cocoonContext);
}
if (request.getClass() != HttpRequest.class)
JXPathIntrospector.registerDynamicClass(request.getClass(), CocoonRequestHandler.class);
context = factory.newContext(parentContext, request);
context.setVariables(new KeywordVariables(Constants.REQUEST_SCOPE, request));
request.setAttribute(Constants.JXPATH_CONTEXT, context);
}
return context;
}
/**
* Returns a JXPathContext bound to the "session" scope. Caches that context
* within the session itself.
*/
public final JXPathContext getSessionContext(Session session, org.apache.cocoon.environment.Context cocoonContext) {
JXPathContext context = (JXPathContext) session.getAttribute(Constants.JXPATH_CONTEXT);
if (context == null) {
if (session.getClass() != HttpSession.class)
JXPathIntrospector.registerDynamicClass(session.getClass(), CocoonSessionHandler.class);
JXPathContext parentContext = getApplicationContext(cocoonContext);
context = factory.newContext(parentContext, session);
context.setVariables(new KeywordVariables(Constants.SESSION_SCOPE, session));
session.setAttribute(Constants.JXPATH_CONTEXT, context);
}
return context;
}
/**
* Returns a JXPathContext bound to the "application" scope. Caches that context
* within the servlet context itself.
*/
public final JXPathContext getApplicationContext(org.apache.cocoon.environment.Context cocoonContext) {
JXPathContext context = (JXPathContext) cocoonContext.getAttribute(Constants.JXPATH_CONTEXT);
if (context == null) {
if (cocoonContext.getClass() != HttpContext.class)
JXPathIntrospector.registerDynamicClass(cocoonContext.getClass(), CocoonContextHandler.class);
context = factory.newContext(null, cocoonContext);
context.setVariables(new KeywordVariables(Constants.APPLICATION_SCOPE, cocoonContext));
cocoonContext.setAttribute(Constants.JXPATH_CONTEXT, context);
}
return context;
}
/*
* @see Recyclable#recycle()
*/
public void recycle() {
this.variableContext = null;
}
}