org.hippoecm.frontend.plugins.console.editor.BinaryEditor.java Source code

Java tutorial

Introduction

Here is the source code for org.hippoecm.frontend.plugins.console.editor.BinaryEditor.java

Source

/*
 *  Copyright 2012-2016 Hippo B.V. (http://www.onehippo.com)
 *
 *  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.hippoecm.frontend.plugins.console.editor;

import java.io.IOException;
import java.io.InputStream;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;

import javax.jcr.Node;
import javax.jcr.Property;
import javax.jcr.RepositoryException;
import javax.jcr.Value;

import org.apache.jackrabbit.api.JackrabbitValue;
import org.apache.jackrabbit.commons.JcrUtils;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.AjaxLink;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.link.Link;
import org.apache.wicket.markup.html.link.ResourceLink;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.request.resource.ResourceStreamResource;
import org.apache.wicket.util.io.IOUtils;
import org.apache.wicket.util.lang.Bytes;
import org.apache.wicket.util.resource.AbstractResourceStream;
import org.apache.wicket.util.resource.IResourceStream;
import org.apache.wicket.util.resource.ResourceStreamNotFoundException;
import org.apache.wicket.util.time.Duration;
import org.apache.wicket.util.time.Time;
import org.hippoecm.frontend.dialog.DialogLink;
import org.hippoecm.frontend.dialog.IDialogFactory;
import org.hippoecm.frontend.dialog.IDialogService;
import org.hippoecm.frontend.model.properties.JcrPropertyModel;
import org.hippoecm.frontend.plugin.IPluginContext;
import org.hippoecm.frontend.plugins.console.dialog.BinaryUploadDialog;
import org.hippoecm.repository.api.HippoNodeType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class BinaryEditor extends Panel {

    private static final Logger log = LoggerFactory.getLogger(BinaryEditor.class);

    private static final long ONE_KB = 1024;
    private static final long ONE_MB = ONE_KB * ONE_KB;
    private static final long ONE_GB = ONE_KB * ONE_MB;

    private String contentIdentity = "";

    public BinaryEditor(String id, JcrPropertyModel model, final IPluginContext pluginContext) {
        super(id, model);
        final IResourceStream stream = new BinaryResourceStream(model);

        // download
        final ResourceStreamResource resource = new ResourceStreamResource(stream);
        resource.setCacheDuration(Duration.NONE);
        try {
            final Node node = model.getProperty().getParent().getParent();
            final StringBuilder fileName = new StringBuilder(node.getName());
            if (isExtractedTextProperty(model.getProperty())) {
                fileName.append(".txt");
            }
            resource.setFileName(fileName.toString());
        } catch (RepositoryException e) {
            log.error("Unexpected exception while determining download filename", e);
        }
        final Link downloadLink = new ResourceLink("binary-download-lnk", resource);
        downloadLink.add(new Label("binary-download-text", "download (" + getSizeString(stream.length()) + ")"));
        add(downloadLink);

        // upload
        IDialogFactory factory = new IDialogFactory() {
            private static final long serialVersionUID = 1L;

            public IDialogService.Dialog createDialog() {
                return new BinaryUploadDialog(model);
            }
        };
        final IDialogService service = pluginContext.getService(IDialogService.class.getName(),
                IDialogService.class);
        final DialogLink uploadLink = new DialogLink("binary-upload-link", new Model<>("Upload binary"), factory,
                service);
        add(uploadLink);

        // Jackrabbit Binary Content Identifier if this Binary is in BinaryStore.
        final Label contentIdentityValueLabel = new Label("content-identity-value",
                new PropertyModel<String>(this, "contentIdentity"));
        contentIdentityValueLabel.setOutputMarkupPlaceholderTag(true);
        contentIdentityValueLabel.setVisible(false);
        add(contentIdentityValueLabel);
        final AjaxLink contentIdentityShowLink = new AjaxLink("content-identity-show-link") {
            @Override
            public void onClick(AjaxRequestTarget target) {
                setContentIdentity(retrieveJackrabbitContentIdentity());
                target.add(contentIdentityValueLabel.setVisible(true));
                target.add(this.setVisible(false));
            }
        };
        add(contentIdentityShowLink);
    }

    public String getContentIdentity() {
        return contentIdentity;
    }

    public void setContentIdentity(String contentIdentity) {
        this.contentIdentity = contentIdentity;
    }

    private String retrieveJackrabbitContentIdentity() {
        String contentIdentity = "";

        try {
            final Value value = ((JcrPropertyModel) getDefaultModel()).getProperty().getValue();

            if (value instanceof JackrabbitValue) {
                contentIdentity = ((JackrabbitValue) value).getContentIdentity();
            }
        } catch (RepositoryException e) {
            log.error("Failed to get Jackrabbit Binary Value Content Identity.", e);
        }

        return contentIdentity;
    }

    private static String getSizeString(final Bytes bytes) {
        if (bytes == null) {
            return "unknown size";
        }
        long length = bytes.bytes();
        String sizeString;
        if (length / ONE_GB > 0) {
            sizeString = String.valueOf(length / ONE_GB) + " GB";
        } else if (length / ONE_MB > 0) {
            sizeString = String.valueOf(length / ONE_MB) + " MB";
        } else if (length / ONE_KB > 0) {
            sizeString = String.valueOf(length / ONE_KB) + " KB";
        } else {
            sizeString = String.valueOf(length) + " bytes";
        }
        return sizeString;
    }

    private static boolean isExtractedTextProperty(Property property) {
        try {
            return property.getName().equals(HippoNodeType.HIPPO_TEXT) && isPartOfHippoDocument(property);
        } catch (RepositoryException e) {
            log.error("Unexpected exception while determining whether property contains extracted text", e);
            return false;
        }
    }

    private static boolean isPartOfHippoDocument(final Property property) throws RepositoryException {
        final Node root = property.getSession().getRootNode();
        Node current = property.getParent();
        while (!current.isSame(root)) {
            Node parent = current.getParent();
            if (parent.isNodeType(HippoNodeType.NT_HANDLE) && current.isNodeType(HippoNodeType.NT_DOCUMENT)) {
                return true;
            }
            current = parent;
        }
        return false;
    }

    private static class BinaryResourceStream extends AbstractResourceStream {

        private transient InputStream is;
        private JcrPropertyModel model;

        private BinaryResourceStream(JcrPropertyModel model) {
            this.model = model;
        }

        @Override
        public String getContentType() {
            try {
                if (BinaryEditor.isExtractedTextProperty(model.getProperty())) {
                    return "text/plain";
                } else {
                    final Node node = model.getProperty().getParent();
                    return JcrUtils.getStringProperty(node, "jcr:mimeType", "unknown");
                }
            } catch (RepositoryException e) {
                log.error("Unexpected exception while determining mime type", e);
            }
            return "unknown";
        }

        @Override
        public Bytes length() {
            try {
                return Bytes.bytes(model.getProperty().getLength());
            } catch (RepositoryException e) {
                return null;
            }
        }

        @Override
        public InputStream getInputStream() throws ResourceStreamNotFoundException {
            try {
                is = model.getProperty().getBinary().getStream();
                return is;
            } catch (RepositoryException e) {
                throw new ResourceStreamNotFoundException(e);
            }
        }

        @Override
        public void close() throws IOException {
            if (is != null) {
                IOUtils.closeQuietly(is);
            }
        }

        @Override
        public Locale getLocale() {
            return null;
        }

        @Override
        public void setLocale(final Locale locale) {
        }

        @Override
        public Time lastModifiedTime() {
            try {
                final Node node = model.getProperty().getParent();
                return Time.valueOf(
                        JcrUtils.getDateProperty(node, "jcr:lastModified", Calendar.getInstance()).getTime());
            } catch (RepositoryException e) {
                log.error("Unexpected exception while determining last modified date", e);
            }
            return Time.valueOf(new Date());
        }
    }
}