org.esupportail.portlet.filemanager.services.opencmis.CmisAccessImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.esupportail.portlet.filemanager.services.opencmis.CmisAccessImpl.java

Source

/**
 * Licensed to EsupPortail under one or more contributor license
 * agreements. See the NOTICE file distributed with this work for
 * additional information regarding copyright ownership.
 *
 * EsupPortail 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.esupportail.portlet.filemanager.services.opencmis;

import java.io.InputStream;
import java.math.BigInteger;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.activation.MimetypesFileTypeMap;

import org.apache.chemistry.opencmis.client.api.CmisObject;
import org.apache.chemistry.opencmis.client.api.Document;
import org.apache.chemistry.opencmis.client.api.FileableCmisObject;
import org.apache.chemistry.opencmis.client.api.Folder;
import org.apache.chemistry.opencmis.client.api.ItemIterable;
import org.apache.chemistry.opencmis.client.api.ObjectId;
import org.apache.chemistry.opencmis.client.api.Session;
import org.apache.chemistry.opencmis.client.runtime.SessionFactoryImpl;
import org.apache.chemistry.opencmis.commons.PropertyIds;
import org.apache.chemistry.opencmis.commons.SessionParameter;
import org.apache.chemistry.opencmis.commons.data.ContentStream;
import org.apache.chemistry.opencmis.commons.enums.Action;
import org.apache.chemistry.opencmis.commons.enums.BaseTypeId;
import org.apache.chemistry.opencmis.commons.enums.BindingType;
import org.apache.chemistry.opencmis.commons.enums.Updatability;
import org.apache.chemistry.opencmis.commons.enums.VersioningState;
import org.apache.chemistry.opencmis.commons.exceptions.CmisBaseException;
import org.apache.chemistry.opencmis.commons.exceptions.CmisConnectionException;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.ContentStreamImpl;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.esupportail.portlet.filemanager.beans.DownloadFile;
import org.esupportail.portlet.filemanager.beans.JsTreeFile;
import org.esupportail.portlet.filemanager.beans.SharedUserPortletParameters;
import org.esupportail.portlet.filemanager.beans.UploadActionType;
import org.esupportail.portlet.filemanager.beans.UserPassword;
import org.esupportail.portlet.filemanager.services.FsAccess;
import org.esupportail.portlet.filemanager.services.ResourceUtils;
import org.springframework.beans.factory.DisposableBean;

public class CmisAccessImpl extends FsAccess implements DisposableBean {

    protected static final Log log = LogFactory.getLog(CmisAccessImpl.class);

    protected ResourceUtils resourceUtils;

    protected Session cmisSession;

    protected String respositoryId = "test";

    // rootPath=@root@" for chemistry cmis server
    protected String rootId = null;

    protected String rootPath = null;

    private static final Set<Updatability> CREATE_UPDATABILITY = new HashSet<Updatability>();
    static {
        CREATE_UPDATABILITY.add(Updatability.ONCREATE);
        CREATE_UPDATABILITY.add(Updatability.READWRITE);
    }

    public void setResourceUtils(ResourceUtils resourceUtils) {
        this.resourceUtils = resourceUtils;
    }

    public void setRespositoryId(String respositoryId) {
        this.respositoryId = respositoryId;
    }

    public void setRootId(String rootId) {
        this.rootId = rootId;
    }

    public void setRootPath(String rootPath) {
        this.rootPath = rootPath;
    }

    @Override
    protected void manipulateUri(Map userInfos, String formUsername) {
        if (rootPath != null & userInfos != null) {
            for (String userInfoKey : (Set<String>) userInfos.keySet()) {
                String userInfo = (String) userInfos.get(userInfoKey);
                String userInfoKeyToken = TOKEN_SPECIAL_CHAR.concat(userInfoKey).concat(TOKEN_SPECIAL_CHAR);
                // in nuxeo @ is replaced by - in path
                userInfo = userInfo.replaceAll("@", "-");
                // in nuxeo . is replaced by - in path
                userInfo = userInfo.replaceAll("\\.", "-");
                this.rootPath = this.rootPath.replaceAll(userInfoKeyToken, userInfo);
            }
        }
        if (formUsername != null) {
            this.rootPath = this.rootPath.replaceAll(TOKEN_FORM_USERNAME, formUsername);
        }
        if (this.uriManipulateService != null)
            this.uri = this.uriManipulateService.manipulate(rootPath);
    }

    /**
     * @param cmisObject
     * @param path
     * @param parentPath
     * @return a JsTreeFile where lid = /cmis_parent_parent_object_idJsTreeFile.ID_TITLE_SPLITcmis_parent_parent_object_name/cmis_parent_object_idJsTreeFile.ID_TITLE_SPLITcmis_parent_object_name/cmis_object_idJsTreeFile.ID_TITLE_SPLITcmis_object_name
     */
    private JsTreeFile cmisObjectAsJsTreeFile(CmisObject cmisObject, String path, String parentPath,
            boolean folderDetails, boolean fileDetails) {
        // TODO: folderDetails
        // TODO: fileDetails
        String title = cmisObject.getName();
        String lid = cmisObject.getId().concat(JsTreeFile.ID_TITLE_SPLIT).concat(title);
        if (path != null) {
            lid = path;
        } else if (parentPath != null) {
            lid = parentPath.concat("/").concat(lid);
        }
        // remove / at the beginning if it exists
        if (lid.startsWith("/"))
            lid = lid.substring(1);

        String type = (BaseTypeId.CMIS_DOCUMENT.equals(cmisObject.getBaseTypeId())) ? "file" : "folder";

        // root case :
        if ("".equals(path)) {
            title = "";
            type = "drive";
        }

        JsTreeFile file = new JsTreeFile(title, lid, type);
        if (fileDetails) {

            if ("file".equals(type)) {
                String icon = resourceUtils.getIcon(title);
                file.setIcon(icon);

                Document document = (Document) cmisObject;
                BigInteger size = BigInteger.ZERO;
                List<Object> contentStreamLength = document.getProperty("cmis:contentStreamLength").getValues();
                if (!contentStreamLength.isEmpty())
                    size = (BigInteger) contentStreamLength.get(0);
                file.setSize(size.longValue());
                file.setOverSizeLimit(file.getSize() > resourceUtils.getSizeLimit(title));
            }

            Date date = cmisObject.getLastModificationDate().getTime();
            file.setLastModifiedTime(new SimpleDateFormat(this.datePattern).format(date));

        }

        if (folderDetails && ("folder".equals(type) || "drive".equals(type))) {
            Folder folder = (Folder) cmisObject;
            ItemIterable<CmisObject> pl = folder.getChildren();
            long totalSize = 0;
            long fileCount = 0;
            long folderCount = 0;
            fileCount = pl.getTotalNumItems();

            for (CmisObject child : pl) {
                String childType = (BaseTypeId.CMIS_DOCUMENT.equals(child.getBaseTypeId())) ? "file" : "folder";
                if ("folder".equals(childType)) {
                    ++folderCount;
                } else if ("file".equals(childType)) {
                    ++fileCount;
                    Document document = (Document) child;
                    BigInteger size = BigInteger.ZERO;
                    List<Object> contentStreamLength = document.getProperty("cmis:contentStreamLength").getValues();
                    if (!contentStreamLength.isEmpty())
                        size = (BigInteger) contentStreamLength.get(0);
                    totalSize += size.longValue();
                }
            }
            file.setTotalSize(totalSize);
            file.setFileCount(fileCount);
            file.setFolderCount(folderCount);
        }

        Set<Action> actions = cmisObject.getAllowableActions().getAllowableActions();
        // check if actions seem to be filled correctly
        if (actions.contains(Action.CAN_GET_PROPERTIES)) {
            // ok, set capability based on available actions
            file.setWriteable(actions.contains(Action.CAN_DELETE_OBJECT));
        }

        return file;
    }

    private CmisObject getCmisObject(String path, SharedUserPortletParameters userParameters) {
        this.open(userParameters);
        String lid = null;
        // in fact we don't use 'path' but ID
        if (path.equals("")) {
            if (rootId != null)
                lid = rootId;
            else if (rootPath != null)
                lid = cmisSession.getObjectByPath(rootPath).getId();
            else
                lid = cmisSession.getRootFolder().getId();
        } else {
            List<String> relParentsIds = Arrays.asList(path.split("/"));
            String lid_name = relParentsIds.get(relParentsIds.size() - 1);
            List<String> lid_nameList = Arrays.asList(lid_name.split(JsTreeFile.ID_TITLE_SPLIT));
            lid = lid_nameList.get(0);
        }
        ObjectId objectId = cmisSession.createObjectId(lid);
        CmisObject cmisObject = cmisSession.getObject(objectId);
        return cmisObject;
    }

    @Override
    public void open(SharedUserPortletParameters userParameters) {

        super.open(userParameters);

        if (!this.isOpened()) {

            Map<String, String> parameters = new HashMap<String, String>();

            parameters.put(SessionParameter.BINDING_TYPE, BindingType.ATOMPUB.value());

            parameters.put(SessionParameter.ATOMPUB_URL, uri);
            parameters.put(SessionParameter.REPOSITORY_ID, respositoryId);

            if (userAuthenticatorService != null) {
                UserPassword userPassword = userAuthenticatorService.getUserPassword(userParameters);
                parameters.put(SessionParameter.USER, userPassword.getUsername());
                parameters.put(SessionParameter.PASSWORD, userPassword.getPassword());

            }
            try {
                cmisSession = SessionFactoryImpl.newInstance().createSession(parameters);
            } catch (CmisConnectionException ce) {
                log.warn("failed to retrieve cmisSession : " + uri
                        + " , repository is not accessible or simply not started ?", ce);
            }
        }
    }

    @Override
    public boolean isOpened() {
        return cmisSession != null;
    }

    public void destroy() throws Exception {
        this.close();
    }

    @Override
    public void close() {
        // TODO
        cmisSession = null;
    }

    @Override
    public JsTreeFile get(String path, SharedUserPortletParameters userParameters, boolean folderDetails,
            boolean fileDetails) {
        CmisObject cmisObject = getCmisObject(path, userParameters);
        return cmisObjectAsJsTreeFile(cmisObject, path, null, folderDetails, fileDetails);
    }

    @Override
    public List<JsTreeFile> getChildren(String path, SharedUserPortletParameters userParameters) {
        Folder folder = (Folder) getCmisObject(path, userParameters);
        ItemIterable<CmisObject> pl = folder.getChildren();

        List<JsTreeFile> childrens = new ArrayList<JsTreeFile>();
        for (CmisObject cmisObject : pl) {
            childrens.add(cmisObjectAsJsTreeFile(cmisObject, null, path, false, true));
        }

        return childrens;
    }

    @Override
    public DownloadFile getFile(String dir, SharedUserPortletParameters userParameters) {
        CmisObject cmisObject = getCmisObject(dir, userParameters);
        Document document = (Document) cmisObject;
        String filename = document.getName();
        InputStream inputStream = document.getContentStream().getStream();
        BigInteger size = (BigInteger) document.getProperty("cmis:contentStreamLength").getValues().get(0);
        String contentType = document.getContentStreamMimeType();
        return new DownloadFile(contentType, size.intValue(), filename, inputStream);
    }

    @Override
    public String createFile(String parentPath, String title, String type,
            SharedUserPortletParameters userParameters) {
        Folder parent = (Folder) getCmisObject(parentPath, userParameters);
        CmisObject createdObject = null;
        if ("folder".equals(type)) {
            Map prop = new HashMap();
            prop.put(PropertyIds.OBJECT_TYPE_ID, BaseTypeId.CMIS_FOLDER.value());
            prop.put(PropertyIds.NAME, String.valueOf(title));
            createdObject = parent.createFolder(prop, null, null, null, cmisSession.getDefaultContext());
        } else if ("file".equals(type)) {
            Map prop = new HashMap();
            prop.put(PropertyIds.OBJECT_TYPE_ID, BaseTypeId.CMIS_DOCUMENT.value());
            prop.put(PropertyIds.NAME, String.valueOf(title));
            createdObject = parent.createDocument(prop, null, null, null, null, null,
                    cmisSession.getDefaultContext());
        }
        JsTreeFile createdJsTreeFile = this.cmisObjectAsJsTreeFile(createdObject, null, parentPath, false, false);
        return createdJsTreeFile.getPath();
    }

    @Override
    public boolean moveCopyFilesIntoDirectory(String dir, List<String> filesToCopy, boolean copy,
            SharedUserPortletParameters userParameters) {
        try {
            Folder targetFolder = (Folder) getCmisObject(dir, userParameters);
            if (copy) {
                return false;
                /*for(String fileTocopy : filesToCopy) {
                   FileableCmisObject cmisObjectToCopy = (FileableCmisObject) getCmisObject(fileTocopy);
                   cmisObjectToCopy.addToFolder(targetFolder, true);
                }*/
            } else {
                for (String fileTocopy : filesToCopy) {

                    // get parent folder id of  fileTocopy
                    List<String> relParentsIds = Arrays.asList(fileTocopy.split("/"));
                    String sourceFolderId;
                    if (relParentsIds.size() > 1) {
                        String lid_name = relParentsIds.get(relParentsIds.size() - 2);
                        List<String> lid_nameList = Arrays.asList(lid_name.split(JsTreeFile.ID_TITLE_SPLIT));
                        sourceFolderId = lid_nameList.get(0);
                    } else {
                        // that's the root
                        sourceFolderId = getCmisObject("", userParameters).getId();
                    }

                    ObjectId sourceFolderObjectId = cmisSession.createObjectId(sourceFolderId);
                    ObjectId targetFolderObjectId = cmisSession.createObjectId(targetFolder.getId());

                    FileableCmisObject cmisObjectToCutPast = (FileableCmisObject) getCmisObject(fileTocopy,
                            userParameters);
                    cmisObjectToCutPast.move(sourceFolderObjectId, targetFolderObjectId);
                }
            }
            return true;
        } catch (CmisBaseException e) {
            log.warn(
                    "error when copy/cust/past files : maybe that's because this operation is not allowed for the user ?",
                    e);
        }
        return false;
    }

    @Override
    public boolean putFile(String dir, String filename, InputStream inputStream,
            SharedUserPortletParameters userParameters, UploadActionType uploadOption) {
        //must manage the upload option.
        log.error("You need to implements feature about upload options!");
        Folder targetFolder = (Folder) getCmisObject(dir, userParameters);
        Map prop = new HashMap();
        prop.put(PropertyIds.OBJECT_TYPE_ID, BaseTypeId.CMIS_DOCUMENT.value());
        prop.put(PropertyIds.NAME, String.valueOf(filename));
        String mimeType = new MimetypesFileTypeMap().getContentType(filename);
        ContentStream stream = new ContentStreamImpl(filename, null, mimeType, inputStream);
        Document document = targetFolder.createDocument(prop, stream, VersioningState.NONE, null, null, null,
                cmisSession.getDefaultContext());
        HashMap m = new HashMap();
        m.put("cmis:name", filename);
        document.updateProperties(m);
        return true;
    }

    @Override
    public boolean remove(String path, SharedUserPortletParameters userParameters) {
        CmisObject cmisObject = getCmisObject(path, userParameters);
        cmisObject.delete(true);
        return true;
    }

    @Override
    public boolean renameFile(String path, String title, SharedUserPortletParameters userParameters) {
        CmisObject cmisObject = getCmisObject(path, userParameters);
        HashMap m = new HashMap();
        m.put("cmis:name", title);
        cmisObject.updateProperties(m);
        return true;
    }

    @Override
    public boolean supportIntraCopyPast() {
        return false;
    }

}