/** * Copyright (C) 2015 Orange * 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 com.francetelecom.clara.cloud.logicalmodel; import com.francetelecom.clara.cloud.commons.GuiClassMapping; import com.francetelecom.clara.cloud.commons.GuiMapping; import org.springframework.util.Assert; import javax.persistence.Entity; import javax.persistence.Table; import javax.validation.constraints.Min; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; import javax.xml.bind.annotation.XmlRootElement; /** * Online object storage service. * <p> * Provides a Java API to store objects (binary files or multimedia content). * that are also accessible through HTTP (for both upload and download * accesses). * <p> * This is similar in concept to Amazon S3 service and is offered as a * JClouds-compatible currently maps to the France Telecom Store storage * enabler. * <p> * To use the JCloud Blob store API within your application deployed in the * paas: * <ol> * <li> * Embed the JClouds blob store provider into your application artefact, this * will in turn pull the jClouds blob store API as a transient dependency. * <p> * <pre> * {@code * <dependency> * <groupId>com.orange.clara.cloud</groupId> * <artifactId>storage-client-jclouds-impl</artifactId> * <version>1.0.1</version> * </dependency> * } * </pre> * <p> * This is available from the Paas maven repository: * <p> * {@code * <repository> * <id>paas.public</id> * <name>Paas Public Group</name> * <url>http://ORANGE_MAVEN_REPO/proxy/content/groups/public/</url> * </repository> * } * * </li> * <li> * Then use the Clouds Blob Store API, by looking up the credentials looked up * in JNDI. See * <a href="http://www.jclouds.org/documentation/userguide/blobstore-guide/"> * blobstore-guide</a> Sample programming model: * * <pre> * { * @code * // Load config parameters from JNDI and place them into a set of well-known * // keys for use by the Store provider * InitialContext initialContext = new InitialContext(); * * String jndiPrefix = ""; // Replace with any prefix that were provisionned in * // app architecture * * String IDENTITY_KEY = "identity"; * String CREDENTIAL_KEY = "credential"; * String ENDPOINT_KEY = "endpoint"; * String CONTAINER_KEY = "container"; * * String identityValue = (String) initialContext.lookup(jndiPrefix + "/" + IDENTITY_KEY); * String credentialValue = (String) initialContext.lookup(jndiPrefix + "/" + CREDENTIAL_KEY); * String endpointValue = (String) initialContext.lookup(jndiPrefix + "/" + ENDPOINT_KEY); * String containerValue = (String) initialContext.lookup(jndiPrefix + "/" + CONTAINER_KEY); * * Properties storeProviderInitProperties = new Properties(); * storeProviderInitProperties.put(IDENTITY_KEY, identityValue); * storeProviderInitProperties.put(CREDENTIAL_KEY, credentialValue); * storeProviderInitProperties.put(ENDPOINT_KEY, endpointValue); * * // Instanciate the context based on the looked up properties * BlobStoreContext context = new BlobStoreContextFactory().createContext("store", storeProviderInitProperties); * BlobStore blobStore = context.getBlobStore(); * * // All blobs should be located in a the single per-environment default * // container whose name is provided in JNDI * String containerNameToUse = (String) initialContext.lookup(CONTAINER_KEY); * boolean newContainerCreated = blobStore.createContainerInLocation(null, containerNameToUse); * * // Write a new Blob * Blob blob = blobStore.blobBuilder("anyBlobName").build(); * blob.setPayload("An example string content for a blob payload. Streams or byte[] can be used instead"); * String blobETag = blobStore.putBlob(containerNameToUse, blob); * * // Read a blob content * Blob readBlobContent = blobStore.getBlob(containerNameToUse, "anyBlobName"); * Payload readBlobContentPayload = readBlobContent.getPayload(); * * // The blob is also accessible by HTTP using a private or public URI * URI uri = readBlobContent.getMetadata().getUri(); * URI publicUri = readBlobContent.getMetadata().getPublicUri(); * * // remove blob * blobStore.removeBlob(containerNameToUse, blobName); * * } * </pre> * <p> * For further examples and tests see the sample application, whose sources code * is available as maven artefact: * <p> * <pre> * {@code * <groupId>com.orange.clara.cloud</groupId> * <artifactId>echo-ws-consumer-war</artifactId> * * } * </pre> * <p> * </li> * </ol> * <p> * See also https://github.com/jclouds/jclouds/blob/master/README.txt * <p> * TODO: add link to Java API javadoc TODO: add reference to sample client */ @XmlRootElement @Entity @Table(name = "STORAGE_SERVICE") @GuiClassMapping(serviceCatalogName = "Blob store", serviceCatalogNameKey = "blob.store", status = GuiClassMapping.StatusType.BETA, isExternal = false) public class LogicalOnlineStorageService extends LogicalService { /** * Reserved storage capacity in MB. */ @Min(value = 1, message = "capacity needs to be positive integer value") @GuiMapping(status = GuiMapping.StatusType.SUPPORTED, functional = false) private int storageCapacityMb = 10; /** * Prefered prefix JNDI keys to be looked up by the application. This allows the application * to distinguish among multiple LogicalOnlineStorageService subscriptions. The prefix should not be left empty. * If the prefix is "petpictures" then * the available keys will be "petpictures/identity". * The injected properties are <ol> * <li>"endpoint"</li> * <li>"identity"</li> * <li>"credential"</li> * <li>"provider"</li> * </ol> */ @NotNull @Size(min = 0) @GuiMapping(status = GuiMapping.StatusType.SUPPORTED) private String serviceName = "storage"; public LogicalOnlineStorageService() { } /** * @deprecated Should not be called anymore, use empty constructor instead * followed by {@link LogicalDeployment#addLogicalService(LogicalService)} */ public LogicalOnlineStorageService(String label, LogicalDeployment logicalDeployment) { super(label, logicalDeployment); } public int getStorageCapacityMb() { return storageCapacityMb; } public void setStorageCapacityMb(int storageCapacityMb) { Assert.isTrue(storageCapacityMb > 1, "Unable to set storage capacity with value <" + storageCapacityMb + ">. Storage capacity should be greater that 1."); this.storageCapacityMb = storageCapacityMb; } public String getServiceName() { return serviceName; } public void setServiceName(String serviceName) { Assert.hasText(serviceName, "Unable to set service name with value <" + serviceName + ">. Service name should not be with empty value."); this.serviceName = serviceName; } }