/*
* [Unwrap.java]
*
* Summary: Unwraps an object shipped via HTTP CGI-POST.
*
* Copyright: (c) 2006-2017 Roedy Green, Canadian Mind Products, http://mindprod.com
*
* Licence: This software may be copied and used freely for any purpose but military.
* http://mindprod.com/contact/nonmil.html
*
* Requires: JDK 1.8+
*
* Created with: JetBrains IntelliJ IDEA IDE http://www.jetbrains.com/idea/
*
* Version History:
* 1.4 2006-03-05 reformat with IntelliJ and add Javadoc.
*/
package com.mindprod.transporter;
import com.mindprod.base64.Base64u;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.zip.GZIPInputStream;
/**
* Unwraps an object shipped via HTTP CGI-POST.
*
* The Object is serialised, compressed, and Base64u armoured.
*
* No encryption or digital
* signing. See Transporter.java for example of use.
*
* @author Roedy Green, Canadian Mind Products
* @version 1.4 2006-03-05 reformat with IntelliJ and add Javadoc.
* @since 2006
*/
public class Unwrap
{
/**
* used to help remove ASCII armouring.
*/
private final Base64u disarmourer;
/**
* constructor
*/
public Unwrap()
{
disarmourer = new Base64u();
disarmourer.setLineLength( Integer.MAX_VALUE );
disarmourer.setLineSeparator( "\n" );
}
/**
* Decompress message.
*
* @param message GZIPPed to be decompressed.
*
* @return message decompressed.
* @throws IOException if cannot decompress the message
*/
protected byte[] decompress( byte[] message ) throws IOException
{
ByteArrayInputStream bais = new ByteArrayInputStream( message );
GZIPInputStream gzis = new GZIPInputStream( bais, 4096/* buffsize */ );
ArrayList v = new ArrayList<>( 11 );
// if all goes well, we will do this all in one read.
// length read of -1 marks EOF.
int decompressedLength;
do
{
// R E A D
byte[] decompressedBlock = new byte[ Tools.TYPICAL_MESSAGE_SIZE ];
decompressedLength = gzis.read( decompressedBlock,
0
/* offset */,
Tools.TYPICAL_MESSAGE_SIZE
/* bytes to read */ );
if ( decompressedLength <= 0 )
{
// nothing or -= eof
}
else if ( decompressedLength < Tools.TYPICAL_MESSAGE_SIZE )
{
v.add( Tools
.subarray( decompressedBlock, 0, decompressedLength ) );
}
else
{
v.add( decompressedBlock );
}
}
while ( decompressedLength >= 0 );
// C L O S E
gzis.close();
// glue all the blocks read together.
return Tools.join( v );
}
/**
* remove ASCII base64u armouring from a Base64u encoded message.
*
* @param armoured armoured Base64u string.
*
* @return raw bytes of message..
*/
protected byte[] disarmour( String armoured )
{
return disarmourer.decode( armoured );
}
/**
* reconstitute a serializsed object
*
* @param pickled pickled object's bytes
*
* @return reconstituted object
* @throws IOException
*/
protected Serializable reconstitute( byte[] pickled ) throws IOException
{
try
{// O P E N
ByteArrayInputStream bais = new ByteArrayInputStream( pickled );
ObjectInputStream ois = new ObjectInputStream( bais );
// R E A D
Serializable o = ( Serializable ) ois.readObject();
// C L O S E
ois.close();
return o;
}
catch ( ClassNotFoundException e )
{
throw new IOException( "Corrupt ObjectStream " + e.getMessage() );
}
}
/**
* unwraps an armoured, compressed, serialised object. does not parse parm=value.
*
* @param s base64u string.
*
* @return reconstituted object.
* @throws IOException if cannot unwrap the message )
*/
public Serializable unwrap( String s ) throws IOException
{
return reconstitute( decompress( disarmour( s ) ) );
}
}