org.broadleafcommerce.vendor.amazon.s3.S3FileServiceProvider Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of broadleaf-amazon Show documentation
Show all versions of broadleaf-amazon Show documentation
BroadleafCommerce Amazon Integrations
The newest version!
/*
* #%L
* BroadleafCommerce Amazon Integrations
* %%
* Copyright (C) 2009 - 2014 Broadleaf Commerce
* %%
* 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.
* #L%
*/
package org.broadleafcommerce.vendor.amazon.s3;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.broadleafcommerce.common.file.FileServiceException;
import org.broadleafcommerce.common.file.domain.FileWorkArea;
import org.broadleafcommerce.common.file.service.BroadleafFileService;
import org.broadleafcommerce.common.file.service.FileServiceProvider;
import org.broadleafcommerce.common.file.service.type.FileApplicationType;
import org.broadleafcommerce.common.site.domain.Site;
import org.broadleafcommerce.common.web.BroadleafRequestContext;
import org.springframework.stereotype.Service;
import com.amazonaws.AmazonServiceException;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.regions.RegionUtils;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.model.AmazonS3Exception;
import com.amazonaws.services.s3.model.GetObjectRequest;
import com.amazonaws.services.s3.model.PutObjectRequest;
import com.amazonaws.services.s3.model.S3Object;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import javax.annotation.Resource;
@Service("blS3FileServiceProvider")
/**
* Provides an Amazon S3 compatible implementation of the FileServiceProvider interface.
*
* Uses the blS3ConfigurationService component to provide the amazon connection details. Once a
* resource is retrieved from Amazon, the resulting input stream is written to a File on the local file system using
* blFileService to determine the local file path.
*
* @author bpolster
*
*/
public class S3FileServiceProvider implements FileServiceProvider {
@Resource(name = "blS3ConfigurationService")
protected S3ConfigurationService s3ConfigurationService;
@Resource(name = "blFileService")
protected BroadleafFileService blFileService;
protected Map configClientMap = new HashMap();
@Override
public File getResource(String name) {
return getResource(name, FileApplicationType.ALL);
}
@Override
public File getResource(String name, FileApplicationType fileApplicationType) {
File returnFile = blFileService.getLocalResource(buildResourceName(name));
OutputStream outputStream = null;
InputStream inputStream = null;
try {
S3Configuration s3config = s3ConfigurationService.lookupS3Configuration();
AmazonS3Client s3 = getAmazonS3Client(s3config);
S3Object object = s3.getObject(new GetObjectRequest(s3config.getDefaultBucketName(), buildResourceName(name)));
inputStream = object.getObjectContent();
if (!returnFile.getParentFile().exists()) {
if (!returnFile.getParentFile().mkdirs()) {
// Other thread could have created - check one more time.
if (!returnFile.getParentFile().exists()) {
throw new RuntimeException("Unable to create parent directories for file: " + name);
}
}
}
outputStream = new FileOutputStream(returnFile);
int read = 0;
byte[] bytes = new byte[1024];
while ((read = inputStream.read(bytes)) != -1) {
outputStream.write(bytes, 0, read);
}
} catch (IOException ioe) {
throw new RuntimeException("Error writing s3 file to local file system", ioe);
} catch (AmazonS3Exception s3Exception) {
if ("NoSuchKey".equals(s3Exception.getErrorCode())) {
return new File("this/path/should/not/exist/" + UUID.randomUUID());
} else {
throw s3Exception;
}
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
throw new RuntimeException("Error closing input stream while writing s3 file to file system", e);
}
}
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
throw new RuntimeException("Error closing output stream while writing s3 file to file system", e);
}
}
}
return returnFile;
}
@Override
public void addOrUpdateResources(FileWorkArea workArea, List files, boolean removeFilesFromWorkArea) {
addOrUpdateResourcesForPaths(workArea, files, removeFilesFromWorkArea);
}
/**
* Writes the resource to S3. If the bucket returns as "NoSuchBucket" then will attempt to create the bucket
* and try again.
*/
@Override
public List addOrUpdateResourcesForPaths(FileWorkArea workArea, List files, boolean removeFilesFromWorkArea) {
S3Configuration s3config = s3ConfigurationService.lookupS3Configuration();
AmazonS3Client s3 = getAmazonS3Client(s3config);
try {
return addOrUpdateResourcesInternal(s3config, s3, workArea, files, removeFilesFromWorkArea);
} catch (AmazonServiceException ase) {
if ("NoSuchBucket".equals(ase.getErrorCode())) {
s3.createBucket(s3config.getDefaultBucketName());
return addOrUpdateResourcesInternal(s3config, s3, workArea, files, removeFilesFromWorkArea);
} else {
throw new RuntimeException(ase);
}
}
}
protected List addOrUpdateResourcesInternal(S3Configuration s3config, AmazonS3Client s3, FileWorkArea workArea, List files, boolean removeFilesFromWorkArea) {
List resourcePaths = new ArrayList();
for (File srcFile : files) {
if (!srcFile.getAbsolutePath().startsWith(workArea.getFilePathLocation())) {
throw new FileServiceException("Attempt to update file " + srcFile.getAbsolutePath() +
" that is not in the passed in WorkArea " + workArea.getFilePathLocation());
}
String fileName = srcFile.getAbsolutePath().substring(workArea.getFilePathLocation().length());
String resourceName = buildResourceName(fileName);
s3.putObject(new PutObjectRequest(s3config.getDefaultBucketName(), resourceName, srcFile));
resourcePaths.add(fileName);
}
return resourcePaths;
}
@Override
public boolean removeResource(String name) {
S3Configuration s3config = s3ConfigurationService.lookupS3Configuration();
AmazonS3Client s3 = getAmazonS3Client(s3config);
s3.deleteObject(s3config.getDefaultBucketName(), buildResourceName(name));
File returnFile = blFileService.getLocalResource(buildResourceName(name));
if (returnFile != null) {
returnFile.delete();
}
return true;
}
/**
* hook for overriding name used for resource in S3
* @param name
* @return
*/
protected String buildResourceName(String name) {
// Strip the starting slash to prevent empty directories in S3 as well as required references by // in the
// public S3 URL
if (name.startsWith("/")) {
name = name.substring(1);
}
String baseDirectory = s3ConfigurationService.lookupS3Configuration().getBucketSubDirectory();
if (StringUtils.isNotEmpty(baseDirectory)) {
if (baseDirectory.startsWith("/")) {
baseDirectory = baseDirectory.substring(1);
}
} else {
// ensure subDirectory is non-null
baseDirectory = "";
}
String siteSpecificResourceName = getSiteSpecificResourceName(name);
return FilenameUtils.concat(baseDirectory, siteSpecificResourceName);
}
protected String getSiteSpecificResourceName(String resourceName) {
BroadleafRequestContext brc = BroadleafRequestContext.getBroadleafRequestContext();
if (brc != null) {
Site site = brc.getNonPersistentSite();
if (site != null) {
String siteDirectory = getSiteDirectory(site);
if (resourceName.startsWith("/")) {
resourceName = resourceName.substring(1);
}
return FilenameUtils.concat(siteDirectory, resourceName);
}
}
return resourceName;
}
protected String getSiteDirectory(Site site) {
String siteDirectory = "site-" + site.getId();
return siteDirectory;
}
protected AmazonS3Client getAmazonS3Client(S3Configuration s3config) {
AmazonS3Client client = configClientMap.get(s3config);
if (client == null) {
client = new AmazonS3Client(getAWSCredentials(s3config));
client.setRegion(RegionUtils.getRegion(s3config.getDefaultBucketRegion()));
if (s3config.getEndpointURI() != null) {
client.setEndpoint(s3config.getEndpointURI());
}
configClientMap.put(s3config, client);
}
return client;
}
protected AWSCredentials getAWSCredentials(final S3Configuration s3configParam) {
return new AWSCredentials() {
private final S3Configuration s3ConfigVar = s3configParam;
@Override
public String getAWSSecretKey() {
return s3ConfigVar.getAwsSecretKey();
}
@Override
public String getAWSAccessKeyId() {
return s3ConfigVar.getGetAWSAccessKeyId();
}
};
}
public void setBroadleafFileService(BroadleafFileService bfs) {
this.blFileService = bfs;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy