com.baasbox.service.storage.FileService.java Source code

Java tutorial

Introduction

Here is the source code for com.baasbox.service.storage.FileService.java

Source

/*
 * 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;
    }

}