Java tutorial
/* * Copyright (c) 2002-2012 Alibaba Group Holding Limited. * All rights reserved. * * 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 com.alibaba.citrus.service.requestcontext.session.encoder; import static com.alibaba.citrus.util.ArrayUtil.*; import static com.alibaba.citrus.util.Assert.*; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.net.URLEncoder; import java.util.Map; import java.util.zip.Deflater; import java.util.zip.DeflaterOutputStream; import java.util.zip.Inflater; import java.util.zip.InflaterInputStream; import com.alibaba.citrus.service.requestcontext.session.SessionStore.StoreContext; import com.alibaba.citrus.service.requestcontext.session.encrypter.Encrypter; import com.alibaba.citrus.service.requestcontext.session.serializer.Serializer; import com.alibaba.citrus.service.requestcontext.session.serializer.impl.HessianSerializer; import com.alibaba.citrus.springext.support.BeanSupport; import com.alibaba.citrus.util.io.ByteArrayOutputStream; import org.apache.commons.codec.binary.Base64; /** * <code>Serializer</code>??????? * <p> * ? * </p> * <ul> * <li><code>Serializer</code>?<code>HessianSerializer</code></li> * <li></li> * <li><code>Encrypter</code>??</li> * <li>Base64?</li> * <li>URL encoding??HTTP header?</li> * </ul> * <p> * ??? * </p> * * @author Michael Zhou */ public abstract class AbstractSerializationEncoder extends BeanSupport implements SessionEncoder { protected Serializer serializer; protected Encrypter encrypter; @Override protected void init() throws Exception { if (serializer == null) { serializer = new HessianSerializer(); } } /** ? */ public String encode(Map<String, Object> attrs, StoreContext storeContext) throws SessionEncoderException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); // 1. ? // 2. Deflater def = new Deflater(Deflater.BEST_COMPRESSION, false); DeflaterOutputStream dos = new DeflaterOutputStream(baos, def); try { serializer.serialize(assertNotNull(attrs, "objectToEncode is null"), dos); } catch (Exception e) { throw new SessionEncoderException("Failed to encode session state", e); } finally { try { dos.close(); } catch (IOException e) { } def.end(); } byte[] plaintext = baos.toByteArray().toByteArray(); // 3. byte[] cryptotext = encrypt(plaintext); // 4. base64? try { String encodedValue = new String(Base64.encodeBase64(cryptotext, false), "ISO-8859-1"); return URLEncoder.encode(encodedValue, "ISO-8859-1"); } catch (UnsupportedEncodingException e) { throw new SessionEncoderException("Failed to encode session state", e); } } /** */ private byte[] encrypt(byte[] plaintext) throws SessionEncoderException { if (encrypter != null) { return encrypter.encrypt(plaintext); } return plaintext; } /** ? */ public Map<String, Object> decode(String encodedValue, StoreContext storeContext) throws SessionEncoderException { // 1. base64? byte[] cryptotext = null; try { encodedValue = URLDecoder.decode(assertNotNull(encodedValue, "encodedValue is null"), "ISO-8859-1"); cryptotext = Base64.decodeBase64(encodedValue.getBytes("ISO-8859-1")); if (isEmptyArray(cryptotext)) { throw new SessionEncoderException("Session state is empty: " + encodedValue); } } catch (Exception e) { throw new SessionEncoderException("Failed to decode session state: ", e); } // 2. byte[] plaintext = decrypt(cryptotext); if (isEmptyArray(plaintext)) { throw new SessionEncoderException("Decrypted session state is empty: " + encodedValue); } // 3. ByteArrayInputStream bais = new ByteArrayInputStream(plaintext); Inflater inf = new Inflater(false); InflaterInputStream iis = new InflaterInputStream(bais, inf); // 4. ??? try { @SuppressWarnings("unchecked") Map<String, Object> attrs = (Map<String, Object>) serializer.deserialize(iis); return attrs; } catch (Exception e) { throw new SessionEncoderException("Failed to parse session state", e); } finally { try { iis.close(); } catch (IOException e) { } inf.end(); } } /** */ private byte[] decrypt(byte[] cryptotext) throws SessionEncoderException { if (encrypter != null) { return encrypter.decrypt(cryptotext); } return cryptotext; } @Override public String toString() { return getClass().getSimpleName() + "[" + serializer + ", " + (encrypter == null ? "no encrypter" : encrypter) + "]"; } }