/*
* Copyright (C) 2000-2015 aw2.0 LTD
*
* This file is part of Open BlueDragon (OpenBD) CFML Server Engine.
*
* OpenBD is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* Free Software Foundation,version 3.
*
* OpenBD 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 OpenBD. If not, see http://www.gnu.org/licenses/
*
* Additional permission under GNU GPL version 3 section 7
*
* If you modify this Program, or any covered work, by linking or combining
* it with any of the JARS listed in the README.txt (or a modified version of
* (that library), containing parts covered by the terms of that JAR, the
* licensors of this Program grant you additional permission to convey the
* resulting work.
* README.txt @ http://www.openbluedragon.org/license/README.txt
*
* http://www.openbd.org/
* $Id: cfVFSData.java 2501 2015-02-04 01:10:04Z alan $
*/
package com.naryx.tagfusion.cfm.file.vfs;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import org.apache.commons.vfs.FileObject;
import org.apache.commons.vfs.FileSystemException;
import org.apache.commons.vfs.FileSystemOptions;
import org.apache.commons.vfs.FileType;
import org.apache.commons.vfs.RandomAccessContent;
import org.apache.commons.vfs.VFS;
import org.apache.commons.vfs.auth.StaticUserAuthenticator;
import org.apache.commons.vfs.impl.DefaultFileSystemConfigBuilder;
import org.apache.commons.vfs.util.RandomAccessMode;
import com.naryx.tagfusion.cfm.engine.cfBooleanData;
import com.naryx.tagfusion.cfm.engine.cfDateData;
import com.naryx.tagfusion.cfm.engine.cfNumberData;
import com.naryx.tagfusion.cfm.engine.cfStringData;
import com.naryx.tagfusion.cfm.engine.cfStructData;
public class cfVFSData extends cfStructData implements java.io.Serializable{
static final long serialVersionUID = 1;
private String fileUrl;
private FileObject fileObject = null;
private File file = null;
transient private BufferedReader bufferedReader = null;
transient private BufferedInputStream bufferedInputStream = null;
transient private BufferedOutputStream bufferedOutputStream = null;
transient private OutputStream outputStream = null;
transient private RandomAccessContent randomAccessContent = null;
transient private RandomAccessFile randomAccessFile = null;
transient private boolean bEOF = false;
private String charset = null;
public cfVFSData( String fileUrl ) throws Exception {
super();
setFileObject( fileUrl );
}
public cfVFSData( String fileUrl, String mode, String charset ) throws Exception {
super();
/* Manage the mode */
this.charset = charset;
mode = mode.toLowerCase().trim();
if ( !mode.equals("read") && !mode.equals("readbinary") && !mode.equals("write") && !mode.equals("append") )
throw new Exception("invalid mode use read/readbinary/write/append");
else
setData( "mode", new cfStringData(mode) );
/* Get a handle to this object */
setFileObject( fileUrl );
populateInfo();
/* Check the modes */
if ( mode.equals("read") || mode.equals("readbinary") ){
if ( mode.equals("read") ){
openReader(charset);
}else{
openInputStream();
}
}else if ( mode.equals("write") || mode.equals("append") ){
if ( mode.equals("write") || (mode.equals("append") && filesize() == 0 ) ){
openOutputStream();
}else if ( mode.equals("append")){
openRandomAccessContent();
}
}
setData( "status", new cfStringData("open") );
}
public void openRandomAccessContent() throws IOException{
if ( fileObject != null ){
randomAccessContent = fileObject.getContent().getRandomAccessContent( RandomAccessMode.READWRITE );
randomAccessContent.seek( randomAccessContent.length() );
}else{
randomAccessFile = new RandomAccessFile( file, "rw" );
randomAccessFile.seek( randomAccessFile.length() );
}
}
public void openOutputStream() throws Exception {
if ( fileObject != null ){
if (!fileObject.isWriteable())
throw new Exception("resource is not writable");
outputStream = fileObject.getContent().getOutputStream();
}else{
outputStream = new FileOutputStream(file);
}
bufferedOutputStream = new BufferedOutputStream( outputStream );
}
public void openInputStream() throws Exception{
if ( fileObject != null ){
if (!fileObject.isReadable())
throw new Exception("resource is not readable");
bufferedInputStream = new BufferedInputStream( fileObject.getContent().getInputStream() );
}else{
if (!file.canRead())
throw new Exception("resource is not readable");
bufferedInputStream = new BufferedInputStream( new FileInputStream( file ) );
}
}
private void openReader( String charset ) throws Exception{
if ( fileObject != null ){
if (!fileObject.isReadable())
throw new Exception("resource is not readable");
if ( charset != null )
bufferedReader = new BufferedReader( new InputStreamReader( fileObject.getContent().getInputStream(), charset ) );
else
bufferedReader = new BufferedReader( new InputStreamReader( fileObject.getContent().getInputStream() ) );
}else{
if (!file.canRead())
throw new Exception("resource is not readable");
if ( charset != null )
bufferedReader = new BufferedReader( new InputStreamReader( new FileInputStream( file ), charset ) );
else
bufferedReader = new BufferedReader( new FileReader( file ) );
}
}
private void setFileObject( String fileUrl ) throws Exception {
// Check to see if this is a native file
boolean bFoundScheme = false;
String[] schemes = VFS.getManager().getSchemes();
for (int x=0; x < schemes.length; x++ ){
if ( fileUrl.startsWith( schemes[x] + "://") ){
bFoundScheme = true;
break;
}
}
if ( !bFoundScheme ){
file = new File( fileUrl );
return;
}
if ( fileUrl.toLowerCase().startsWith("s3://") ){
/* This is an S3 object, so we pull out the details here */
int c1 = fileUrl.indexOf("@");
if ( c1 == -1 )
throw new Exception("provider S3 authentication 's3://[accesskey]@[secretkey]/[bucket]' or 's3://@[datasource]/[bucket]'");
int c2 = fileUrl.indexOf("/", c1 + 1 );
String accessKey = fileUrl.substring( 5, c1 );
String secretKey = fileUrl.substring( c1+1, c2 );
String domain = null;
if ( accessKey.length() == 0 ){
//This is an Amazon datasource format
org.alanwilliamson.amazon.AmazonKey amazonKey = org.alanwilliamson.amazon.AmazonKeyFactory.getDS( secretKey );
if ( amazonKey == null )
throw new Exception( "The Amazon Datasource [" + secretKey + "] has not been registered; use AmazonRegisterDataSource()" );
accessKey = amazonKey.getKey();
secretKey = amazonKey.getSecret();
domain = amazonKey.getS3Host();
}else
domain = "http://s3.amazonaws.com/";
fileUrl = "s3://" + fileUrl.substring( c2 );
FileSystemOptions opts = new FileSystemOptions();
DefaultFileSystemConfigBuilder.getInstance().setUserAuthenticator(opts, new StaticUserAuthenticator(domain, accessKey, secretKey ) );
this.fileUrl = fileUrl;
fileObject = VFS.getManager().resolveFile( this.fileUrl, opts ).resolveFile(null);
}else{
this.fileUrl = fileUrl;
fileObject = VFS.getManager().resolveFile( this.fileUrl );
}
}
public boolean isNative(){
return (file != null);
}
public String getFileName(){
if ( fileObject != null ){
return fileObject.getName().getBaseName();
}else{
return file.getName();
}
}
public String getFullName(){
if ( fileObject != null ){
return fileObject.getName().getFriendlyURI();
}else{
return file.getPath();
}
}
public String getParent(){
if ( fileObject != null ){
return fileObject.getName().getParent().getFriendlyURI();
}else{
return file.getParent() + File.separator;
}
}
public void populateInfo() {
setData( "name", new cfStringData( getFileName() ) );
setData( "path", new cfStringData( getFullName() ) );
setData( "filepath", new cfStringData( getFullName() ) );
setData( "parent", new cfStringData( getParent() ) );
if ( fileObject != null ){
try{
setData( "size", new cfNumberData( fileObject.getContent().getSize() ) );
}catch(Exception e){ setData( "size", new cfNumberData( 0 ) ); }
try{
setData( "lastmodified", new cfDateData( fileObject.getContent().getLastModifiedTime() ) );
}catch(Exception e){ setData( "lastmodified", cfStringData.EMPTY_STRING ); }
try{
setData( "canread", cfBooleanData.getcfBooleanData(fileObject.isReadable()) );
}catch(Exception e){ setData( "canread", cfBooleanData.FALSE ); }
try{
setData( "canwrite", cfBooleanData.getcfBooleanData(fileObject.isWriteable()) );
}catch(Exception e){ setData( "canwrite", cfBooleanData.FALSE ); }
try{
setData( "ishidden", cfBooleanData.getcfBooleanData(fileObject.isHidden()) );
}catch(Exception e){ setData( "ishidden", cfBooleanData.FALSE ); }
try{
setData( "type", fileObject.getType() == FileType.FILE ? new cfStringData("file") : new cfStringData("directory") );
}catch(Exception e){ setData( "type", new cfStringData("unknown") ); }
}else{
setData( "size", new cfNumberData( file.length() ) );
setData( "lastmodified", new cfDateData( file.lastModified() ) );
setData( "canread", cfBooleanData.getcfBooleanData(file.canRead()) );
setData( "canwrite", cfBooleanData.getcfBooleanData(file.canWrite()) );
setData( "canexecute", cfBooleanData.getcfBooleanData(file.canExecute()) );
setData( "ishidden", cfBooleanData.getcfBooleanData(file.isHidden()) );
setData( "type", file.isDirectory() ? new cfStringData("directory") : new cfStringData("file") );
}
}
private long filesize() throws FileSystemException{
if ( fileObject != null )
return fileObject.getContent().getSize();
else
return file.length();
}
public void write( String s ) throws Exception {
if ( bufferedOutputStream != null ){
if ( charset == null )
bufferedOutputStream.write( s.getBytes() );
else
bufferedOutputStream.write( s.getBytes(charset) );
}else if ( randomAccessContent != null ){
randomAccessContent.writeBytes( s );
}else if ( randomAccessFile != null ){
randomAccessFile.writeBytes( s );
}
}
public void writeln( String s ) throws Exception {
if ( bufferedOutputStream != null ){
write( s );
write( "\r\n" );
}else if ( randomAccessContent != null ){
randomAccessContent.writeBytes( s );
randomAccessContent.writeBytes( "\r\n" );
}else if ( randomAccessFile != null ){
randomAccessFile.writeBytes( s );
randomAccessFile.writeBytes( "\r\n" );
}
}
public void write( byte[] b ) throws Exception {
if ( bufferedOutputStream != null ){
bufferedOutputStream.write(b);
}else if ( randomAccessContent != null ){
randomAccessContent.write(b);
}else if ( randomAccessFile != null ){
randomAccessFile.write(b);
}
}
public void flushWrite() throws Exception {
if ( bufferedOutputStream != null ){
bufferedOutputStream.flush();
}
}
public boolean isReadable(){
return (bufferedReader != null) || (bufferedInputStream != null);
}
public boolean isBinaryMode(){
return (bufferedInputStream != null);
}
public boolean isWriteable(){
return (bufferedOutputStream != null) || (randomAccessContent != null) || (randomAccessFile != null);
}
public BufferedInputStream getStreamReader(){
return bufferedInputStream;
}
public BufferedOutputStream getStreamWriter(){
return bufferedOutputStream;
}
public BufferedReader getReader(){
return bufferedReader;
}
public void close() throws Exception {
if ( bufferedInputStream != null ){
bufferedInputStream.close();
if ( fileObject != null )
fileObject.getContent().close();
bufferedInputStream = null;
}
if ( bufferedReader != null ){
bufferedReader.close();
if ( fileObject != null )
fileObject.getContent().close();
bufferedReader = null;
}
if ( bufferedOutputStream != null ){
bufferedOutputStream.flush();
outputStream.flush();
bufferedOutputStream.close();
outputStream.close();
if ( fileObject != null )
fileObject.getContent().close();
outputStream = null;
bufferedOutputStream = null;
}
if ( randomAccessContent != null ){
randomAccessContent.close();
randomAccessContent = null;
}
if ( randomAccessFile != null ){
randomAccessFile.close();
randomAccessFile = null;
}
if ( fileObject != null )
fileObject.close();
setData( "status", new cfStringData("closed") );
}
public boolean exists() throws Exception {
if ( fileObject != null )
return fileObject.exists();
else
return file.exists();
}
public FileObject getFileObject(){
return fileObject;
}
public File getFile(){
return file;
}
public void setEOF(){
bEOF = true;
}
public boolean isEOF() {
return bEOF;
}
public boolean isDirectory() throws FileSystemException {
if ( fileObject != null )
return (fileObject.getType() == FileType.FOLDER);
else
return file.isDirectory();
}
public void delete() throws FileSystemException {
if ( fileObject != null )
fileObject.delete();
else
file.delete();
}
}