/***************************************************************************************** Infosistema - OpenBaas Copyright(C) 2002-2014 Infosistema, S.A. 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. 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 along with this program. If not, see <http://www.gnu.org/licenses/>. www.infosistema.com info@openbaas.com Av. José Gomes Ferreira, 11 3rd floor, s.34 Miraflores 1495-139 Algés Portugal ****************************************************************************************/ package infosistema.openbaas.dataaccess.files; import infosistema.openbaas.data.enums.ModelEnum; import infosistema.openbaas.utils.Const; import infosistema.openbaas.utils.Log; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.List; import org.apache.commons.io.IOUtils; import com.amazonaws.AmazonClientException; import com.amazonaws.AmazonServiceException; import com.amazonaws.auth.ClasspathPropertiesFileCredentialsProvider; import com.amazonaws.regions.Region; import com.amazonaws.regions.Regions; import com.amazonaws.services.identitymanagement.AmazonIdentityManagementClient; import com.amazonaws.services.identitymanagement.model.AddUserToGroupRequest; import com.amazonaws.services.identitymanagement.model.CreateAccessKeyRequest; import com.amazonaws.services.identitymanagement.model.CreateUserRequest; import com.amazonaws.services.identitymanagement.model.DeleteUserRequest; import com.amazonaws.services.identitymanagement.model.EntityAlreadyExistsException; import com.amazonaws.services.identitymanagement.model.NoSuchEntityException; import com.amazonaws.services.s3.AmazonS3; import com.amazonaws.services.s3.AmazonS3Client; import com.amazonaws.services.s3.model.GetObjectRequest; import com.amazonaws.services.s3.model.ObjectMetadata; import com.amazonaws.services.s3.model.PutObjectRequest; import com.amazonaws.services.s3.model.S3Object; import com.amazonaws.services.s3.model.S3ObjectInputStream; public class AwsModel implements FileInterface { private static final String PATH_FORMAT = "apps/%s/media/%s/%s.%s"; private static AwsModel instance; private AmazonS3 s3; private AmazonIdentityManagementClient client; public static AwsModel getInstance() { if (instance == null) { instance = new AwsModel(); instance.startAWS(); instance.startIAM(); } return instance; } private AwsModel() { } // *** PRIVATE *** // /** * Starts the S3 Amazon connection. */ private void startAWS() { s3 = new AmazonS3Client(new ClasspathPropertiesFileCredentialsProvider()); Region euWest = Region.getRegion(Regions.EU_WEST_1); s3.setRegion(euWest); } /** * Starts the Amazon Identity Management Client */ private void startIAM() { client = new AmazonIdentityManagementClient(new ClasspathPropertiesFileCredentialsProvider()); } //*** PRIVATE *** // private String getFilePath(String appId, ModelEnum type, String id, String extension) { return String.format(PATH_FORMAT, appId, type.toString(), id, extension); } // *** CREATE *** // /** * Other possibility is to deploy individual buckets per app, not viable * because you can't create buckets that already exists in the AWS. Try to * create a twitter bucket and you get an error, this would severelly limit * our application system, we do not want to be name limited by amazon. * * It is harder to handle user permissions this way but it is possible to * restrict users to their app folders. * * @param appId * @return */ @Override public boolean createApp(String appId) throws EntityAlreadyExistsException, AmazonServiceException { this.startAWS(); this.startIAM(); boolean sucess = false; // ------------Creating the AppMaster User + Adding it to the AppMasters group (limited permissions) CreateUserRequest user = new CreateUserRequest(appId); CreateAccessKeyRequest key = new CreateAccessKeyRequest(); key.withUserName(user.getUserName()); user.setRequestCredentials(key.getRequestCredentials()); user.setPath("/"); client.createUser(user); AddUserToGroupRequest addUserToGroupRequest = new AddUserToGroupRequest() .withGroupName(Const.getAwsAppMastersGroup()).withUserName(appId); client.addUserToGroup(addUserToGroupRequest); // ------------------------------------------------ // ------------Creating the Default Folders-------- InputStream input = new ByteArrayInputStream(new byte[0]); ObjectMetadata metadata = new ObjectMetadata(); metadata.setContentLength(0); s3.putObject(Const.getAwsOpenBaasBucket(), "apps/" + appId + "/", input, metadata); s3.putObject(Const.getAwsOpenBaasBucket(), "apps/" + appId + "/media/storage/", input, metadata); s3.putObject(Const.getAwsOpenBaasBucket(), "apps/" + appId + "/media/audio/", input, metadata); s3.putObject(Const.getAwsOpenBaasBucket(), "apps/" + appId + "/media/images/", input, metadata); s3.putObject(Const.getAwsOpenBaasBucket(), "apps/" + appId + "/media/video/", input, metadata); sucess = true; return sucess; } // *** UPLOAD *** // @Override public String upload(String appId, ModelEnum type, String id, String extension, InputStream stream) throws AmazonServiceException, AmazonClientException { this.startAWS(); String filePath = getFilePath(appId, type, id, extension); s3.putObject(new PutObjectRequest(Const.getAwsOpenBaasBucket(), filePath, stream, new ObjectMetadata())); return filePath; } // *** DOWNLOAD *** // /** * Allowed types images, audio, video * * Allowed structures, media, storage * * @param appId * @param requestType * @param id * @return * @throws IOException */ @Override public byte[] download(String appId, ModelEnum type, String id, String extension, String quality, String bars) throws IOException { OutputStream soutputStream=null; byte[] byteArray = null; try{ this.startAWS(); StringBuffer directory = new StringBuffer("apps/" + appId + "/media/" + type.toString() + "/" + id); if(extension!=null) directory.append("."+extension); S3Object object = s3.getObject(new GetObjectRequest(Const.getAwsOpenBaasBucket(), directory.toString())); S3ObjectInputStream s3ObjInputStream = object.getObjectContent(); byteArray = IOUtils.toByteArray(s3ObjInputStream); soutputStream = new FileOutputStream(new File(directory.toString())); int read = 0; byte[] bytes = new byte[1024]; S3Object object2 = s3.getObject(new GetObjectRequest(Const.getAwsOpenBaasBucket(), directory.toString())); while ((read = object2.getObjectContent().read(bytes)) != -1) { soutputStream.write(bytes, 0, read); } } catch(Exception e) { Log.error("", this, "download", "An error ocorred.", e); }finally{ soutputStream.close(); } return byteArray; } // *** DETETE *** // @Override public boolean deleteFile(String appId, ModelEnum type, String id, String extension) { this.startAWS(); s3.deleteObject(Const.getAwsOpenBaasBucket(), getFilePath(appId, type, id, extension)); return true; } @Override public Boolean delFilesResolution(String appId, ModelEnum type, List<String> filesRes) { // TODO return null; } }