package org.atricore.idbus.capabilities.oauth2.common.util; import org.apache.commons.codec.binary.Base64; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.atricore.idbus.capabilities.oauth2.common.OAuth2AccessToken; import org.atricore.idbus.capabilities.oauth2.common.OAuth2AccessTokenEnvelope; import org.codehaus.jackson.map.ObjectMapper; import java.io.*; import java.util.ArrayList; import java.util.List; import java.util.zip.DataFormatException; import java.util.zip.Deflater; import java.util.zip.Inflater; /** * @author <a href=mailto:sgonzalez@atricore.org>Sebastian Gonzalez Oyuela</a> */ public class JasonUtils { private static final Log logger = LogFactory.getLog(JasonUtils.class); private static ObjectMapper mapper = new ObjectMapper(); static { mapper.writerWithType(List.class).withType(ArrayList.class); } public static String marshalAccessToken(OAuth2AccessToken accessToken) throws IOException { return marshalAccessToken(accessToken, true); } public static String marshalAccessToken(OAuth2AccessToken accessToken, boolean encode) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(1024); mapper.writeValue(baos, accessToken); String jsonToken = new String(baos.toByteArray()); if (logger.isTraceEnabled()) logger.trace("Marshaled AccessToken (JSON):\n" + jsonToken); if (encode) return new String(Base64.encodeBase64(jsonToken.getBytes())); else return jsonToken; } public static OAuth2AccessToken unmarshalAccessToken(String strAccessToken, boolean decode) throws IOException { if (decode) strAccessToken = new String(Base64.decodeBase64(strAccessToken.getBytes())); if (logger.isTraceEnabled()) logger.trace("Unmarshal Access Token (JSON)\n" + strAccessToken); return mapper.readValue(new ByteArrayInputStream(strAccessToken.getBytes()), OAuth2AccessToken.class); } public static OAuth2AccessToken unmarshalAccessToken(String strAccessToken) throws IOException { return unmarshalAccessToken(strAccessToken, true); } public static String marshalAccessTokenEnvelope(OAuth2AccessTokenEnvelope envelope) throws IOException { return marshalAccessTokenEnvelope(envelope, true); } public static String marshalAccessTokenEnvelope(OAuth2AccessTokenEnvelope envelope, boolean encode) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(1024); mapper.writeValue(baos, envelope); String jsonEnv = new String(baos.toByteArray()); if (logger.isTraceEnabled()) logger.trace("Marshaled AccessTokenEnvelope (JSON):\n" + jsonEnv); if (encode) return deflate(jsonEnv, true); else return jsonEnv; } public static OAuth2AccessTokenEnvelope unmarshalAccessTokenEnvelope(String strAccessTokenEnvelope) throws IOException { return unmarshalAccessTokenEnvelope(strAccessTokenEnvelope, true); } public static OAuth2AccessTokenEnvelope unmarshalAccessTokenEnvelope(String strAccessTokenEnvelope, boolean decode) throws IOException { if (decode) strAccessTokenEnvelope = inflate(strAccessTokenEnvelope, true); if (logger.isTraceEnabled()) logger.trace("Unmarshal AccessTokenEnvelope (JSON):\n" + strAccessTokenEnvelope); return mapper.readValue(new ByteArrayInputStream(strAccessTokenEnvelope.getBytes()), OAuth2AccessTokenEnvelope.class); } public static String deflate(String tokenStr, boolean encode) { int n = tokenStr.length(); byte[] redirIs = null; try { redirIs = tokenStr.getBytes("UTF-8"); } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } byte[] deflated = new byte[n]; Deflater deflater = new Deflater(Deflater.DEFAULT_COMPRESSION, true); deflater.setInput(redirIs); deflater.finish(); int len = deflater.deflate(deflated); deflater.end(); byte[] exact = new byte[len]; System.arraycopy(deflated, 0, exact, 0, len); if (encode) { byte[] base64Str = new Base64().encode(exact); return new String(base64Str); } return new String(exact); } public static String inflate(String tokenStr, boolean decode) { if (tokenStr == null || tokenStr.length() == 0) { throw new RuntimeException("Token string cannot be null or empty"); } byte[] redirBin = null; if (decode) redirBin = new Base64().decode(removeNewLineChars(tokenStr).getBytes()); else redirBin = tokenStr.getBytes(); // Decompress the bytes Inflater inflater = new Inflater(true); inflater.setInput(redirBin); int resultLen = 4096; byte[] result = new byte[resultLen]; int resultLength = 0; try { resultLength = inflater.inflate(result); } catch (DataFormatException e) { throw new RuntimeException("Cannot inflate OAuth2 Token : " + e.getMessage(), e); } inflater.end(); // Decode the bytes into a String String outputString = null; try { outputString = new String(result, 0, resultLength, "UTF-8"); } catch (UnsupportedEncodingException e) { throw new RuntimeException("Cannot convert byte array to string " + e.getMessage(), e); } return outputString; } public static String removeNewLineChars(String s) { String retString = null; if ((s != null) && (s.length() > 0) && (s.indexOf('\n') != -1)) { char[] chars = s.toCharArray(); int len = chars.length; StringBuffer sb = new StringBuffer(len); for (int i = 0; i < len; i++) { char c = chars[i]; if (c != '\n') { sb.append(c); } } retString = sb.toString(); } else { retString = s; } return retString; } }