blob: 7afd51567cd99a89cc78295948141a9094327787 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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 org.apache.cocoon.webapps.session.components;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.apache.avalon.framework.activity.Disposable;
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.avalon.framework.logger.AbstractLogEnabled;
import org.apache.avalon.framework.service.ServiceException;
import org.apache.avalon.framework.service.ServiceManager;
import org.apache.avalon.framework.service.ServiceSelector;
import org.apache.avalon.framework.service.Serviceable;
import org.apache.avalon.framework.thread.ThreadSafe;
import org.apache.cocoon.ProcessingException;
import org.apache.cocoon.components.ContextHelper;
import org.apache.cocoon.environment.Request;
import org.apache.cocoon.environment.Session;
import org.apache.cocoon.util.Deprecation;
import org.apache.cocoon.webapps.session.ContextManager;
import org.apache.cocoon.webapps.session.context.SessionContext;
import org.apache.cocoon.webapps.session.context.SessionContextProvider;
import org.apache.cocoon.webapps.session.context.SimpleSessionContext;
import org.apache.excalibur.source.SourceResolver;
import org.apache.excalibur.xml.xpath.XPathProcessor;
import org.xml.sax.SAXException;
/**
* Context manager
*
* @author <a href="mailto:cziegeler@apache.org">Carsten Ziegeler</a>
* @deprecated This block is deprecated and will be removed in future versions.
* @version CVS $Id$
*/
public final class DefaultContextManager
extends AbstractLogEnabled
implements Serviceable, ContextManager, ThreadSafe, Component, Contextualizable, Disposable {
/** The <code>ServiceManager</code> */
private ServiceManager manager;
/** The context */
private Context context;
/** selector for context provider */
private ServiceSelector contextSelector;
/** The xpath processor */
private XPathProcessor xpathProcessor;
/** The source resolver */
private SourceResolver resolver;
/* The list of reserved contexts */
static private final String[] reservedContextNames = {"session",
"context"};
/**
* Avalon Serviceable Interface
*/
public void service(ServiceManager manager)
throws ServiceException {
this.manager = manager;
this.contextSelector = (ServiceSelector)this.manager.lookup(SessionContextProvider.ROLE+"Selector");
this.xpathProcessor = (XPathProcessor)this.manager.lookup(XPathProcessor.ROLE);
this.resolver = (SourceResolver)this.manager.lookup(SourceResolver.ROLE);
Deprecation.logger.warn("The session-fw block is deprecated. Please use the provided alternatives instead.");
}
/**
* Get the session
*/
private Session getSession(boolean create) {
final Request request = ContextHelper.getRequest( this.context );
return request.getSession( create );
}
/**
* Get the list of contexts
*/
private Map getSessionContexts(Session session) {
Map contexts;
contexts = (Map)session.getAttribute(SessionContext.class.getName());
if (contexts == null) {
contexts = new HashMap(5, 3);
session.setAttribute(SessionContext.class.getName(), contexts);
}
return contexts;
}
/**
* Checks if the context name is a reserved context.
*/
private boolean isReservedContextName(String name) {
// synchronized (not needed)
int i, l;
boolean found;
found = false;
i = 0;
l = reservedContextNames.length;
while (i < l && found == false) {
found = reservedContextNames[i].equals(name);
i++;
}
if (!found ) {
found = false;
SessionContextProvider provider = null;
try {
provider = (SessionContextProvider)this.contextSelector.select( name );
found = true;
} catch (ServiceException ignore) {
} finally {
this.contextSelector.release(provider);
}
}
return found;
}
/**
* Get a reserved context
*/
private boolean existsReservedContext(String name)
throws ProcessingException {
// synchronized (not needed)
boolean exists = false;
SessionContextProvider provider = null;
try {
provider = (SessionContextProvider)this.contextSelector.select( name );
exists = provider.existsSessionContext( name );
} catch (ServiceException ignore) {
} finally {
this.contextSelector.release(provider);
}
return exists;
}
/**
* Get a reserved context
*/
private SessionContext getReservedContext(String name)
throws ProcessingException {
// synchronized
SessionContext context = null;
SessionContextProvider provider = null;
try {
provider = (SessionContextProvider)this.contextSelector.select( name );
synchronized (provider) {
context = provider.getSessionContext(name);
}
} catch (ServiceException ignore) {
} finally {
this.contextSelector.release(provider);
}
return context;
}
/**
* Create a new public context in the session.
* Create a new public session context for this user. If this context
* already exists no new context is created and the old one will be used
* instead.
*/
public SessionContext createContext(String name, String loadURI, String saveURI)
throws IOException, SAXException, ProcessingException {
// synchronized
if (this.getLogger().isDebugEnabled()) {
this.getLogger().debug("BEGIN createContext name=" + name +
"load=" + loadURI +
"save=" + saveURI);
}
// test arguments
if (name == null) {
throw new ProcessingException("CreateContext: Name is required");
}
Session session = this.getSession(true);
if (session == null) {
throw new ProcessingException("CreateContext: Session is required");
}
SessionContext context;
synchronized(session) {
// test for reserved context
if (this.isReservedContextName(name)) {
throw new ProcessingException("SessionContext with name " + name + " is reserved and cannot be created manually.");
}
if (this.existsContext(name)) {
context = this.getContext(name);
} else {
Map contexts = this.getSessionContexts(session);
context = new SimpleSessionContext(this.xpathProcessor, this.resolver);
context.setup(name, loadURI, saveURI);
contexts.put(name, context);
}
}
if (this.getLogger().isDebugEnabled()) {
this.getLogger().debug("END createContext context="+context);
}
return context;
}
/**
* Delete a public context in the session.
* If the context exists for this user, it and all of its information
* is deleted.
*/
public void deleteContext(String name)
throws ProcessingException {
// synchronized
if (this.getLogger().isDebugEnabled() ) {
this.getLogger().debug("BEGIN deleteContext name=" + name);
}
// test arguments
if (name == null) {
throw new ProcessingException("SessionManager.deleteContext: Name is required");
}
if (this.isReservedContextName(name)) {
throw new ProcessingException("SessionContext with name " + name + " is reserved and cannot be deleted manually.");
}
Session session = this.getSession(false);
if (session == null) {
throw new ProcessingException("SessionManager.deleteContext: Session is required");
}
synchronized(session) {
final Map contexts = this.getSessionContexts(session);
if (contexts.containsKey(name)) {
contexts.remove(name);
}
}
if (this.getLogger().isDebugEnabled() ) {
this.getLogger().debug("END deleteContext");
}
}
/**
* Get a public context.
* The session context with the given name is returned. If the context does
* not exist <CODE>null</CODE> is returned.
*/
public SessionContext getContext(String name)
throws ProcessingException {
// synchronized
if (this.getLogger().isDebugEnabled() ) {
this.getLogger().debug("BEGIN getContext name=" + name);
}
SessionContext context;
if (this.isReservedContextName(name) ) {
context = this.getReservedContext(name);
} else {
Session session = this.getSession(false);
if ( session != null) {
synchronized (session) {
final Map contexts = this.getSessionContexts( session );
context = (SessionContext)contexts.get(name);
}
} else {
context = null;
}
}
if (this.getLogger().isDebugEnabled() ) {
this.getLogger().debug("END getContext context=" + context);
}
return context;
}
/**
* Check if a context exists
*/
public boolean hasSessionContext()
throws ProcessingException {
Session session = this.getSession(false);
if (session == null) {
throw new ProcessingException("SessionManager.hasSessionContext: Session is required.");
}
synchronized (session) {
final Map contexts = this.getSessionContexts(session);
return !(contexts.isEmpty());
}
}
/**
* Check if a public context exists.
* If the session context with the given name exists, <CODE>true</CODE> is
* returned.
*/
public boolean existsContext(String name)
throws ProcessingException {
Session session = this.getSession(false);
if (session == null) {
throw new ProcessingException("SessionManager.existsContext: Session is required.");
}
synchronized (session) {
final Map contexts = this.getSessionContexts(session);
boolean result = contexts.containsKey(name);
if (!result && this.isReservedContextName(name) ) {
result = this.existsReservedContext(name);
}
return result;
}
}
/* (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;
}
/* (non-Javadoc)
* @see org.apache.avalon.framework.activity.Disposable#dispose()
*/
public void dispose() {
if ( this.manager != null) {
this.manager.release( this.contextSelector );
this.manager.release( this.xpathProcessor );
this.manager.release( this.resolver );
this.contextSelector = null;
this.xpathProcessor = null;
this.resolver = null;
this.manager = null;
}
}
}