Package com.alibaba.citrus.service.requestcontext.session.valueencoder

Source Code of com.alibaba.citrus.service.requestcontext.session.valueencoder.AbstractSessionValueEncoder

/*
* 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;
}
TOP

Related Classes of com.alibaba.citrus.service.requestcontext.session.valueencoder.AbstractSessionValueEncoder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.