001    /**
002     * Copyright (c) 2000-present 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.exception.SystemException;
019    import com.liferay.portal.kernel.nio.charset.CharsetEncoderUtil;
020    import com.liferay.portal.kernel.util.StringBundler;
021    import com.liferay.portal.kernel.util.StringPool;
022    import com.liferay.portal.kernel.util.StringUtil;
023    
024    import java.io.Serializable;
025    
026    import java.nio.CharBuffer;
027    import java.nio.charset.CharacterCodingException;
028    import java.nio.charset.Charset;
029    import java.nio.charset.CharsetEncoder;
030    
031    import java.security.MessageDigest;
032    import java.security.NoSuchAlgorithmException;
033    
034    /**
035     * @author Shuyang Zhou
036     */
037    public class MessageDigestCacheKeyGenerator extends BaseCacheKeyGenerator {
038    
039            public MessageDigestCacheKeyGenerator(String algorithm)
040                    throws NoSuchAlgorithmException {
041    
042                    this(algorithm, StringPool.UTF8);
043            }
044    
045            public MessageDigestCacheKeyGenerator(String algorithm, String charsetName)
046                    throws NoSuchAlgorithmException {
047    
048                    _messageDigest = MessageDigest.getInstance(algorithm);
049                    _charsetEncoder = CharsetEncoderUtil.getCharsetEncoder(charsetName);
050            }
051    
052            @Override
053            public CacheKeyGenerator clone() {
054                    Charset charset = _charsetEncoder.charset();
055    
056                    try {
057                            return new MessageDigestCacheKeyGenerator(
058                                    _messageDigest.getAlgorithm(), charset.name());
059                    }
060                    catch (NoSuchAlgorithmException nsae) {
061                            throw new IllegalStateException(nsae);
062                    }
063            }
064    
065            @Override
066            public Serializable getCacheKey(String key) {
067                    try {
068                            _messageDigest.update(_charsetEncoder.encode(CharBuffer.wrap(key)));
069    
070                            return StringUtil.bytesToHexString(_messageDigest.digest());
071                    }
072                    catch (CharacterCodingException cce) {
073                            throw new SystemException(cce);
074                    }
075            }
076    
077            @Override
078            public Serializable getCacheKey(String[] keys) {
079                    return getCacheKey(keys, keys.length);
080            }
081    
082            @Override
083            public Serializable getCacheKey(StringBundler sb) {
084                    return getCacheKey(sb.getStrings(), sb.index());
085            }
086    
087            @Override
088            public boolean isCallingGetCacheKeyThreadSafe() {
089                    return _CALLING_GET_CACHE_KEY_THREAD_SAFE;
090            }
091    
092            protected Serializable getCacheKey(String[] keys, int length) {
093                    try {
094                            for (int i = 0; i < length; i++) {
095                                    _messageDigest.update(
096                                            _charsetEncoder.encode(CharBuffer.wrap(keys[i])));
097                            }
098    
099                            return StringUtil.bytesToHexString(_messageDigest.digest());
100                    }
101                    catch (CharacterCodingException cce) {
102                            throw new SystemException(cce);
103                    }
104            }
105    
106            private static final boolean _CALLING_GET_CACHE_KEY_THREAD_SAFE = false;
107    
108            private final CharsetEncoder _charsetEncoder;
109            private final MessageDigest _messageDigest;
110    
111    }