org.pentaho.platform.repository2.unified.fs.FileSystemRepositoryFileDao.java Source code

Java tutorial

Introduction

Here is the source code for org.pentaho.platform.repository2.unified.fs.FileSystemRepositoryFileDao.java

Source

/*
 * This program is free software; you can redistribute it and/or modify it under the
 * terms of the GNU General Public License, version 2 as published by the Free Software
 * Foundation.
 *
 * You should have received a copy of the GNU General Public License along with this
 * program; if not, you can obtain a copy at http://www.gnu.org/licenses/gpl-2.0.html
 * or from the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * 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.
 *
 *
 * Copyright 2006 - 2013 Pentaho Corporation.  All rights reserved.
 */

package org.pentaho.platform.repository2.unified.fs;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.filefilter.WildcardFileFilter;
import org.apache.commons.lang.StringUtils;
import org.pentaho.platform.api.locale.IPentahoLocale;
import org.pentaho.platform.api.repository2.unified.IRepositoryFileData;
import org.pentaho.platform.api.repository2.unified.RepositoryFile;
import org.pentaho.platform.api.repository2.unified.RepositoryFileAcl;
import org.pentaho.platform.api.repository2.unified.RepositoryFileTree;
import org.pentaho.platform.api.repository2.unified.RepositoryRequest;
import org.pentaho.platform.api.repository2.unified.UnifiedRepositoryException;
import org.pentaho.platform.api.repository2.unified.VersionSummary;
import org.pentaho.platform.api.repository2.unified.data.node.NodeRepositoryFileData;
import org.pentaho.platform.api.repository2.unified.data.simple.SimpleRepositoryFileData;
import org.pentaho.platform.repository.RepositoryFilenameUtils;
import org.pentaho.platform.repository2.unified.IRepositoryFileDao;
import org.pentaho.platform.util.RepositoryPathEncoder;

@SuppressWarnings("nls")
public class FileSystemRepositoryFileDao implements IRepositoryFileDao {
    private File rootDir = new File(System.getProperty("solution.root.dir", System.getProperty("user.dir")));
    private static List<Character> reservedChars = Collections
            .unmodifiableList(Arrays.asList(new Character[] { '/', '\\', '\t', '\r', '\n' }));
    private static List<Character> reservedCharsWindows = Collections
            .unmodifiableList(Arrays.asList(new Character[] { '?', '*', ':', '<', '>', '|' }));

    public FileSystemRepositoryFileDao() {
        this(new File(System.getProperty("solution.root.dir", System.getProperty("user.dir"))));
    }

    public FileSystemRepositoryFileDao(final String baseDir) {
        this(new File(baseDir));
    }

    public FileSystemRepositoryFileDao(File baseDir) {
        // Detect OS
        final String os = System.getProperty("os.name").toLowerCase();
        if (os.contains("win") && baseDir.getPath().equals("\\")) {
            baseDir = new File("C:\\");
        }
        assert (baseDir.exists() && baseDir.isDirectory());
        this.rootDir = baseDir;
    }

    public boolean canUnlockFile(Serializable fileId) {
        throw new UnsupportedOperationException("This operation is not support by this repository");
    }

    public File getRootDir() {
        return new File(rootDir.getAbsolutePath());
    }

    private byte[] inputStreamToBytes(InputStream in) throws IOException {

        ByteArrayOutputStream out = new ByteArrayOutputStream(4096);
        byte[] buffer = new byte[4096];
        int len;

        while ((len = in.read(buffer)) >= 0) {
            out.write(buffer, 0, len);
        }

        in.close();
        out.close();
        return out.toByteArray();
    }

    public RepositoryFile createFile(Serializable parentFolderId, RepositoryFile file, IRepositoryFileData data,
            RepositoryFileAcl acl, String versionMessage) {
        String fileNameWithPath = RepositoryFilenameUtils.concat(parentFolderId.toString(), file.getName());
        FileOutputStream fos = null;
        File f = new File(fileNameWithPath);

        try {
            f.createNewFile();
            fos = new FileOutputStream(f);
            if (data instanceof SimpleRepositoryFileData) {
                fos.write(inputStreamToBytes(((SimpleRepositoryFileData) data).getInputStream()));
            } else if (data instanceof NodeRepositoryFileData) {
                fos.write(inputStreamToBytes(
                        new ByteArrayInputStream(((NodeRepositoryFileData) data).getNode().toString().getBytes())));
            }
        } catch (FileNotFoundException e) {
            throw new UnifiedRepositoryException("Error writing file [" + fileNameWithPath + "]", e);
        } catch (IOException e) {
            throw new UnifiedRepositoryException("Error writing file [" + fileNameWithPath + "]", e);
        } finally {
            IOUtils.closeQuietly(fos);
        }

        return internalGetFile(f);
    }

    public RepositoryFile createFolder(Serializable parentFolderId, RepositoryFile file, RepositoryFileAcl acl,
            String versionMessage) {
        try {
            String folderNameWithPath = parentFolderId + "/" + file.getName();
            File newFolder = new File(folderNameWithPath);
            newFolder.mkdir();
            final RepositoryFile repositoryFolder = internalGetFile(newFolder);
            return repositoryFolder;
        } catch (Throwable th) {
            throw new UnifiedRepositoryException();
        }
    }

    public void deleteFile(Serializable fileId, String versionMessage) {
        try {
            File f = new File(fileId.toString());
            f.delete();
        } catch (Exception e) {
            // CHECKSTYLES IGNORE
        }

    }

    public void deleteFileAtVersion(Serializable fileId, Serializable versionId) {
        deleteFile(fileId, null);
    }

    @Override
    public List<RepositoryFile> getChildren(RepositoryRequest repositoryRequest) {
        List<RepositoryFile> children = new ArrayList<RepositoryFile>();
        File folder = new File(getPhysicalFileLocation(repositoryRequest.getPath()));
        for (Iterator<File> iterator = FileUtils
                .listFiles(folder, new WildcardFileFilter(repositoryRequest.getChildNodeFilter()), null)
                .iterator(); iterator.hasNext();) {
            children.add(internalGetFile((File) iterator.next()));
        }
        return children;
    }

    @Deprecated
    public List<RepositoryFile> getChildren(Serializable folderId) {
        return getChildren(folderId, "", false);
    }

    @Deprecated
    public List<RepositoryFile> getChildren(Serializable folderId, String filter) {
        return getChildren(folderId, filter, false);
    }

    @Deprecated
    public List<RepositoryFile> getChildren(Serializable folderId, String filter, Boolean showHiddenFiles) {
        return getChildren(new RepositoryRequest(folderId.toString(), showHiddenFiles, -1, filter));
    }

    @SuppressWarnings("unchecked")
    public <T extends IRepositoryFileData> T getData(Serializable fileId, Serializable versionId,
            Class<T> dataClass) {
        File f = new File(fileId.toString());
        T data = null;
        try {
            if (SimpleRepositoryFileData.class.getName().equals(dataClass.getName())) {
                data = (T) new SimpleRepositoryFileData(new FileInputStream(f), "UTF-8", "text/plain");

            } else if (NodeRepositoryFileData.class.getName().equals(dataClass.getName())) {
                throw new UnsupportedOperationException("This operation is not support by this repository");
            }

        } catch (FileNotFoundException e) {
            throw new UnifiedRepositoryException(e);
        }
        return data;
    }

    public List<RepositoryFile> getDeletedFiles(Serializable folderId, String filter) {
        throw new UnsupportedOperationException("This operation is not support by this repository");
    }

    public List<RepositoryFile> getDeletedFiles() {
        throw new UnsupportedOperationException("This operation is not support by this repository");
    }

    public RepositoryFile internalGetFile(File f) {

        RepositoryFile file = null;
        if (f.exists()) {
            String jcrPath = f.getAbsolutePath().substring(rootDir.getAbsolutePath().length());
            if (jcrPath.length() == 0) {
                jcrPath = "/";
            }
            file = new RepositoryFile.Builder(f.getAbsolutePath(), f.getName())
                    .createdDate(new Date(f.lastModified())).lastModificationDate(new Date(f.lastModified()))
                    .folder(f.isDirectory()).versioned(false).path(jcrPath).versionId(f.getName()).locked(false)
                    .lockDate(null).lockMessage(null).lockOwner(null).title(f.getName()).description(f.getName())
                    .locale(null).fileSize(f.length()).build();
        }
        return file;

    }

    public RepositoryFile getFile(String relPath) {
        return internalGetFile(new File(getPhysicalFileLocation(relPath)));
    }

    static String idToPath(String relPath) {
        relPath = RepositoryPathEncoder.decodeRepositoryPath(relPath);
        return relPath.replaceFirst("^/?([A-z])/[/\\\\](.*)", "$1:/$2");
    }

    public RepositoryFile getFile(Serializable fileId, Serializable versionId) {
        return getFile(fileId.toString());
    }

    public RepositoryFile getFileByAbsolutePath(String absPath) {
        return getFile(absPath);
    }

    public RepositoryFile getFileById(Serializable fileId) {
        return getFile(fileId.toString());
    }

    public RepositoryFile getFile(String relPath, boolean loadLocaleMaps) {
        return getFile(relPath);
    }

    public RepositoryFile getFileById(Serializable fileId, boolean loadLocaleMaps) {
        return getFile(fileId.toString());
    }

    @Override
    public RepositoryFile getFile(String relPath, IPentahoLocale locale) {
        return getFile(relPath);
    }

    @Override
    public RepositoryFile getFileById(Serializable fileId, IPentahoLocale locale) {
        return getFile(fileId.toString());
    }

    @Override
    public RepositoryFile getFile(String relPath, boolean loadLocaleMaps, IPentahoLocale locale) {
        return getFile(relPath);
    }

    @Override
    public RepositoryFile getFileById(Serializable fileId, boolean loadLocaleMaps, IPentahoLocale locale) {
        return getFile(fileId.toString());
    }

    @Override
    public RepositoryFileTree getTree(RepositoryRequest repositoryRequest) {

        File root = new File(getPhysicalFileLocation(repositoryRequest.getPath()));

        //TODO ACL     
        return getTree(root, repositoryRequest.getDepth().intValue(), repositoryRequest.getChildNodeFilter(),
                repositoryRequest.getTypes());
    }

    @Deprecated
    public RepositoryFileTree getTree(String relPath, int depth, String filter, boolean showHidden) {

        File root = new File(getPhysicalFileLocation(relPath));

        //TODO ACL     
        return getTree(root, depth, filter, RepositoryRequest.FILES_TYPE_FILTER.FILES_FOLDERS);
    }

    private RepositoryFileTree getTree(final File file, final int depth, final String childNodeFilter,
            RepositoryRequest.FILES_TYPE_FILTER types) {

        RepositoryFile rootFile = internalGetFile(file);

        List<RepositoryFileTree> children;

        if (depth != 0) {
            children = new ArrayList<RepositoryFileTree>();

            if (file.isDirectory()) {

                File[] childrenArray = file.listFiles();

                for (File child : childrenArray) {

                    if (child.isFile()) {

                        if (types == RepositoryRequest.FILES_TYPE_FILTER.FILES_FOLDERS
                                || types == RepositoryRequest.FILES_TYPE_FILTER.FILES) {
                            children.add(new RepositoryFileTree(internalGetFile(child),
                                    new ArrayList<RepositoryFileTree>()));
                        }

                        continue;
                    }

                    RepositoryFileTree repositoryChildFileTree = getTree(child, depth - 1, childNodeFilter, types);
                    if (repositoryChildFileTree != null) {
                        children.add(repositoryChildFileTree);
                    }
                }
            }
            Collections.sort(children);
        } else {
            children = null;
        }
        return new RepositoryFileTree(rootFile, children);
    }

    public List<VersionSummary> getVersionSummaries(Serializable fileId) {
        throw new UnsupportedOperationException("This operation is not support by this repository");
    }

    public VersionSummary getVersionSummary(Serializable fileId, Serializable versionId) {
        RepositoryFile file = getFile(fileId, versionId);
        List<String> labels = new ArrayList<String>();
        return new VersionSummary(fileId, (versionId != null ? versionId : fileId), false, file.getCreatedDate(),
                file.getCreatorId(), StringUtils.EMPTY, labels);
    }

    public void lockFile(Serializable fileId, String message) {
        throw new UnsupportedOperationException("This operation is not support by this repository");
    }

    public void moveFile(Serializable fileId, String destRelPath, String versionMessage) {
        RepositoryFile file = getFileById(fileId);
        SimpleRepositoryFileData data = getData(fileId, null, SimpleRepositoryFileData.class);
        deleteFile(fileId, versionMessage);
        createFile(null, file, data, null, versionMessage);
    }

    public void permanentlyDeleteFile(Serializable fileId, String versionMessage) {
        throw new UnsupportedOperationException("This operation is not support by this repository");
    }

    public void restoreFileAtVersion(Serializable fileId, Serializable versionId, String versionMessage) {
        throw new UnsupportedOperationException("This operation is not support by this repository");
    }

    public void undeleteFile(Serializable fileId, String versionMessage) {
        throw new UnsupportedOperationException("This operation is not support by this repository");
    }

    public void unlockFile(Serializable fileId) {
        throw new UnsupportedOperationException("This operation is not support by this repository");
    }

    public RepositoryFile updateFile(RepositoryFile file, IRepositoryFileData data, String versionMessage) {
        File f = new File(file.getId().toString());
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(f, false);
            if (data instanceof SimpleRepositoryFileData) {
                fos.write(inputStreamToBytes(((SimpleRepositoryFileData) data).getInputStream()));
            } else if (data instanceof NodeRepositoryFileData) {
                fos.write(inputStreamToBytes(
                        new ByteArrayInputStream(((NodeRepositoryFileData) data).getNode().toString().getBytes())));
            }
        } catch (FileNotFoundException e) {
            throw new UnifiedRepositoryException(e);
        } catch (IOException e) {
            throw new UnifiedRepositoryException(e);
        } finally {
            IOUtils.closeQuietly(fos);
        }

        return getFile(file.getPath());
    }

    public List<RepositoryFile> getReferrers(Serializable fileId) {
        throw new UnsupportedOperationException();
    }

    public void setRootDir(File rootDir) {
        this.rootDir = rootDir;
    }

    public void setFileMetadata(final Serializable fileId, Map<String, Serializable> metadataMap) {
        final File targetFile = new File(fileId.toString());
        if (targetFile.exists()) {
            FileOutputStream fos = null;
            try {
                final File metadataDir = new File(targetFile.getParent() + File.separatorChar + ".metadata");
                if (!metadataDir.exists()) {
                    metadataDir.mkdir();
                }
                final File metadataFile = new File(metadataDir, targetFile.getName());
                if (!metadataFile.exists()) {
                    metadataFile.createNewFile();
                }

                final StringBuilder data = new StringBuilder();
                for (String key : metadataMap.keySet()) {
                    data.append(key).append('=');
                    if (metadataMap.get(key) != null) {
                        data.append(metadataMap.get(key).toString());
                    }
                    data.append('\n');
                }
                fos = new FileOutputStream(metadataFile);
                fos.write(data.toString().getBytes());
            } catch (FileNotFoundException e) {
                throw new UnifiedRepositoryException("Error writing file metadata [" + fileId + "]", e);
            } catch (IOException e) {
                throw new UnifiedRepositoryException("Error writing file metadata [" + fileId + "]", e);
            } finally {
                IOUtils.closeQuietly(fos);
            }
        }
    }

    public Map<String, Serializable> getFileMetadata(final Serializable fileId) {
        final String metadataFilename = FilenameUtils.concat(
                FilenameUtils.concat(FilenameUtils.getFullPathNoEndSeparator(fileId.toString()), ".metadata"),
                FilenameUtils.getName(fileId.toString()));
        final Map<String, Serializable> metadata = new HashMap<String, Serializable>();
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new FileReader(metadataFilename));
            String data = reader.readLine();
            while (data != null) {
                final int pos = data.indexOf('=');
                if (pos > 0) {
                    final String key = data.substring(0, pos);
                    final String value = (data.length() > pos ? data.substring(pos + 1) : null);
                    metadata.put(key, value);
                }
                data = reader.readLine();
            }
        } catch (FileNotFoundException e) {
            // Do nothing ... metadata empty
        } catch (IOException e) {
            throw new UnifiedRepositoryException("Error reading metadata [" + fileId + "]", e);
        } finally {
            IOUtils.closeQuietly(reader);
        }
        return metadata;
    }

    public void copyFile(Serializable fileId, String destAbsPath, String versionMessage) {
        throw new UnsupportedOperationException("This operation is not support by this repository");
    }

    public List<RepositoryFile> getDeletedFiles(String origParentFolderPath, String filter) {
        throw new UnsupportedOperationException("This operation is not support by this repository");
    }

    @Override
    public List<Character> getReservedChars() {
        List<Character> charList = new ArrayList<Character>();
        String osName = System.getProperty("os.name");
        charList.addAll(reservedChars);
        if (osName.contains("Windows")) {
            charList.addAll(reservedCharsWindows);
        }
        return charList;
    }

    @Override
    public List<Locale> getAvailableLocalesForFileById(Serializable fileId) {
        throw new UnsupportedOperationException("This operation is not support by this repository");
    }

    @Override
    public List<Locale> getAvailableLocalesForFileByPath(String relPath) {
        throw new UnsupportedOperationException("This operation is not support by this repository");
    }

    @Override
    public List<Locale> getAvailableLocalesForFile(RepositoryFile repositoryFile) {
        throw new UnsupportedOperationException("This operation is not support by this repository");
    }

    @Override
    public Properties getLocalePropertiesForFileById(Serializable fileId, String locale) {
        throw new UnsupportedOperationException("This operation is not support by this repository");
    }

    @Override
    public Properties getLocalePropertiesForFileByPath(String relPath, String locale) {
        throw new UnsupportedOperationException("This operation is not support by this repository");
    }

    @Override
    public Properties getLocalePropertiesForFile(RepositoryFile repositoryFile, String locale) {
        throw new UnsupportedOperationException("This operation is not support by this repository");
    }

    @Override
    public void setLocalePropertiesForFileById(Serializable fileId, String locale, Properties properties) {
        throw new UnsupportedOperationException("This operation is not support by this repository");
    }

    @Override
    public void setLocalePropertiesForFileByPath(String relPath, String locale, Properties properties) {
        throw new UnsupportedOperationException("This operation is not support by this repository");
    }

    @Override
    public void setLocalePropertiesForFile(RepositoryFile repositoryFile, String locale, Properties properties) {
        throw new UnsupportedOperationException("This operation is not support by this repository");
    }

    @Override
    public void deleteLocalePropertiesForFile(RepositoryFile repositoryFile, String locale) {
        throw new UnsupportedOperationException("This operation is not support by this repository");
    }

    @Override
    public RepositoryFile updateFolder(RepositoryFile file, String versionMessage) {
        throw new UnsupportedOperationException("This operation is not support by this repository");
    }

    private String getPhysicalFileLocation(String relPath) {

        if (StringUtils.isEmpty(relPath)) {
            return relPath;
        }

        String physicalFileLocation = relPath;
        if (relPath.equals("/")) {
            physicalFileLocation = rootDir.getAbsolutePath();
        } else if (relPath.startsWith(rootDir.getAbsolutePath())) {
            physicalFileLocation = relPath;
        } else {
            physicalFileLocation = RepositoryFilenameUtils.concat(rootDir.getAbsolutePath(),
                    relPath.substring(RepositoryFilenameUtils.getPrefixLength(relPath)));
        }

        return physicalFileLocation;
    }
}