/*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software
* Foundation.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.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 Lesser General Public License for more details.
*
* Copyright (c) 2006 - 2013 Pentaho Corporation and Contributors. All rights reserved.
*/
package org.pentaho.reporting.libraries.repository.file;
import org.pentaho.reporting.libraries.base.util.IOUtils;
import org.pentaho.reporting.libraries.repository.ContentCreationException;
import org.pentaho.reporting.libraries.repository.ContentEntity;
import org.pentaho.reporting.libraries.repository.ContentIOException;
import org.pentaho.reporting.libraries.repository.ContentItem;
import org.pentaho.reporting.libraries.repository.ContentLocation;
import org.pentaho.reporting.libraries.repository.Repository;
import org.pentaho.reporting.libraries.repository.RepositoryUtilities;
import java.io.File;
import java.io.IOException;
/**
* A content-location that uses a directory as backend.
*
* @author Thomas Morgner
*/
public class FileContentLocation extends FileContentEntity implements ContentLocation {
private static final long serialVersionUID = -5452372293937107734L;
/**
* Creates a new location for the given parent and directory.
*
* @param parent the parent location.
* @param backend the backend.
* @throws ContentIOException if an error occured or the file did not point to a directory.
*/
public FileContentLocation( final ContentLocation parent, final File backend ) throws ContentIOException {
super( parent, backend );
if ( backend.exists() == false || backend.isDirectory() == false ) {
throw new ContentIOException( "The given backend-file is not a directory." );
}
}
/**
* Creates a new root-location for the given repository and directory.
*
* @param repository the repository for which a location should be created.
* @param backend the backend.
* @throws ContentIOException if an error occured or the file did not point to a directory.
*/
public FileContentLocation( final Repository repository, final File backend ) throws ContentIOException {
super( repository, backend );
if ( backend.exists() == false || backend.isDirectory() == false ) {
throw new ContentIOException( "The given backend-file is not a directory." );
}
}
/**
* Lists all content entities stored in this content-location. This method filters out all files that have an invalid
* name (according to the repository rules).
*
* @return the content entities for this location.
* @throws ContentIOException if an repository error occured.
*/
public ContentEntity[] listContents() throws ContentIOException {
final File file = getBackend();
final File[] files = file.listFiles();
final ContentEntity[] entities = new ContentEntity[ files.length ];
for ( int i = 0; i < files.length; i++ ) {
final File child = files[ i ];
if ( RepositoryUtilities.isInvalidPathName( child.getName() ) ) {
continue;
}
if ( child.isDirectory() ) {
entities[ i ] = new FileContentLocation( this, child );
} else if ( child.isFile() ) {
entities[ i ] = new FileContentLocation( this, child );
}
}
return entities;
}
/**
* Returns the content entity with the given name. If the entity does not exist, an Exception will be raised.
*
* @param name the name of the entity to be retrieved.
* @return the content entity for this name, never null.
* @throws ContentIOException if an repository error occured.
*/
public ContentEntity getEntry( final String name ) throws ContentIOException {
if ( RepositoryUtilities.isInvalidPathName( name ) ) {
throw new IllegalArgumentException( "The name given is not valid." );
}
final File file = getBackend();
final File child = new File( file, name );
if ( child.exists() == false ) {
throw new ContentIOException( "Not found:" + child );
}
try {
if ( IOUtils.getInstance().isSubDirectory( file, child ) == false ) {
throw new ContentIOException( "The given entry does not point to a sub-directory of this content-location" );
}
} catch ( IOException e ) {
throw new ContentIOException( "IO Error.", e );
}
if ( child.isDirectory() ) {
return new FileContentLocation( this, child );
} else if ( child.isFile() ) {
return new FileContentItem( this, child );
} else {
throw new ContentIOException( "Not File nor directory." );
}
}
/**
* Creates a new data item in the current location. This method must never return null. This method will fail if an
* entity with the same name exists in this location.
*
* @param name the name of the new entity.
* @return the newly created entity, never null.
* @throws ContentCreationException if the item could not be created.
*/
public ContentItem createItem( final String name ) throws ContentCreationException {
if ( RepositoryUtilities.isInvalidPathName( name ) ) {
throw new IllegalArgumentException( "The name given is not valid." );
}
final File file = getBackend();
final File child = new File( file, name );
if ( child.exists() ) {
if ( child.length() == 0 ) {
// probably one of the temp files created by the pentaho-system
return new FileContentItem( this, child );
}
throw new ContentCreationException( "File already exists: " + child );
}
try {
if ( child.createNewFile() == false ) {
throw new ContentCreationException( "Unable to create the file." );
}
return new FileContentItem( this, child );
} catch ( IOException e ) {
throw new ContentCreationException( "IOError while create", e );
}
}
/**
* Creates a new content location in the current location. This method must never return null. This method will fail
* if an entity with the same name exists in this location.
*
* @param name the name of the new entity.
* @return the newly created entity, never null.
* @throws ContentCreationException if the item could not be created.
*/
public ContentLocation createLocation( final String name )
throws ContentCreationException {
if ( RepositoryUtilities.isInvalidPathName( name ) ) {
throw new IllegalArgumentException( "The name given is not valid." );
}
final File file = getBackend();
final File child = new File( file, name );
if ( child.exists() ) {
throw new ContentCreationException( "File already exists." );
}
if ( child.mkdir() == false ) {
throw new ContentCreationException( "Unable to create the directory" );
}
try {
return new FileContentLocation( this, child );
} catch ( ContentIOException e ) {
throw new ContentCreationException( "Failed to create the content-location", e );
}
}
/**
* Checks, whether an content entity with the given name exists in this content location. This method will report
* invalid filenames as non-existent.
*
* @param name the name of the new entity.
* @return true, if an entity exists with this name, false otherwise.
*/
public boolean exists( final String name ) {
if ( RepositoryUtilities.isInvalidPathName( name ) ) {
return false;
}
final File file = getBackend();
final File child = new File( file, name );
return ( child.exists() );
}
}