001    /**
002     * Copyright (c) 2000-2013 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.util;
016    
017    import com.liferay.portal.kernel.log.Log;
018    import com.liferay.portal.kernel.log.LogFactoryUtil;
019    import com.liferay.portal.kernel.security.SecureRandomUtil;
020    import com.liferay.portal.kernel.util.StringBundler;
021    import com.liferay.portal.kernel.util.StringUtil;
022    import com.liferay.portal.kernel.util.Validator;
023    
024    /**
025     * @author Brian Wing Shun Chan
026     * @author Amos Fong
027     * @author Shuyang Zhou
028     */
029    public class PwdGenerator {
030    
031            public static final String KEY1 = "0123456789";
032    
033            public static final String KEY2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
034    
035            public static final String KEY3 = "abcdefghijklmnopqrstuvwxyz";
036    
037            public static String getPassword() {
038                    return getPassword(8, KEYS);
039            }
040    
041            public static String getPassword(int length) {
042                    return getPassword(length, KEYS);
043            }
044    
045            public static String getPassword(int length, String... keys) {
046                    if (keys == null) {
047                            throw new IllegalArgumentException("Keys are null");
048                    }
049    
050                    StringBundler fullKeySB = new StringBundler(keys);
051    
052                    String fullKey = fullKeySB.toString();
053    
054                    int fullKeyLength = fullKey.length();
055    
056                    int refreshPeriod = (int) (_MULTIPLIER / Math.log(fullKeyLength));
057    
058                    long secureLong = 0;
059    
060                    StringBuilder sb = new StringBuilder(length);
061    
062                    for (int i = 0; i < length; i++) {
063                            if ((i % refreshPeriod) == 0) {
064                                    secureLong = SecureRandomUtil.nextLong();
065                            }
066    
067                            int pos = Math.abs((int)(secureLong % fullKeyLength));
068    
069                            secureLong = secureLong / fullKeyLength;
070    
071                            sb.append(fullKey.charAt(pos));
072                    }
073    
074                    return sb.toString();
075            }
076    
077            public static String getPassword(String key, int length) {
078                    int keysCount = 0;
079    
080                    if (key.contains(KEY1)) {
081                            keysCount++;
082                    }
083    
084                    if (key.contains(KEY2)) {
085                            keysCount++;
086                    }
087    
088                    if (key.contains(KEY3)) {
089                            keysCount++;
090                    }
091    
092                    if (keysCount > length) {
093                            if (_log.isWarnEnabled()) {
094                                    _log.warn("Length is too short");
095                            }
096    
097                            length = keysCount;
098                    }
099    
100                    while (true) {
101                            String password = getPassword(length, key);
102    
103                            if (key.contains(KEY1)) {
104                                    if (Validator.isNull(StringUtil.extractDigits(password))) {
105                                            continue;
106                                    }
107                            }
108    
109                            if (key.contains(KEY2)) {
110                                    if (password.equals(StringUtil.toLowerCase(password))) {
111                                            continue;
112                                    }
113                            }
114    
115                            if (key.contains(KEY3)) {
116                                    if (password.equals(StringUtil.toUpperCase(password))) {
117                                            continue;
118                                    }
119                            }
120    
121                            return password;
122                    }
123            }
124    
125            public static String getPassword(
126                    String key, int length, boolean useAllKeys) {
127    
128                    if (useAllKeys) {
129                            return getPassword(key, length);
130                    }
131    
132                    return getPassword(length, key);
133            }
134    
135            public static String getPinNumber() {
136                    return getPassword(4, KEY1);
137            }
138    
139            private static final double _MULTIPLIER = Long.SIZE * Math.log(2);
140    
141            private static final String[] KEYS = {KEY1, KEY2, KEY3};
142    
143            private static Log _log = LogFactoryUtil.getLog(PwdGenerator.class);
144    
145    }