/* * Copyright 2010 Outerthought bvba * * 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 org.lilyproject.repository.api; import java.util.Arrays; import org.lilyproject.util.ArgumentValidator; /** * A Blob is a {@link ValueType value type} that can be used to store arbitrarily large binary data. * Besides the binary data itself, a blob holds some metadata such as the media-type and size. * * <p>Storing and retrieving data to and from the blob happens through {@link java.io.OutputStream} and * {@link java.io.InputStream}. * * <p>These streams are available via the Repository through {@link Repository#getOutputStream(Blob)} and * {@link Repository#getInputStream(Blob)}. * * <p><b>Important:</b> to add a blob to a record, you first need to upload the data via the OutputStream. Once * finished, close the OutputStream using {@link java.io.OutputStream#close()}. This will trigger the update of * the {@link #setValue value} of this blob object (which will usually be a pointer to the storage location * of the blob, though for tiny blobs -- sorry for the oxymoron -- this might be the binary data itself). * Once that's done, you can store the {@link Record} itself. Thus: first upload all blobs and close their * OutputStreams, then save the record. It does not matter when the blob value is set on the record object itself. */ public class Blob implements Cloneable { private String mediaType; private Long size; private String name; private byte[] value; /** * This is the default constructor to create a Blob. * * @param mediaType the media type of the data represented by the blob. * @param size the size in number of bytes of the data that will be written. The size is a mandatory parameter. * @param name a name with no extra semantic meaning. Typically used to store a filename, e.g. for when a user * downloads this blob to her desktop. Optional, can be null. */ public Blob(String mediaType, Long size, String name) { this(null, mediaType, size, name); } /** * This constructor should only be used internally. * * @param value the value will be generated after data has been written to the OutputStream and the stream * has been closed. */ public Blob(byte[] value, String mediaType, Long size, String name) { ArgumentValidator.notNull(size, "size"); this.value = value; this.mediaType = mediaType; this.size = size; this.name = name; } /** * Create a clone of the Blob object. * <p> * Note that this does NOT create a copy of the actual blob-data (e.g. on HDFS). */ @Override public Blob clone() throws CloneNotSupportedException { final Blob clone = (Blob)super.clone(); clone.value = value; clone.mediaType = mediaType; clone.size = size; clone.name = name; return clone; } public byte[] getValue() { return value; } public void setValue(byte[] value) { this.value = value; } public String getMediaType() { return mediaType; } public void setMediaType(String mediaType) { this.mediaType = mediaType; } public Long getSize() { return size; } public void setSize(Long size) { this.size = size; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((name == null) ? 0 : name.hashCode()); result = prime * result + Arrays.hashCode(value); result = prime * result + ((mediaType == null) ? 0 : mediaType.hashCode()); result = prime * result + ((size == null) ? 0 : size.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } Blob other = (Blob) obj; if (name == null) { if (other.name != null) { return false; } } else if (!name.equals(other.name)) { return false; } if (!Arrays.equals(value, other.value)) { return false; } if (mediaType == null) { if (other.mediaType != null) { return false; } } else if (!mediaType.equals(other.mediaType)) { return false; } if (size == null) { if (other.size != null) { return false; } } else if (!size.equals(other.size)) { return false; } return true; } @Override public String toString() { return "Blob [name=" + name + ", mediatype=" + mediaType + ", size=" + size + ", value=" + Arrays.toString(value) + "]"; } }