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