/** * Copyright (C) 2012 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.web.analytics.json; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; import javax.ws.rs.Consumes; import javax.ws.rs.FormParam; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import org.apache.commons.codec.binary.Base64InputStream; import org.apache.commons.codec.binary.Base64OutputStream; import org.json.JSONObject; import com.google.common.collect.ImmutableMap; /** * REST endpoint for compressing and decompressing the state of the web UI using GZIP and encoding it using base64. */ @Path("compressor") public class Compressor { /** * Compresses the "content" parameter using GZIP, encodes it to base64 and returns it wrapped in a JSON object * with the key "data". * @param content The content that needs to be compressed * @return Response containing JSON with the compressed content keyed with "data" * @throws IOException If compression fails */ @POST @Path("compress") @Consumes(MediaType.APPLICATION_FORM_URLENCODED) public Response compress(@FormParam("content") String content) throws IOException { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); compressStream(new ByteArrayInputStream(content.getBytes()), outputStream); ImmutableMap<String, String> data = ImmutableMap.of("data", outputStream.toString()); return Response.status(Response.Status.OK).entity(new JSONObject(data).toString()).build(); } /** * Decodes the "content" parameter from base64, decompresses it using GZIP and returns it wrapped in a JSON object * with the key "data". * @param content The content that needs to be decompressed * @return Response containing JSON with the decompressed content keyed with "data" * @throws IOException If decompression fails */ @POST @Path("decompress") @Consumes(MediaType.APPLICATION_FORM_URLENCODED) public Response decompress(@FormParam("content") String content) throws IOException { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); decompressStream(new ByteArrayInputStream(content.getBytes()), outputStream); String data = "{\"data\":" + outputStream.toString() + "}"; return Response.status(Response.Status.OK).entity(data).build(); } /* package */ static void compressStream(InputStream inputStream, OutputStream outputStream) throws IOException { InputStream iStream = new BufferedInputStream(inputStream); GZIPOutputStream oStream = new GZIPOutputStream(new Base64OutputStream(new BufferedOutputStream(outputStream), true, -1, null), 2048); byte[] buffer = new byte[2048]; int bytesRead; while ((bytesRead = iStream.read(buffer)) != -1) { oStream.write(buffer, 0, bytesRead); } oStream.close(); // this is necessary for the gzip and base64 streams } /* package */ static void decompressStream(InputStream inputStream, OutputStream outputStream) throws IOException { @SuppressWarnings("resource") InputStream iStream = new GZIPInputStream(new Base64InputStream(new BufferedInputStream(inputStream), false, -1, null)); OutputStream oStream = new BufferedOutputStream(outputStream); byte[] buffer = new byte[2048]; int bytesRead; while ((bytesRead = iStream.read(buffer)) != -1) { oStream.write(buffer, 0, bytesRead); } oStream.flush(); } }