Java tutorial
/* * Copyright (c) 2014. * * BaasBox - info-at-baasbox.com * * 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.baasbox.service.storage; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map.Entry; import org.apache.commons.io.output.ByteArrayOutputStream; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.baasbox.configuration.ImagesConfiguration; import com.baasbox.controllers.CustomHttpCode; import com.baasbox.dao.FileDao; import com.baasbox.dao.PermissionsHelper; import com.baasbox.dao.RoleDao; import com.baasbox.dao.exception.DocumentNotFoundException; import com.baasbox.dao.exception.FileNotFoundException; import com.baasbox.dao.exception.InvalidModelException; import com.baasbox.dao.exception.SqlInjectionException; import com.baasbox.enumerations.Permissions; import com.baasbox.exception.AclNotValidException; import com.baasbox.exception.AclNotValidException.Type; import com.baasbox.exception.DocumentIsNotAFileException; import com.baasbox.exception.DocumentIsNotAnImageException; import com.baasbox.exception.FileTooBigException; import com.baasbox.exception.InvalidSizePatternException; import com.baasbox.exception.RoleNotFoundException; import com.baasbox.exception.UserNotFoundException; import com.baasbox.service.storage.StorageUtils.ImageDimensions; import com.baasbox.service.storage.StorageUtils.WritebleImageFormat; import com.baasbox.service.user.RoleService; import com.baasbox.service.user.UserService; import com.baasbox.util.QueryParams; import com.orientechnologies.orient.core.metadata.security.ORole; import com.orientechnologies.orient.core.metadata.security.OUser; import com.orientechnologies.orient.core.record.impl.ODocument; public class FileService { public static final String DATA_FIELD_NAME = "attachedData"; public static final String BINARY_FIELD_NAME = FileDao.BINARY_FIELD_NAME; public final static String CONTENT_TYPE_FIELD_NAME = FileDao.CONTENT_TYPE_FIELD_NAME; public final static String CONTENT_LENGTH_FIELD_NAME = FileDao.CONTENT_LENGTH_FIELD_NAME; public static ODocument createFile(String fileName, String data, String contentType, byte[] content) throws Throwable { InputStream is = new ByteArrayInputStream(content); ODocument doc; try { doc = createFile(fileName, data, contentType, content.length, is); } finally { if (is != null) is.close(); } return doc; } public static ODocument createFile(String fileName, String data, String contentType, long contentLength, InputStream is, HashMap<String, ?> metadata, String contentString) throws Throwable { FileDao dao = FileDao.getInstance(); ODocument doc = dao.create(fileName, contentType, contentLength, is, metadata, contentString); if (data != null && !data.trim().isEmpty()) { ODocument metaDoc = (new ODocument()).fromJSON("{ '" + DATA_FIELD_NAME + "' : " + data + "}"); doc.merge(metaDoc, true, false); } dao.save(doc); return doc; } public static ODocument createFile(String fileName, String dataJson, String aclJsonString, String contentType, long length, InputStream is, HashMap<String, Object> extractedMetaData, String extractedContent) throws Throwable { ODocument doc = createFile(fileName, dataJson, contentType, length, is, extractedMetaData, extractedContent); //sets the permissions ObjectMapper mapper = new ObjectMapper(); JsonNode aclJson = null; try { aclJson = mapper.readTree(aclJsonString); } catch (JsonProcessingException e) { throw e; } setAcl(doc, aclJson); return doc; }//createFile with permission private static void setAcl(ODocument doc, JsonNode aclJson) throws UserNotFoundException, RoleNotFoundException, FileNotFoundException, SqlInjectionException, InvalidModelException, AclNotValidException { Iterator<Entry<String, JsonNode>> itAction = aclJson.fields(); //read,update,delete while (itAction.hasNext()) { Entry<String, JsonNode> nextAction = itAction.next(); String action = nextAction.getKey(); Permissions actionPermission = null; if (action.equalsIgnoreCase("read")) actionPermission = Permissions.ALLOW_READ; else if (action.equalsIgnoreCase("update")) actionPermission = Permissions.ALLOW_UPDATE; else if (action.equalsIgnoreCase("delete")) actionPermission = Permissions.ALLOW_DELETE; else if (action.equalsIgnoreCase("all")) actionPermission = Permissions.FULL_ACCESS; if (actionPermission == null) throw new AclNotValidException(Type.ACL_KEY_NOT_VALID, "'" + action + "' is not a valid permission to set. Allowed ones are: read, update, delete, all"); Iterator<Entry<String, JsonNode>> itUsersRoles = nextAction.getValue().fields(); while (itUsersRoles.hasNext()) { Entry<String, JsonNode> usersOrRoles = itUsersRoles.next(); JsonNode listOfElements = usersOrRoles.getValue(); if (listOfElements.isArray()) { for (final JsonNode element : listOfElements) { if (usersOrRoles.getKey().equalsIgnoreCase("users")) grantPermissionToUser((String) doc.field("id"), actionPermission, element.asText()); else grantPermissionToRole((String) doc.field("id"), actionPermission, element.asText()); } } } } //set permissions } public static ODocument createFile(String fileName, String data, String contentType, long contentLength, InputStream content) throws Throwable { FileDao dao = FileDao.getInstance(); ODocument doc = dao.create(fileName, contentType, contentLength, content); if (data != null && !data.trim().isEmpty()) { ODocument metaDoc = (new ODocument()).fromJSON("{ '" + DATA_FIELD_NAME + "' : " + data + "}"); doc.merge(metaDoc, true, false); } dao.save(doc); return doc; } public static ODocument createFile(String fileName, String data, String contentType, HashMap<String, ?> metadata, long contentLength, InputStream content) throws Throwable { FileDao dao = FileDao.getInstance(); ODocument doc = dao.create(fileName, contentType, contentLength, content); if (data != null && !data.trim().isEmpty()) { ODocument metaDoc = (new ODocument()).fromJSON("{ '" + DATA_FIELD_NAME + "' : " + data + "}"); doc.merge(metaDoc, true, false); } dao.save(doc); return doc; } public static ODocument getById(String id) throws SqlInjectionException, InvalidModelException { FileDao dao = FileDao.getInstance(); return dao.getById(id); } public static void deleteById(String id) throws Throwable, SqlInjectionException, FileNotFoundException { FileDao dao = FileDao.getInstance(); ODocument file = getById(id); if (file == null) throw new FileNotFoundException(); dao.delete(file.getIdentity()); } public static List<ODocument> getFiles(QueryParams criteria) throws SqlInjectionException { FileDao dao = FileDao.getInstance(); return dao.get(criteria); } public static ODocument grantPermissionToRole(String id, Permissions permission, String rolename) throws RoleNotFoundException, FileNotFoundException, SqlInjectionException, InvalidModelException { ORole role = RoleDao.getRole(rolename); if (role == null) throw new RoleNotFoundException(rolename); ODocument doc = getById(id); if (doc == null) throw new FileNotFoundException(id); return PermissionsHelper.grant(doc, permission, role); } public static ODocument revokePermissionToRole(String id, Permissions permission, String rolename) throws RoleNotFoundException, FileNotFoundException, SqlInjectionException, InvalidModelException { ORole role = RoleDao.getRole(rolename); if (role == null) throw new RoleNotFoundException(rolename); ODocument doc = getById(id); if (doc == null) throw new FileNotFoundException(id); return PermissionsHelper.revoke(doc, permission, role); } public static ODocument grantPermissionToUser(String id, Permissions permission, String username) throws UserNotFoundException, RoleNotFoundException, FileNotFoundException, SqlInjectionException, IllegalArgumentException, InvalidModelException { OUser user = UserService.getOUserByUsername(username); if (user == null) throw new UserNotFoundException(username); ODocument doc = getById(id); if (doc == null) throw new FileNotFoundException(id); return PermissionsHelper.grant(doc, permission, user); } public static ODocument revokePermissionToUser(String id, Permissions permission, String username) throws UserNotFoundException, RoleNotFoundException, FileNotFoundException, SqlInjectionException, IllegalArgumentException, InvalidModelException { OUser user = UserService.getOUserByUsername(username); if (user == null) throw new UserNotFoundException(username); ODocument doc = getById(id); if (doc == null) throw new FileNotFoundException(id); return PermissionsHelper.revoke(doc, permission, user); } /** * * @param id * @param width The desired width. It can be expressed both in pixel or in percentage (100px, or 20%) * @param height The desired height. It can be expressed both in pixel or in percentage (100px, or 20%) * @return * @throws InvalidSizePatternException * @throws SqlInjectionException * @throws DocumentIsNotAnImageException * @throws DocumentIsNotAFileException * @throws DocumentNotFoundException * @throws IOException * @throws FileTooBigException */ public static byte[] getResizedPicture(String id, String width, String height) throws InvalidSizePatternException, SqlInjectionException, DocumentIsNotAnImageException, DocumentIsNotAFileException, DocumentNotFoundException, IOException, FileTooBigException { String sizePattern = width + "-" + height; return getResizedPicture(id, sizePattern); } public static byte[] getResizedPicture(String id, int sizeId) throws InvalidSizePatternException, SqlInjectionException, DocumentIsNotAnImageException, DocumentIsNotAFileException, DocumentNotFoundException, IOException, FileTooBigException { String sizePattern = ""; try { sizePattern = ImagesConfiguration.IMAGE_ALLOWED_AUTOMATIC_RESIZE_FORMATS.getValueAsString() .split(" ")[sizeId]; } catch (IndexOutOfBoundsException e) { throw new InvalidSizePatternException("The specified id is out of range."); } return getResizedPicture(id, sizePattern); } public static byte[] getResizedPicture(String id, String sizePattern) throws InvalidSizePatternException, SqlInjectionException, DocumentIsNotAnImageException, DocumentIsNotAFileException, DocumentNotFoundException, IOException, FileTooBigException { ImageDimensions dimensions = StorageUtils.convertPatternToDimensions(sizePattern); return getResizedPicture(id, dimensions); } public static byte[] getResizedPicture(String id, ImageDimensions dimensions) throws SqlInjectionException, DocumentIsNotAnImageException, DocumentNotFoundException, DocumentIsNotAFileException, IOException, FileTooBigException { //get the file ODocument file; try { file = getById(id); } catch (InvalidModelException e1) { throw new DocumentIsNotAFileException("The id " + id + " is not a file"); } if (file == null) throw new DocumentNotFoundException(); //is the file an image? if (!StorageUtils.docIsAnImage(file)) throw new DocumentIsNotAnImageException("The file " + id + " is not an image"); //are the dimensions allowed? //the check is delegated to the caller String sizePattern = dimensions.toString(); try { FileDao dao = FileDao.getInstance(); byte[] resizedImage = dao.getStoredResizedPicture(file, sizePattern); if (resizedImage != null) return resizedImage; ByteArrayOutputStream fileContent = StorageUtils.extractFileFromDoc(file); if (fileContent.toByteArray().length == 0) return new byte[] {}; String contentType = getContentType(file); String ext = contentType.substring(contentType.indexOf("/") + 1); WritebleImageFormat format; try { format = WritebleImageFormat.valueOf(ext); } catch (Exception e) { format = WritebleImageFormat.png; } resizedImage = StorageUtils.resizeImage(fileContent.toByteArray(), format, dimensions); //save the resized image for future requests dao.storeResizedPicture(file, sizePattern, resizedImage); return resizedImage; } catch (InvalidModelException e) { throw new RuntimeException("A very strange error occurred! ", e); } catch (OutOfMemoryError e) { throw new FileTooBigException(); } } public static String getContentType(ODocument file) { return (String) file.field(CONTENT_TYPE_FIELD_NAME); } public static String getExtractedContent(String id) throws SqlInjectionException, InvalidModelException, FileNotFoundException { ODocument file = getById(id); if (file == null) throw new FileNotFoundException(); FileDao dao = FileDao.getInstance(); String ret = dao.getExtractedContent(file); return ret; } }