Package org.apache.cocoon.webapps.session.components

Source Code of org.apache.cocoon.webapps.session.components.DefaultSessionManager

/*
* 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 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.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.webapps.session.ContextManager;
import org.apache.cocoon.webapps.session.SessionConstants;
import org.apache.cocoon.webapps.session.SessionManager;
import org.apache.cocoon.webapps.session.context.SessionContext;
import org.apache.cocoon.xml.XMLConsumer;
import org.apache.cocoon.xml.XMLUtils;
import org.apache.cocoon.xml.dom.DOMUtil;
import org.w3c.dom.DocumentFragment;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

/**
*  This is the default implementation of the session 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: DefaultSessionManager.java 433543 2006-08-22 06:22:54Z crossley $
*/
public final class DefaultSessionManager
extends AbstractLogEnabled
implements Serviceable, Component, ThreadSafe, SessionManager, Disposable, Contextualizable {

    /** The context */
    private Context context;
   
    /** The <code>ServiceManager</code> */
    private ServiceManager manager;

    /** The context manager */
    private ContextManager contextManager;
   
    /**
    * Avalon Serviceable Interface
    */
   public void service(ServiceManager manager)
   throws ServiceException {
       this.manager = manager;
       this.contextManager = (ContextManager)this.manager.lookup(ContextManager.ROLE);
   }

    /**
     * Avalon Disposable Interface
     */
    public void dispose() {
        if (this.manager != null ) {
            this.manager.release(this.contextManager);
            this.manager = null;
            this.contextManager = null;
        }
    }
    /**
     *  Create a new session for the user.
     *  A new session is created for this user. If the user has already a session,
     *  no new session is created and the old one is returned.
     */
    public Session createSession() {
        // synchronized
        if (this.getLogger().isDebugEnabled() ) {
            this.getLogger().debug("BEGIN createSession");
        }
        Session session = this.getSession(true);

        if (this.getLogger().isDebugEnabled() ) {
            this.getLogger().debug("END createSession session=" + session);
        }
        return session;
    }

    /**
     * Get the session for the current user.
     * If the user has no session right now, <CODE>null</CODE> is returned.
     * If createFlag is true, the session is created if it does not exist.
     */
    public Session getSession(boolean createFlag) {
        final Request request = ContextHelper.getRequest(this.context);

        // synchronized
        if (this.getLogger().isDebugEnabled() ) {
            this.getLogger().debug("BEGIN getSession create=" + createFlag);
        }
        Session session = request.getSession(createFlag);

        if (this.getLogger().isDebugEnabled() ) {
            this.getLogger().debug("END getSession session=" + session);
        }

        return session;
    }

    /**
     *  Terminate the current session.
     *  If the user has a session, this session is terminated and all of its
     *  data is deleted.
     *  @param force If this is set to true the session is terminated, if
     *                   it is set to false, the session is only terminated
     *                   if no session context is available.
     */
    public void terminateSession(boolean force)
    throws ProcessingException {
        // synchronized
        if (this.getLogger().isDebugEnabled() ) {
            this.getLogger().debug("BEGIN terminateSession force="+force);
        }

        Session session = this.getSession( false );
        if (session != null) {
            if (force || this.contextManager.hasSessionContext() ) {
                synchronized(session) {
                    session.invalidate();
                }
            }
        }
        if (this.getLogger().isDebugEnabled()) {
            this.getLogger().debug("END terminateSession");
        }
    }

    /**
     * Get information from the context.
     * A document fragment containg the xml data stored in the session context
     * with the given name is returned. If the information is not available,
     * <CODE>null</CODE> is returned.
     * @param contextName The name of the public context.
     * @param path        XPath expression specifying which data to get.
     * @return A DocumentFragment containing the data or <CODE>null</CODE>
     */
    public DocumentFragment getContextFragment(String  contextName,
                                                     String  path)
    throws ProcessingException  {
        // synchronized via context
        if (this.getLogger().isDebugEnabled() ) {
            this.getLogger().debug("BEGIN getContextFragment name=" + contextName + ", path=" + path);
        }

        // test arguments
        if (contextName == null) {
            throw new ProcessingException("SessionManager.getContextFragment: Name is required");
        }
        if (path == null) {
            throw new ProcessingException("SessionManager.getContextFragment: Path is required");
        }

        SessionContext context = this.contextManager.getContext( contextName );

        if (context == null) {
            throw new ProcessingException("SessionManager.getContextFragment: Context '" + contextName + "' not found.");
        }

        DocumentFragment frag;
        frag = context.getXML(path);

        if (this.getLogger().isDebugEnabled() ) {
            this.getLogger().debug("END getContextFragment documentFragment=" + (frag == null ? "null" : XMLUtils.serializeNode(frag, XMLUtils.createPropertiesForXML(false))));
        }
        return frag;
    }

    /**
     * Stream public context data.
     * The document fragment containing the data from a path in the
     * given context is streamed to the consumer.
     *
     * @param contextName The name of the public context.
     * @param path        XPath expression specifying which data to get.
     *
     * @return If the data is available <code>true</code> is returned,
     *         otherwise <code>false</code> is returned.
     */
    public boolean streamContextFragment(String  contextName,
                                           String  path,
                                           XMLConsumer consumer)
    throws SAXException, ProcessingException  {
        // synchronized via context
        if (this.getLogger().isDebugEnabled() ) {
            this.getLogger().debug("BEGIN streamContextFragment name=" + contextName + ", path=" + path + ", consumer"+consumer);
        }
        boolean streamed = false;

        // test arguments
        if (contextName == null) {
            throw new ProcessingException("SessionManager.streamContextFragment: Name is required");
        }
        if (path == null) {
            throw new ProcessingException("SessionManager.streamContextFragment: Path is required");
        }

        SessionContext context = this.contextManager.getContext( contextName );

        if (context == null) {
            throw new ProcessingException("SessionManager.streamContextFragment: Context '" + contextName + "' not found.");
        }

        streamed = context.streamXML(path, consumer, consumer);

        if (this.getLogger().isDebugEnabled() ) {
            this.getLogger().debug("END streamContextFragment streamed=" + streamed);
        }
        return streamed;
    }

    /**
     * Set data in a public context.
     * The document fragment containing the data is set at the given path in the
     * public session context.
     *
     * @param contextName The name of the public context.
     * @param path        XPath expression specifying where to set the data.
     * @param fragment    The DocumentFragment containing the data.
     *
     */
    public void setContextFragment(String  contextName,
                                    String  path,
                                    DocumentFragment fragment)
    throws ProcessingException  {
        // synchronized via context

        if (this.getLogger().isDebugEnabled()) {
            this.getLogger().debug("BEGIN setContextFragment name=" + contextName + ", path=" + path +
               ", fragment=" + (fragment == null ? "null" : XMLUtils.serializeNode(fragment, XMLUtils.createPropertiesForXML(false))));
        }
        // test arguments
        if (contextName == null) {
            throw new ProcessingException("SessionManager.setContextFragment: Name is required");
        }
        if (path == null) {
            throw new ProcessingException("SessionManager.setContextFragment: Path is required");
        }
        if (fragment == null) {
            throw new ProcessingException("SessionManager.setContextFragment: Fragment is required");
        }

        // get context
        SessionContext context = this.contextManager.getContext( contextName );

        // check context
        if (context == null) {
            throw new ProcessingException("SessionManager.setContextFragment: Context '" + contextName + "' not found.");
        }

        context.setXML(path, fragment);

        if (this.getLogger().isDebugEnabled() ) {
            this.getLogger().debug("END setContextFragment");
        }
    }

    /**
     * Append data in a public context.
     * The document fragment containing the data is appended at the given
     * path in the public session context.
     *
     * @param contextName The name of the public context.
     * @param path        XPath expression specifying where to append the data.
     * @param fragment    The DocumentFragment containing the data.
     *
     */
    public void appendContextFragment(String  contextName,
                                       String  path,
                                       DocumentFragment fragment)
    throws ProcessingException  {
        // synchronized via context
        if (this.getLogger().isDebugEnabled() ) {
            this.getLogger().debug("BEGIN appendContextFragment name=" + contextName +
                              ", path=" + path +
                              ", fragment=" + (fragment == null ? "null" : XMLUtils.serializeNode(fragment, XMLUtils.createPropertiesForXML(false))));
        }
        // test arguments
        if (contextName == null) {
            throw new ProcessingException("SessionManager.appendContextFragment: Name is required");
        }
        if (path == null) {
            throw new ProcessingException("SessionManager.appendContextFragment: Path is required");
        }
        if (fragment == null) {
            throw new ProcessingException("SessionManager.appendContextFragment: Fragment is required");
        }

        // get context
        SessionContext context = this.contextManager.getContext( contextName );

        // check context
        if (context == null) {
            throw new ProcessingException("SessionManager.appendContextFragment: Context '" + contextName + "' not found.");
        }

        context.appendXML(path, fragment);

        if (this.getLogger().isDebugEnabled() ) {
            this.getLogger().debug("END appendContextFragment");
        }
    }

    /**
     * Merge data in a public context.
     * The document fragment containing the data is merged at the given
     * path in the public session context.
     *
     * @param contextName The name of the public context.
     * @param path        XPath expression specifying where to merge the data.
     * @param fragment    The DocumentFragment containing the data.
     *
     */
    public void mergeContextFragment(String  contextName,
                                      String  path,
                                      DocumentFragment fragment)
    throws ProcessingException  {
        // synchronized via context
        if (this.getLogger().isDebugEnabled() ) {
            this.getLogger().debug("BEGIN mergeContextFragment name=" + contextName + ", path=" + path +
                ", fragment=" + (fragment == null ? "null" : XMLUtils.serializeNode(fragment, XMLUtils.createPropertiesForXML(false))));
        }

        // test arguments
        if (contextName == null) {
            throw new ProcessingException("SessionManager.mergeContextFragment: Name is required");
        }
        if (path == null) {
            throw new ProcessingException("SessionManager.mergeContextFragment: Path is required");
        }
        if (fragment == null) {
            throw new ProcessingException("SessionManager.mergeContextFragment: Fragment is required");
        }

        // get context
        SessionContext context = this.contextManager.getContext( contextName );

        // check context
        if (context == null) {
            throw new ProcessingException("SessionManager.mergeContextFragment: Context '" + contextName + "' not found.");
        }

        Node contextNode = context.getSingleNode(path);
        if (contextNode == null) {
            // no merge required
            context.setXML(path, fragment);
        } else {
            this.importNode(contextNode, fragment, false);
            context.setNode(path, contextNode);
        }

        if (this.getLogger().isDebugEnabled()) {
            this.getLogger().debug("END mergeContextFragment");
        }
    }

    /**
     * Remove data in a public context.
     * The data specified by the path is removed from the public session context.
     *
     * @param contextName The name of the public context.
     * @param path        XPath expression specifying where to merge the data.
     *
     */
    public void removeContextFragment(String  contextName,
                                        String  path)
    throws ProcessingException  {
        // synchronized via context
        if (this.getLogger().isDebugEnabled() ) {
            this.getLogger().debug("BEGIN removeContextFragment name=" + contextName + ", path=" + path);
        }
        // test arguments
        if (contextName == null) {
            throw new ProcessingException("SessionManager.removeContextFragment: Name is required");
        }
        if (path == null) {
            throw new ProcessingException("SessionManager.removeContextFragment: Path is required");
        }

        // get context
        SessionContext context = this.contextManager.getContext( contextName );

        // check context
        if (context == null) {
            throw new ProcessingException("SessionManager.removeContextFragment: Context '" + contextName + "' not found.");
        }

        context.removeXML(path);

        if (this.getLogger().isDebugEnabled() ) {
            this.getLogger().debug("END removeContextFragment");
        }
    }

    /**
     * Import nodes. If preserve is set to true, the nodes
     * marked with cocoon:preserve are always imported
     * overwriting others!
     */
    private void importNode(Node profile, Node delta, boolean preserve) {
        // no sync req
        NodeList profileChilds = null;
        NodeList deltaChilds   = delta.getChildNodes();
        int      i, len;
        int      m, l;
        boolean  found;
        Node     currentDelta = null;
        Node     currentProfile = null;

        len = deltaChilds.getLength();
        for(i = 0; i < len; i++) {
            currentDelta = deltaChilds.item(i);
            if (currentDelta.getNodeType() == Node.ELEMENT_NODE) {
                // search the delta node in the profile
                profileChilds = profile.getChildNodes();
                l = profileChilds.getLength();
                m = 0;
                found = false;
                while (found == false && m < l) {
                    currentProfile = profileChilds.item(m);
                    if (currentProfile.getNodeType() == Node.ELEMENT_NODE
                        && currentProfile.getNodeName().equals(currentDelta.getNodeName()) == true) {

                        // now we have found a node with the same name
                        // next: the attributes must match also
                        found = DOMUtil.compareAttributes((Element)currentProfile, (Element)currentDelta);
                    }
                    if (found == false) m++;
                }
                if (found == true) {
                    // this is not new

                    if (preserve == true
                        && ((Element)currentDelta).hasAttributeNS(SessionConstants.SESSION_NAMESPACE_URI, "preserve")
                        && ((Element)currentDelta).getAttributeNS(SessionConstants.SESSION_NAMESPACE_URI, "preserve").equalsIgnoreCase("true")) {
                        // replace the original with the delta
                        profile.replaceChild(profile.getOwnerDocument().importNode(currentDelta, true),
                                              currentProfile);
                    } else {
                        // do we have elements as children or text?
                        if (currentDelta.hasChildNodes() == true) {
                            currentDelta.normalize();
                            currentProfile.normalize();
                            // do a recursive call for sub elements
                            this.importNode(currentProfile, currentDelta, preserve);
                            // and now the text nodes: Remove all from the profile and add all
                            // of the delta
                            NodeList childs = currentProfile.getChildNodes();
                            int      index, max;
                            max = childs.getLength();
                            for(index = max - 1; index >= 0; index--) {
                                if (childs.item(index).getNodeType() == Node.TEXT_NODE) {
                                    currentProfile.removeChild(childs.item(index));
                                }
                            }
                            childs = currentDelta.getChildNodes();
                            max = childs.getLength();
                            for(index = 0; index < max; index++) {
                                if (childs.item(index).getNodeType() == Node.TEXT_NODE) {
                                    currentProfile.appendChild(currentProfile.getOwnerDocument()
                                     .createTextNode(childs.item(index).getNodeValue()));
                                }
                            }
                        }
                    }
                } else {
                    profile.appendChild(profile.getOwnerDocument().importNode(currentDelta, true));
                }
            }

        }

    }

    /* (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;
    }

}
TOP

Related Classes of org.apache.cocoon.webapps.session.components.DefaultSessionManager

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.