org.linagora.linshare.view.tapestry.components.ListSharedDocument.java Source code

Java tutorial

Introduction

Here is the source code for org.linagora.linshare.view.tapestry.components.ListSharedDocument.java

Source

/*
 * LinShare is an open source filesharing software, part of the LinPKI software
 * suite, developed by Linagora.
 * 
 * Copyright (C) 2015 LINAGORA
 * 
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License as published by the Free
 * Software Foundation, either version 3 of the License, or (at your option) any
 * later version, provided you comply with the Additional Terms applicable for
 * LinShare software by Linagora pursuant to Section 7 of the GNU Affero General
 * Public License, subsections (b), (c), and (e), pursuant to which you must
 * notably (i) retain the display of the LinShare? trademark/logo at the top
 * of the interface window, the display of the You are using the Open Source
 * and free version of LinShare, powered by Linagora  20092015. Contribute to
 * Linshare R&D by subscribing to an Enterprise offer!? infobox and in the
 * e-mails sent with the Program, (ii) retain all hypertext links between
 * LinShare and linshare.org, between linagora.com and Linagora, and (iii)
 * refrain from infringing Linagora intellectual property rights over its
 * trademarks and commercial brands. Other Additional Terms apply, see
 * <http://www.linagora.com/licenses/> for more details.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU Affero General Public License and
 * its applicable Additional Terms for LinShare along with this program. If not,
 * see <http://www.gnu.org/licenses/> for the GNU Affero General Public License
 * version 3 and <http://www.linagora.com/licenses/> for the Additional Terms
 * applicable to LinShare software.
 */
package org.linagora.linshare.view.tapestry.components;

import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import javax.imageio.ImageIO;

import org.apache.commons.lang.StringUtils;
import org.apache.tapestry5.BindingConstants;
import org.apache.tapestry5.ComponentResources;
import org.apache.tapestry5.Link;
import org.apache.tapestry5.StreamResponse;
import org.apache.tapestry5.annotations.Component;
import org.apache.tapestry5.annotations.Import;
import org.apache.tapestry5.annotations.InjectComponent;
import org.apache.tapestry5.annotations.OnEvent;
import org.apache.tapestry5.annotations.Parameter;
import org.apache.tapestry5.annotations.Persist;
import org.apache.tapestry5.annotations.Property;
import org.apache.tapestry5.annotations.SetupRender;
import org.apache.tapestry5.annotations.SupportsInformalParameters;
import org.apache.tapestry5.beaneditor.BeanModel;
import org.apache.tapestry5.corelib.components.Zone;
import org.apache.tapestry5.ioc.Messages;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.services.BeanModelSource;
import org.apache.tapestry5.services.PageRenderLinkSource;
import org.apache.tapestry5.services.PersistentLocale;
import org.apache.tapestry5.services.Response;
import org.linagora.LinThumbnail.utils.Constants;
import org.linagora.linshare.core.domain.vo.DocToSignContext;
import org.linagora.linshare.core.domain.vo.DocumentVo;
import org.linagora.linshare.core.domain.vo.ShareDocumentVo;
import org.linagora.linshare.core.domain.vo.UserVo;
import org.linagora.linshare.core.exception.BusinessErrorCode;
import org.linagora.linshare.core.exception.BusinessException;
import org.linagora.linshare.core.facade.AbstractDomainFacade;
import org.linagora.linshare.core.facade.DocumentFacade;
import org.linagora.linshare.core.facade.ShareFacade;
import org.linagora.linshare.core.utils.FileUtils;
import org.linagora.linshare.view.tapestry.enums.ActionFromBarDocument;
import org.linagora.linshare.view.tapestry.enums.BusinessUserMessageType;
import org.linagora.linshare.view.tapestry.models.SorterModel;
import org.linagora.linshare.view.tapestry.models.impl.SharedFileSorterModel;
import org.linagora.linshare.view.tapestry.objects.BusinessUserMessage;
import org.linagora.linshare.view.tapestry.objects.FileStreamResponse;
import org.linagora.linshare.view.tapestry.objects.MessageSeverity;
import org.linagora.linshare.view.tapestry.services.BusinessMessagesManagementService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@SupportsInformalParameters
@Import(library = { "ListDocument.js" })
public class ListSharedDocument {

    private static final Logger logger = LoggerFactory.getLogger(ListSharedDocument.class);

    /***********************************
     * Parameters
     ***********************************/
    /**
     * The user owner for the document list.
     */
    @Parameter(required = true, defaultPrefix = BindingConstants.PROP)
    private UserVo user;

    /**
     * The list of documents.
     */
    @Parameter(required = true, defaultPrefix = BindingConstants.PROP)
    @Property
    private List<ShareDocumentVo> shareDocuments;

    @Parameter(required = false, defaultPrefix = BindingConstants.PROP)
    @Property
    private boolean inSearch;

    @Parameter(required = false, defaultPrefix = BindingConstants.PROP)
    @Property
    private boolean disableDeletion;

    /***********************************
     * Properties
     ***********************************/

    @Property
    private ShareDocumentVo shareDocument;

    @Property
    @Persist
    private List<ShareDocumentVo> listSelected;

    /***********************************
     * Service injection
     ***********************************/

    @Inject
    private PersistentLocale persistentLocale;

    @Inject
    private DocumentFacade documentFacade;

    @Inject
    private ShareFacade shareFacade;

    @Inject
    private AbstractDomainFacade domainFacade;

    @Inject
    private ComponentResources componentResources;

    @Inject
    private Response response;

    @Inject
    private BeanModelSource beanModelSource;

    @InjectComponent
    private UserDetailsDisplayer userDetailsDisplayer;

    @Component(parameters = { "share=true" })
    private SignatureDetailsDisplayer signatureDetailsDisplayer;

    @InjectComponent
    private PasswordDecryptPopup passwordDecryptPopup;

    @Inject
    private PageRenderLinkSource linkFactory;

    @Property
    @Persist
    private BeanModel model;

    @Inject
    private Messages messages;

    @Inject
    private BusinessMessagesManagementService businessMessagesManagementService;

    /***********************************
     * Flags
     ***********************************/
    @Persist
    private String currentUuid;

    @Persist
    private List<ShareDocumentVo> componentdocuments;

    @Property
    private boolean activeSignature;

    @Property
    private boolean activeEncypher;

    @Property
    private boolean enabledToUpload;

    @Persist
    private boolean refreshFlag;

    @Persist
    private List<ShareDocumentVo> docs;

    private boolean filesSelected;

    @Property
    private Boolean valueCheck;

    @Persist("flash")
    private ActionFromBarDocument actionbutton;

    @Property
    private String action;

    @Property
    private String deleteConfirmed;

    @Persist
    private String pass;

    /**
     * Components Model.
     */
    @Property
    @Persist
    private SorterModel<ShareDocumentVo> sorterModel;

    @Property
    @InjectComponent
    private ShareEditForm shareEditForm;

    private final Integer truncatedValue = 40;

    /*********************************
     * Phase render
     *********************************/

    /**
     * Initialization of the selected list and set the userLogin from the user ASO.
     * @throws BusinessException 
     */
    @SetupRender
    public void init() throws BusinessException {
        listSelected = new ArrayList<ShareDocumentVo>();
        Collections.sort(shareDocuments);
        this.componentdocuments = shareDocuments;
        this.activeSignature = documentFacade.isSignatureActive(user);
        this.activeEncypher = documentFacade.isEnciphermentActive(user);
        //if(model==null) // need to redo the model each type, for the config may change 
        model = initModel();

    }

    /********************************
     * ActionLink methods
     *********************************/

    /**
     * The action declenched when the user click on the download link on the name of the file. 
     */
    public StreamResponse onActionFromDownload(String uuid) throws BusinessException {
        logger.debug("onActionFromDownload");
        // when user has been logged out
        if (componentdocuments == null) {
            return null;
        }

        ShareDocumentVo currentSharedDocumentVo = searchDocumentVoByUUid(componentdocuments, uuid);
        if (null == currentSharedDocumentVo) {
            businessMessagesManagementService.notify(new BusinessException(
                    BusinessErrorCode.SHARED_DOCUMENT_NOT_FOUND, "invalid uuid for this user"));
            return null;
        } else {
            InputStream stream = shareFacade.getShareStream(user, currentSharedDocumentVo.getIdentifier());
            return new FileStreamResponse(currentSharedDocumentVo, stream);
        }

    }

    public void onActionFromDelete(String uuid) {
        currentUuid = uuid;
    }

    public Object onActionFromSignature(String uuid) throws BusinessException {
        currentUuid = uuid;
        ShareDocumentVo shareddoc = searchDocumentVoByUUid(componentdocuments, uuid);

        if (null == shareddoc) {
            throw new BusinessException(BusinessErrorCode.INVALID_UUID, "invalid uuid for this user");
        } else {
            // context is shared document
            return linkFactory.createPageRenderLinkWithContext("signature/SelectPolicy",
                    new Object[] { DocToSignContext.SHARED.toString(), shareddoc.getIdentifier() });
        }
    }

    public void onActionFromDecryptIcon(String uuid) throws BusinessException {
        currentUuid = uuid;
        actionbutton = ActionFromBarDocument.DECRYPT_ACTION;
        passwordDecryptPopup.getFormPassword().clearErrors(); // delete popup message
    }

    public Zone onActionFromShowUser(String mail) throws BusinessException {
        return userDetailsDisplayer.getShowUser(mail);
    }

    public Zone onActionFromShowSignature(String docidentifier) throws BusinessException {
        return signatureDetailsDisplayer.getShowSignature(docidentifier);
    }

    public void onActionFromCopy(String docIdentifier) {
        logger.debug("onActionFromCopy");
        ShareDocumentVo shareDocumentVo = searchDocumentVoByUUid(componentdocuments, docIdentifier);
        boolean copyDone = false;

        //create the copy of the document and remove it from the received documents
        try {
            shareFacade.createLocalCopy(shareDocumentVo, user);
            copyDone = true;
        } catch (BusinessException e) {
            // process business exception. Can be thrown if no space left or wrong mime type.
            businessMessagesManagementService.notify(e);
        }

        if (copyDone) {
            businessMessagesManagementService
                    .notify(new BusinessUserMessage(BusinessUserMessageType.LOCAL_COPY_OK, MessageSeverity.INFO));
            componentResources.triggerEvent("resetListFiles", null, null);
        }
    }

    public Object onSuccessFromSearch() {
        if (listSelected.size() < 1) {
            businessMessagesManagementService.notify(
                    new BusinessUserMessage(BusinessUserMessageType.NOFILE_SELECTED, MessageSeverity.WARNING));
            return null;
        }

        actionbutton = ActionFromBarDocument.fromString(action);

        switch (actionbutton) {
        case DELETE_ACTION:
            if ("true".equals(deleteConfirmed)) {
                componentResources.getContainer().getComponentResources()
                        .triggerEvent("eventDeleteFromListDocument", listSelected.toArray(), null);
            }
            break;
        case SIGNATURE_ACTION:
            componentResources.getContainer().getComponentResources().triggerEvent("eventSignatureFromListDocument",
                    listSelected.toArray(), null);
            break;
        case COPY_ACTION:
            copyFromListDocument(listSelected);
            break;
        case FORWARD_ACTION:
            componentResources.getContainer().getComponentResources().triggerEvent("eventForwardFromListDocument",
                    listSelected.toArray(), null);
            break;
        case DECRYPT_ACTION:
            List<Object> decryptParameters = new ArrayList<Object>();
            decryptParameters.add(this.pass);
            decryptParameters.add(listSelected);
            componentResources.getContainer().getComponentResources()
                    .triggerEvent("eventDecryptListDocFromListDocument", decryptParameters.toArray(), null);
            break;
        case NO_ACTION:
        default:
            break;
        }

        actionbutton = ActionFromBarDocument.NO_ACTION;

        return null;
    }

    public Zone onValidateFormFromPasswordDecryptPopup() throws BusinessException {
        String pass = passwordDecryptPopup.getPassword();

        ShareDocumentVo currentSharedDocumentVo = searchDocumentVoByUUid(componentdocuments, currentUuid);

        if (null == currentSharedDocumentVo) {
            throw new BusinessException(BusinessErrorCode.INVALID_UUID, "invalid uuid for this user");
        } else {
            boolean copyDone = false;

            //create the copy of the document and remove it from the received documents
            DocumentVo copyDoc = null;
            try {
                copyDoc = shareFacade.createLocalCopy(currentSharedDocumentVo, user);
                copyDone = true;
            } catch (BusinessException e) {
                // process business exception. Can be thrown if no space left or wrong mime type.
                businessMessagesManagementService.notify(e);
            }

            if (copyDone) {
                businessMessagesManagementService.notify(
                        new BusinessUserMessage(BusinessUserMessageType.LOCAL_COPY_OK, MessageSeverity.INFO));
            }

            //decrypt document
            if (copyDoc != null && copyDoc.getEncrypted()) {
                try {
                    documentFacade.decryptDocument(copyDoc, user, pass);
                    businessMessagesManagementService.notify(
                            new BusinessUserMessage(BusinessUserMessageType.DECRYPTION_OK, MessageSeverity.INFO));

                } catch (BusinessException e) {
                    businessMessagesManagementService.notify(new BusinessUserMessage(
                            BusinessUserMessageType.DECRYPTION_FAILED, MessageSeverity.WARNING));
                    logger.debug(e.toString());
                }

            }
        }
        return passwordDecryptPopup.formSuccess();
    }

    /***************************
     * Events 
     ***************************/

    /**
     * The event triggered by the confirm window when the user pushes on YES.
     * @throws BusinessException exception throws when the uuid doesn't exist.
     */
    @OnEvent(value = "listDocumentEvent")
    public void removeDocument() throws BusinessException {
        if (null != currentUuid) {
            componentResources.getContainer().getComponentResources()
                    .triggerEvent("eventDeleteUniqueFromListDocument", new Object[] { currentUuid }, null);
        } else {
            throw new BusinessException(BusinessErrorCode.INVALID_UUID, "invalid uuid");
        }
    }

    @OnEvent(value = "signatureDocumentEvent")
    public void signatureDocument() throws BusinessException {
        if (null != currentUuid) {
            componentResources.getContainer().getComponentResources()
                    .triggerEvent("eventSignatureUniqueFromListDocument", new Object[] { currentUuid }, null);
        } else {
            throw new BusinessException(BusinessErrorCode.INVALID_UUID, "invalid uuid");
        }
    }

    public void copyFromListDocument(List<ShareDocumentVo> shares) {
        logger.debug("copyFromListDocument");

        for (ShareDocumentVo shareDocumentVo : shares) {
            boolean copyDone = false;

            //create the copy of the document and remove it from the received documents
            try {
                shareFacade.createLocalCopy(shareDocumentVo, user);
                copyDone = true;
            } catch (BusinessException e) {
                // process business exception. Can be thrown if no space left or wrong mime type.
                businessMessagesManagementService.notify(e);
            }
            if (copyDone) {
                businessMessagesManagementService.notify(
                        new BusinessUserMessage(BusinessUserMessageType.LOCAL_COPY_OK, MessageSeverity.INFO));
            }
        }
        componentResources.triggerEvent("resetListFiles", null, null);
    }

    /***************************
     * Other methods
     ****************************/

    /**
     * Property used for know if the list is empty.
     * @return true if the list is empty. else false.
     * 
     */
    public boolean isEmptyList() {
        return (null == shareDocuments || shareDocuments.isEmpty());
    }

    /**
     * Format the creation date for good displaying using DateFormatUtils of apache commons lib.
     * @return creation date the date in localized format.
     */
    public String getCreationDate() {
        SimpleDateFormat formatter = new SimpleDateFormat(messages.get("global.pattern.timestamp"));
        return formatter.format(shareDocument.getCreationDate().getTime());
    }

    /**
     * Format the creation date for good displaying using DateFormatUtils of apache commons lib.
     * @return creation date the date in localized format.
     */
    public String getExpirationDate() {
        SimpleDateFormat formatter = new SimpleDateFormat(messages.get("global.pattern.timestamp"));
        return formatter.format(shareDocument.getShareExpirationDate().getTime());
    }

    public String getSharingDate() {
        SimpleDateFormat formatter = new SimpleDateFormat(messages.get("global.pattern.timestamp"));
        return formatter.format(shareDocument.getSharingDate().getTime());
    }

    public String getFriendlySize() {
        return FileUtils.getFriendlySize(shareDocument.getSize(), messages);
    }

    public String getSharedBy() {
        return shareDocument.getSender().getFirstName() + " " + shareDocument.getSender().getLastName();
    }

    public boolean isDocumentSignedByCurrentUser() throws BusinessException {
        return shareFacade.isSignedShare(user, shareDocument);
    }

    public boolean isDocumentNotSignedByCurrentUserAndDocNotEncrypted() throws BusinessException {
        return !shareDocument.getEncrypted() && !isDocumentSignedByCurrentUser();
    }

    public boolean isDocumentSigned() {
        return shareFacade.isSignedShare(user, shareDocument);
    }

    /**
     * 
     * @return false (the document is never filesSelected by default)
     */
    public boolean isFilesSelected() {
        return false;
    }

    /**
     * This method is called when the form is submitted.
     * 
     * @param filesSelected
     *            filesSelected or not in the form.
     */
    public void setFilesSelected(boolean selected) {
        if (selected) {
            listSelected.add(shareDocument);
        }
    }

    /**
     * Help method for use in this component. It retrieves a documentVo by it's id.
     * @param documents list of documents.  
     * @param uuid the uuid of the document to retrieve.
     * @return DocumentVo concerned by the search.
     */
    private ShareDocumentVo searchDocumentVoByUUid(List<ShareDocumentVo> documents, String uuid) {
        for (ShareDocumentVo share : documents) {
            if (uuid.equals(share.getIdentifier())) {
                return share;
            }
        }
        return null;
    }

    public String getTruncatedFileName() {
        String result = StringUtils.abbreviate(shareDocument.getFileName(), truncatedValue);
        return result;
    }

    @SuppressWarnings("unchecked")
    @OnEvent(value = "eventReorderList")
    public void reorderList(Object[] o1) {
        if (o1 != null && o1.length > 0) {
            this.docs = (List<ShareDocumentVo>) Arrays.copyOf(o1, 1)[0];
            this.sorterModel = new SharedFileSorterModel(this.docs);
            refreshFlag = true;
        }

    }

    /**
     * model for the datagrid
     * we need it to switch off the signature column dynamically
     * administration can deactivate the signature function
     * @return
     * @throws BusinessException
     */
    public BeanModel initModel() throws BusinessException {

        //Initialize the sorter model for sorter component.
        if (refreshFlag) {
            shareDocuments = docs;
            refreshFlag = false;
        }

        sorterModel = new SharedFileSorterModel(shareDocuments);

        model = beanModelSource.createDisplayModel(ShareDocumentVo.class, componentResources.getMessages());

        // Native TML in HTML was:
        // exclude="fileName, identifier, size, encrypted, ownerLogin, shared, type, shareActive, downloaded, comment"
        // add="fileProperties,expirationDate,signed,actions"

        // Another native TML in HTML was: 
        // exclude="identifier, size, encrypted, ownerLogin, shared, type, shareActive, downloaded, comment"
        // add="friendlySize,createDate,expirationDate,signed,sharedBy,actions"

        model.add("fileProperties", null);
        //model.add("expirationDate",null);
        model.add("shareEdit", null);
        model.add("selectedValue", null);
        //       model.add("actions",null);

        if (activeSignature && activeEncypher) {
            model.add("signed", null);
            model.add("encryptedAdd", null);
            model.reorder("fileProperties", "expirationDate", "shareEdit", "signed", "encryptedAdd",
                    "selectedValue");
        } else if (activeSignature) {
            model.add("signed", null);
            model.reorder("fileProperties", "expirationDate", "shareEdit", "signed", "selectedValue");
        } else if (activeEncypher) {
            model.add("encryptedAdd", null);
            model.reorder("fileProperties", "expirationDate", "shareEdit", "encryptedAdd", "selectedValue");
        } else {
            model.reorder("fileProperties", "expirationDate", "shareEdit", "selectedValue");
        }
        return model;
    }

    public boolean isActiveSignature() {
        return activeSignature;
    }

    public boolean isEnabledToUpload() {
        return user.isUpload();
    }

    public Link getThumbnailPath() {
        return componentResources.createEventLink("thumbnail", shareDocument.getIdentifier());
    }

    public boolean getThumbnailExists() {
        return shareDocument.hasThumbnail();
    }

    public String getTypeCSSClass() {
        String ret = shareDocument.getType();
        ret = ret.replace("/", "_");
        ret = ret.replace("+", "__");
        ret = ret.replace(".", "_-_");
        return ret;
    }

    public void onThumbnail(String docID) throws BusinessException {
        InputStream stream = null;
        DocumentVo currentDocumentVo = searchDocumentVoByUUid(componentdocuments, docID);
        stream = shareFacade.getShareThumbnailStream(user, currentDocumentVo.getIdentifier());
        if (stream == null)
            return;
        OutputStream os = null;
        response.setDateHeader("Expires", 0);
        response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
        response.setHeader("Cache-Control", "post-check=0, pre-check=0");
        response.setHeader("Pragma", "no-cache");
        try {
            os = response.getOutputStream("image/png");
            BufferedImage bufferedImage = ImageIO.read(stream);
            if (bufferedImage != null)
                ImageIO.write(bufferedImage, Constants.THMB_DEFAULT_FORMAT, os);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (os != null) {
                    os.flush();
                    os.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }

    /**
     * remove all carriage return for chenille kit tool tip
     * @return
     */
    public String getFormatedComment() {
        String result = shareDocument.getFileComment().replaceAll("\r", "");
        result = result.replaceAll("\n", " ");
        return result;
    }

    public Zone onActionFromShareEditProperties(String persistenceId) throws BusinessException {
        shareEditForm.setEditShareWithId(persistenceId);
        return shareEditForm.getShowPopupWindow();
    }
}