com.alibaba.citrus.service.requestcontext.session.valueencoder.AbstractSessionValueEncoder.java Source code

Java tutorial

Introduction

Here is the source code for com.alibaba.citrus.service.requestcontext.session.valueencoder.AbstractSessionValueEncoder.java

Source

/*
 * 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.valueencoder;

import static com.alibaba.citrus.util.StringUtil.*;

import java.beans.PropertyEditor;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
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.configuration.support.PropertyEditorRegistrarsSupport;
import com.alibaba.citrus.service.requestcontext.session.SessionStore.StoreContext;
import com.alibaba.citrus.service.requestcontext.session.encoder.SessionEncoderException;
import com.alibaba.citrus.service.requestcontext.session.encrypter.Encrypter;
import com.alibaba.citrus.springext.support.BeanSupport;
import com.alibaba.citrus.util.StringEscapeUtil;
import com.alibaba.citrus.util.io.StreamUtil;
import org.apache.commons.codec.binary.Base64;
import org.springframework.beans.PropertyEditorRegistrar;
import org.springframework.beans.PropertyEditorRegistry;
import org.springframework.beans.SimpleTypeConverter;
import org.springframework.beans.TypeConverter;

/**
 * <code>SessionEncoder</code>??base64????
 *
 * @author youqun.zhangyq
 * @author Michael Zhou
 */
public abstract class AbstractSessionValueEncoder extends BeanSupport implements SessionValueEncoder {
    private static final String DEFAULT_CHARSET = "UTF-8";
    private PropertyEditorRegistrarsSupport propertyEditorRegistrars = new PropertyEditorRegistrarsSupport();
    protected Encrypter encrypter;
    private String charset;

    public void setPropertyEditorRegistrars(PropertyEditorRegistrar[] registrars) {
        propertyEditorRegistrars.setPropertyEditorRegistrars(registrars);
    }

    public void setEncrypter(Encrypter encrypter) {
        this.encrypter = encrypter;
    }

    public String getCharset() {
        return charset == null ? DEFAULT_CHARSET : charset;
    }

    public void setCharset(String charset) {
        this.charset = trimToNull(charset);
    }

    protected abstract boolean doURLEncode();

    protected abstract boolean doCompress();

    public String encode(Object value, StoreContext storeContext) throws SessionValueEncoderException {
        try {
            String encodedValue = encodeValue(value);

            // ??encrypter
            if (encrypter != null) {
                encodedValue = new String(
                        Base64.encodeBase64(encrypter.encrypt(compress(encodedValue.getBytes("UTF-8")))), "8859_1");
            }

            // url encoding
            if (doURLEncode() || encrypter != null) {
                encodedValue = StringEscapeUtil.escapeURL(encodedValue, getCharset());
            }

            return encodedValue;
        } catch (Exception e) {
            throw new SessionEncoderException("Failed to encode single value", e);
        }
    }

    public Object decode(String encodedValue, StoreContext storeContext) throws SessionValueEncoderException {
        try {
            // url decoding
            if (doURLEncode() || encrypter != null) {
                encodedValue = StringEscapeUtil.unescapeURL(encodedValue, getCharset());
            }

            // ??encrypter
            if (encrypter != null) {
                encodedValue = new String(
                        decompress(encrypter.decrypt(Base64.decodeBase64(encodedValue.getBytes("8859_1")))),
                        "UTF-8");
            }

            return decodeValue(encodedValue);
        } catch (Exception e) {
            throw new SessionEncoderException("Failed to decode single value", e);
        }
    }

    private byte[] compress(byte[] data) throws SessionValueEncoderException {
        if (!doCompress()) {
            return data;
        }

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        Deflater def = new Deflater(Deflater.BEST_COMPRESSION, false);
        DeflaterOutputStream dos = new DeflaterOutputStream(baos, def);

        try {
            dos.write(data);
        } catch (Exception e) {
            throw new SessionValueEncoderException(e);
        } finally {
            try {
                dos.close();
            } catch (IOException e) {
            }

            def.end();
        }

        return baos.toByteArray();
    }

    private byte[] decompress(byte[] data) throws SessionValueEncoderException {
        if (!doCompress()) {
            return data;
        }

        ByteArrayInputStream bais = new ByteArrayInputStream(data);
        Inflater inf = new Inflater(false);
        InflaterInputStream iis = new InflaterInputStream(bais, inf);

        try {
            return StreamUtil.readBytes(iis, true).toByteArray();
        } catch (Exception e) {
            throw new SessionValueEncoderException(e);
        } finally {
            inf.end();
        }
    }

    protected final TypeConverter getTypeConverter() {
        SimpleTypeConverter typeConverter = new SimpleTypeConverter();
        propertyEditorRegistrars.registerCustomEditors(typeConverter);
        return typeConverter;
    }

    protected final String convertToString(Class<?> type, Object value, TypeConverter converter) {
        if (value instanceof String) {
            return (String) value;
        } else {
            if (converter instanceof PropertyEditorRegistry && type != null && type.isInstance(value)) {
                PropertyEditor editor = ((PropertyEditorRegistry) converter).findCustomEditor(type, null);

                if (editor != null) {
                    editor.setValue(value);
                    return editor.getAsText();
                }
            }

            return (String) getTypeConverter().convertIfNecessary(value, String.class);
        }
    }

    protected final Object convertToType(Class<?> type, String encodedValue, TypeConverter converter) {
        if (type != null && !type.equals(String.class)) {
            return converter.convertIfNecessary(encodedValue, type);
        } else {
            return encodedValue;
        }
    }

    protected abstract String encodeValue(Object value) throws Exception;

    protected abstract Object decodeValue(String encodedValue) throws Exception;
}