Package org.apache.chemistry.opencmis.client.bindings.spi.atompub

Source Code of org.apache.chemistry.opencmis.client.bindings.spi.atompub.AbstractAtomPubService

/*
* 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.chemistry.opencmis.client.bindings.spi.atompub;

import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.chemistry.opencmis.client.bindings.impl.CmisBindingsHelper;
import org.apache.chemistry.opencmis.client.bindings.spi.BindingSession;
import org.apache.chemistry.opencmis.client.bindings.spi.LinkAccess;
import org.apache.chemistry.opencmis.client.bindings.spi.atompub.objects.AtomAcl;
import org.apache.chemistry.opencmis.client.bindings.spi.atompub.objects.AtomBase;
import org.apache.chemistry.opencmis.client.bindings.spi.atompub.objects.AtomElement;
import org.apache.chemistry.opencmis.client.bindings.spi.atompub.objects.AtomEntry;
import org.apache.chemistry.opencmis.client.bindings.spi.atompub.objects.AtomLink;
import org.apache.chemistry.opencmis.client.bindings.spi.atompub.objects.RepositoryWorkspace;
import org.apache.chemistry.opencmis.client.bindings.spi.atompub.objects.ServiceDoc;
import org.apache.chemistry.opencmis.client.bindings.spi.http.HttpInvoker;
import org.apache.chemistry.opencmis.client.bindings.spi.http.Output;
import org.apache.chemistry.opencmis.client.bindings.spi.http.Response;
import org.apache.chemistry.opencmis.commons.PropertyIds;
import org.apache.chemistry.opencmis.commons.SessionParameter;
import org.apache.chemistry.opencmis.commons.data.Ace;
import org.apache.chemistry.opencmis.commons.data.Acl;
import org.apache.chemistry.opencmis.commons.data.ExtensionsData;
import org.apache.chemistry.opencmis.commons.data.ObjectData;
import org.apache.chemistry.opencmis.commons.data.RepositoryInfo;
import org.apache.chemistry.opencmis.commons.definitions.TypeDefinition;
import org.apache.chemistry.opencmis.commons.enums.AclPropagation;
import org.apache.chemistry.opencmis.commons.enums.IncludeRelationships;
import org.apache.chemistry.opencmis.commons.exceptions.CmisBaseException;
import org.apache.chemistry.opencmis.commons.exceptions.CmisConnectionException;
import org.apache.chemistry.opencmis.commons.exceptions.CmisConstraintException;
import org.apache.chemistry.opencmis.commons.exceptions.CmisContentAlreadyExistsException;
import org.apache.chemistry.opencmis.commons.exceptions.CmisFilterNotValidException;
import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException;
import org.apache.chemistry.opencmis.commons.exceptions.CmisNameConstraintViolationException;
import org.apache.chemistry.opencmis.commons.exceptions.CmisNotSupportedException;
import org.apache.chemistry.opencmis.commons.exceptions.CmisObjectNotFoundException;
import org.apache.chemistry.opencmis.commons.exceptions.CmisPermissionDeniedException;
import org.apache.chemistry.opencmis.commons.exceptions.CmisProxyAuthenticationException;
import org.apache.chemistry.opencmis.commons.exceptions.CmisRuntimeException;
import org.apache.chemistry.opencmis.commons.exceptions.CmisStorageException;
import org.apache.chemistry.opencmis.commons.exceptions.CmisStreamNotSupportedException;
import org.apache.chemistry.opencmis.commons.exceptions.CmisUnauthorizedException;
import org.apache.chemistry.opencmis.commons.exceptions.CmisUpdateConflictException;
import org.apache.chemistry.opencmis.commons.exceptions.CmisVersioningException;
import org.apache.chemistry.opencmis.commons.impl.Constants;
import org.apache.chemistry.opencmis.commons.impl.ReturnVersion;
import org.apache.chemistry.opencmis.commons.impl.UrlBuilder;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.AccessControlEntryImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.AccessControlListImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.AccessControlPrincipalDataImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.ObjectDataImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertiesImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyIdImpl;

/**
* Base class for all AtomPub client services.
*/
public abstract class AbstractAtomPubService implements LinkAccess {

    protected enum IdentifierType {
        ID, PATH
    }

    protected static final String NAME_COLLECTION = "collection";
    protected static final String NAME_URI_TEMPLATE = "uritemplate";
    protected static final String NAME_PATH_SEGMENT = "pathSegment";
    protected static final String NAME_RELATIVE_PATH_SEGMENT = "relativePathSegment";
    protected static final String NAME_NUM_ITEMS = "numItems";

    private BindingSession session;

    /**
     * Sets the current session.
     */
    protected void setSession(BindingSession session) {
        this.session = session;
    }

    /**
     * Gets the current session.
     */
    protected BindingSession getSession() {
        return session;
    }

    /**
     * Gets the HTTP Invoker object.
     */
    protected HttpInvoker getHttpInvoker() {
        return CmisBindingsHelper.getHttpInvoker(session);
    }   
   
    /**
     * Returns the service document URL of this session.
     */
    protected String getServiceDocURL() {
        Object url = session.get(SessionParameter.ATOMPUB_URL);
        if (url instanceof String) {
            return (String) url;
        }

        return null;
    }

    // ---- link cache ----

    /**
     * Returns the link cache or creates a new cache if it doesn't exist.
     */
    protected LinkCache getLinkCache() {
        LinkCache linkCache = (LinkCache) getSession().get(SpiSessionParameter.LINK_CACHE);
        if (linkCache == null) {
            linkCache = new LinkCache(getSession());
            getSession().put(SpiSessionParameter.LINK_CACHE, linkCache);
        }

        return linkCache;
    }

    /**
     * Gets a link from the cache.
     */
    protected String getLink(String repositoryId, String id, String rel, String type) {
        if (repositoryId == null) {
            throw new CmisInvalidArgumentException("Repository id must be set!");
        }

        if (id == null) {
            throw new CmisInvalidArgumentException("Object id must be set!");
        }

        return getLinkCache().getLink(repositoryId, id, rel, type);
    }

    /**
     * Gets a link from the cache.
     */
    protected String getLink(String repositoryId, String id, String rel) {
        return getLink(repositoryId, id, rel, null);
    }

    /**
     * Gets a link from the cache if it is there or loads it into the cache if
     * it is not there.
     */
    public String loadLink(String repositoryId, String id, String rel, String type) {
        String link = getLink(repositoryId, id, rel, type);
        if (link == null) {
            getObjectInternal(repositoryId, IdentifierType.ID, id, ReturnVersion.THIS, null, null, null, null, null,
                    null, null);
            link = getLink(repositoryId, id, rel, type);
        }

        return link;
    }

    /**
     * Gets the content link from the cache if it is there or loads it into the
     * cache if it is not there.
     */
    public String loadContentLink(String repositoryId, String id) {
        return loadLink(repositoryId, id, AtomPubParser.LINK_REL_CONTENT, null);
    }

    /**
     * Adds a link to the cache.
     */
    protected void addLink(String repositoryId, String id, String rel, String type, String link) {
        getLinkCache().addLink(repositoryId, id, rel, type, link);
    }

    /**
     * Adds a link to the cache.
     */
    protected void addLink(String repositoryId, String id, AtomLink link) {
        getLinkCache().addLink(repositoryId, id, link.getRel(), link.getType(), link.getHref());
    }

    /**
     * Removes all links of an object.
     */
    protected void removeLinks(String repositoryId, String id) {
        getLinkCache().removeLinks(repositoryId, id);
    }

    /**
     * Locks the link cache.
     */
    protected void lockLinks() {
        getLinkCache().lockLinks();
    }

    /**
     * Unlocks the link cache.
     */
    protected void unlockLinks() {
        getLinkCache().unlockLinks();
    }

    /**
     * Checks a link throw an appropriate exception.
     */
    protected void throwLinkException(String repositoryId, String id, String rel, String type) {
        int index = getLinkCache().checkLink(repositoryId, id, rel, type);

        switch (index) {
        case 0:
            throw new CmisObjectNotFoundException("Unknown repository!");
        case 1:
            throw new CmisObjectNotFoundException("Unknown object!");
        case 2:
            throw new CmisNotSupportedException("Operation not supported by the repository for this object!");
        case 3:
            throw new CmisNotSupportedException("No link with matching media type!");
        case 4:
            throw new CmisRuntimeException("Nothing wrong! Either this is a bug or a threading issue.");
        default:
            throw new CmisRuntimeException("Unknown error!");
        }
    }

    /**
     * Gets a type link from the cache.
     */
    protected String getTypeLink(String repositoryId, String typeId, String rel, String type) {
        if (repositoryId == null) {
            throw new CmisInvalidArgumentException("Repository id must be set!");
        }

        if (typeId == null) {
            throw new CmisInvalidArgumentException("Type id must be set!");
        }

        return getLinkCache().getTypeLink(repositoryId, typeId, rel, type);
    }

    /**
     * Gets a type link from the cache.
     */
    protected String getTypeLink(String repositoryId, String typeId, String rel) {
        return getTypeLink(repositoryId, typeId, rel, null);
    }

    /**
     * Gets a link from the cache if it is there or loads it into the cache if
     * it is not there.
     */
    protected String loadTypeLink(String repositoryId, String typeId, String rel, String type) {
        String link = getTypeLink(repositoryId, typeId, rel, type);
        if (link == null) {
            getTypeDefinitionInternal(repositoryId, typeId);
            link = getTypeLink(repositoryId, typeId, rel, type);
        }

        return link;
    }

    /**
     * Adds a type link to the cache.
     */
    protected void addTypeLink(String repositoryId, String typeId, String rel, String type, String link) {
        getLinkCache().addTypeLink(repositoryId, typeId, rel, type, link);
    }

    /**
     * Adds a type link to the cache.
     */
    protected void addTypeLink(String repositoryId, String typeId, AtomLink link) {
        getLinkCache().addTypeLink(repositoryId, typeId, link.getRel(), link.getType(), link.getHref());
    }

    /**
     * Removes all links of a type.
     */
    protected void removeTypeLinks(String repositoryId, String id) {
        getLinkCache().removeTypeLinks(repositoryId, id);
    }

    /**
     * Locks the type link cache.
     */
    protected void lockTypeLinks() {
        getLinkCache().lockTypeLinks();
    }

    /**
     * Unlocks the type link cache.
     */
    protected void unlockTypeLinks() {
        getLinkCache().unlockTypeLinks();
    }

    /**
     * Gets a collection from the cache.
     */
    protected String getCollection(String repositoryId, String collection) {
        return getLinkCache().getCollection(repositoryId, collection);
    }

    /**
     * Gets a collection from the cache if it is there or loads it into the
     * cache if it is not there.
     */
    protected String loadCollection(String repositoryId, String collection) {
        String link = getCollection(repositoryId, collection);
        if (link == null) {
            // cache repository info
            getRepositoriesInternal(repositoryId);
            link = getCollection(repositoryId, collection);
        }

        return link;
    }

    /**
     * Adds a collection to the cache.
     */
    protected void addCollection(String repositoryId, String collection, String link) {
        getLinkCache().addCollection(repositoryId, collection, link);
    }

    /**
     * Gets a repository link from the cache.
     */
    protected String getRepositoryLink(String repositoryId, String rel) {
        return getLinkCache().getRepositoryLink(repositoryId, rel);
    }

    /**
     * Gets a repository link from the cache if it is there or loads it into the
     * cache if it is not there.
     */
    protected String loadRepositoryLink(String repositoryId, String rel) {
        String link = getRepositoryLink(repositoryId, rel);
        if (link == null) {
            // cache repository info
            getRepositoriesInternal(repositoryId);
            link = getRepositoryLink(repositoryId, rel);
        }

        return link;
    }

    /**
     * Adds a repository link to the cache.
     */
    protected void addRepositoryLink(String repositoryId, String rel, String link) {
        getLinkCache().addRepositoryLink(repositoryId, rel, link);
    }

    /**
     * Adds a repository link to the cache.
     */
    protected void addRepositoryLink(String repositoryId, AtomLink link) {
        addRepositoryLink(repositoryId, link.getRel(), link.getHref());
    }

    /**
     * Gets an URI template from the cache.
     */
    protected String getTemplateLink(String repositoryId, String type, Map<String, Object> parameters) {
        return getLinkCache().getTemplateLink(repositoryId, type, parameters);
    }

    /**
     * Gets a template link from the cache if it is there or loads it into the
     * cache if it is not there.
     */
    protected String loadTemplateLink(String repositoryId, String type, Map<String, Object> parameters) {
        String link = getTemplateLink(repositoryId, type, parameters);
        if (link == null) {
            // cache repository info
            getRepositoriesInternal(repositoryId);
            link = getTemplateLink(repositoryId, type, parameters);
        }

        return link;
    }

    /**
     * Adds an URI template to the cache.
     */
    protected void addTemplate(String repositoryId, String type, String link) {
        getLinkCache().addTemplate(repositoryId, type, link);
    }

    // ---- exceptions ----

    /**
     * Converts a HTTP status code into an Exception.
     */
    protected CmisBaseException convertStatusCode(int code, String message, String errorContent, Throwable t) {
        String exception = extractException(errorContent);
        message = extractErrorMessage(message, errorContent);

        switch (code) {
        case 400:
            if (CmisFilterNotValidException.EXCEPTION_NAME.equals(exception)) {
                return new CmisFilterNotValidException(message, errorContent, t);
            }
            return new CmisInvalidArgumentException(message, errorContent, t);
        case 401:
            return new CmisUnauthorizedException(message, errorContent, t);
        case 403:
            if (CmisStreamNotSupportedException.EXCEPTION_NAME.equals(exception)) {
                return new CmisStreamNotSupportedException(message, errorContent, t);
            }
            return new CmisPermissionDeniedException(message, errorContent, t);
        case 404:
            return new CmisObjectNotFoundException(message, errorContent, t);
        case 405:
            return new CmisNotSupportedException(message, errorContent, t);
        case 407:
            return new CmisProxyAuthenticationException(message, errorContent, t);
        case 409:
            if (CmisContentAlreadyExistsException.EXCEPTION_NAME.equals(exception)) {
                return new CmisContentAlreadyExistsException(message, errorContent, t);
            } else if (CmisVersioningException.EXCEPTION_NAME.equals(exception)) {
                return new CmisVersioningException(message, errorContent, t);
            } else if (CmisUpdateConflictException.EXCEPTION_NAME.equals(exception)) {
                return new CmisUpdateConflictException(message, errorContent, t);
            } else if (CmisNameConstraintViolationException.EXCEPTION_NAME.equals(exception)) {
                return new CmisNameConstraintViolationException(message, errorContent, t);
            }
            return new CmisConstraintException(message, errorContent, t);
        default:
            if (CmisStorageException.EXCEPTION_NAME.equals(exception)) {
                return new CmisStorageException(message, errorContent, t);
            }
            return new CmisRuntimeException(message, errorContent, t);
        }
    }

    protected String extractException(String errorContent) {
        if (errorContent == null) {
            return null;
        }

        int begin = errorContent.indexOf("<!--exception-->");
        int end = errorContent.indexOf("<!--/exception-->");

        if (begin == -1 || end == -1 || begin > end) {
            return null;
        }

        return errorContent.substring(begin + "<!--exception-->".length(), end);
    }

    protected String extractErrorMessage(String message, String errorContent) {
        if (errorContent == null) {
            return message;
        }

        int begin = errorContent.indexOf("<!--message-->");
        int end = errorContent.indexOf("<!--/message-->");

        if (begin == -1 || end == -1 || begin > end) {
            return message;
        }

        return errorContent.substring(begin + "<!--message-->".length(), end);
    }

    // ---- helpers ----

    protected boolean is(String name, AtomElement element) {
        return name.equals(element.getName().getLocalPart());
    }

    protected boolean isStr(String name, AtomElement element) {
        return is(name, element) && (element.getObject() instanceof String);
    }

    protected boolean isInt(String name, AtomElement element) {
        return is(name, element) && (element.getObject() instanceof BigInteger);
    }

    protected boolean isNextLink(AtomElement element) {
        return Constants.REL_NEXT.equals(((AtomLink) element.getObject()).getRel());
    }

    /**
     * Creates a CMIS object that only contains an id in the property list.
     * Modified
     */
    protected ObjectData createIdObject(String objectId) {
        ObjectDataImpl object = new ObjectDataImpl();

        PropertiesImpl properties = new PropertiesImpl();
        object.setProperties(properties);

        PropertyIdImpl idProperty = new PropertyIdImpl(PropertyIds.OBJECT_ID, objectId);
        properties.addProperty(idProperty);

        return object;
    }

    /**
     * Parses an input stream.
     */
    @SuppressWarnings("unchecked")
    protected <T extends AtomBase> T parse(InputStream stream, Class<T> clazz) {
        AtomPubParser parser = new AtomPubParser(stream);

        try {
            parser.parse();
        } catch (Exception e) {
            throw new CmisConnectionException("Parsing exception!", e);
        }

        AtomBase parseResult = parser.getResults();

        if (!clazz.isInstance(parseResult)) {
            throw new CmisConnectionException("Unexpected document! Received: "
                    + (parseResult == null ? "something unknown" : parseResult.getType()));
        }

        return (T) parseResult;
    }

    /**
     * Performs a GET on an URL, checks the response code and returns the
     * result.
     */
    protected Response read(UrlBuilder url) {
        // make the call
        //Log.d("URL", url.toString());
        Response resp = getHttpInvoker().invokeGET(url, session);

        // check response code
        if (resp.getResponseCode() != 200) {
            throw convertStatusCode(resp.getResponseCode(), resp.getResponseMessage(), resp.getErrorContent(), null);
        }

        return resp;
    }

    /**
     * Performs a POST on an URL, checks the response code and returns the
     * result.
     */
    protected Response post(UrlBuilder url, String contentType, Output writer) {
        // make the call
        //Log.d("URL", url.toString());
        Response resp = getHttpInvoker().invokePOST(url, contentType, writer, session);

        // check response code
        if (resp.getResponseCode() != 201) {
            throw convertStatusCode(resp.getResponseCode(), resp.getResponseMessage(), resp.getErrorContent(), null);
        }

        return resp;
    }

    /**
     * Performs a PUT on an URL, checks the response code and returns the
     * result.
     */
    protected Response put(UrlBuilder url, String contentType, Output writer) {
        return put(url, contentType, null, writer);
    }

    /**
     * Performs a PUT on an URL, checks the response code and returns the
     * result.
     */
    protected Response put(UrlBuilder url, String contentType, Map<String, String> headers,
            Output writer) {
        // make the call
        //Log.d("URL", url.toString());
        Response resp = getHttpInvoker().invokePUT(url, contentType, headers, writer, session);

        // check response code
        if ((resp.getResponseCode() < 200) || (resp.getResponseCode() > 299)) {
            throw convertStatusCode(resp.getResponseCode(), resp.getResponseMessage(), resp.getErrorContent(), null);
        }

        return resp;
    }

    /**
     * Performs a DELETE on an URL, checks the response code and returns the
     * result.
     */
    protected void delete(UrlBuilder url) {
        // make the call
        //Log.d("URL", url.toString());
        Response resp = getHttpInvoker().invokeDELETE(url, session);

        // check response code
        if (resp.getResponseCode() != 204) {
            throw convertStatusCode(resp.getResponseCode(), resp.getResponseMessage(), resp.getErrorContent(), null);
        }
    }

    // ---- common operations ----

    /**
     * Checks if at least one ACE list is not empty.
     */
    protected boolean isAclMergeRequired(Acl addAces, Acl removeAces) {
        return (addAces != null && addAces.getAces() != null && !addAces.getAces().isEmpty())
                || (removeAces != null && removeAces.getAces() != null && !removeAces.getAces().isEmpty());
    }

    /**
     * Merges the new ACL from original, add and remove ACEs lists.
     */
    protected Acl mergeAcls(Acl originalAces, Acl addAces, Acl removeAces) {
        Map<String, Set<String>> originals = convertAclToMap(originalAces);
        Map<String, Set<String>> adds = convertAclToMap(addAces);
        Map<String, Set<String>> removes = convertAclToMap(removeAces);
        List<Ace> newAces = new ArrayList<Ace>();

        // iterate through the original ACEs
        for (Map.Entry<String, Set<String>> ace : originals.entrySet()) {

            // add permissions
            Set<String> addPermissions = adds.get(ace.getKey());
            if (addPermissions != null) {
                ace.getValue().addAll(addPermissions);
            }

            // remove permissions
            Set<String> removePermissions = removes.get(ace.getKey());
            if (removePermissions != null) {
                ace.getValue().removeAll(removePermissions);
            }

            // create new ACE
            if (!ace.getValue().isEmpty()) {
                newAces.add(new AccessControlEntryImpl(new AccessControlPrincipalDataImpl(ace.getKey()),
                        new ArrayList<String>(ace.getValue())));
            }
        }

        // find all ACEs that should be added but are not in the original ACE
        // list
        for (Map.Entry<String, Set<String>> ace : adds.entrySet()) {
            if (!originals.containsKey(ace.getKey()) && !ace.getValue().isEmpty()) {
                newAces.add(new AccessControlEntryImpl(new AccessControlPrincipalDataImpl(ace.getKey()),
                        new ArrayList<String>(ace.getValue())));
            }
        }

        return new AccessControlListImpl(newAces);
    }

    /**
     * Converts a list of ACEs into Map for better handling.
     */
    private static Map<String, Set<String>> convertAclToMap(Acl acl) {
        Map<String, Set<String>> result = new HashMap<String, Set<String>>();

        if (acl == null || acl.getAces() == null) {
            return result;
        }

        for (Ace ace : acl.getAces()) {
            // don't consider indirect ACEs - we can't change them
            if (!ace.isDirect()) {
                // ignore
                continue;
            }

            // although a principal must not be null, check it
            if (ace.getPrincipal() == null || ace.getPrincipal().getId() == null) {
                // ignore
                continue;
            }

            Set<String> permissions = result.get(ace.getPrincipal().getId());
            if (permissions == null) {
                permissions = new HashSet<String>();
                result.put(ace.getPrincipal().getId(), permissions);
            }

            if (ace.getPermissions() != null) {
                permissions.addAll(ace.getPermissions());
            }
        }

        return result;
    }

    /**
     * Retrieves the Service Document from the server and caches the repository
     * info objects, collections, links, URI templates, etc.
     */
    @SuppressWarnings("unchecked")
    protected List<RepositoryInfo> getRepositoriesInternal(String repositoryId) {
        List<RepositoryInfo> repInfos = new ArrayList<RepositoryInfo>();

        // retrieve service doc
        UrlBuilder url = new UrlBuilder(getServiceDocURL());
        url.addParameter(Constants.PARAM_REPOSITORY_ID, repositoryId);

        // read and parse
        Response resp = read(url);
        ServiceDoc serviceDoc = parse(resp.getStream(), ServiceDoc.class);

        // walk through the workspaces
        for (RepositoryWorkspace ws : serviceDoc.getWorkspaces()) {
            if (ws.getId() == null) {
                // found a non-CMIS workspace
                continue;
            }

            for (AtomElement element : ws.getElements()) {
                if (is(NAME_COLLECTION, element)) {
                    Map<String, String> colMap = (Map<String, String>) element.getObject();
                    addCollection(ws.getId(), colMap.get("collectionType"), colMap.get("href"));
                } else if (element.getObject() instanceof AtomLink) {
                    addRepositoryLink(ws.getId(), (AtomLink) element.getObject());
                } else if (is(NAME_URI_TEMPLATE, element)) {
                    Map<String, String> tempMap = (Map<String, String>) element.getObject();
                    addTemplate(ws.getId(), tempMap.get("type"), tempMap.get("template"));
                } else if (element.getObject() instanceof RepositoryInfo) {
                    repInfos.add((RepositoryInfo) element.getObject());
                }
            }
        }

        return repInfos;
    }

    /**
     * Retrieves an object from the server and caches the links.
     */
    protected ObjectData getObjectInternal(String repositoryId, IdentifierType idOrPath, String objectIdOrPath,
            ReturnVersion returnVersion, String filter, Boolean includeAllowableActions,
            IncludeRelationships includeRelationships, String renditionFilter, Boolean includePolicyIds,
            Boolean includeAcl, ExtensionsData extension) {

        Map<String, Object> parameters = new HashMap<String, Object>();
        parameters.put(Constants.PARAM_ID, objectIdOrPath);
        parameters.put(Constants.PARAM_PATH, objectIdOrPath);
        parameters.put(Constants.PARAM_RETURN_VERSION, returnVersion);
        parameters.put(Constants.PARAM_FILTER, filter);
        parameters.put(Constants.PARAM_ALLOWABLE_ACTIONS, includeAllowableActions);
        parameters.put(Constants.PARAM_ACL, includeAcl);
        parameters.put(Constants.PARAM_POLICY_IDS, includePolicyIds);
        parameters.put(Constants.PARAM_RELATIONSHIPS, includeRelationships);
        parameters.put(Constants.PARAM_RENDITION_FILTER, renditionFilter);

        String link = loadTemplateLink(repositoryId, (idOrPath == IdentifierType.ID ? Constants.TEMPLATE_OBJECT_BY_ID
                : Constants.TEMPLATE_OBJECT_BY_PATH), parameters);
        if (link == null) {
            throw new CmisObjectNotFoundException("Unknown repository!");
        }

        UrlBuilder url = new UrlBuilder(link);
        // workaround for missing template parameter in the CMIS spec
        if (returnVersion != null && returnVersion != ReturnVersion.THIS) {
            url.addParameter(Constants.PARAM_RETURN_VERSION, returnVersion);
        }

        // read and parse
        Response resp = read(url);
        AtomEntry entry = parse(resp.getStream(), AtomEntry.class);

        // we expect a CMIS entry
        if (entry.getId() == null) {
            throw new CmisConnectionException("Received Atom entry is not a CMIS entry!");
        }

        lockLinks();
        ObjectData result = null;
        try {
            // clean up cache
            removeLinks(repositoryId, entry.getId());

            // walk through the entry
            for (AtomElement element : entry.getElements()) {
                if (element.getObject() instanceof AtomLink) {
                    addLink(repositoryId, entry.getId(), (AtomLink) element.getObject());
                } else if (element.getObject() instanceof ObjectData) {
                    result = (ObjectData) element.getObject();
                }
            }
        } finally {
            unlockLinks();
        }

        return result;
    }

    /**
     * Retrieves a type definition.
     */
    protected TypeDefinition getTypeDefinitionInternal(String repositoryId, String typeId) {

        Map<String, Object> parameters = new HashMap<String, Object>();
        parameters.put(Constants.PARAM_ID, typeId);

        String link = loadTemplateLink(repositoryId, Constants.TEMPLATE_TYPE_BY_ID, parameters);
        if (link == null) {
            throw new CmisObjectNotFoundException("Unknown repository!");
        }

        // read and parse
        Response resp = read(new UrlBuilder(link));
        AtomEntry entry = parse(resp.getStream(), AtomEntry.class);

        // we expect a CMIS entry
        if (entry.getId() == null) {
            throw new CmisConnectionException("Received Atom entry is not a CMIS entry!");
        }

        lockTypeLinks();
        TypeDefinition result = null;
        try {
            // clean up cache
            removeTypeLinks(repositoryId, entry.getId());

            // walk through the entry
            for (AtomElement element : entry.getElements()) {
                if (element.getObject() instanceof AtomLink) {
                    addTypeLink(repositoryId, entry.getId(), (AtomLink) element.getObject());
                } else if (element.getObject() instanceof TypeDefinition) {
                    result = (TypeDefinition) element.getObject();
                }
            }
        } finally {
            unlockTypeLinks();
        }

        return result;
    }

    /**
     * Retrieves the ACL of an object.
     */
    public Acl getAclInternal(String repositoryId, String objectId, Boolean onlyBasicPermissions,
            ExtensionsData extension) {

        // find the link
        String link = loadLink(repositoryId, objectId, Constants.REL_ACL, Constants.MEDIATYPE_ACL);

        if (link == null) {
            throwLinkException(repositoryId, objectId, Constants.REL_ACL, Constants.MEDIATYPE_ACL);
        }

        UrlBuilder url = new UrlBuilder(link);
        url.addParameter(Constants.PARAM_ONLY_BASIC_PERMISSIONS, onlyBasicPermissions);

        // read and parse
        Response resp = read(url);
        AtomAcl acl = parse(resp.getStream(), AtomAcl.class);

        return acl.getACL();
    }

    /**
     * Updates the ACL of an object.
     */
    protected AtomAcl updateAcl(String repositoryId, String objectId, final Acl acl, AclPropagation aclPropagation) {

        // find the link
        String link = loadLink(repositoryId, objectId, Constants.REL_ACL, Constants.MEDIATYPE_ACL);

        if (link == null) {
            throwLinkException(repositoryId, objectId, Constants.REL_ACL, Constants.MEDIATYPE_ACL);
        }

        UrlBuilder aclUrl = new UrlBuilder(link);
        aclUrl.addParameter(Constants.PARAM_ACL_PROPAGATION, aclPropagation);

        // update
        Response resp = put(aclUrl, Constants.MEDIATYPE_ACL, new Output() {
            public void write(OutputStream out) throws Exception {
                // TODO not implemented
                AtomEntryWriter.writeACL(out, acl);
            }
        });

        // parse new entry
        return parse(resp.getStream(), AtomAcl.class);
    }

}
TOP

Related Classes of org.apache.chemistry.opencmis.client.bindings.spi.atompub.AbstractAtomPubService

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.