/*
* Copyright (c) 2010, Paul Merlin. All Rights Reserved.
*
* 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.qi4j.entitystore.jclouds;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.util.Map;
import org.jclouds.blobstore.BlobStoreContext;
import org.jclouds.blobstore.BlobStoreContextFactory;
import org.jclouds.blobstore.InputStreamMap;
import org.qi4j.api.entity.EntityReference;
import org.qi4j.api.service.Activatable;
import org.qi4j.api.unitofwork.NoSuchEntityException;
import org.qi4j.entitystore.map.MapEntityStore;
import org.qi4j.spi.entity.EntityType;
import org.qi4j.spi.entitystore.EntityNotFoundException;
import org.qi4j.spi.entitystore.EntityStoreException;
public class JCloudsMapEntityStoreMixin
implements Activatable, MapEntityStore
{
private static final String CONTAINER_NAME = "qi4j-data";
private BlobStoreContext blobStoreContext;
private InputStreamMap map;
public void activate()
throws Exception
{
blobStoreContext = new BlobStoreContextFactory().createContext( "transient", "", "" );
if ( !blobStoreContext.getBlobStore().createContainerInLocation( null, CONTAINER_NAME ) ) {
throw new EntityStoreException( "Container '" + CONTAINER_NAME + "' did not exists in BlobStore and could not be created." );
}
map = blobStoreContext.createInputStreamMap( CONTAINER_NAME );
}
public void passivate()
throws Exception
{
blobStoreContext.close();
}
public Reader get( EntityReference er )
throws EntityStoreException
{
InputStream is = null;
try {
is = map.get( er.identity() );
if ( is == null ) {
throw new NoSuchEntityException( er );
}
return new StringReader( readInputStream( is ).toString() );
} finally {
if ( is != null ) {
try {
is.close();
} catch ( IOException ignored ) {
}
}
}
}
public void visitMap( MapEntityStoreVisitor visitor )
{
for ( Map.Entry<String, InputStream> eachEntry : map.entrySet() ) {
InputStream is = eachEntry.getValue();
try {
visitor.visitEntity( new StringReader( readInputStream( is ).toString() ) );
} finally {
if ( is != null ) {
try {
is.close();
} catch ( IOException ignored ) {
}
}
}
}
}
public void applyChanges( MapChanges changes )
throws IOException
{
changes.visitMap( new MapChanger()
{
public Writer newEntity( final EntityReference ref, EntityType entityType )
throws IOException
{
return new StringWriter( 1000 )
{
@Override
public void close()
throws IOException
{
super.close();
map.putString( ref.identity(), toString() );
}
};
}
public Writer updateEntity( final EntityReference ref, EntityType entityType )
throws IOException
{
return new StringWriter( 1000 )
{
@Override
public void close()
throws IOException
{
super.close();
map.putString( ref.identity(), toString() );
}
};
}
public void removeEntity( EntityReference ref, EntityType entityType )
throws EntityNotFoundException
{
map.remove( ref.identity() );
}
} );
}
private CharSequence readInputStream( InputStream is )
{
Reader in = null;
try {
final char[] buffer = new char[ 0x10000 ]; // 64K Blocks
StringBuilder out = new StringBuilder();
in = new InputStreamReader( is, "UTF-8" );
int read;
do {
read = in.read( buffer, 0, buffer.length );
if ( read > 0 ) {
out.append( buffer, 0, read );
}
} while ( read >= 0 );
return out;
} catch ( IOException ex ) {
throw new EntityStoreException( "Unable to read data from BlobStore", ex );
} finally {
try {
if ( in != null ) {
in.close();
}
} catch ( IOException ignored ) {
}
}
}
}