/**
* Copyright 2013 OpenSocial Foundation
* Copyright 2013 International Business Machines Corporation
*
* 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.
*
* Utility library for working with Activity Streams Actions
* Requires underscorejs.
*
* @author James M Snell (jasnell@us.ibm.com)
*/
package com.ibm.common.activitystreams.legacy;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectStreamException;
import java.io.OutputStream;
import java.io.StringReader;
import java.io.StringWriter;
import com.google.common.hash.Hashing;
import com.google.common.hash.HashingInputStream;
import com.google.common.hash.HashingOutputStream;
import com.google.common.io.BaseEncoding;
import com.google.common.net.MediaType;
import com.ibm.common.activitystreams.ASObject;
/**
* The legacy "binary" objectType.
*
* <pre>
* InputStream in = ...
* // will base64 encode, gzip compress and md5 sum the input data
* // will also set the length property accordingly
* Binary binary =
* LegacyMakers.binary()
* .gzipData(in)
* .get();
* </pre>
*
* @author james
*
*/
public final class Binary
extends ASObject {
public static final class Builder
extends ASObject.AbstractBuilder<Binary, Builder> {
Builder() {
objectType("binary");
}
/**
* Set the input data without any compression. Will automatically
* set calculate the md5 sum and length properties
* @param in InputStream
* @return Builder
* @throws IOException
*/
public Builder data(
InputStream in)
throws IOException {
return data(in,null);
}
/**
* Set the input data with GZip compression. Will automatically
* set calculate the md5 sum and length properties
* @param in InputStream
* @return Builder
* @throws IOException
*/
public Builder gzipData(InputStream in) throws IOException {
return data(in, Compression.GZipCompression);
}
/**
* Set the input data with Deflate compression. Will automatically
* set calculate the md5 sum and length properties
* @param in InputStream
* @return Builder
* @throws IOException
*/
public Builder deflateData(InputStream in) throws IOException {
return data(in, Compression.DeflateCompression);
}
/**
* Set the input data the given Compression. Will automatically
* set calculate the md5 sum and length properties
* @param in InputStream
* @return Builder
* @throws IOException
*/
public Builder data(
InputStream in,
Compression<?,?> compression)
throws IOException {
StringWriter writer = new StringWriter();
OutputStream out =
BaseEncoding.base64Url().encodingStream(writer);
if (compression != null)
out = compression.compressor(out);
HashingOutputStream hout =
new HashingOutputStream(
Hashing.md5(), out);
byte[] buf = new byte[1024];
int r = -1;
long size = 0;
while((r = in.read(buf)) > -1) {
hout.write(buf,0,r);
size += r;
}
set("length", size);
if (compression != null) {
set("compression", compression.label());
compression.finish(out);
}
hout.close();
set("md5", hout.hash().toString());
return set("data",writer.toString());
}
/**
* Manually set the md5 properties (this is not recommended. calling the data
* methods will automatically generate the md5 checksum for you)
*
* @param md5 String
* @return Builder
*/
public Builder md5(String md5) {
return set("md5", md5);
}
/**
* Set the fileUrl property
* @param fileUrl String
* @return Builder
*/
public Builder fileUrl(String fileUrl) {
return set("fileUrl", fileUrl);
}
/**
* Set the MIME Media Type using the Legacy "mimeType" property name
* rather than the AS 2.0 "mediaType" property name
* @param mt MediaType
* @return Builder
*/
@Override
public Builder mediaType(MediaType mt) {
return set("mimeType", mt);
}
/**
* Get the built Binary object
*/
public Binary get() {
return new Binary(this);
}
}
private Binary(Builder builder) {
super(builder);
}
/**
* Get the fileUrl property
* @return String
*/
public String fileUrl() {
return getString("fileUrl");
}
/**
* Get the length property
* @return long
*/
public long length() {
return getLong("length");
}
/**
* Get the compression property value (typically "gzip" or "deflate")
* @return String
*/
public String compression() {
return getString("compression");
}
/**
* True if compression = gzip
* @return boolean
*/
public boolean isGzip() {
return "gzip".equalsIgnoreCase(compression());
}
/**
* True if compression = deflate
* @return boolean
*/
public boolean isDeflate() {
return "deflate".equalsIgnoreCase(compression());
}
/**
* Return the md5 checksum
* @return String
*/
public String md5() {
return getString("md5");
}
/**
* Return the literal string content of the data property.
* This will be base64 encoded and optionally compressed
* @return String
*/
public String data() {
return getString("data");
}
/**
* Return an InputStream for reading the data. Will
* decompress and base64 decode as necessary
* @return InputStream
* @throws IOException
*/
public InputStream read() throws IOException {
Compression<?,?> compression =
isGzip() ? Compression.GZipCompression :
isDeflate() ? Compression.DeflateCompression :
null;
return read(compression);
}
/**
* Return an InputStream for reading the data
* @param compression Compression
* @return InputStream
* @throws IOException
*/
public InputStream read(Compression<?,?> compression) throws IOException {
StringReader reader = new StringReader(data());
InputStream in = BaseEncoding.base64Url().decodingStream(reader);
if (compression != null)
in = compression.decompressor(in);
if (has("md5"))
in = new HashingInputStream(Hashing.md5(),in);
return in;
}
/**
* Return the MIME MediaType using the legacy "mimeType" property name
* rather than the AS 2.0 "mediaType" name
*/
@Override
public MediaType mediaType() {
return this.<MediaType>get("mimeType");
}
// Java Serialization Support
Object writeReplace() throws java.io.ObjectStreamException {
return new SerializedForm(this);
}
private static class SerializedForm
extends AbstractSerializedForm<Binary> {
private static final long serialVersionUID = -2060301713159936285L;
protected SerializedForm(Binary obj) {
super(obj);
}
Object readResolve() throws ObjectStreamException {
return super.doReadResolve();
}
protected Binary.Builder builder() {
return new Builder();
}
}
}