Java tutorial
/* * 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.fileio; import org.apache.commons.lang.StringUtils; import org.pentaho.platform.api.repository2.unified.ISourcesStreamEvents; import org.pentaho.platform.api.repository2.unified.IStreamListener; import org.pentaho.platform.api.repository2.unified.IUnifiedRepository; import org.pentaho.platform.api.repository2.unified.RepositoryFile; import org.pentaho.platform.api.repository2.unified.data.simple.SimpleRepositoryFileData; import org.pentaho.platform.engine.core.system.PentahoSystem; import org.pentaho.platform.repository.RepositoryFilenameUtils; import org.pentaho.platform.util.web.MimeHelper; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.Serializable; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collections; import java.util.List; public class RepositoryFileOutputStream extends ByteArrayOutputStream implements ISourcesStreamEvents { protected boolean hidden = false; protected String path = null; protected IUnifiedRepository repository; protected String charsetName = null; protected boolean autoCreateUniqueFileName = false; protected boolean autoCreateDirStructure = false; protected boolean closed = false; protected boolean flushed = false; protected ArrayList<IStreamListener> listeners = new ArrayList<IStreamListener>(); public RepositoryFileOutputStream(final String path, final boolean autoCreateUniqueFileName, final boolean autoCreateDirStructure, final IUnifiedRepository repository, final boolean hidden) { setRepository(repository); this.path = path; this.hidden = hidden; this.autoCreateDirStructure = autoCreateDirStructure; this.autoCreateUniqueFileName = autoCreateUniqueFileName; } public RepositoryFileOutputStream(final Serializable id, final boolean autoCreateUniqueFileName, final boolean autoCreateDirStructure, final IUnifiedRepository repository, final boolean hidden) throws FileNotFoundException { setRepository(repository); RepositoryFile file = this.repository.getFileById(id); if (file == null) { throw new FileNotFoundException( MessageFormat.format("Repository file with id {0} not readable or does not exist", id)); } this.hidden = hidden; this.path = file.getPath(); this.autoCreateDirStructure = autoCreateDirStructure; this.autoCreateUniqueFileName = autoCreateUniqueFileName; } public RepositoryFileOutputStream(final RepositoryFile file, final boolean autoCreateUniqueFileName, final boolean autoCreateDirStructure, final IUnifiedRepository repository) { this(file.getPath(), autoCreateUniqueFileName, autoCreateDirStructure, repository, false); } public RepositoryFileOutputStream(final String path, final boolean autoCreateUniqueFileName, final boolean autoCreateDirStructure) { this(path, autoCreateUniqueFileName, autoCreateDirStructure, null, false); } public RepositoryFileOutputStream(final Serializable id, final boolean autoCreateUniqueFileName, final boolean autoCreateDirStructure) throws FileNotFoundException { this(id, autoCreateUniqueFileName, autoCreateDirStructure, null, false); } public RepositoryFileOutputStream(final RepositoryFile file, final boolean autoCreateUniqueFileName, final boolean autoCreateDirStructure) { this(file, autoCreateUniqueFileName, autoCreateDirStructure, null); } public RepositoryFileOutputStream(final String path) { this(path, false, false, null, false); } public RepositoryFileOutputStream(final String path, final boolean hidden) { this(path, false, false, null, hidden); } public RepositoryFileOutputStream(final RepositoryFile file) { this(file.getPath(), false, false, null, file.isHidden()); } public RepositoryFileOutputStream(final Serializable id) throws FileNotFoundException { this(id, false, false, null, false); } // // // charsetName is required as metadata so the JCR can be provided the correct encoding, provided // we are storing text. These are package private methosd only and should only be called by // RepositoryFileWriter, because if you are wanting to write characters to a repository file, // you need to use RepositoryFileWriter, not this class. // protected RepositoryFileOutputStream(String path, String charsetName) throws FileNotFoundException { this(path); this.charsetName = charsetName; } protected RepositoryFileOutputStream(RepositoryFile file, String charsetName) throws FileNotFoundException { this(file); this.charsetName = charsetName; } protected RepositoryFileOutputStream(Serializable id, String charsetName) throws FileNotFoundException { this(id); this.charsetName = charsetName; } // // // protected RepositoryFile getParent(String path) { String newFilePath = StringUtils.removeEnd(path, "/"); //$NON-NLS-1$ String parentPath = StringUtils.substringBeforeLast(newFilePath, "/"); //$NON-NLS-1$ if (parentPath.isEmpty()) { parentPath = "/"; } return repository.getFile(parentPath); } @Override public void close() throws IOException { if (!closed) { flush(); closed = true; reset(); } } @Override public void flush() throws IOException { if (closed) { return; } super.flush(); ByteArrayInputStream bis = new ByteArrayInputStream(toByteArray()); // make an effort to determine the correct mime type, default to application/octet-stream String ext = RepositoryFilenameUtils.getExtension(path); String mimeType = "application/octet-stream"; //$NON-NLS-1$ if (ext != null) { String tempMimeType = MimeHelper.getMimeTypeFromExtension("." + ext); //$NON-NLS-1$ if (tempMimeType != null) { mimeType = tempMimeType; } } if (charsetName == null && mimeType != null) { charsetName = MimeHelper.getDefaultCharset(mimeType); } // FIXME: not a good idea that we assume we are dealing with text. Best if this is somehow moved to the // RepositoryFileWriter // but I couldn't figure out a clean way to do that. For now, charsetName is passed in here and we use it if // available. final SimpleRepositoryFileData payload = new SimpleRepositoryFileData(bis, charsetName, mimeType); if (!flushed) { RepositoryFile file = repository.getFile(path); RepositoryFile parentFolder = getParent(path); String baseFileName = RepositoryFilenameUtils.getBaseName(path); String extension = RepositoryFilenameUtils.getExtension(path); if (file == null) { if (autoCreateDirStructure) { ArrayList<String> foldersToCreate = new ArrayList<String>(); String parentPath = RepositoryFilenameUtils.getFullPathNoEndSeparator(path); // Make sure the parent path isn't the root while ((parentPath != null) && (parentPath.length() > 0 && !path.equals(parentPath)) && (repository.getFile(parentPath) == null)) { foldersToCreate.add(RepositoryFilenameUtils.getName(parentPath)); parentPath = RepositoryFilenameUtils.getFullPathNoEndSeparator(parentPath); } Collections.reverse(foldersToCreate); parentFolder = ((parentPath != null) && (parentPath.length() > 0)) ? repository.getFile(parentPath) : repository.getFile("/"); if (!parentFolder.isFolder()) { throw new FileNotFoundException(); } for (String folderName : foldersToCreate) { parentFolder = repository.createFolder(parentFolder.getId(), new RepositoryFile.Builder(folderName).folder(true).build(), null); } } else { if (parentFolder == null) { throw new FileNotFoundException(); } } file = new RepositoryFile.Builder(RepositoryFilenameUtils.getName(path)).hidden(hidden) .versioned(true).build(); // Default // versioned to true so that we're keeping history file = repository.createFile(parentFolder.getId(), file, payload, "commit from " + RepositoryFileOutputStream.class.getName()); //$NON-NLS-1$ for (IStreamListener listener : listeners) { listener.fileCreated(path); } } else if (file.isFolder()) { throw new FileNotFoundException( MessageFormat.format("Repository file {0} is a directory", file.getPath())); } else { if (autoCreateUniqueFileName) { int nameCount = 1; String newFileName = null; List<RepositoryFile> children = repository.getChildren(parentFolder.getId()); boolean hasFile = true; while (hasFile) { hasFile = false; nameCount++; if ((extension != null) && (extension.length() > 0)) { newFileName = baseFileName + "(" + nameCount + ")." + extension; //$NON-NLS-1$ //$NON-NLS-2$ } else { newFileName = baseFileName + "(" + nameCount + ")"; //$NON-NLS-1$ //$NON-NLS-2$ } for (RepositoryFile child : children) { if (child.getPath().equals(parentFolder.getPath() + "/" + newFileName)) { hasFile = true; break; } } } file = new RepositoryFile.Builder(newFileName).versioned(true).build(); // Default versioned to true // so // that we're keeping history file = repository.createFile(parentFolder.getId(), file, payload, "New File"); //$NON-NLS-1$ path = file.getPath(); for (IStreamListener listener : listeners) { listener.fileCreated(path); } } else { repository.updateFile(file, payload, "New File"); //$NON-NLS-1$ path = file.getPath(); for (IStreamListener listener : listeners) { listener.fileCreated(path); } } } } else { RepositoryFile file = repository.getFile(path); repository.updateFile(file, payload, "New File"); //$NON-NLS-1$ } flushed = true; } public String getFilePath() { return path; } public void setFilePath(String path) { if (!path.equals(this.path)) { this.path = path; reset(); flushed = false; closed = false; } } public boolean getAutoCreateUniqueFileName() { return autoCreateUniqueFileName; } public boolean getAutoCreateDirStructure() { return autoCreateDirStructure; } public void setAutoCreateDirStructure(boolean autoCreateDirStructure) { this.autoCreateDirStructure = autoCreateDirStructure; } public void addListener(IStreamListener listener) { listeners.add(listener); } public void setRepository(final IUnifiedRepository repository) { this.repository = (repository != null ? repository : PentahoSystem.get(IUnifiedRepository.class)); } public IUnifiedRepository getRepository() { return this.repository; } public String getCharsetName() { return charsetName; } public void setCharsetName(final String charsetName) { this.charsetName = charsetName; } public boolean isFlushed() { return flushed; } }