com.flexive.shared.value.BinaryDescriptor.java Source code

Java tutorial

Introduction

Here is the source code for com.flexive.shared.value.BinaryDescriptor.java

Source

/***************************************************************
 *  This file is part of the [fleXive](R) framework.
 *
 *  Copyright (c) 1999-2014
 *  UCS - unique computing solutions gmbh (http://www.ucs.at)
 *  All rights reserved
 *
 *  The [fleXive](R) project is free software; you can redistribute
 *  it and/or modify it under the terms of the GNU Lesser General Public
 *  License version 2.1 or higher as published by the Free Software Foundation.
 *
 *  The GNU Lesser General Public License can be found at
 *  http://www.gnu.org/licenses/lgpl.html.
 *  A copy is found in the textfile LGPL.txt and important notices to the
 *  license from the author are found in LICENSE.txt distributed with
 *  these libraries.
 *
 *  This library 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 General Public License for more details.
 *
 *  For further information about UCS - unique computing solutions gmbh,
 *  please see the company website: http://www.ucs.at
 *
 *  For further information about [fleXive](R), please see the
 *  project website: http://www.flexive.org
 *
 *
 *  This copyright notice MUST APPEAR in all copies of the file!
 ***************************************************************/
package com.flexive.shared.value;

import com.flexive.shared.EJBLookup;
import com.flexive.shared.FxContext;
import com.flexive.shared.FxSharedUtils;
import com.flexive.shared.ObjectWithLabel;
import com.flexive.shared.exceptions.FxStreamException;
import com.flexive.shared.stream.BinaryUploadPayload;
import com.flexive.shared.stream.FxStreamUtils;
import com.flexive.stream.ServerLocation;
import org.apache.commons.lang.StringUtils;

import java.io.*;
import java.util.List;

/**
 * Descriptor for binaries (immutable).
 * Qualities and Versions are currently only planned features but not yet functional.
 *
 * @author Markus Plesser (markus.plesser@flexive.com), UCS - unique computing solutions gmbh (http://www.ucs.at)
 */
public class BinaryDescriptor implements Serializable {
    private static final long serialVersionUID = -416186902840155773L;

    private static final String MIME_TYPE_UNKNOWN = "unknown/unknown";

    public final static int SYS_UNKNOWN = -1;
    public final static int SYS_NOACCESS = -2;
    public final static int SYS_AUDIO = -3;
    public final static int SYS_DOC = -4;
    public final static int SYS_ICAL = -5;
    public final static int SYS_INFO = -6;
    public final static int SYS_PDF = -7;
    public final static int SYS_TXT = -8;
    public final static int SYS_VIDEO = -9;
    public final static int SYS_XLS = -10;
    public final static int SYS_PPT = -6; //TODO: find a fitting thumbnail!
    public final static int SYS_HTML = -8; //TODO: find a fitting thumbnail!

    public final static int SYS_SELECTLIST_DEFAULT = -11;

    public final static String EMPTY = "[EMPTY]";
    /**
     * For images: box scaled size for preview 1
     */
    public final static int PREVIEW1_BOX = 42;
    /**
     * For images: box scaled size for preview 2
     */
    public final static int PREVIEW2_BOX = 85;
    /**
     * For images: box scaled size for preview 3
     */
    public final static int PREVIEW3_BOX = 232;
    /**
     * For images: scaled size for screenviews (1024x768)
     *
     * @since 3.1
     */
    public final static int SCREENVIEW_WIDTH = 1024;
    public final static int SCREENVIEW_HEIGHT = 768;

    /**
     * Enumeration of all available preview sizes.
     */
    public static enum PreviewSizes implements ObjectWithLabel {
        /**
         * 42x42 thumbnail
         */
        PREVIEW1(1, PREVIEW1_BOX),
        /**
         * 85x85 thumbnail
         */
        PREVIEW2(2, PREVIEW2_BOX),
        /**
         * 232x232 thumbnail
         */
        PREVIEW3(3, PREVIEW3_BOX),
        /**
         * 1024x768 screenview
         */
        SCREENVIEW(4, SCREENVIEW_WIDTH),
        /**
         * The original, unscaled image
         */
        ORIGINAL(0, -1);

        private final int blobIndex;
        private final int size;

        /**
         * Ctor
         *
         * @param blobIndex blob index in the database
         * @param size      size constant
         */
        PreviewSizes(int blobIndex, int size) {
            this.blobIndex = blobIndex;
            this.size = size;
        }

        /**
         * Get the binary size constant
         *
         * @return binary size constant
         */
        public int getSize() {
            return size;
        }

        /**
         * Get the blob index in the database containing the binary
         *
         * @return blob index in the database containing the binary
         */
        public int getBlobIndex() {
            return blobIndex;
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public FxString getLabel() {
            return FxSharedUtils.getEnumLabel(this, size, size);
        }

        /**
         * Get a previewSize from a numeric String
         *
         * @param s String with numeric size
         * @return PreviewSizes
         */
        public static PreviewSizes fromString(String s) {
            int size = Integer.parseInt(s);
            for (PreviewSizes p : PreviewSizes.values())
                if (p.getBlobIndex() == size)
                    return p;
            return PreviewSizes.ORIGINAL;
        }

        /**
         * Get a previewSize from a numeric String
         *
         * @param size size constant
         * @return PreviewSizes
         */
        public static PreviewSizes fromSize(int size) {
            for (PreviewSizes p : PreviewSizes.values())
                if (p.getBlobIndex() == size)
                    return p;
            return PreviewSizes.ORIGINAL;
        }
    }

    private final String handle;
    private final boolean newBinary;
    private final List<ServerLocation> server;

    private long id = -1;
    private final int version;
    private final int quality;
    private final long creationTime;
    private final String name;
    private final long size;
    private String metadata;
    private final String mimeType;
    private final boolean image;
    private final double resolution;
    private final int width;
    private final int height;
    private String md5sum = "unknown";

    /**
     * Constructor for a new empty binary
     */
    public BinaryDescriptor() {
        this(EMPTY);
    }

    /**
     * Constructor (for new Binaries)
     *
     * @param handle binary_transit handle
     */
    public BinaryDescriptor(String handle) {
        this(handle, EMPTY, -1, null, null);
    }

    /**
     * Constructor for new Binaries in prepareSave process ..
     *
     * @param handle   handle
     * @param name     name of the binary
     * @param size     size in bytes
     * @param mimeType MIME type
     * @param metadata xml meta data
     */
    public BinaryDescriptor(String handle, String name, long size, String mimeType, String metadata) {
        this.handle = handle;
        this.newBinary = true;
        this.name = name;
        this.size = size;
        this.metadata = metadata;
        this.mimeType = mimeType;
        this.server = null;
        this.id = -1;
        this.version = -1;
        this.quality = -1;
        this.creationTime = -1;
        this.image = false;
        this.resolution = 0;
        this.width = -1;
        this.height = -1;
    }

    /**
     * Constructor for new Binaries in identifyAndTransferTransitBinary process ..
     *
     * @param handle   handle
     * @param name     name of the binary
     * @param size     size in bytes
     * @param mimeType MIME type
     * @param metadata xml meta data
     * @param md5sum   MD5 checksum
     */
    public BinaryDescriptor(String handle, String name, long size, String mimeType, String metadata,
            String md5sum) {
        this.handle = handle;
        this.newBinary = true;
        this.name = name;
        this.size = size;
        this.metadata = metadata;
        this.mimeType = mimeType;
        this.server = null;
        this.id = -1;
        this.version = -1;
        this.quality = -1;
        this.creationTime = -1;
        this.image = false;
        this.resolution = 0;
        this.width = -1;
        this.height = -1;
        this.md5sum = md5sum;
    }

    /**
     * Constructor (for new Binaries)
     *
     * @param name         name of the binary
     * @param streamLength expected size of the binary
     * @param stream       an open input stream for the binary to upload
     * @throws FxStreamException on upload errors
     */
    public BinaryDescriptor(String name, long streamLength, InputStream stream) throws FxStreamException {
        this(FxStreamUtils.uploadBinary(streamLength, stream).getHandle(), name, streamLength, null, null);
    }

    /**
     * Constructor (for new Binaries)
     *
     * @param name         name of the binary
     * @param streamLength expected size of the binary
     * @param mimeType     the mime type to be used if auto-detection fails
     * @param stream       an open input stream for the binary to upload
     * @throws FxStreamException on upload errors
     * @since 3.1
     */
    public BinaryDescriptor(String name, long streamLength, String mimeType, InputStream stream)
            throws FxStreamException {
        this(FxStreamUtils.uploadBinary(streamLength, stream, mimeType), name, mimeType);
    }

    /**
     * Constructor (for new Binaries with unknown size)
     *
     * @param name     name of the binary
     * @param mimeType the MIME type to be used, regardless of the stream content
     * @param stream   an open input stream for the binary to upload
     * @throws FxStreamException on upload errors
     * @since 3.1
     */
    public BinaryDescriptor(String name, String mimeType, InputStream stream) throws FxStreamException {
        this(FxStreamUtils.uploadBinary(-1L, stream, mimeType), name, mimeType);
    }

    /**
     * Internal Constructor (for new Binaries with unknown size)
     *
     * @param payload  payload from the streaming server to read the actual size
     * @param name     name of the binary
     * @param mimeType the MIME type to be used, regardless of the stream content
     * @since 3.1
     */
    protected BinaryDescriptor(BinaryUploadPayload payload, String name, String mimeType) {
        this(payload.getHandle(), name, payload.getActualLength(), mimeType, null, null);
    }

    /**
     * Constructor (for new Binaries with unknown length - use with care since it will have to create a temp file to determine length!)
     *
     * @param name   name of the binary
     * @param stream an open input stream for the binary to upload
     * @throws FxStreamException on upload errors
     */
    public BinaryDescriptor(String name, InputStream stream) throws FxStreamException {
        this.name = name;

        File tmp = null;
        FileOutputStream fos = null;
        FileInputStream fin = null;
        final int BUF_SIZE = 4096;
        try {
            tmp = File.createTempFile("FxBinary", ".bin");
            fos = new FileOutputStream(tmp);
            byte[] buffer = new byte[BUF_SIZE];
            int read;
            while ((read = stream.read(buffer)) != -1) {
                fos.write(buffer, 0, read);
            }
            fos.flush();
            fos.close();
            fos = null;
            fin = new FileInputStream(tmp);
            this.size = tmp.length();
            BinaryUploadPayload payload = FxStreamUtils.uploadBinary(tmp.length(), fin);
            this.handle = payload.getHandle();
        } catch (IOException e) {
            throw new FxStreamException(e, "ex.stream", e.getMessage());
        } finally {
            try {
                if (fos != null)
                    fos.close();
            } catch (IOException e) {
                //ignore
            }
            try {
                if (fin != null)
                    fin.close();
            } catch (IOException e) {
                //ignore
            }
            if (tmp != null) {
                if (!tmp.delete())
                    tmp.deleteOnExit();
            }
        }
        this.newBinary = true;
        this.mimeType = null;
        this.metadata = null;
        this.server = null;
        this.id = -1;
        this.version = -1;
        this.quality = -1;
        this.creationTime = -1;
        this.image = false;
        this.resolution = 0;
        this.width = -1;
        this.height = -1;
    }

    /**
     * Constructor - used for loading from the content engine
     *
     * @param server       server location
     * @param id           binary id
     * @param version      binary version
     * @param quality      quality
     * @param creationTime timestamp when the binary data was created in the storage
     * @param name         name
     * @param size         size
     * @param metadata     xml metadata
     * @param mimeType     mime type
     * @param image        binary is an image?
     * @param resolution   resoltion (if image and detected)
     * @param width        width (if image and detected)
     * @param height       height (if image and detected)
     * @param md5sum       MD5 checksum of the binary
     */
    public BinaryDescriptor(List<ServerLocation> server, long id, int version, int quality, long creationTime,
            String name, long size, String metadata, String mimeType, boolean image, double resolution, int width,
            int height, String md5sum) {
        this.newBinary = false;
        this.server = server;
        this.id = id;
        this.version = version;
        this.quality = quality;
        this.creationTime = creationTime;
        this.name = name;
        this.size = size;
        this.metadata = metadata;
        this.mimeType = mimeType;
        this.image = image;
        this.resolution = resolution;
        this.width = width;
        this.height = height;
        this.handle = null;
        this.md5sum = md5sum;
    }

    /**
     * Set the binary id, only allowed if not assigned previously
     *
     * @param binaryId binary id
     */
    public void setId(long binaryId) {
        if (this.id == -1)
            this.id = binaryId;
    }

    /**
     * Downloads the binary to the given stream.
     * The stream won't be flushed or closed!
     *
     * @param stream stream used for download
     * @throws FxStreamException on errors
     */
    public void download(OutputStream stream) throws FxStreamException {
        FxStreamUtils.downloadBinary(server, stream, this);
    }

    /**
     * Downloads the binary in the requested size (original or preview images if available) to the given stream.
     * The stream won't be flushed or closed!
     *
     * @param stream stream used for download
     * @param size   requested size (original or preview images if available)
     * @throws FxStreamException on errors
     */
    public void download(OutputStream stream, PreviewSizes size) throws FxStreamException {
        FxStreamUtils.downloadBinary(server, stream, this, size);
    }

    /**
     * Get the binary as InputStream for a requested preview size
     *
     * @param size requested preview size
     * @return InputStream
     * @throws FxStreamException on errors
     * @since 3.1.4
     */
    public InputStream getInputStream(PreviewSizes size) throws FxStreamException {
        return FxStreamUtils.getBinaryStream(this, size);
    }

    /**
     * Get the (original) binary as InputStream
     *
     * @return InputStream
     * @throws FxStreamException on errors
     * @since 3.1.4
     */
    public InputStream getInputStream() throws FxStreamException {
        return FxStreamUtils.getBinaryStream(this, PreviewSizes.ORIGINAL);
    }

    /**
     * Is this BinaryDescriptor empty?
     *
     * @return BinaryDescriptor is empty
     */
    public boolean isEmpty() {
        return EMPTY.equals(handle);
    }

    /**
     * Getter for the handle
     *
     * @return handle
     */
    public String getHandle() {
        return handle;
    }

    /**
     * Is this a new binary?
     *
     * @return new binary?
     */
    public boolean isNewBinary() {
        return newBinary;
    }

    /**
     * Getter for the binary id (not content instance id!)
     *
     * @return binary id
     */
    public long getId() {
        return id;
    }

    /**
     * Getter for the binary version
     *
     * @return binary version
     */
    public int getVersion() {
        return version;
    }

    /**
     * Getter for the quality
     *
     * @return quality
     */
    public int getQuality() {
        return quality;
    }

    /**
     * Getter for the creation timestamp
     *
     * @return creation timestamp
     */
    public long getCreationTime() {
        if (creationTime == -1)
            return System.currentTimeMillis();
        return creationTime;
    }

    /**
     * Name of the binary
     *
     * @return name of the binary
     */
    public String getName() {
        return name;
    }

    /**
     * Getter for the binary size in bytes
     *
     * @return binary size in bytes
     */
    public long getSize() {
        return size;
    }

    /**
     * Get the MD5 checksum of the binary, only available after a binary has been loaded from the storage!
     *
     * @return MD5 checksum of the binary
     * @since 3.1
     */
    public String getMd5sum() {
        return md5sum;
    }

    /**
     * Getter for optional metadata (usually XML)
     *
     * @return optional metadata (usually XML)
     */
    public synchronized String getMetadata() {
        if (metadata != null || this.isNewBinary())
            return metadata;
        FxContext.startRunningAsSystem();
        try {
            metadata = EJBLookup.getContentEngine().getBinaryMetaData(this.getId());
        } finally {
            FxContext.stopRunningAsSystem();
        }
        return metadata;
    }

    /**
     * Getter for the mime type (if available)
     *
     * @return mime type (if available)
     */
    public String getMimeType() {
        return StringUtils.defaultString(mimeType, MIME_TYPE_UNKNOWN);
    }

    /**
     * Is this binary an image?
     *
     * @return binary is an image
     */
    public boolean isImage() {
        return image;
    }

    /**
     * If binary is an image, getter for the resolution in dpi
     *
     * @return resolution in dpi
     */
    public double getResolution() {
        return resolution;
    }

    /**
     * If binary is an image, getter for the width in pixel
     *
     * @return width in pixel
     */
    public int getWidth() {
        return width;
    }

    /**
     * If binary is an image, getter for the height in pixel
     *
     * @return height in pixel
     */
    public int getHeight() {
        return height;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public synchronized boolean equals(Object obj) {
        if (!(obj instanceof BinaryDescriptor))
            return false;
        BinaryDescriptor b = (BinaryDescriptor) obj;
        //        if( this.isNewBinary() && b.isNewBinary() )
        //            return true;
        final String otherMeta;
        synchronized (b) {
            otherMeta = b.metadata;
        }
        return
        //                !(b.getMetadata() != null && !b.getMetadata().equals(this.getMetadata())) &&
        //                !(this.getMetadata() != null && !this.getMetadata().equals(b.getMetadata())) &&
        !(this.metadata == null && otherMeta != null) && !(otherMeta == null && this.metadata != null)
                && !(b.getMimeType() != null && !b.getMimeType().equals(this.getMimeType()))
                && !(this.getMimeType() != null && !this.getMimeType().equals(b.getMimeType()))
                && !(this.getMimeType() == null && b.getMimeType() != null)
                && !(b.getMimeType() == null && this.getMimeType() != null)
                && !(this.handle != null && !this.handle.equals(b.handle)) && !(this.id != -1 && this.id != b.id)
                && !(this.md5sum != null && !this.md5sum.equals(b.md5sum));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int hashCode() {
        return (int) this.id + (this.handle != null ? 31 * this.handle.hashCode() : 0);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String toString() {
        return this.getName() + " " + (this.mimeType == null ? MIME_TYPE_UNKNOWN : this.mimeType);
    }
}