org.jahia.services.content.impl.external.vfs.VFSDataSource.java Source code

Java tutorial

Introduction

Here is the source code for org.jahia.services.content.impl.external.vfs.VFSDataSource.java

Source

/**
 * This file is part of Jahia, next-generation open source CMS:
 * Jahia's next-generation, open source CMS stems from a widely acknowledged vision
 * of enterprise application convergence - web, search, document, social and portal -
 * unified by the simplicity of web content management.
 *
 * For more information, please visit http://www.jahia.com.
 *
 * Copyright (C) 2002-2012 Jahia Solutions Group SA. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 * As a special exception to the terms and conditions of version 2.0 of
 * the GPL (or any later version), you may redistribute this Program in connection
 * with Free/Libre and Open Source Software ("FLOSS") applications as described
 * in Jahia's FLOSS exception. You should have received a copy of the text
 * describing the FLOSS exception, and it is also available here:
 * http://www.jahia.com/license
 *
 * Commercial and Supported Versions of the program (dual licensing):
 * alternatively, commercial and supported versions of the program may be used
 * in accordance with the terms and conditions contained in a separate
 * written agreement between you and Jahia Solutions Group SA.
 *
 * If you are unsure which license is appropriate for your use,
 * please contact the sales department at sales@jahia.com.
 */

package org.jahia.services.content.impl.external.vfs;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.vfs.*;
import org.apache.jackrabbit.util.ISO8601;
import org.jahia.api.Constants;
import org.jahia.services.content.JCRContentUtils;
import org.jahia.services.content.impl.external.ExternalData;
import org.jahia.services.content.impl.external.ExternalDataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.jcr.Binary;
import javax.jcr.ItemNotFoundException;
import javax.jcr.PathNotFoundException;
import javax.jcr.RepositoryException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.*;

public class VFSDataSource implements ExternalDataSource, ExternalDataSource.Writable {
    private static final List<String> SUPPORTED_NODE_TYPES = Arrays.asList(Constants.JAHIANT_FILE,
            Constants.JAHIANT_FOLDER, Constants.JCR_CONTENT);
    public static final Logger logger = LoggerFactory.getLogger(VFSDataSource.class);
    protected String root;
    protected String rootPath;
    protected FileSystemManager manager;

    public void setRoot(String root) {
        this.root = root;

        try {
            manager = VFS.getManager();
            rootPath = getFile("/").getName().getPath();
        } catch (FileSystemException e) {
            logger.error(e.getMessage(), e);
        }
    }

    public boolean isSupportsUuid() {
        return false;
    }

    public boolean isSupportsSearch() {
        return false;
    }

    public List<String> getSupportedNodeTypes() {
        return SUPPORTED_NODE_TYPES;
    }

    public ExternalData getItemByIdentifier(String identifier) throws ItemNotFoundException {
        try {
            UUID.fromString(identifier);
            throw new ItemNotFoundException("This repository does not support UUID as identifiers");
        } catch (IllegalArgumentException iae) {
            // this is expected, we should not be using UUIDs
        }
        if (identifier.startsWith("/")) {
            try {
                return getItemByPath(identifier);
            } catch (PathNotFoundException e) {
                throw new ItemNotFoundException(identifier);
            }
        }
        FileObject fileObject = null;
        try {
            if (identifier.startsWith(root)) {
                fileObject = manager.resolveFile(identifier);
                if (!fileObject.exists()) {
                    throw new ItemNotFoundException(identifier);
                }
                return getFile(fileObject);
            } else {
                throw new ItemNotFoundException("File system exception while trying to retrieve " + identifier);
            }
        } catch (FileSystemException fse) {
            throw new ItemNotFoundException("File system exception while trying to retrieve " + identifier, fse);
        }
    }

    public ExternalData getItemByPath(String path) throws PathNotFoundException {
        try {
            if (path.endsWith("/" + Constants.JCR_CONTENT)) {
                FileContent content = getFile(StringUtils.substringBeforeLast(path, "/" + Constants.JCR_CONTENT))
                        .getContent();
                return getFileContent(content);
            } else {
                FileObject fileObject = getFile(path);
                if (!fileObject.exists()) {
                    throw new PathNotFoundException(path);
                }
                return getFile(fileObject);
            }

        } catch (FileSystemException e) {
            throw new PathNotFoundException("File system exception while trying to retrieve " + path, e);
        }
    }

    public FileObject getFile(String path) throws FileSystemException {
        return manager.resolveFile(root + path);
    }

    public List<String> getChildren(String path) {
        try {
            if (!path.endsWith("/" + Constants.JCR_CONTENT)) {
                FileObject fileObject = getFile(path);
                if (fileObject.getType() == FileType.FILE) {
                    return Arrays.asList(Constants.JCR_CONTENT);
                } else if (fileObject.getType() == FileType.FOLDER) {
                    List<String> children = new ArrayList<String>();
                    for (FileObject object : fileObject.getChildren()) {
                        children.add(object.getName().getBaseName());
                    }
                    return children;
                } else {
                    logger.warn("Found non file or folder entry, maybe an alias. VFS file type="
                            + fileObject.getType());
                }
            }
        } catch (FileSystemException e) {
            logger.error("Cannot get node children", e);
        }

        return new ArrayList<String>();
    }

    public void removeItemByPath(String path) throws PathNotFoundException {
        try {
            getFile(path).delete();
        } catch (FileSystemException e) {
            throw new PathNotFoundException(e);
        }
    }

    public void saveItem(ExternalData data) {
        if (data.getType().equals(Constants.NT_RESOURCE)) {
            OutputStream outputStream = null;
            try {
                final Binary[] binaries = data.getBinaryProperties().get(Constants.JCR_DATA);
                if (binaries.length > 0) {
                    outputStream = getFile(
                            data.getPath().substring(0, data.getPath().indexOf("/" + Constants.JCR_CONTENT)))
                                    .getContent().getOutputStream();
                    for (Binary binary : binaries) {
                        InputStream stream = null;
                        try {
                            stream = binary.getStream();
                            IOUtils.copy(stream, outputStream);
                        } finally {
                            IOUtils.closeQuietly(stream);
                            binary.dispose();
                        }
                    }
                }
            } catch (IOException e) {
                logger.error(e.getMessage(), e);
            } catch (RepositoryException e) {
                logger.error(e.getMessage(), e);
            } finally {
                IOUtils.closeQuietly(outputStream);
            }
        }
    }

    public void move(String oldPath, String newPath) throws PathNotFoundException {
        try {
            getFile(oldPath).moveTo(getFile(newPath));
        } catch (FileSystemException e) {
            throw new PathNotFoundException(oldPath);
        }
    }

    private ExternalData getFile(FileObject fileObject) throws FileSystemException {
        String identifier = fileObject.getURL().toString();
        String type;

        type = getDataType(fileObject);

        Map<String, String[]> properties = new HashMap<String, String[]>();
        if (fileObject.getContent() != null) {
            long lastModifiedTime = fileObject.getContent().getLastModifiedTime();
            if (lastModifiedTime > 0) {
                Calendar calendar = Calendar.getInstance();
                calendar.setTimeInMillis(lastModifiedTime);
                String[] timestampt = new String[] { ISO8601.format(calendar) };
                properties.put(Constants.JCR_CREATED, timestampt);
                properties.put(Constants.JCR_LASTMODIFIED, timestampt);
            }
        }

        String path = fileObject.getName().getPath().substring(rootPath.length());
        if (!path.startsWith("/")) {
            path = "/" + path;
        }

        return new ExternalData(identifier, path, type, properties);
    }

    public String getDataType(FileObject fileObject) throws FileSystemException {
        return fileObject.getType() == FileType.FILE ? Constants.JAHIANT_FILE : Constants.JAHIANT_FOLDER;
    }

    private ExternalData getFileContent(final FileContent content) throws FileSystemException {
        Map<String, String[]> properties = new HashMap<String, String[]>();

        String s1 = content.getContentInfo().getContentType();
        if (s1 == null) {
            s1 = JCRContentUtils.getMimeType(content.getFile().getName().getBaseName());
        }
        if (s1 == null) {
            s1 = "application/octet-stream";
        }
        properties.put(Constants.JCR_MIMETYPE, new String[] { s1 });

        Map<String, Binary[]> binaryProperties = new HashMap<String, Binary[]>();
        binaryProperties.put(Constants.JCR_DATA, new Binary[] { new VFSBinaryImpl(content) });

        String path = content.getFile().getName().getPath().substring(rootPath.length());

        ExternalData externalData = new ExternalData(path + "/" + Constants.JCR_CONTENT,
                path + "/" + Constants.JCR_CONTENT, Constants.NT_RESOURCE, properties);
        externalData.setBinaryProperties(binaryProperties);
        return externalData;
    }

    class VFSBinaryImpl implements Binary {

        FileContent fileContent;
        InputStream inputStream = null;

        public VFSBinaryImpl(InputStream inputStream) {
            // here we should copy the content of the inputstream, but where ??? Keeping it in memory is a bad idea.
            this.inputStream = inputStream;
        }

        public VFSBinaryImpl(FileContent fileContent) {
            this.fileContent = fileContent;
        }

        public InputStream getStream() throws RepositoryException {
            if (fileContent == null) {
                return inputStream;
            }
            try {
                inputStream = fileContent.getInputStream();
            } catch (FileSystemException e) {
                throw new RepositoryException("Error retrieving inputstream to file content", e);
            }
            return inputStream;
        }

        public int read(byte[] b, long position) throws IOException, RepositoryException {
            if (inputStream == null) {
                getStream();
            }
            return inputStream.read(b, (int) position, b.length);
        }

        public long getSize() throws RepositoryException {
            try {
                if (!fileContent.getFile().exists()) {
                    return 0;
                }
                return fileContent.getSize();
            } catch (FileSystemException e) {
                throw new RepositoryException("Error retrieving file's size", e);
            }
        }

        public void dispose() {
            try {
                fileContent.close();
            } catch (FileSystemException e) {
                logger.error("Error", e);
            }
        }
    }

}