/* * LinShare is an open source filesharing software, part of the LinPKI software * suite, developed by Linagora. * * Copyright (C) 2016 LINAGORA * * This program is free software: you can redistribute it and/or modify it under * the terms of the GNU Affero General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version, provided you comply with the Additional Terms applicable for * LinShare software by Linagora pursuant to Section 7 of the GNU Affero General * Public License, subsections (b), (c), and (e), pursuant to which you must * notably (i) retain the display of the “LinShare™” trademark/logo at the top * of the interface window, the display of the “You are using the Open Source * and free version of LinShare™, powered by Linagora © 2009–2015. Contribute to * Linshare R&D by subscribing to an Enterprise offer!” infobox and in the * e-mails sent with the Program, (ii) retain all hypertext links between * LinShare and linshare.org, between linagora.com and Linagora, and (iii) * refrain from infringing Linagora intellectual property rights over its * trademarks and commercial brands. Other Additional Terms apply, see * <http://www.linagora.com/licenses/> for more details. * * 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 Affero General Public License for more * details. * * You should have received a copy of the GNU Affero General Public License and * its applicable Additional Terms for LinShare along with this program. If not, * see <http://www.gnu.org/licenses/> for the GNU Affero General Public License * version 3 and <http://www.linagora.com/licenses/> for the Additional Terms * applicable to LinShare software. */ package org.linagora.linshare.core.dao.impl; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.Date; import java.util.Properties; import java.util.UUID; import org.jclouds.ContextBuilder; import org.jclouds.blobstore.BlobStore; import org.jclouds.blobstore.BlobStoreContext; import org.jclouds.blobstore.domain.Blob; import org.jclouds.io.Payload; import org.jclouds.io.Payloads; import org.linagora.linshare.core.dao.FileDataStore; import org.linagora.linshare.core.domain.objects.FileMetaData; import org.linagora.linshare.core.exception.TechnicalErrorCode; import org.linagora.linshare.core.exception.TechnicalException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class JcloudObjectStorageFileDataStoreImpl implements FileDataStore { protected static final Logger logger = LoggerFactory.getLogger(JcloudObjectStorageFileDataStoreImpl.class); protected static String SWIFT_KEYSTONE = "swift-keystone"; protected static String FILESYSTEM = "filesystem"; protected String provider; protected BlobStoreContext context; protected String baseDirectory; protected String identity; protected String credential; protected String endpoint; protected String bucketIdentifier; public JcloudObjectStorageFileDataStoreImpl(String provider) { super(); this.provider = provider; this.context = null; this.baseDirectory = null; this.identity = null; this.credential = null; this.endpoint = null; this.bucketIdentifier = null; } public void afterPropertiesSet() throws Exception { Properties properties = new Properties(); ContextBuilder contextBuilder = null; if (provider.equals(SWIFT_KEYSTONE)) { properties.setProperty(org.jclouds.Constants.PROPERTY_TRUST_ALL_CERTS, "true"); properties.setProperty(org.jclouds.Constants.PROPERTY_LOGGER_WIRE_LOG_SENSITIVE_INFO, "true"); contextBuilder = ContextBuilder.newBuilder(SWIFT_KEYSTONE); contextBuilder.endpoint(endpoint).credentials(identity, credential); } else if (provider.equals(FILESYSTEM)) { properties.setProperty(org.jclouds.filesystem.reference.FilesystemConstants.PROPERTY_BASEDIR, baseDirectory); contextBuilder = ContextBuilder.newBuilder(FILESYSTEM); } else { throw new IllegalArgumentException(" only " + SWIFT_KEYSTONE + " or " + FILESYSTEM); } context = contextBuilder.overrides(properties).buildView(BlobStoreContext.class); BlobStore blobStore = context.getBlobStore(); if (!blobStore.containerExists(bucketIdentifier)) { blobStore.createContainerInLocation(null, bucketIdentifier); } } public void destroy() { if (context != null) context.close(); } public BlobStore getBlobStore(String containerName) { BlobStore blobStore = context.getBlobStore(); if (!blobStore.containerExists(containerName)) { logger.warn("bucket does not exists : " + containerName); blobStore.createContainerInLocation(null, bucketIdentifier); } return blobStore; } /** * Ugly statistics and debug function :) */ public static void stats(Date start, String title) { if (logger.isDebugEnabled()) { logger.debug("diff : " + title + " : " + String.valueOf(new Date().getTime() - start.getTime())); } } @Override public void remove(FileMetaData metadata) { String containerName = metadata.getBucketUuid(); BlobStore blobStore = getBlobStore(containerName); Date start = new Date(); try { blobStore.removeBlob(containerName, metadata.getUuid()); } catch (org.jclouds.blobstore.ContainerNotFoundException e) { logger.error(e.getMessage(), e); } stats(start, "blobRetrieved"); } @Override public FileMetaData add(File file, FileMetaData metadata) { try (FileInputStream fis = new FileInputStream(file)) { return metadata = add(fis, metadata); } catch (IOException e) { logger.error(e.getMessage(), e); throw new TechnicalException(TechnicalErrorCode.GENERIC, "Can not add a new file : " + e.getMessage()); } } @Override public FileMetaData add(InputStream file, FileMetaData metadata) { BlobStore blobStore = getBlobStore(bucketIdentifier); Date start = null; // Create a Blob start = new Date(); Payload payload = Payloads.newInputStreamPayload(file); stats(start, "Payload"); start = new Date(); Blob blob; metadata.setUuid(UUID.randomUUID().toString()); metadata.setBucketUuid(bucketIdentifier); blob = blobStore.blobBuilder(metadata.getUuid()).payload(payload) // .contentLength(file.size()) .build(); stats(start, "blob"); // Upload the Blob start = new Date(); String eTag = blobStore.putBlob(bucketIdentifier, blob); logger.debug("etag : {}", eTag); stats(start, "putBlob"); return metadata; } @Override public InputStream get(FileMetaData metadata) { String containerName = metadata.getBucketUuid(); BlobStore blobStore = getBlobStore(containerName); Date start = new Date(); Blob blobRetrieved = blobStore.getBlob(containerName, metadata.getUuid()); stats(start, "blobRetrieved"); try { return blobRetrieved.getPayload().openStream(); } catch (IOException e) { logger.error(e.getMessage(), e); throw new TechnicalException(TechnicalErrorCode.GENERIC, "Can not add a new file : " + e.getMessage()); } } @Override public boolean exists(FileMetaData metadata) { String containerName = metadata.getBucketUuid(); if (containerName == null) { // document stored in jackrabbit does not have bucket_uuid. :) return false; } BlobStore blobStore = getBlobStore(containerName); return blobStore.blobExists(containerName, metadata.getUuid()); } public String getBaseDirectory() { return baseDirectory; } public void setBaseDirectory(String baseDirectory) { this.baseDirectory = baseDirectory; } public String getIdentity() { return identity; } public void setIdentity(String identity) { this.identity = identity; } public String getCredential() { return credential; } public void setCredential(String credential) { this.credential = credential; } public String getEndpoint() { return endpoint; } public void setEndpoint(String endpoint) { this.endpoint = endpoint; } public String getBucketIdentifier() { return bucketIdentifier; } public void setBucketIdentifier(String bucketIdentifier) { this.bucketIdentifier = bucketIdentifier; } }