piecework.content.concrete.GridFSContentProviderReceiver.java Source code

Java tutorial

Introduction

Here is the source code for piecework.content.concrete.GridFSContentProviderReceiver.java

Source

/*
 * Copyright 2013 University of Washington
 *
 * Licensed under the Educational Community License, Version 1.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.opensource.org/licenses/ecl1.php
 *
 * 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 piecework.content.concrete;

import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import com.mongodb.gridfs.GridFSDBFile;
import com.mongodb.gridfs.GridFSFile;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.gridfs.GridFsCriteria;
import org.springframework.data.mongodb.gridfs.GridFsOperations;
import piecework.common.UuidGenerator;
import piecework.content.ContentProvider;
import piecework.content.ContentReceiver;
import piecework.content.ContentResource;
import piecework.content.Version;
import piecework.enumeration.AlarmSeverity;
import piecework.enumeration.Scheme;
import piecework.exception.ForbiddenError;
import piecework.exception.MisconfiguredProcessException;
import piecework.exception.NotFoundError;
import piecework.exception.PieceworkException;
import piecework.persistence.ContentProfileProvider;
import piecework.persistence.ProcessInstanceProvider;
import piecework.security.AccessTracker;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

import static org.springframework.data.mongodb.core.query.Query.query;

/**
 * @author James Renfro
 */
public class GridFSContentProviderReceiver implements ContentProvider, ContentReceiver {

    private static final Logger LOG = Logger.getLogger(GridFSContentProviderReceiver.class);

    @Autowired
    AccessTracker accessTracker;

    @Autowired
    GridFsOperations gridFsOperations;

    @Autowired
    UuidGenerator uuidGenerator;

    @Override
    public ContentResource checkout(ContentProfileProvider modelProvider, String location)
            throws PieceworkException, IOException {
        return findByLocation(modelProvider, location);
    }

    @Override
    public boolean expire(ContentProfileProvider modelProvider, String location) throws IOException {
        return false;
    }

    @Override
    public ContentResource findByLocation(ContentProfileProvider modelProvider, String location)
            throws PieceworkException {
        if (StringUtils.isEmpty(location))
            throw new MisconfiguredProcessException("Unable to find content with an empty location");

        String normalized = FilenameUtils.normalize(location);
        String basePath = basePath(modelProvider);

        if (!normalized.startsWith(basePath)) {
            accessTracker.alarm(AlarmSeverity.MINOR,
                    "Attempt to access path " + normalized + " outside of " + basePath + " forbidden",
                    modelProvider.principal());
            throw new ForbiddenError();
        }

        return gridFsContentResource(null, location);
    }

    @Override
    public boolean publish(ProcessInstanceProvider modelProvider) throws PieceworkException, IOException {
        return false;
    }

    @Override
    public boolean release(ContentProfileProvider modelProvider, String location)
            throws PieceworkException, IOException {
        return false;
    }

    @Override
    public ContentResource replace(ContentProfileProvider modelProvider, ContentResource contentResource,
            String location) throws PieceworkException, IOException {
        BasicDBObject metadata = new BasicDBObject();
        metadata.put(GridFsContentResource.NAME, contentResource.getName());
        metadata.put(GridFsContentResource.DESCRIPTION, contentResource.getDescription());
        metadata.put(GridFsContentResource.FILENAME, contentResource.getFilename());
        metadata.put(GridFsContentResource.CONTENT_LENGTH, contentResource.contentLength());
        metadata.put(GridFsContentResource.E_TAG, contentResource.eTag());
        metadata.put(GridFsContentResource.LAST_MODIFIED, contentResource.lastModified());
        metadata.put(GridFsContentResource.LAST_MODIFIED_BY, contentResource.lastModifiedBy());

        // GridFS will version automatically, and retrieve the latest version using the uploadDate timestamp
        GridFSFile file = gridFsOperations.store(contentResource.getInputStream(), location,
                contentResource.contentType(), metadata);
        return gridFsContentResource(file, location);
    }

    @Override
    public ContentResource save(ContentProfileProvider modelProvider, ContentResource contentResource)
            throws PieceworkException, IOException {
        BasicDBObject metadata = new BasicDBObject();
        metadata.put(GridFsContentResource.NAME, contentResource.getName());
        metadata.put(GridFsContentResource.DESCRIPTION, contentResource.getDescription());
        metadata.put(GridFsContentResource.FILENAME, contentResource.getFilename());
        metadata.put(GridFsContentResource.CONTENT_LENGTH, contentResource.contentLength());
        metadata.put(GridFsContentResource.E_TAG, contentResource.eTag());
        metadata.put(GridFsContentResource.LAST_MODIFIED, contentResource.lastModified());
        metadata.put(GridFsContentResource.LAST_MODIFIED_BY, contentResource.lastModifiedBy());

        String id = uuidGenerator.getNextId();
        String location = basePath(modelProvider) + id;

        GridFSFile file = gridFsOperations.store(contentResource.getInputStream(), location,
                contentResource.contentType(), metadata);
        return gridFsContentResource(file, location);
    }

    @Override
    public Scheme getScheme() {
        return Scheme.REPOSITORY;
    }

    @Override
    public String getKey() {
        return "default-gridfs";
    }

    /*
     * The base path for all storage in the GridFS repository is the process definition key
     */
    private static String basePath(ContentProfileProvider contentProfileProvider) {
        String processDefinitionKey = contentProfileProvider.processDefinitionKey();
        return new StringBuilder("/").append(processDefinitionKey).append("/").toString();
    }

    private GridFsContentResource gridFsContentResource(GridFSFile current, String location) throws NotFoundError {
        // Retrieve in ascending order, then reverse versions - this allows us to count up in an intuition way,
        // setting version numbers
        if (location == null)
            return null;

        List<GridFSDBFile> files;

        Date uploadDate = null;
        int indexOf = location.indexOf("?uploadDate=");
        if (indexOf != -1) {
            String uploadDateMillis = location.substring(indexOf + 12);
            uploadDate = new Date(Long.valueOf(uploadDateMillis));
            location = location.substring(0, indexOf);
            files = gridFsOperations.find(query(GridFsCriteria.whereFilename().is(location))
                    .addCriteria(GridFsCriteria.where("uploadDate").is(uploadDate)));
        } else {
            files = gridFsOperations.find(query(GridFsCriteria.whereFilename().is(location))
                    .with(new Sort(Sort.Direction.ASC, "uploadDate")));
        }
        List<Version> versions = new ArrayList<Version>();
        GridFSFile latest = current;
        if (files != null && !files.isEmpty()) {
            int count = 1;
            for (GridFSDBFile file : files) {
                DBObject dbObject = file.getMetaData();
                Object createDateObj = dbObject != null ? dbObject.get(GridFsContentResource.LAST_MODIFIED) : null;
                Long createDate = createDateObj != null ? Long.class.cast(createDateObj) : Long.valueOf(0);
                Object createdByObj = dbObject != null ? dbObject.get(GridFsContentResource.LAST_MODIFIED_BY)
                        : null;
                String createdBy = createdByObj != null ? createdByObj.toString() : null;

                String versionId = file != null && file.getUploadDate() != null
                        ? file.getId().toString() + "?uploadDate=" + file.getUploadDate().getTime()
                        : null;
                String versionLocation = file != null && file.getUploadDate() != null
                        ? location + "?uploadDate=" + file.getUploadDate().getTime()
                        : null;

                versions.add(
                        new Version("" + count, createdBy, createDate.longValue(), versionId, versionLocation));
                if (current == null)
                    latest = file;
                count++;
            }
        }

        if (latest == null)
            throw new NotFoundError();

        uploadDate = latest.getUploadDate();

        Collections.reverse(versions);
        return new GridFsContentResource(gridFsOperations, latest, location, uploadDate, versions);
    }

}