/*
* 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) 2008 - 2009 Pentaho Corporation and Contributors. All rights reserved.
*/
package org.pentaho.reporting.libraries.docbundle;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
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.RepositoryUtilities;
import org.pentaho.reporting.libraries.repository.zip.ZipRepository;
import org.pentaho.reporting.libraries.resourceloader.FactoryParameterKey;
import org.pentaho.reporting.libraries.resourceloader.ResourceBundleLoader;
import org.pentaho.reporting.libraries.resourceloader.ResourceKey;
import org.pentaho.reporting.libraries.resourceloader.ResourceKeyCreationException;
import org.pentaho.reporting.libraries.resourceloader.ResourceManager;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Map;
/**
* A document bundle implementation that holds all entries in memory.
*
* @author Thomas Morgner
*/
public class MemoryDocumentBundle implements WriteableDocumentBundle {
private static final Log logger = LogFactory.getLog( MemoryDocumentBundle.class );
private ZipRepository zipRepository;
private MemoryDocumentMetaData metaData;
private ResourceKey bundleKey;
private ResourceManager resourceManager;
public MemoryDocumentBundle() {
this( null );
}
public MemoryDocumentBundle( final ResourceKey parent ) {
this.zipRepository = new ZipRepository();
this.metaData = new MemoryDocumentMetaData();
final ResourceManager defaultResourceManager = new ResourceManager();
final BundleResourceManagerBackend backend =
new BundleResourceManagerBackend( zipRepository, defaultResourceManager.getBackend(), parent );
this.bundleKey = backend.getBundleMainKey();
this.resourceManager = new ResourceManager( defaultResourceManager, backend );
}
public ResourceKey getBundleMainKey() {
return bundleKey;
}
public ResourceManager getResourceManager() {
return resourceManager;
}
public OutputStream createEntry( final String path, final String mimetype ) throws IOException {
if ( path == null ) {
throw new NullPointerException();
}
if ( mimetype == null ) {
throw new NullPointerException( "Invalid Bundle: There is no mime-type for entry " + path );
}
final String[] name = RepositoryUtilities.splitPath( path, "/" );
try {
final ContentItem contentItem = RepositoryUtilities.createItem( zipRepository, name );
metaData.setEntryMimeType( path, mimetype );
return contentItem.getOutputStream();
} catch ( ContentIOException cioe ) {
logger.warn( "Failed to create content item " + path, cioe );
throw new IOException( "Failed to create content item " + path );
}
}
public WriteableDocumentMetaData getWriteableDocumentMetaData() {
return metaData;
}
public DocumentMetaData getMetaData() {
return metaData;
}
public void createDirectoryEntry( final String name, final String mimeType ) throws IOException {
if ( name == null ) {
throw new NullPointerException();
}
if ( mimeType == null ) {
throw new NullPointerException();
}
try {
RepositoryUtilities.createLocation( zipRepository, RepositoryUtilities.splitPath( name, "/" ) );
if ( ( name.length() > 0 && name.charAt( name.length() - 1 ) == '/' ) == false ) {
metaData.setEntryMimeType( name + '/', mimeType );
} else {
metaData.setEntryMimeType( name, mimeType );
}
} catch ( ContentIOException e ) {
throw new IOException( "Failed to create content-location " + name );
}
}
public boolean isEntryExists( final String name ) {
if ( name == null ) {
throw new NullPointerException();
}
final String[] splitName = RepositoryUtilities.split( name, "/" );
try {
return RepositoryUtilities.isExistsEntity( zipRepository, splitName );
} catch ( ContentIOException e ) {
return false;
}
}
public boolean isEntryReadable( final String name ) {
if ( name == null ) {
throw new NullPointerException();
}
try {
final String[] splitName = RepositoryUtilities.split( name, "/" );
final ContentEntity contentEntity = RepositoryUtilities.getEntity( zipRepository, splitName );
return ( contentEntity instanceof ContentItem );
} catch ( ContentIOException cioe ) {
return false;
}
}
public InputStream getEntryAsStream( final String name ) throws IOException {
if ( name == null ) {
throw new NullPointerException();
}
try {
final String[] splitName = RepositoryUtilities.split( name, "/" );
final ContentEntity contentEntity = RepositoryUtilities.getEntity( zipRepository, splitName );
if ( contentEntity instanceof ContentItem ) {
final ContentItem contentItem = (ContentItem) contentEntity;
return contentItem.getInputStream();
}
} catch ( ContentIOException cioe ) {
if ( logger.isDebugEnabled() ) {
logger.debug( "Failed to lookup entry for entry " + name, cioe );
}
throw new IOException( "Failure while looking up the stream: " + cioe );
}
throw new IOException( "No such stream: " + name );
}
public String getEntryMimeType( final String name ) {
if ( name == null ) {
throw new NullPointerException();
}
final String definedMimeType = metaData.getEntryMimeType( name );
if ( definedMimeType != null ) {
return definedMimeType;
}
try {
final String[] splitName = RepositoryUtilities.split( name, "/" );
final ContentEntity contentEntity = RepositoryUtilities.getEntity( zipRepository, splitName );
if ( contentEntity instanceof ContentItem ) {
final ContentItem contentItem = (ContentItem) contentEntity;
return contentItem.getMimeType();
}
return ""; // for directories ..
} catch ( ContentIOException cioe ) {
// ignored.
if ( logger.isDebugEnabled() ) {
logger.debug( "Failed to lookup entry mime-type for entry " + name, cioe );
}
return null;
}
}
public boolean removeEntry( final String name ) {
if ( name == null ) {
throw new NullPointerException();
}
try {
final String[] splitName = RepositoryUtilities.split( name, "/" );
final ContentEntity contentEntity = RepositoryUtilities.getEntity( zipRepository, splitName );
if ( contentEntity == null ) {
return false;
}
if ( contentEntity instanceof ContentItem ) {
if ( contentEntity.delete() ) {
metaData.removeEntry( name );
return true;
}
} else if ( contentEntity.delete() ) {
// its a directory, so removing is a bit more complicated.
final String[] entryNames = metaData.getManifestEntryNames();
for ( int i = 0; i < entryNames.length; i++ ) {
final String entryName = entryNames[ i ];
if ( entryName.startsWith( name ) ) {
metaData.removeEntry( entryName );
}
}
return true;
}
} catch ( ContentIOException cioe ) {
// ignored.
return false;
}
return false;
}
public ResourceKey createResourceKey( final String entryName,
final Map factoryParameters ) throws ResourceKeyCreationException {
if ( entryName == null ) {
throw new NullPointerException();
}
final ResourceKey bundleKey = getBundleMainKey().getParent();
final ResourceBundleLoader o = (ResourceBundleLoader)
bundleKey.getFactoryParameters().get( new FactoryParameterKey( "repository-loader" ) );
if ( o == null ) {
throw new ResourceKeyCreationException( "Unable to create a inner-bundle key, no loader available." );
}
return o.deriveKey( getBundleMainKey(), entryName, factoryParameters );
}
public ResourceKey getBundleKey() {
return getBundleMainKey();
}
public boolean isEmbeddedKey( final ResourceKey resourceKey ) {
return ( resourceKey != null && getBundleMainKey().getParent().equals( resourceKey.getParent() ) );
}
}