001    /**
002     * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.cache.key;
016    
017    import com.liferay.portal.kernel.cache.key.CacheKeyGenerator;
018    import com.liferay.portal.kernel.log.Log;
019    import com.liferay.portal.kernel.log.LogFactoryUtil;
020    import com.liferay.portal.kernel.nio.charset.CharsetEncoderUtil;
021    import com.liferay.portal.kernel.util.StringBundler;
022    import com.liferay.portal.kernel.util.StringPool;
023    
024    import java.nio.CharBuffer;
025    import java.nio.charset.CharsetEncoder;
026    
027    import java.security.MessageDigest;
028    import java.security.NoSuchAlgorithmException;
029    
030    /**
031     * @author Michael C. Han
032     * @author Shuyang Zhou
033     */
034    public class JavaMD5CacheKeyGenerator extends BaseCacheKeyGenerator {
035    
036            public JavaMD5CacheKeyGenerator() throws NoSuchAlgorithmException {
037                    this(-1);
038            }
039    
040            public JavaMD5CacheKeyGenerator(int maxLength)
041                    throws NoSuchAlgorithmException {
042    
043                    _maxLength = maxLength;
044                    _messageDigest = MessageDigest.getInstance(_ALGORITHM_MD5);
045                    _charsetEncoder = CharsetEncoderUtil.getCharsetEncoder(StringPool.UTF8);
046            }
047    
048            public CacheKeyGenerator clone() {
049                    try {
050                            return new JavaMD5CacheKeyGenerator(_maxLength);
051                    }
052                    catch (NoSuchAlgorithmException nsae) {
053                            throw new IllegalStateException(nsae.getMessage(), nsae);
054                    }
055            }
056    
057            public String getCacheKey(String key) {
058                    if ((_maxLength > -1) && (key.length() < _maxLength)) {
059                            return key;
060                    }
061    
062                    try {
063                            _messageDigest.update(_charsetEncoder.encode(CharBuffer.wrap(key)));
064    
065                            byte[] bytes = _messageDigest.digest();
066    
067                            return encodeCacheKey(bytes);
068                    }
069                    catch (Exception e) {
070                            _log.error(e, e);
071    
072                            return key;
073                    }
074            }
075    
076            public String getCacheKey(String[] keys) {
077                    return getCacheKey(new StringBundler(keys));
078            }
079    
080            public String getCacheKey(StringBundler sb) {
081                    if ((_maxLength > -1) && (sb.length() < _maxLength)) {
082                            return sb.toString();
083                    }
084    
085                    try {
086                            for (int i = 0; i < sb.index(); i++) {
087                                    String key = sb.stringAt(i);
088    
089                                    _messageDigest.update(
090                                            _charsetEncoder.encode(CharBuffer.wrap(key)));
091                            }
092    
093                            byte[] bytes = _messageDigest.digest();
094    
095                            return encodeCacheKey(bytes);
096                    }
097                    catch (Exception e) {
098                            _log.error(e, e);
099    
100                            return sb.toString();
101                    }
102            }
103    
104            public void setMaxLength(int maxLength) {
105                    _maxLength = maxLength;
106            }
107    
108            protected String encodeCacheKey(byte[] bytes) {
109                    for (int i = 0; i < bytes.length; i++) {
110                            int value = bytes[i] & 0xff;
111    
112                            _encodeBuffer[i * 2] = _HEX_CHARACTERS[value >> 4];
113                            _encodeBuffer[i * 2 + 1] = _HEX_CHARACTERS[value & 0xf];
114                    }
115    
116                    return new String(_encodeBuffer);
117            }
118    
119            private static final String _ALGORITHM_MD5 = "MD5";
120    
121            private static final char[] _HEX_CHARACTERS = {
122                    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd',
123                    'e', 'f'
124            };
125    
126            private static Log _log = LogFactoryUtil.getLog(
127                    JavaMD5CacheKeyGenerator.class);
128    
129            private CharsetEncoder _charsetEncoder;
130            private char[] _encodeBuffer = new char[32];
131            private int _maxLength = -1;
132            private MessageDigest _messageDigest;
133    
134    }