Package org.apache.slide.structure

Source Code of org.apache.slide.structure.StructureImpl

/*
* $Header: /home/cvs/jakarta-slide/src/share/org/apache/slide/structure/StructureImpl.java,v 1.39.2.1 2004/02/05 16:05:13 mholz Exp $
* $Revision: 1.39.2.1 $
* $Date: 2004/02/05 16:05:13 $
*
* ====================================================================
*
* Copyright 1999-2002 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.slide.structure;

import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.List;
import java.util.Vector;

import org.apache.slide.common.Namespace;
import org.apache.slide.common.NamespaceConfig;
import org.apache.slide.common.ServiceAccessException;
import org.apache.slide.common.SlideToken;
import org.apache.slide.common.SlideTokenWrapper;
import org.apache.slide.common.Uri;
import org.apache.slide.common.UriPath;
import org.apache.slide.common.UriTokenizer;
import org.apache.slide.content.NodeRevisionDescriptor;
import org.apache.slide.content.NodeRevisionNumber;
import org.apache.slide.content.RevisionDescriptorNotFoundException;
import org.apache.slide.lock.Lock;
import org.apache.slide.lock.ObjectLockedException;
import org.apache.slide.security.AccessDeniedException;
import org.apache.slide.security.Security;
import org.apache.slide.store.Store;
import org.apache.slide.util.Configuration;

/**
* Default implementation of the Structure interface.
*
* @author <a href="mailto:remm@apache.org">Remy Maucherat</a>
* @version $Revision: 1.39.2.1 $
*/
public final class StructureImpl implements Structure {
   
   
    // ----------------------------------------------------------- Constructors
   
   
    /**
     * Constructor.
     *
     * @param namespace the namespace associated with the helper object
     * @param namespaceConfig configuration of the namespace
     * @param securityHelper the associated security helper
     * @param lockHelper the associated lock helper
     */
    public StructureImpl(Namespace namespace, NamespaceConfig namespaceConfig,
                         Security securityHelper, Lock lockHelper) {
        this.namespace = namespace;
        this.namespaceConfig = namespaceConfig;
        this.securityHelper = securityHelper;
        this.lockHelper = lockHelper;
    }
   
   
    // ----------------------------------------------------- Instance Variables
   
   
    /**
     * Namespace.
     */
    private Namespace namespace;
   
   
    /**
     * Namespace configuration.
     */
    private NamespaceConfig namespaceConfig;
   
   
    /**
     * Security helper.
     */
    private Security securityHelper;
   
   
    /**
     * Lock helper.
     */
    private Lock lockHelper;
   
   
    // ------------------------------------------------------ Structure Methods
   
   
    public Enumeration getChildren(SlideToken token, ObjectNode object)
        throws ServiceAccessException, ObjectNotFoundException,
        LinkedObjectNotFoundException {
        Enumeration childrenUri = object.enumerateChildren();
        Vector result = new Vector();
        while (childrenUri.hasMoreElements()) {
            String childUri = (String) childrenUri.nextElement();
            try {
                ObjectNode child = retrieve(token, childUri, false);
                result.addElement(child);
            } catch (AccessDeniedException e) {
            }
        }
        return result.elements();
    }
   
   
    public ObjectNode getParent(SlideToken token, ObjectNode object)
        throws ServiceAccessException, ObjectNotFoundException,
        LinkedObjectNotFoundException, AccessDeniedException {
        String objectUriStr = object.getUri();
        Uri parentUri = namespace.getUri(token, objectUriStr).getParentUri();
        if (parentUri == null) {
            return null;
        }
        String parentUriStr = parentUri.toString();
        ObjectNode parent = retrieve(token, parentUriStr);
        return parent;
    }
   
   
    public ObjectNode retrieve(SlideToken token, String strUri)
        throws ServiceAccessException, ObjectNotFoundException,
        LinkedObjectNotFoundException, AccessDeniedException {
        return retrieve(token, strUri, true);
    }
   
   
    public ObjectNode retrieve(SlideToken token, String strUri,
                               boolean translateLastUriElement)
        throws ServiceAccessException, ObjectNotFoundException,
        LinkedObjectNotFoundException, AccessDeniedException {
       
        Uri uri = namespace.getUri(token, strUri);
       
        ObjectNode result = null;
       
        // First of all, we try to load the object directly from the given Uri.
        try {
            result = uri.getStore().retrieveObject(uri);
            securityHelper.checkCredentials
                (token, result, namespaceConfig.getReadObjectAction());
            if ((translateLastUriElement) && (result instanceof LinkNode)) {
                LinkNode link = (LinkNode) result;
                Uri linkedUri = namespace.getUri(token, link.getLinkedUri());
                result = linkedUri.getStore()
                    .retrieveObject(linkedUri);
                securityHelper.checkCredentials
                    (token, result, namespaceConfig.getReadObjectAction());
            }
        } catch (ObjectNotFoundException e) {
        }
       
        // If the attempt to load the uri failed, it means there is at least
        // one link in the uri (or that the uri doe'sn't have any associated
        // object).
        if (result == null) {
           
            String resolvedUri = uri.toString();
           
            // 1 - Tokemization of the Uri
            UriTokenizer uriTokenizer = new UriTokenizer(token, uri.getNamespace(),
                                                         resolvedUri);
           
            // 2 - For each element of the Uri
            Uri courUri = null;
            ObjectNode courObject = null;
            while (uriTokenizer.hasMoreElements()) {
               
                // 3 - Load object's class from the uri. If the object
                // does not exist, a DataException is thrown.
                courUri = uriTokenizer.nextUri();
                courObject = courUri.getStore()
                    .retrieveObject(courUri);
               
                // We check to see if the credentials gives access to
                //the current object
                securityHelper.checkCredentials
                    (token, courObject, namespaceConfig.getReadObjectAction());
               
                // 4 - Test if object is a link, ie if it is an instance
                // of LinkNode or one of its subclasses
                if (((translateLastUriElement)
                         && (courObject instanceof LinkNode)) ||
                        ((!translateLastUriElement)
                             && (uriTokenizer.hasMoreElements())
                             && (courObject instanceof LinkNode))
                   ) {
                   
                    // 5 - If the object is a link, we get the uri of
                    // the linked object
                    // Note : courUri still IS the Uri of the link, and so,
                    // in a way courUri is the parent of linkedUri.
                    Uri linkedUri = namespace
                        .getUri(((LinkNode) courObject).getLinkedUri());
                   
                    // 6 - We replace the courUri scope in the original uri
                    String courStrUri = courUri.toString();
                    resolvedUri = linkedUri.toString()
                        + resolvedUri.substring(courStrUri.length());
                   
                    // 7 - We tokenize again the uri
                    uriTokenizer = new UriTokenizer(token, uri.getNamespace(),
                                                    resolvedUri);
                   
                    // 8 - We parse it till we get back to the point
                    // where we stopped
                    boolean isUriFound = false;
                    while ((!isUriFound) && (uriTokenizer.hasMoreElements())) {
                        if (linkedUri.equals(uriTokenizer.nextUri())) {
                            isUriFound = true;
                        }
                    }
                    if (!isUriFound) {
                        throw new LinkedObjectNotFoundException(courUri,
                                                                resolvedUri);
                    }
                   
                }
               
                // 9 - We continue to go down in the Uri tree
            }
           
            // 10 - We return the last object which has been found
           
            result = courObject;
        }
       
        return result;
       
    }
   
   
    public void create(SlideToken token, ObjectNode object,
                       String strUri)
        throws ServiceAccessException, ObjectAlreadyExistsException,
        ObjectNotFoundException, LinkedObjectNotFoundException,
        AccessDeniedException, ObjectLockedException {
       
        // Checking roles
        Enumeration roles = securityHelper.getRoles(object);
        while (roles.hasMoreElements()) {
            if (!securityHelper.hasRole(token, (String)roles.nextElement())) {
                // Allow only the namespace admin to create roles
                // he doesn't have
                Uri rootUri = namespace.getUri(token, "/");
                ObjectNode rootObject =
                    rootUri.getStore().retrieveObject(rootUri);
                securityHelper.checkCredentials
                    (token, rootObject,
                     namespaceConfig.getGrantPermissionAction());
                break;
            }
        }
       
        String resolvedUri = strUri;
       
        // 1 - Tokenization of the Uri
        UriTokenizer uriTokenizer = new UriTokenizer(token, namespace, resolvedUri);
       
        // 2 - For each element of the Uri
        Uri courUri = null;
        ObjectNode courObject = null;
        ObjectNode parentObject = null;
       
        boolean alreadyExists = false;
       
        while (uriTokenizer.hasMoreElements()) {
           
            parentObject = courObject;
           
            // 3 - Load object's class from the uri. If the object does
            // not exist, a DataException is thrown.
            courUri = uriTokenizer.nextUri();
            try {
                courObject = courUri.getStore()
                    .retrieveObject(courUri);
                securityHelper
                    .checkCredentials(token, courObject,
                                      namespaceConfig.getReadObjectAction());
                if (!uriTokenizer.hasMoreElements()) {
                    // The object already exists
                    alreadyExists = true;
                }
            } catch (ObjectNotFoundException e) {
                // Load failed, probably because object was not found
                // We try to create a new one.
                // We have to test if the uri is the last in the list,
                // we must create the requested element.
                // By default, we create a SubjectNode.
                ObjectNode newObject = null;
                if (uriTokenizer.hasMoreElements()) {
                    throw new ObjectNotFoundException(courUri);
                } else {
                    newObject = object;
                }
                if (parentObject != null) {
                    securityHelper
                        .checkCredentials(token, courObject, namespaceConfig
                                              .getBindMemberAction());
                   
                    // Now creating the new object
                    newObject.setUri(courUri.toString());
                    courUri.getStore().createObject(courUri, newObject);
                   
                    // re-read to obtain UURI
                    //                    newObject = courUri.getStore().retrieveObject(courUri);
                   
                    // re-read the parent taking the forceEnlistment flag into account
                    Uri parentUri = namespace.getUri(token, parentObject.getUri());
                    parentObject = parentUri.getStore().retrieveObject(parentUri);
                    // Add the newly created object to its parent's
                    // children list
                    ObjectNode oldChild = null;
                    // we can check the parentUri, it's in the same store as newObject
                    if (Configuration.useBinding(parentUri.getStore())) {
                        String bindingName = newObject.getPath().lastSegment();
                        if (parentObject.hasBinding(bindingName)) {
                            oldChild = retrieve(token, parentObject.getUri()+"/"+bindingName, false);
                            parentObject.removeChild(oldChild);
                            store(token, oldChild);
                        }
                    }
                    lockHelper.checkLock
                        (token, parentObject, namespaceConfig.getCreateObjectAction());
                    parentObject.addChild(newObject);
                    //namespace.getUri(token, parentObject.getUri())
                    //.getDataSource().storeObject(parentObject, false);
                    store(token, parentObject, true);
                    store(token, newObject);
                   
                } else {
                    throw new ObjectNotFoundException(courUri);
                }
                courObject = newObject;
            }
           
            // 4 - Test if object is a link, ie if it is an instance of
            // LinkNode or one of its subclasses
            if ((uriTokenizer.hasMoreElements())
                && (courObject instanceof LinkNode)) {
               
                // 5 - If the object is a link, we get the uri of the
                // linked object
                // Note : courUri still IS the Uri of the link, and so,
                // in a way courUri is the parent of linkedUri.
                Uri linkedUri = namespace
                    .getUri(((LinkNode) courObject).getLinkedUri());
               
                // 6 - We replace the courUri scope in the original uri
                String courStrUri = courUri.toString();
                resolvedUri = linkedUri.toString()
                    + resolvedUri.substring(courStrUri.length());
               
                // 7 - We tokenize again the uri
                uriTokenizer = new UriTokenizer(token, namespace, resolvedUri);
               
                // 8 - We parse it till we get back to the point
                // where we stopped
                boolean isUriFound = false;
                while ((!isUriFound) && (uriTokenizer.hasMoreElements())) {
                    if (linkedUri.equals(uriTokenizer.nextUri())) {
                        isUriFound = true;
                    }
                }
                if (!isUriFound) {
                    throw new LinkedObjectNotFoundException
                        (courUri, resolvedUri);
                }
               
            }
           
            // 9 - We continue to go down in the Uri tree
        }
       
        if (alreadyExists) {
            if (courUri.isStoreRoot()) {
                // if the object already exists map it anyway into
                // the node hierarchy, to prevent loose of nodes
                // during start up
                if (!parentObject.hasChild(courObject)) {
                    parentObject.addChild(courObject);
                    store(token, parentObject, true);
                }
            }
            throw new ObjectAlreadyExistsException(strUri);
        }
    }
   
    public void createLink(SlideToken token, LinkNode link,
                           String linkUri, ObjectNode linkedObject)
        throws ServiceAccessException, ObjectAlreadyExistsException,
        ObjectNotFoundException, LinkedObjectNotFoundException,
        AccessDeniedException, ObjectLockedException {
        link.setLinkedUri(linkedObject.getUri());
        create(token, link, linkUri);
    }
   
   
    public void store(SlideToken token, ObjectNode object)
        throws ServiceAccessException, ObjectNotFoundException,
        AccessDeniedException, LinkedObjectNotFoundException {
       
        store(token, object, false);
    }
   
   
    public void store(SlideToken token, ObjectNode object, boolean setModificationDate)
        throws ServiceAccessException, ObjectNotFoundException,
        AccessDeniedException, LinkedObjectNotFoundException {
       
        // Checking roles
        Enumeration roles = securityHelper.getRoles(object);
        while (roles.hasMoreElements()) {
            if (!securityHelper.hasRole(token, (String)roles.nextElement())) {
                // Allow only the namespace admin to create roles
                // he doesn't have
                Uri rootUri = namespace.getUri(token, "/");
                ObjectNode rootObject =
                    rootUri.getStore().retrieveObject(rootUri);
                securityHelper.checkCredentials
                    (token, rootObject,
                     namespaceConfig.getGrantPermissionAction());
                break;
            }
        }
       
        ObjectNode realObject = retrieve(token, object.getUri(), false);
        securityHelper
            .checkCredentials(token, realObject,
                              namespaceConfig.getCreateObjectAction());
        Uri realObjectUri = namespace.getUri(token, realObject.getUri());
        Store store = realObjectUri.getStore();
        store.storeObject(realObjectUri, object);
       
        if (setModificationDate) {
            try {
                NodeRevisionDescriptor revisionDescriptor = store.retrieveRevisionDescriptor(realObjectUri, new NodeRevisionNumber());
                revisionDescriptor.setModificationDate(new Date());
                revisionDescriptor.setModificationUser(
                    securityHelper.getPrincipal(token).getPath().lastSegment());
                store.storeRevisionDescriptor(realObjectUri, revisionDescriptor );
            }
            catch (RevisionDescriptorNotFoundException e) {
                // ignore silently
            }
        }
    }
   
   
    /**
     * Method remove
     *
     * @param    token               a  SlideToken
     * @param    object              an ObjectNode
     *
     * @throws   ServiceAccessException
     * @throws   ObjectNotFoundException
     * @throws   ObjectHasChildrenException
     * @throws   AccessDeniedException
     * @throws   LinkedObjectNotFoundException
     * @throws   ObjectLockedException
     *
     */
    public void remove(SlideToken token, ObjectNode object)
        throws ServiceAccessException, ObjectNotFoundException,
        ObjectHasChildrenException, AccessDeniedException,
        LinkedObjectNotFoundException, ObjectLockedException {
       
        ObjectNode nodeToDelete = retrieve(token, object.getUri(), false);
        Uri uri = namespace.getUri(token, nodeToDelete.getUri());
       
        if (!object.getUri().equals("/")) {
            Uri curUri = namespace.getUri(token, nodeToDelete.getUri());
            Uri parentUri = curUri.getParentUri();
            ObjectNode parentNode = parentUri.getStore().retrieveObject(parentUri);
           
            securityHelper.checkCredentials
                (token, nodeToDelete, namespaceConfig.getRemoveObjectAction());
            securityHelper.checkCredentials
                (token, parentNode, namespaceConfig.getUnbindMemberAction());
            lockHelper.checkLock
                (token, nodeToDelete, namespaceConfig.getRemoveObjectAction());
            lockHelper.checkLock
                (token, parentNode, namespaceConfig.getUnbindMemberAction());

            parentNode.removeChild(nodeToDelete);
            store(token, parentNode, true);
           
            if (Configuration.useBinding(curUri.getStore()) && nodeToDelete.numberOfParentBindings() > 0) {
                store(token, nodeToDelete);
            }
            else {
                Enumeration enum = nodeToDelete.enumerateChildren();
                if (enum.hasMoreElements()) {
                    throw new ObjectHasChildrenException(uri);
                }
                uri.getStore().removeObject(uri, nodeToDelete);
            }
        }
    }
   
   
    /**
     * Modifies the collection identified by <b>collectionNode</b>, by adding a new binding
     * from the specified segment to the resource identified by <b>sourceNode</b>.
     *
     * @param    token               a  SlideToken
     * @param    collectionNode      an ObjectNode
     * @param    segment             a  String
     * @param    sourceNode          an ObjectNode
     *
     * @throws   ServiceAccessException
     * @throws   ObjectNotFoundException
     * @throws   AccessDeniedException
     * @throws   LinkedObjectNotFoundException
     * @throws   ObjectLockedException
     *
     */
    public void addBinding(SlideToken token, ObjectNode collectionNode, String segment, ObjectNode sourceNode) throws ServiceAccessException, ObjectNotFoundException, AccessDeniedException, LinkedObjectNotFoundException, ObjectLockedException, CrossServerBindingException {
        if (Configuration.useBinding(namespace.getUri(token, collectionNode.getUri()).getStore())) {
            collectionNode = retrieve(token, collectionNode.getUri(), false);
            sourceNode = retrieve(token, sourceNode.getUri(), false);
            Uri collectionUri = namespace.getUri(token, collectionNode.getUri());
            Uri sourceUri = namespace.getUri(token, sourceNode.getUri());
           
//            if (collectionUri.getStore() != sourceUri.getStore()) {
//                throw new CrossServerBindingException(collectionNode.getUri(), sourceNode.getUri());
//            }
           
            lockHelper.checkLock
                (token, collectionNode, namespaceConfig.getCreateObjectAction());
           
            ObjectNode oldChild = null;
            if (collectionNode.hasBinding(segment)) {
                oldChild = retrieve(token, collectionNode.getUri()+"/"+segment, false);
                lockHelper.checkLock
                    (token, oldChild, namespaceConfig.getCreateObjectAction());
                collectionNode.removeChild(oldChild);
                store( token, oldChild );
            }
            collectionNode.addBinding( segment, sourceNode );
           
            store( token, collectionNode, true );
            store( token, sourceNode );
        }
    }
   
   
    /**
     * Modifies the collection identified by <b>collectionNode</b>, by removing the binding
     * for the specified segment.
     *
     * @param    token               a  SlideToken
     * @param    collectionNode      an ObjectNode
     * @param    segment             a  String
     *
     * @throws   ServiceAccessException
     * @throws   ObjectNotFoundException
     * @throws   AccessDeniedException
     * @throws   LinkedObjectNotFoundException
     * @throws   ObjectLockedException
     *
     */
    public void removeBinding(SlideToken token, ObjectNode collectionNode, String segment) throws ServiceAccessException, ObjectNotFoundException, AccessDeniedException, LinkedObjectNotFoundException, ObjectLockedException {
        if (Configuration.useBinding(namespace.getUri(token, collectionNode.getUri()).getStore())) {
            collectionNode = retrieve(token, collectionNode.getUri(), false);
            ObjectNode childNode = retrieve(token, collectionNode.getUri()+"/"+segment, false);
           
            lockHelper.checkLock
                (token, collectionNode, namespaceConfig.getCreateObjectAction());
            lockHelper.checkLock
                (token, childNode, namespaceConfig.getCreateObjectAction());
           
            collectionNode.removeChild( childNode );
           
            store( token, childNode );
            store( token, collectionNode, true );
        }
    }
   
   
    /**
     * Return all parents of this object node. If pathOnly=true, only parents
     * on the path of the specified ObjectNode are returned, all parents (binding!)
     * otherwise. If storeOnly=true, only parents within the scope of the store
     * in charge of the specified ObjectNode are returned, parents up to the root
     * ObjectNode (uri="/") otherwise.
     *
     * @param    token               a  SlideToken
     * @param    object              an ObjectNode
     * @param    pathOnly            if true, only parents on the path of the specified
     *                               ObjectNode are returned, all parents (binding!)
     *                               otherwise
     * @param    storeOnly           if true, only parents within the scope of the store
     *                               in charge of the specified ObjectNode are returned,
     *                               parents up to the root ObjectNode (uri="/") otherwise
     * @param    includeSelf         if true, the ObjectNode specified by object is included,
     *                               otherwise, it is excluded
     *
     * @return   a List of ObjectNode instances
     *
     * @throws   ServiceAccessException
     * @throws   ObjectNotFoundException
     * @throws   LinkedObjectNotFoundException
     * @throws   AccessDeniedException
     *
     */
    public List getParents(SlideToken token, ObjectNode object, boolean pathOnly, boolean storeOnly, boolean includeSelf) throws ServiceAccessException, ObjectNotFoundException, LinkedObjectNotFoundException, AccessDeniedException {
        List result = new ArrayList();
        if (token.isForceStoreEnlistment()) {
            // get read-only token
            token = new SlideTokenWrapper(token, false);
        }
       
        if (pathOnly) {
            String[] uriTokens = object.getPath().tokens();
            UriPath path = new UriPath("/");
            Uri currentUri = namespace.getUri(token, path.toString());
            Uri objectUri = namespace.getUri(token, object.getUri());
            if (!storeOnly || currentUri.getStore() == objectUri.getStore()) {
                result.add( retrieve(token, path.toString()) );
            }
           
            for (int i = 0; i < uriTokens.length; i++) {
                path = path.child( uriTokens[i] );
                currentUri = namespace.getUri(token, path.toString());
                if (i == uriTokens.length - 1 && !includeSelf) {
                    break;
                }
                if (!storeOnly || currentUri.getStore() == objectUri.getStore()) {
                    result.add( retrieve(token, path.toString()) );
                }
            }
}
        else {
            // TODO
        }
       
        return result;
    }
}

TOP

Related Classes of org.apache.slide.structure.StructureImpl

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.