Package org.apache.cocoon.webapps.session.context

Source Code of org.apache.cocoon.webapps.session.context.SimpleSessionContext

/*
* 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.webapps.session.context;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import org.apache.cocoon.ProcessingException;
import org.apache.cocoon.components.source.SourceUtil;
import org.apache.cocoon.xml.IncludeXMLConsumer;
import org.apache.cocoon.xml.dom.DOMUtil;
import org.apache.excalibur.source.Source;
import org.apache.excalibur.source.SourceException;
import org.apache.excalibur.source.SourceParameters;
import org.apache.excalibur.source.SourceResolver;
import org.apache.excalibur.xml.xpath.NodeListImpl;
import org.apache.excalibur.xml.xpath.XPathProcessor;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentFragment;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.xml.sax.ext.LexicalHandler;

/**
*  This is a simple implementation of the session context.
*
* @author <a href="mailto:cziegeler@s-und-n.de">Carsten Ziegeler</a>
* @version CVS $Id: SimpleSessionContext.java,v 1.9 2004/03/19 14:16:55 cziegeler Exp $
*/
public final class SimpleSessionContext
implements SessionContext {

    /** Context name */
    private String   name;

    /** The content of the context */
    private Document data;

    /** The attributes */
    private Map attributes = new HashMap();

    /** load resource */
    private String loadResource;
   
    /** save resource */
    private String saveResource;

    /** The XPath Processor */
    private XPathProcessor xpathProcessor;

    /** The source resolver */
    private SourceResolver resolver;
   
    /**
     * Constructor
     */
    public SimpleSessionContext(XPathProcessor xPathProcessor, SourceResolver resolver)
    throws ProcessingException {
        this.data = DOMUtil.createDocument();
        this.data.appendChild(data.createElementNS(null, "context"));
        this.xpathProcessor = xPathProcessor;
        this.resolver = resolver;
    }

    /**
     * Get the name of the context
     */
    public String getName() {
        return this.name;
    }

    /* (non-Javadoc)
     * @see org.apache.cocoon.webapps.session.context.SessionContext#setup(java.lang.String, java.lang.String, java.lang.String)
     */
    public void setup(String value, String loadResource, String saveResource) {
        this.name = value;
        this.loadResource = loadResource;
        this.saveResource = saveResource;
    }

    public synchronized DocumentFragment getXML(String path)
    throws ProcessingException {
        DocumentFragment result = null;
        NodeList list;
        path = this.createPath(path);

        String[] pathComponents = DOMUtil.buildPathArray(path);
        if (pathComponents == null) {
            list = this.xpathProcessor.selectNodeList(this.data, path);
        } else {
            list = DOMUtil.getNodeListFromPath(data, pathComponents);
        }

        if (list != null && list.getLength() > 0) {
            Document doc = DOMUtil.createDocument();
            result = doc.createDocumentFragment();

            for(int i = 0; i < list.getLength(); i++) {

                // the found node is either an attribute or an element
                if (list.item(i).getNodeType() == Node.ATTRIBUTE_NODE) {
                    // if it is an attribute simple create a new text node with the value of the attribute
                    result.appendChild(doc.createTextNode(list.item(i).getNodeValue()));
                } else {
                    // now we have an element
                    // copy all children of this element in the resulting tree
                    NodeList childs = list.item(i).getChildNodes();
                    if (childs != null) {
                        for(int m = 0; m < childs.getLength(); m++) {
                            result.appendChild(doc.importNode(childs.item(m), true));
                        }
                    }
                }
            }
        }

        return result;
    }


    public synchronized void setXML(String path, DocumentFragment fragment)
    throws ProcessingException {
        path = this.createPath(path);
        Node node = DOMUtil.selectSingleNode(data, path, this.xpathProcessor);
        if (node.getNodeType() == Node.ATTRIBUTE_NODE) {
            // now we have to serialize the fragment to a string and insert this
            Attr attr = (Attr)node;
            attr.setNodeValue(DOMUtil.getValueOfNode(fragment));

        } else {

            // remove old childs
            while (node.hasChildNodes() == true) {
                node.removeChild(node.getFirstChild());
            }

            // Insert new childs
            NodeList childs = fragment.getChildNodes();
            if (childs != null && childs.getLength() > 0) {
                for(int i = 0; i < childs.getLength(); i++) {
                    Node n = data.importNode(childs.item(i), true);
                    node.appendChild(n);
                }
            }
        }
    }

    /**
     * Append a document fragment at the given path. The implementation of this
     * method is context specific.
     * Usually the children of the fragment are appended as new children of the
     * node specified by the path.
     * If the path is not existent it is created.
     */
    public synchronized void appendXML(String path, DocumentFragment fragment)
    throws ProcessingException {
        path = this.createPath(path);
        Node node = DOMUtil.selectSingleNode(data, path, this.xpathProcessor);
        if (node.getNodeType() == Node.ATTRIBUTE_NODE) {
            Attr attr;

            if (node.getNodeValue() != null || node.getNodeValue().trim().length() > 0) {
                // this is an existing attr, create a new one
                attr = node.getOwnerDocument().createAttributeNS(null, node.getNodeName());
                node.getParentNode().appendChild(attr);
            } else {
                attr = (Attr)node;
            }

            // now we have to serialize the fragment to a string and insert this
            attr.setNodeValue(DOMUtil.getValueOfNode(fragment));
        } else {

            // Insert new childs
            NodeList childs = fragment.getChildNodes();
            if (childs != null && childs.getLength() > 0) {
                for(int i = 0; i < childs.getLength(); i++) {
                    Node n = data.importNode(childs.item(i), true);
                    node.appendChild(n);
                }
            }
        }
    }

    /**
     * Build path
     */
    private String createPath(String path) {
        if (path == null) path ="/";
        if (!path.startsWith("/") ) path = "/" + path;
        path = "context" + path;
        if (path.endsWith("/")) path = path.substring(0, path.length() - 1);
        return path;
    }

    /**
     * Remove nodes
     */
    public synchronized void removeXML(String path)
    throws ProcessingException {
        NodeList list;
        path = this.createPath(path);

        String[] pathComponents = DOMUtil.buildPathArray(path);
        if (pathComponents == null) {
            list = this.xpathProcessor.selectNodeList(this.data, path);
        } else {
            list = DOMUtil.getNodeListFromPath(data, pathComponents);
        }
        if (list != null && list.getLength() > 0) {
            int  len = list.getLength();
            Node child;
            for(int i = 0; i < len; i++) {
                child = list.item(len - 1 -i);
                child.getParentNode().removeChild(child);
            }
        }
    }

    /**
     * Get a copy the first node specified by the path.
     */
    public synchronized Node getSingleNode(String path)
    throws ProcessingException {
        Node result = null;

        path = this.createPath(path);

        try {
            result = DOMUtil.getSingleNode(data, path, this.xpathProcessor);
            if (result != null) result = result.cloneNode(true);
        } catch (javax.xml.transform.TransformerException localException) {
            throw new ProcessingException("TransformerException: " + localException, localException);
        }

        return result;
    }

    /**
     * Get a copy all the nodes specified by the path.
     */
    public synchronized NodeList getNodeList(String path)
    throws ProcessingException {
        NodeList result = null;

        path = this.createPath(path);

        String[] pathComponents = DOMUtil.buildPathArray(path);
        if (pathComponents == null) {
            result = this.xpathProcessor.selectNodeList(this.data, path);
        } else {
            result = DOMUtil.getNodeListFromPath(data, pathComponents);
        }
        // clone list
        if (result != null) {
            result = new NodeListImpl(result);
        }

        return result;
    }

    /**
     * Set the value of a node. The node is copied before insertion.
     */
    public synchronized void setNode(String path, Node node)
    throws ProcessingException {
        if ( path == null || path.equals("/")) {
            data = DOMUtil.createDocument();
            data.appendChild(data.createElementNS(null, "context"));
            data.getFirstChild().appendChild(data.importNode(node, true));
        } else {
            path = this.createPath(path);       
            Node removeNode = DOMUtil.selectSingleNode(data, path, this.xpathProcessor);
            removeNode.getParentNode().replaceChild(data.importNode(node, true), removeNode);
        }
    }


    /**
     * Set a context attribute. If value is null the attribute is removed.
     */
    public synchronized void setAttribute(String key, Object value) {
        if (value == null) {
            attributes.remove(key);
        } else {
            attributes.put(key, value);
        }
    }

    /**
     * Get a context attribute. If the attribute is not available return null
     */
    public synchronized Object getAttribute(String key) {
        return attributes.get(key);
    }

    /**
     * Get a context attribute. If the attribute is not available the defaultObject is returned
     */
    public synchronized Object getAttribute(String key, Object defaultObject) {
        Object value = attributes.get(key);
        if (value == null) value = defaultObject;
        return value;
    }

    /**
     * Get the value of this node. This is similiar to the xsl:value-of
     * function. If the node does not exist, <code>null</code> is returned.
     */
    public synchronized String getValueOfNode(String path)
    throws ProcessingException {
        String value = null;

        path = this.createPath(path); // correct path
        value = DOMUtil.getValueOf(data, path, this.xpathProcessor);

        return value;
    }

    /**
     * Set the value of a node.
     */
    public synchronized void setValueOfNode(String path, String value)
    throws ProcessingException {
        path = this.createPath(path); // correct path

        Node node = DOMUtil.selectSingleNode(data, path, this.xpathProcessor);
        if (node.getNodeType() == Node.ATTRIBUTE_NODE) {
            Attr attr = (Attr)node;
            attr.setNodeValue(value);

        } else {

            // remove old childs
            while (node.hasChildNodes() == true) {
                node.removeChild(node.getFirstChild());
            }

            node.appendChild(node.getOwnerDocument().createTextNode(value));
        }
    }

    /**
     * Stream the XML directly to the handler. This streams the contents of getXML()
     * to the given handler without creating a DocumentFragment containing a copy
     * of the data
     */
    public synchronized boolean streamXML(String path, ContentHandler contentHandler,
                           LexicalHandler lexicalHandler)
    throws SAXException, ProcessingException {
        NodeList list;
        boolean  streamed = false;
        path = this.createPath(path);

        String[] pathComponents = DOMUtil.buildPathArray(path);
        if (pathComponents == null) {
            list = this.xpathProcessor.selectNodeList(this.data, path);
        } else {
            list = DOMUtil.getNodeListFromPath(data, pathComponents);
        }
        if (list != null && list.getLength() > 0) {
            streamed = true;
            for(int i = 0; i < list.getLength(); i++) {

                // the found node is either an attribute or an element
                if (list.item(i).getNodeType() == Node.ATTRIBUTE_NODE) {
                    // if it is an attribute simple create a new text node with the value of the attribute
                    String value = list.item(i).getNodeValue();
                    contentHandler.characters(value.toCharArray(), 0, value.length());
                } else {
                    // now we have an element
                    // stream all children of this element to the resulting tree
                    NodeList childs = list.item(i).getChildNodes();
                    if (childs != null) {
                        for(int m = 0; m < childs.getLength(); m++) {
                            IncludeXMLConsumer.includeNode(childs.item(m), contentHandler, lexicalHandler);
                        }
                    }
                }
            }
         }

        return streamed;
    }

    /**
     * Try to load XML into the context.
     * If the context does not provide the ability of loading,
     * an exception is thrown.
     */
    public void loadXML(String            path,
                        SourceParameters  parameters)
    throws SAXException, ProcessingException, IOException {
        if (this.loadResource == null) {
            throw new ProcessingException("The context " + this.name + " does not support loading.");
        }
        Source source = null;
        try {
            source = SourceUtil.getSource(this.loadResource, null, parameters, this.resolver);
            Document doc = SourceUtil.toDOM(source);
            DocumentFragment df = doc.createDocumentFragment();
            df.appendChild(doc.getDocumentElement());
            this.setXML(path, df);
        } catch (SourceException se) {
            throw SourceUtil.handle(se);
        } finally {
            resolver.release(source);
        }
    }

    /**
     * Try to save XML from the context.
     * If the context does not provide the ability of saving,
     * an exception is thrown.
     */
    public void saveXML(String path,
                        SourceParameters parameters)
    throws SAXException, ProcessingException, IOException {
        if (this.saveResource == null) {
            throw new ProcessingException("The context " + this.name + " does not support saving.");
        }
        DocumentFragment frag = this.getXML(path);
        if (frag == null) {
            // create empty fake document
            frag = DOMUtil.createDocument().createDocumentFragment();
        }

        SourceUtil.writeDOM(this.saveResource,
                            null,
                            parameters,
                            frag,
                            this.resolver,
                            "xml");
    }

}
TOP

Related Classes of org.apache.cocoon.webapps.session.context.SimpleSessionContext

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.