Package com.elasticinbox.core.blob.store

Source Code of com.elasticinbox.core.blob.store.CloudStoreProxy

/**
* Copyright (c) 2011-2012 Optimax Software Ltd.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
*  * Redistributions of source code must retain the above copyright notice,
*    this list of conditions and the following disclaimer.
*  * Redistributions in binary form must reproduce the above copyright notice,
*    this list of conditions and the following disclaimer in the documentation
*    and/or other materials provided with the distribution.
*  * Neither the name of Optimax Software, ElasticInbox, nor the names
*    of its contributors may be used to endorse or promote products derived
*    from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package com.elasticinbox.core.blob.store;

import static com.elasticinbox.core.blob.store.BlobStoreConstants.*;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.security.GeneralSecurityException;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;

import org.jclouds.blobstore.BlobStore;
import org.jclouds.blobstore.BlobStoreContext;
import org.jclouds.ContextBuilder;
import org.jclouds.blobstore.domain.BlobBuilder;
import org.jclouds.filesystem.reference.FilesystemConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.elasticinbox.common.utils.Assert;
import com.elasticinbox.config.Configurator;
import com.elasticinbox.config.blob.BlobStoreProfile;
import com.elasticinbox.core.blob.BlobUtils;
import com.elasticinbox.core.log.JcloudsSlf4JLoggingModule;
import com.google.common.collect.ImmutableSet;

/**
* This is a proxy class for jClouds Blobstore API.
* <p>
* Each blob store has its own configuration profile {@link BlobStoreProfile}
* which contains connection information. Connections to the blob stores (such
* as S3, OpenStack, etc.) are established on demand and cached.
*
* @author Rustam Aliyev
* @see {@link BlobStoreProfile}
* @see {@link BlobStore}
* @see {@link BlobStoreContext}
* @see <a href="http://www.jclouds.org/">jClouds</a>
*/
public final class CloudStoreProxy
{
  private static final Logger logger =
      LoggerFactory.getLogger(CloudStoreProxy.class);

  private static final String PROVIDER_FILESYSTEM = "filesystem";
  private static final String PROVIDER_TRANSIENT = "transient";
 
  private static ConcurrentHashMap<String, BlobStoreContext> blobStoreContexts =
      new ConcurrentHashMap<String, BlobStoreContext>();

  /**
   * Store Blob
   *
   * @param blobName
   *            Blob filename including relative path
   * @param profileName
   *            Blob store profile name
   * @param in
   *            Payload
   * @param size
   *            Payload size in bytes
   * @return
   * @throws IOException
   */
  public static void write(final String blobName, final String profileName, InputStream in, final Long size)
      throws IOException, GeneralSecurityException
  {
    Assert.notNull(in, "No data to store");
    Assert.notNull(size, "Blob size must be specified");

    final String container = Configurator.getBlobStoreProfile(profileName).getContainer();
    BlobStoreContext context = getBlobStoreContext(profileName);

    logger.debug("Storing blob {} on {}", blobName, profileName);

    BlobStore blobStore = context.getBlobStore();
    BlobBuilder blobBuilder = blobStore.blobBuilder(blobName).payload(in).contentLength(size);

    // store blob
    blobStore.putBlob(container, blobBuilder.build());
  }

  /**
   * Read Blob contents
   *
   * @param uri
   * @return
   */
  public static InputStream read(URI uri)
  {
    // check if blob was stored for the message
    Assert.notNull(uri, "URI cannot be null");

    logger.debug("Reading blob {}", uri);

    String profileName = uri.getHost();
    String container = Configurator.getBlobStoreProfile(profileName).getContainer();
    BlobStoreContext context = getBlobStoreContext(profileName);
    String path = BlobUtils.relativize(uri.getPath());

    InputStream in = context.getBlobStore()
        .getBlob(container, path)
        .getPayload().getInput();

    return in;
  }

  /**
   * Delete blob
   *
   * @param uri
   */
  public static void delete(URI uri)
  {
    // check if blob was stored for the message, skip if not
    if (uri == null) {
      return;
    }

    logger.debug("Deleting blob {}", uri);

    String profileName = uri.getHost();
    BlobStoreProfile profile = Configurator.getBlobStoreProfile(profileName);
    String path = BlobUtils.relativize(uri.getPath());
   
    if (profile.getProvider().equals(PROVIDER_FILESYSTEM))
    {
      // Following part is added as a replacement for jClouds delete due to
      // performance issues with jClouds

      String fileName = new StringBuilder(profile.getEndpoint())
          .append(File.separator).append(profile.getContainer())
          .append(File.separator).append(path).toString();
     
      File f = new File(fileName);

      // If file does not exist, skip
      if (!f.exists()) {
        return;
      }

      // Make sure the file is writable
      Assert.isTrue(f.canWrite(), "File is write protected: " + fileName);

      // Check if it is a directory
      Assert.isTrue(!f.isDirectory(), "Can't delete directory: " + fileName);

      // Attempt to delete it
      boolean success = f.delete();

      Assert.isTrue(success, "Deletion failed");
    } else {
      String container = profile.getContainer();
      BlobStoreContext context = getBlobStoreContext(profileName);
      context.getBlobStore().removeBlob(container, path);
    }
  }

  /**
   * Build {@link BlobStoreContext} from blob profile
   *
   * @param profile
   *            blob store profile name
   * @return
   */
  private static BlobStoreContext getBlobStoreContext(String profileName)
  {
    if(blobStoreContexts.containsKey(profileName)) {
      return blobStoreContexts.get(profileName);
    } else {
      synchronized (CloudStoreProxy.class)
      {
        logger.debug("Creating new connection for '{}' blob store.", profileName);
       
        Properties properties = new Properties();
        BlobStoreProfile profile = Configurator.getBlobStoreProfile(profileName);
        ContextBuilder contextBuilder = ContextBuilder.newBuilder(profile.getProvider());

        if (profile.getProvider().equals(PROVIDER_FILESYSTEM)) {
          // use endpoint as fs basedir, see: http://code.google.com/p/jclouds/issues/detail?id=776
          properties.setProperty(FilesystemConstants.PROPERTY_BASEDIR, profile.getEndpoint());
          contextBuilder.endpoint(profile.getEndpoint());
          //properties.setProperty(PROPERTY_CREDENTIAL, "dummy");
        } else if (BLOBSTORE_PROVIDERS.contains(profile.getProvider())) {
          if (profile.getEndpoint() != null) {
            contextBuilder.endpoint(profile.getEndpoint());
          }
          if (profile.getApiversion() != null) {
            contextBuilder.apiVersion(profile.getApiversion());
          }
          if (profile.getIdentity() != null && profile.getCredential() != null) {
            contextBuilder.credentials(profile.getIdentity(), profile.getCredential());
          }
        } else {
          throw new UnsupportedOperationException(
              "Unsupported Blobstore provider: " + profile.getProvider());
        }

        // get a context with filesystem that offers the portable BlobStore api
        BlobStoreContext context = contextBuilder
            .overrides(properties)
            .modules(ImmutableSet.of(new JcloudsSlf4JLoggingModule()))
            .buildView(BlobStoreContext.class);

        // create container for transient store
        if(profile.getProvider().equals(PROVIDER_TRANSIENT)) {
          context.getBlobStore().createContainerInLocation(null, profile.getContainer());
        }

        blobStoreContexts.put(profileName, context);
      }

      return blobStoreContexts.get(profileName);
    }
  }

  /**
   * Close all blob store connections
   */
  public static synchronized void closeAll()
  {
    for (String profileName : blobStoreContexts.keySet()) {
      blobStoreContexts.get(profileName).close();
      blobStoreContexts.remove(profileName);
    }
  }

}
TOP

Related Classes of com.elasticinbox.core.blob.store.CloudStoreProxy

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.