Package org.fcrepo.server.storage.types

Source Code of org.fcrepo.server.storage.types.DatastreamManagedContent

/* The contents of this file are subject to the license and copyright terms
* detailed in the license directory at the root of the source tree (also
* available online at http://fedora-commons.org/license/).
*/
package org.fcrepo.server.storage.types;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.fcrepo.common.Constants;

import org.fcrepo.server.Context;
import org.fcrepo.server.ReadOnlyContext;
import org.fcrepo.server.Server;
import org.fcrepo.server.errors.InitializationException;
import org.fcrepo.server.errors.StreamIOException;
import org.fcrepo.server.errors.ValidationException;
import org.fcrepo.server.storage.ContentManagerParams;
import org.fcrepo.server.storage.ExternalContentManager;
import org.fcrepo.server.storage.lowlevel.ILowlevelStorage;
import org.fcrepo.server.utilities.StreamUtility;
import org.fcrepo.server.validation.ValidationUtility;
import org.fcrepo.server.validation.ecm.jaxb.DsTypeModel;



/**
* @author Chris Wilper
* @version $Id$
*/
public class DatastreamManagedContent
        extends Datastream {

    private static final Logger logger =
        LoggerFactory.getLogger(DatastreamManagedContent.class);


    /**
     * Internal scheme to indicating that a copy should made of the resource.
     */
    public static final String COPY_SCHEME = "copy://";

    public static final String TEMP_SCHEME = "temp://";

    public static final String UPLOADED_SCHEME = "uploaded://";

    private static ILowlevelStorage s_llstore;

    private static Server m_server;

    private static ExternalContentManager s_ecm;

    private static File m_tempUploadDir;

    public int DSMDClass = 0;

    public DatastreamManagedContent() {
    }

    @Override
    public Datastream copy() {
        DatastreamManagedContent ds = new DatastreamManagedContent();
        copy(ds);
        return ds;
    }

    private ILowlevelStorage getLLStore() throws Exception {
        if (s_llstore == null) {
            try {
                s_llstore =
                        (ILowlevelStorage) getServer()
                                .getModule("org.fcrepo.server.storage.lowlevel.ILowlevelStorage");
            } catch (InitializationException ie) {
                throw new Exception("Unable to get LLStore Module: "
                        + ie.getMessage(), ie);
            }
        }
        return s_llstore;
    }
    /**
     * Get the location for storing temporary uploaded files (not for general temporary files)
     * @return the directory
     * @throws Exception
     */
    private File getTempUploadDir() throws Exception {
        if (m_tempUploadDir == null) {
            try {
                m_tempUploadDir = getServer().getUploadDir();
            } catch (InitializationException e) {
                throw new Exception("Unable to get server: " + e.getMessage(), e);
            }
        }
        return m_tempUploadDir;
    }

    private Server getServer() throws Exception {
        if (m_server == null) {
            try {
                m_server = Server.getInstance(new File(Constants.FEDORA_HOME),
                                              false);
            } catch (InitializationException e) {
                throw new Exception("Unable to get Server: " + e.getMessage(), e);
            }
        }
        return m_server;
    }

    private ExternalContentManager getExternalContentManager() throws Exception {
        if (s_ecm == null) {
            try {
                s_ecm = (ExternalContentManager) getServer()
                        .getModule("org.fcrepo.server.storage.ExternalContentManager");
            } catch (InitializationException e) {
                throw new Exception("Unable to get ExternalContentManager Module: "
                                    + e.getMessage(), e);
            }
        }
        return s_ecm;
    }

    // Note: might seem strange to pass through the Context, but DatastreamManagedContent looks after
    // datastreams before they have been ingested, ie while location is still external (file, URL), so without
    // Context authz will fail
    public InputStream getContentStream(Context ctx) throws StreamIOException {
        try {
            // For new or modified datastreams, the new bytestream hasn't yet been
            // committed. However, we need to access it in order to compute
            // the datastream checksum
            if (DSLocation.startsWith(UPLOADED_SCHEME)) {
                // TODO: refactor to use proper temp file management - FCREPO-718
                // for now, just get the file directly (see also DefaultManagement.getTempStream(...))
                String internalId = DSLocation.substring(UPLOADED_SCHEME.length());
                File uploadedFile = new File(getTempUploadDir(), internalId);
                // check it has not been automatically purged (see DefaultManagement.purgeUploadedFiles())
                if (uploadedFile.exists()) {
                    return new FileInputStream(uploadedFile);
                } else {
                    throw new StreamIOException("Uploaded file " + DSLocation + " no longer exists.");
                }

            } else if (DSLocation.startsWith(TEMP_SCHEME)) {
                // TODO: refactor to use proper temp file management - FCREPO-718
                String fileName = DSLocation.substring(TEMP_SCHEME.length());
                File tempFile = new File(fileName);
                // check it has not been removed elsewhere (should not happen)
                if (tempFile.exists()) {
                    return new FileInputStream(tempFile);
                } else {
                    throw new StreamIOException("Temp file " + DSLocation + " no longer exists.");
                }
            } else if (Datastream.DS_LOCATION_TYPE_INTERNAL.equals(DSLocationType)) {
                return getLLStore().retrieveDatastream(DSLocation);
            } else if (Datastream.DS_LOCATION_TYPE_URL.equals(DSLocationType)) {
                // Managed content can have URL dsLocation on ingest
                ValidationUtility.validateURL(DSLocation, this.DSControlGrp);
                // If validation has succeeded, assume an external resource.
                // Fetch it, store it locally, update DSLocation
                if (ctx == null) {
                    ctx = ReadOnlyContext.getContext(null, null, "", false);
                    // changed from below, which sets noOp to true, seems to cause an AuthZ permitted exception
                    // in PolicyEnforcementPoint.enforce(...)
                    // ctx = ReadOnlyContext.EMPTY;
                }
               ContentManagerParams params = new ContentManagerParams(DSLocation);
                params.setContext(ctx);
                MIMETypedStream stream = getExternalContentManager()
                        .getExternalContent(params);

                // TODO: refactor temp file management - see FCREPO-718; for now create temp file and write to it
                // note - don't use temp upload directory, use (container's) temp dir (upload dir is for uploads)
                File tempFile = File.createTempFile("managedcontentupdate", null);
                OutputStream os = new FileOutputStream(tempFile);
                StreamUtility.pipeStream(stream.getStream(), os, 32768);
                DSLocation = TEMP_SCHEME + tempFile.getAbsolutePath();
                return new FileInputStream(new File(tempFile.getAbsolutePath()));
            }
        } catch (Throwable th) {
            throw new StreamIOException("[DatastreamManagedContent] returned "
                    + " the error: \"" + th.getClass().getName()
                    + "\". Reason: " + th.getMessage(), th);
        }
        throw new StreamIOException("[DatastreamManagedContent] could not resolve dsLocation " + DSLocation + " dsLocationType " + DSLocationType);
    }

    /**
     * Set the contents of this managed datastream by storing as a temp file.  If the previous content
     * was stored in a temp file, clean up this file.
     * @param stream - the data to store in this datastream
     * @throws StreamIOException
     */
    public void putContentStream(MIMETypedStream stream) throws StreamIOException {

        // TODO: refactor to use proper temp file management - FCREPO-718
        // for now, write to new temp file, clean up existing location
        String oldDSLocation = DSLocation;
        try {
            // note: don't use temp upload dir, use (container's) temp dir (upload dir is for uploads)
            File tempFile = File.createTempFile("managedcontentupdate", null);
            OutputStream os = new FileOutputStream(tempFile);
            StreamUtility.pipeStream(stream.getStream(), os, 32768);
            DSLocation = TEMP_SCHEME + tempFile.getAbsolutePath();
        } catch (Exception e) {
            throw new StreamIOException("Error creating new temp file for updated managed content (existing content is:" + oldDSLocation + ")", e);
        }

        // if old location was a temp location, clean it up
        // (if old location was uploaded, DefaultManagement should do this, but refactor up as part of FCREPO-718)
        if (oldDSLocation != null && oldDSLocation.startsWith(TEMP_SCHEME)) {
            File oldFile;
            try {
                oldFile = new File(oldDSLocation.substring(TEMP_SCHEME.length()));
            } catch (Exception e) {
                throw new StreamIOException("Error removing old temp file while updating managed content (location: " + oldDSLocation + ")", e);
            }
            if (oldFile.exists()) {
                if (!oldFile.delete()) {
                    logger.warn("Failed to delete temp file, marked for deletion when VM closes " + oldFile.getAbsolutePath());
                    oldFile.deleteOnExit();
                }
            } else
                logger.warn("Cannot delete temp file as it no longer exists " + oldFile.getAbsolutePath());
        }
    }

}
TOP

Related Classes of org.fcrepo.server.storage.types.DatastreamManagedContent

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.