org.alfresco.mobile.android.api.services.impl.AlfrescoService.java Source code

Java tutorial

Introduction

Here is the source code for org.alfresco.mobile.android.api.services.impl.AlfrescoService.java

Source

/*******************************************************************************
 * Copyright (C) 2005-2013 Alfresco Software Limited.
 * 
 * This file is part of the Alfresco Mobile SDK.
 * 
 * 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.alfresco.mobile.android.api.services.impl;

import java.io.File;
import java.util.List;
import java.util.Map;

import org.alfresco.mobile.android.api.exceptions.AlfrescoServiceException;
import org.alfresco.mobile.android.api.exceptions.ErrorCodeRegistry;
import org.alfresco.mobile.android.api.exceptions.impl.ExceptionHelper;
import org.alfresco.mobile.android.api.model.ContentFile;
import org.alfresco.mobile.android.api.model.ContentStream;
import org.alfresco.mobile.android.api.model.Node;
import org.alfresco.mobile.android.api.model.impl.ContentFileImpl;
import org.alfresco.mobile.android.api.model.impl.DocumentImpl;
import org.alfresco.mobile.android.api.model.impl.FolderImpl;
import org.alfresco.mobile.android.api.services.Service;
import org.alfresco.mobile.android.api.services.ServiceRegistry;
import org.alfresco.mobile.android.api.session.AlfrescoSession;
import org.alfresco.mobile.android.api.session.CloudSession;
import org.alfresco.mobile.android.api.session.RepositorySession;
import org.alfresco.mobile.android.api.session.impl.AbstractAlfrescoSessionImpl;
import org.alfresco.mobile.android.api.utils.IOUtils;
import org.alfresco.mobile.android.api.utils.messages.Messagesl18n;
import org.apache.chemistry.opencmis.client.api.CmisObject;
import org.apache.chemistry.opencmis.client.bindings.impl.CmisBindingsHelper;
import org.apache.chemistry.opencmis.client.bindings.impl.SessionImpl;
import org.apache.chemistry.opencmis.client.bindings.spi.BindingSession;
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.SessionParameter;
import org.apache.chemistry.opencmis.commons.impl.UrlBuilder;
import org.apache.http.HttpStatus;

import android.os.Parcel;

/**
 * Abstract base class for all public Alfresco SDK Services. Contains all
 * utility methods that are common for building a service. </br> Developers can
 * extend this class if they want to add new services inside the SDK.</br> NB :
 * Don't forget to add the newly service to a custom {@link ServiceRegistry}
 * 
 * @author Jean Marie Pascal
 */
public abstract class AlfrescoService implements Service {
    /** Repository Session. */
    protected AlfrescoSession session;

    private BindingSession bindingSession;

    /**
     * Default empty Constructor.
     */
    public AlfrescoService() {
    }

    /**
     * Default constructor for service. </br> Used by the
     * {@link ServiceRegistry}.
     * 
     * @param repositorySession : Repository Session.
     * @param cmisSession : CMIS session.
     */
    public AlfrescoService(AlfrescoSession repositorySession) {
        this.session = repositorySession;
        this.bindingSession = new SessionImpl();
        bindingSession.put(CmisBindingsHelper.AUTHENTICATION_PROVIDER_OBJECT,
                ((AbstractAlfrescoSessionImpl) session).getPassthruAuthenticationProvider());
        bindingSession.put(SessionParameter.HTTP_INVOKER_CLASS,
                repositorySession.getParameter(AlfrescoSession.HTTP_INVOKER_CLASSNAME));
    }

    // //////////////////////////////////////////////////////////////////////////////////////////
    // HTTP using CMIS httpUtils
    // /////////////////////////////////////////////////////////////////////////////////////////

    /**
     * Performs a GET on an URL, checks the response code and returns the
     * result.
     * 
     * @param url : requested URL. @ : if network or internal problems occur
     *            during the process.
     */
    protected Response read(UrlBuilder url, int errorCode) {
        // Log.d("URL", url.toString());
        Response resp = getHttpInvoker().invokeGET(url, getSessionHttp());

        // check response code
        if (resp.getResponseCode() != HttpStatus.SC_OK) {
            convertStatusCode(resp, errorCode);
        }

        return resp;
    }

    /**
     * Performs a POST on an URL, checks the response code and returns the
     * result. @ : if network or internal problems occur during the process.
     */
    protected Response post(UrlBuilder url, String contentType, Output writer, int errorCode) {
        // make the call
        Response resp = getHttpInvoker().invokePOST(url, contentType, writer, getSessionHttp());

        // check response code
        if (resp.getResponseCode() != HttpStatus.SC_OK && resp.getResponseCode() != HttpStatus.SC_CREATED) {
            convertStatusCode(resp, errorCode);
        }

        return resp;
    }

    /**
     * Performs a DELETE on an URL, checks the response code and returns the
     * result. @ : if network or internal problems occur during the process.
     */
    protected void delete(UrlBuilder url, int errorCode) {
        // make the call
        Response resp = getHttpInvoker().invokeDELETE(url, getSessionHttp());

        // check response code
        if (resp.getResponseCode() != HttpStatus.SC_NO_CONTENT && resp.getResponseCode() != HttpStatus.SC_OK) {
            convertStatusCode(resp, errorCode);
        }

    }

    /**
     * Performs a PUT on an URL, checks the response code and returns the
     * result. @ : if network or internal problems occur during the process.
     */
    protected Response put(UrlBuilder url, String contentType, Map<String, String> headers, Output writer,
            int errorCode) {
        Response resp = getHttpInvoker().invokePUT(url, contentType, headers, writer, getSessionHttp());

        // check response code
        if ((resp.getResponseCode() < HttpStatus.SC_OK) || (resp.getResponseCode() > 299)) {
            convertStatusCode(resp, errorCode);
        }

        return resp;
    }

    /**
     * @return Binding session for passing the authenticationProvider to execute
     *         the http request.
     */
    protected BindingSession getSessionHttp() {
        if (bindingSession == null) {
            bindingSession = new SessionImpl();
            bindingSession.put(CmisBindingsHelper.AUTHENTICATION_PROVIDER_OBJECT,
                    ((AbstractAlfrescoSessionImpl) session).getPassthruAuthenticationProvider());
            bindingSession.put(SessionParameter.HTTP_INVOKER_CLASS,
                    ((AbstractAlfrescoSessionImpl) session).getParameter(AlfrescoSession.HTTP_INVOKER_CLASSNAME));
        } else if (bindingSession != null
                && bindingSession.get(CmisBindingsHelper.AUTHENTICATION_PROVIDER_OBJECT) == null) {
            bindingSession.put(CmisBindingsHelper.AUTHENTICATION_PROVIDER_OBJECT,
                    ((AbstractAlfrescoSessionImpl) session).getPassthruAuthenticationProvider());
        }
        return bindingSession;
    }

    /**
     * Gets the HTTP Invoker object.
     */
    protected HttpInvoker getHttpInvoker() {
        return CmisBindingsHelper.getHttpInvoker(bindingSession);
    }

    // //////////////////////////////////////////////////////////////////////////////////////////
    // UTILS
    // /////////////////////////////////////////////////////////////////////////////////////////
    /**
     * Wrap and transform cmisobject into NodeObject
     * 
     * @param object : Underlying OpenCMIS Object
     * @return Alfresco Node Object.
     */
    protected Node convertNode(CmisObject object) {
        return convertNode(object, true);
    }

    protected Node convertNode(CmisObject object, boolean hasAllProperties) {
        if (isObjectNull(object)) {
            throw new IllegalArgumentException(
                    String.format(Messagesl18n.getString("ErrorCodeRegistry.GENERAL_INVALID_ARG_NULL"), "object"));
        }

        /* determine type */
        switch (object.getBaseTypeId()) {
        case CMIS_DOCUMENT:
            return new DocumentImpl(object, hasAllProperties);
        case CMIS_FOLDER:
            return new FolderImpl(object, hasAllProperties);
        default:
            throw new AlfrescoServiceException(ErrorCodeRegistry.DOCFOLDER_WRONG_NODE_TYPE,
                    Messagesl18n.getString("AlfrescoService.2") + object.getBaseTypeId());
        }
    }

    /**
     * Utils method to check if an object is null.
     * 
     * @param o : object to check
     * @return true if the object is null.
     */
    protected boolean isObjectNull(Object o) {
        return (o == null);
    }

    /**
     * Utils method to check if a string objec is null or empty.
     * 
     * @param s : String to check
     * @return true if the string is null/empty.
     */
    protected boolean isStringNull(String s) {
        return (s == null || s.length() == 0 || s.trim().length() == 0);
    }

    /**
     * Utils method to check if a list is null/empty.
     * 
     * @param l : object to check
     * @return true if the list is null or empty.
     */
    @SuppressWarnings("rawtypes")
    protected boolean isListNull(List l) {
        return (l == null || l.isEmpty());
    }

    /**
     * Utils method to check if a map is null/empty.
     * 
     * @param l : object to check
     * @return true if the list is null or empty.
     */
    @SuppressWarnings("rawtypes")
    protected boolean isMapNull(Map m) {
        return (m == null || m.isEmpty());
    }

    protected boolean isOnPremiseSession() {
        return (session instanceof RepositorySession);
    }

    protected boolean isCloudSession() {
        return (session instanceof CloudSession);
    }

    // //////////////////////////////////////////////////////////////////////////////////////////
    // EXCEPTION
    // /////////////////////////////////////////////////////////////////////////////////////////
    /**
     * Catch all underlying CMIS or not exception and throw them as
     * {@link AlfrescoServiceException}
     * 
     * @param t : exceptions catched
     * @throw AlfrescoServiceException : Reasons why the requested response code
     *        is not valid.
     */
    protected static void convertException(Exception t) {
        ExceptionHelper.convertException(t);
    }

    /**
     * Try to convert error response from repository into high level
     * ErrorContent object. This object allow developper to retrieve information
     * on the exception.
     * 
     * @param resp : http response.
     * @param serviceErrorCode : service from which the error occurs.
     */
    public void convertStatusCode(Response resp, int serviceErrorCode) {
        ExceptionHelper.convertStatusCode(session, resp, serviceErrorCode);
    }

    // //////////////////////////////////////////////////////////////////////////////////////////
    // CACHE
    // /////////////////////////////////////////////////////////////////////////////////////////
    protected static final int RENDITION_CACHE = 1;

    protected static final int CONTENT_CACHE = 2;

    /**
     * Allow to save a contentStream inside the devices file system. The content
     * is saved as cache file inside a cache folder. It's possible to determine
     * the subfolders.
     * 
     * @param contentStream : Content stream of any content
     * @param cacheFileName : Name of the cache file
     * @param storageType : Determine in which subfolders the content is stored
     * @return ContentFile associated to the cache file.
     */
    protected ContentFile saveContentStream(ContentStream contentStream, String cacheFileName, int storageType)

    {
        if (contentStream == null || contentStream.getInputStream() == null) {
            return null;
        }

        try {
            String folderName = (String) session.getParameter(AlfrescoSession.CACHE_FOLDER);
            switch (storageType) {
            case RENDITION_CACHE:
                folderName += "/rendition";
                break;
            case CONTENT_CACHE:
                folderName += "/content";
                break;
            default:
                break;
            }

            File f = new File(folderName, cacheFileName);
            IOUtils.ensureOrCreatePathAndFile(f);
            IOUtils.copyFile(contentStream.getInputStream(), f);
            return new ContentFileImpl(f, contentStream.getFileName(), contentStream.getMimeType());
        } catch (Exception e) {
            convertException(e);
        }
        return null;
    }

    // ////////////////////////////////////////////////////
    // CACHING
    // ////////////////////////////////////////////////////
    public void clear() {
        // Must be implemented in subclass.
    }

    // ////////////////////////////////////////////////////
    // Save State - serialization / deserialization
    // ////////////////////////////////////////////////////
    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int arg1) {
        dest.writeParcelable(session, PARCELABLE_WRITE_RETURN_VALUE);
    }
}