/*
* Copyright 2008-2014 the original author or authors
*
* 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.kaleidofoundry.core.store;
import static org.kaleidofoundry.core.store.FileStoreConstants.DEFAULT_BUFFER_SIZE;
import static org.kaleidofoundry.core.store.FileStoreConstants.FileSystemStorePluginName;
import static org.kaleidofoundry.core.store.FileStoreContextBuilder.BufferSize;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URI;
import org.kaleidofoundry.core.context.RuntimeContext;
import org.kaleidofoundry.core.io.FileHelper;
import org.kaleidofoundry.core.io.MimeTypeResolverFactory;
import org.kaleidofoundry.core.lang.annotation.Immutable;
import org.kaleidofoundry.core.lang.annotation.NotNull;
import org.kaleidofoundry.core.plugin.Declare;
/**
* File system store implementation (Windows, Linux, MacOS, ...) <br/>
* <p>
* You can use following variable in the file system uri:
* <ul>
* <li><code>file:/${basedir.default}</code> - the default application basedir (it can be override using the java system properties
* -Dbasedir.default=...)</li>
* <li><code>file:/${yourapp.basedir}</code> - your custom application basedir (it can be override using the java system properties
* -Dyourapp.basedir=...)</li>
* <li><code>file:/.</code> - the current system path</li>
* <li><code>file:/..</code> - the parent of the current system path</li>
* </ul>
* </p>
*
* @author jraduget
* @see FileStoreContextBuilder enum of context configuration properties available
*/
@Immutable
@Declare(FileSystemStorePluginName)
public class FileSystemStore extends AbstractFileStore implements FileStore {
/**
* @param context
*/
public FileSystemStore(@NotNull final RuntimeContext<FileStore> context) {
super(context);
}
/**
* @param baseUri
* @param context
*/
public FileSystemStore(final String baseUri, final RuntimeContext<FileStore> context) {
super(baseUri, context);
}
/**
* @see AbstractFileStore#AbstractFileStore()
*/
FileSystemStore() {
super();
}
/*
* (non-Javadoc)
* @see org.kaleidofoundry.core.store.AbstractFileStore#doLoad(java.net.URI)
*/
@Override
protected ResourceHandler doGet(final URI resourceUri) throws ResourceNotFoundException, ResourceException {
try {
File file = new File(resourceUri.getPath());
ResourceHandler resource = createResourceHandler(resourceUri.toString(), new FileInputStream(file));
// Set some meta datas
if (resource instanceof ResourceHandlerBean) {
((ResourceHandlerBean) resource).setLastModified(file.lastModified());
((ResourceHandlerBean) resource).setLength(file.length());
((ResourceHandlerBean) resource).setMimeType(MimeTypeResolverFactory.getService().getMimeType(
FileHelper.getFileNameExtension(resourceUri.getPath())));
}
return resource;
} catch (final FileNotFoundException fnfe) {
throw new ResourceNotFoundException(resourceUri.toString());
}
}
/*
* (non-Javadoc)
* @see org.kaleidofoundry.core.store.AbstractFileStore#doRemove(java.net.URI)
*/
@Override
protected void doRemove(final URI resourceUri) throws ResourceNotFoundException, ResourceException {
final File file = new File(resourceUri.getPath());
if (file.isDirectory()) {
throw new ResourceException("store.remove.directory", resourceUri.toString());
} else {
if (!file.delete()) { throw new ResourceException("store.remove.illegal", resourceUri.toString()); }
}
}
/*
* (non-Javadoc)
* @see org.kaleidofoundry.core.store.AbstractFileStore#doStore(java.net.URI, org.kaleidofoundry.core.store.ResourceHandler)
*/
@Override
protected void doStore(final URI resourceUri, final ResourceHandler resource) throws ResourceException {
File file;
FileOutputStream out = null;
try {
file = new File(resourceUri.getPath());
out = new FileOutputStream(file, false);
final byte[] buff = new byte[context.getInteger(BufferSize, DEFAULT_BUFFER_SIZE)];
int lengthToWrite = resource.getInputStream().read(buff);
while (lengthToWrite != -1) {
out.write(buff, 0, lengthToWrite);
lengthToWrite = resource.getInputStream().read(buff);
}
out.flush();
} catch (final IOException ioe) {
throw new ResourceException(ioe, resourceUri.toString());
} finally {
if (out != null) {
try {
out.close();
} catch (final IOException ioe) {
throw new ResourceException(ioe, resourceUri.toString());
}
}
}
}
/*
* (non-Javadoc)
* @see org.kaleidofoundry.core.store.AbstractFileStore#getStoreType()
*/
@Override
public FileStoreType[] getStoreType() {
return new FileStoreType[] { FileStoreTypeEnum.file };
}
/**
* @param filePath
* @param fileName
* @return Normalize the filename and path separator, depending the current OS
*/
protected String buildFilePath(final String filePath, final String fileName) {
return FileHelper.buildPath(filePath) + String.valueOf(fileName);
}
}