/**
* $RCSfile: ,v $
* $Revision: $
* $Date: $
*
* Copyright (C) 2004-2011 Jive Software. 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 org.jivesoftware.spark.util;
import javax.swing.KeyStroke;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.BreakIterator;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Utility class to peform common String manipulation algorithms.
*/
public class StringUtils {
// Constants used by escapeHTMLTags
private static final char[] QUOTE_ENCODE = """.toCharArray();
private static final char[] AMP_ENCODE = "&".toCharArray();
private static final char[] LT_ENCODE = "<".toCharArray();
private static final char[] GT_ENCODE = ">".toCharArray();
// patterns for the email address checks
private static Pattern basicAddressPattern;
private static Pattern validUserPattern;
private static Pattern domainPattern;
private static Pattern ipDomainPattern;
private static Pattern tldPattern;
// prepare the patterns
static {
// constants used in the parsing of email addresses
String basicAddress = "^([\\w\\.-]+)@([\\w\\.-]+)$";
String specialChars = "\\(\\)><@,;:\\\\\\\"\\.\\[\\]";
String validChars = "[^ \f\n\r\t" + specialChars + "]";
String atom = validChars + "+";
String quotedUser = "(\"[^\"]+\")";
String word = "(" + atom + "|" + quotedUser + ")";
String validUser = "^" + word + "(\\." + word + ")*$";
String domain = "^" + atom + "(\\." + atom + ")+$";
String ipDomain = "^(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$";
// from http://www.icann.org/tlds/
String knownTLDs = "^\\.(com|net|org|edu|int|mil|gov|arpa|biz|aero|name|coop|info|pro|museum)$";
basicAddressPattern = Pattern.compile(basicAddress,
Pattern.CASE_INSENSITIVE);
validUserPattern = Pattern.compile(validUser, Pattern.CASE_INSENSITIVE);
domainPattern = Pattern.compile(domain, Pattern.CASE_INSENSITIVE);
ipDomainPattern = Pattern.compile(ipDomain, Pattern.CASE_INSENSITIVE);
tldPattern = Pattern.compile(knownTLDs, Pattern.CASE_INSENSITIVE);
}
/**
* Replaces all instances of oldString with newString in string.
*
* @param string
* the String to search to perform replacements on
* @param oldString
* the String that should be replaced by newString
* @param newString
* the String that will replace all instances of oldString
* @return a String will all instances of oldString replaced by newString
*/
public static String replace(String string, String oldString,
String newString) {
if (string == null) {
return null;
}
// If the newString is null or zero length, just return the string since
// there's nothing
// to replace.
if (newString == null) {
return string;
}
int i = 0;
// Make sure that oldString appears at least once before doing any
// processing.
if ((i = string.indexOf(oldString, i)) >= 0) {
// Use char []'s, as they are more efficient to deal with.
char[] string2 = string.toCharArray();
char[] newString2 = newString.toCharArray();
int oLength = oldString.length();
StringBuffer buf = new StringBuffer(string2.length);
buf.append(string2, 0, i).append(newString2);
i += oLength;
int j = i;
// Replace all remaining instances of oldString with newString.
while ((i = string.indexOf(oldString, i)) > 0) {
buf.append(string2, j, i - j).append(newString2);
i += oLength;
j = i;
}
buf.append(string2, j, string2.length - j);
return buf.toString();
}
return string;
}
/**
* Replaces all instances of oldString with newString in line with the added
* feature that matches of newString in oldString ignore case.
*
* @param line
* the String to search to perform replacements on
* @param oldString
* the String that should be replaced by newString
* @param newString
* the String that will replace all instances of oldString
* @return a String will all instances of oldString replaced by newString
*/
public static String replaceIgnoreCase(String line, String oldString,
String newString) {
if (line == null) {
return null;
}
String lcLine = line.toLowerCase();
String lcOldString = oldString.toLowerCase();
int i = 0;
if ((i = lcLine.indexOf(lcOldString, i)) >= 0) {
char[] line2 = line.toCharArray();
char[] newString2 = newString.toCharArray();
int oLength = oldString.length();
StringBuffer buf = new StringBuffer(line2.length);
buf.append(line2, 0, i).append(newString2);
i += oLength;
int j = i;
while ((i = lcLine.indexOf(lcOldString, i)) > 0) {
buf.append(line2, j, i - j).append(newString2);
i += oLength;
j = i;
}
buf.append(line2, j, line2.length - j);
return buf.toString();
}
return line;
}
/**
* Replaces all instances of oldString with newString in line with the added
* feature that matches of newString in oldString ignore case. </p> The
* count paramater is set to the number of replaces performed.
*
* @param line
* the String to search to perform replacements on
* @param oldString
* the String that should be replaced by newString
* @param newString
* the String that will replace all instances of oldString
* @param count
* a value that will be updated with the number of replaces
* <p/>
* performed.
* @return a String will all instances of oldString replaced by newString
*/
public static String replaceIgnoreCase(String line, String oldString,
String newString, int[] count) {
if (line == null) {
return null;
}
String lcLine = line.toLowerCase();
String lcOldString = oldString.toLowerCase();
int i = 0;
if ((i = lcLine.indexOf(lcOldString, i)) >= 0) {
int counter = 1;
char[] line2 = line.toCharArray();
char[] newString2 = newString.toCharArray();
int oLength = oldString.length();
StringBuffer buf = new StringBuffer(line2.length);
buf.append(line2, 0, i).append(newString2);
i += oLength;
int j = i;
while ((i = lcLine.indexOf(lcOldString, i)) > 0) {
counter++;
buf.append(line2, j, i - j).append(newString2);
i += oLength;
j = i;
}
buf.append(line2, j, line2.length - j);
count[0] = counter;
return buf.toString();
}
return line;
}
/**
* Replaces all instances of oldString with newString in line.
* <p/>
* The count Integer is updated with number of replaces.
*
* @param line
* the String to search to perform replacements on
* @param oldString
* the String that should be replaced by newString
* @param newString
* the String that will replace all instances of oldString
* @param count
* Number of replaces.
* @return a String will all instances of oldString replaced by newString
*/
public static String replace(String line, String oldString,
String newString, int[] count) {
if (line == null) {
return null;
}
int i = 0;
if ((i = line.indexOf(oldString, i)) >= 0) {
int counter = 1;
char[] line2 = line.toCharArray();
char[] newString2 = newString.toCharArray();
int oLength = oldString.length();
StringBuffer buf = new StringBuffer(line2.length);
buf.append(line2, 0, i).append(newString2);
i += oLength;
int j = i;
while ((i = line.indexOf(oldString, i)) > 0) {
counter++;
buf.append(line2, j, i - j).append(newString2);
i += oLength;
j = i;
}
buf.append(line2, j, line2.length - j);
count[0] = counter;
return buf.toString();
}
return line;
}
/**
* This method takes a string and strips out all tags except <br>
* tags while still leaving the tag body intact.
*
* @param in
* the text to be converted.
* @return the input string with all tags removed.
*/
public static String stripTags(String in) {
if (in == null) {
return null;
}
return stripTags(in, false);
}
/**
* This method takes a string and strips out all tags while still leaving
* the tag body intact.
*
* @param in
* the text to be converted.
* @param stripBRTag
* Remove BR tags.
* @return the input string with all tags removed.
*/
public static String stripTags(String in, boolean stripBRTag) {
if (in == null) {
return null;
}
char ch;
int i = 0;
int last = 0;
char[] input = in.toCharArray();
int len = input.length;
StringBuffer out = new StringBuffer((int) (len * 1.3));
for (; i < len; i++) {
ch = input[i];
if (ch > '>') {
// Nothing to do
} else if (ch == '<') {
if (!stripBRTag && i + 3 < len && input[i + 1] == 'b'
&& input[i + 2] == 'r' && input[i + 3] == '>') {
i += 3;
continue;
}
if (i > last) {
if (last > 0) {
out.append(" ");
}
out.append(input, last, i - last);
}
last = i + 1;
} else if (ch == '>') {
last = i + 1;
}
}
if (last == 0) {
return in;
}
if (i > last) {
out.append(input, last, i - last);
}
return out.toString();
}
/**
* This method takes a string which may contain HTML tags (ie, <b>,
* <table>, etc) and converts the '<' and '>' characters to their
* HTML escape sequences.
*
* @param in
* the text to be converted.
* @return the input string with the characters '<' and '>' replaced
* with their HTML escape sequences.
*/
public static String escapeHTMLTags(String in) {
if (in == null) {
return null;
}
char ch;
int i = 0;
int last = 0;
char[] input = in.toCharArray();
int len = input.length;
StringBuffer out = new StringBuffer((int) (len * 1.3));
for (; i < len; i++) {
ch = input[i];
if (ch > '>') {
// Nothing to do
} else if (ch == '<') {
if (i > last) {
out.append(input, last, i - last);
}
last = i + 1;
out.append(LT_ENCODE);
} else if (ch == '>') {
if (i > last) {
out.append(input, last, i - last);
}
last = i + 1;
out.append(GT_ENCODE);
} else if (ch == '"') {
if (i > last) {
out.append(input, last, i - last);
}
last = i + 1;
out.append(QUOTE_ENCODE);
}
}
if (last == 0) {
return in;
}
if (i > last) {
out.append(input, last, i - last);
}
return out.toString();
}
/**
* Used by the hash method.
*/
private static MessageDigest digest = null;
/**
* <b>Hashes a String using the Md5 algorithm</b> and returns the result as
* a String of hexadecimal numbers. This method is synchronized to avoid
* excessive MessageDigest object creation. If calling this method becomes a
* bottleneck in your code, you may wish to maintain a pool of MessageDigest
* objects instead of using this method.
* <p/>
* A hash is a one-way function -- that is, given an input, an output is
* easily computed. However, given the output, the input is almost
* impossible to compute. This is useful for passwords since we can store
* the hash and a hacker will then have a very hard time determining the
* original password.
* <p/>
* In Jive, every time a user logs in, we simply take their plain text
* password, compute the hash, and compare the generated hash to the stored
* hash. Since it is almost impossible that two passwords will generate the
* same hash, we know if the user gave us the correct password or not. The
* only negative to this system is that password recovery is basically
* impossible. Therefore, a reset password method is used instead.
*
* @param data
* the String to compute the hash of.
* @return a hashed version of the passed-in String
*/
public synchronized static String hash(String data) {
if (digest == null) {
try {
digest = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException nsae) {
// Nothing to do
}
}
// Now, compute hash.
try {
digest.update(data.getBytes("utf-8"));
} catch (UnsupportedEncodingException e) {
// Nothing to do
}
return encodeHex(digest.digest());
}
public synchronized static String hash(byte[] data) {
if (digest == null) {
try {
digest = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException nsae) {
// Nothing to do
}
}
// Now, compute hash.
digest.update(data);
return encodeHex(digest.digest());
}
/**
* Turns an array of bytes into a String representing each byte as an
* unsigned hex number.
*
* @param bytes
* an array of bytes to convert to a hex-string
* @return generated hex string
*/
public static String encodeHex(byte[] bytes) {
StringBuffer buf = new StringBuffer(bytes.length * 2);
int i;
for (i = 0; i < bytes.length; i++) {
if (((int) bytes[i] & 0xff) < 0x10) {
buf.append("0");
}
buf.append(Long.toString((int) bytes[i] & 0xff, 16));
}
return buf.toString();
}
/**
* Turns a hex encoded string into a byte array. It is specifically meant to
* "reverse" the toHex(byte[]) method.
*
* @param hex
* a hex encoded String to transform into a byte array.
* @return a byte array representing the hex String[
*/
public static byte[] decodeHex(String hex) {
char[] chars = hex.toCharArray();
byte[] bytes = new byte[chars.length / 2];
int byteCount = 0;
for (int i = 0; i < chars.length; i += 2) {
int newByte = 0x00;
newByte |= hexCharToByte(chars[i]);
newByte <<= 4;
newByte |= hexCharToByte(chars[i + 1]);
bytes[byteCount] = (byte) newByte;
byteCount++;
}
return bytes;
}
/**
* Returns the the byte value of a hexadecmical char (0-f). It's assumed
* that the hexidecimal chars are lower case as appropriate.
*
* @param ch
* a hexedicmal character (0-f)
* @return the byte value of the character (0x00-0x0F)
*/
private static byte hexCharToByte(char ch) {
switch (ch) {
case '0':
return 0x00;
case '1':
return 0x01;
case '2':
return 0x02;
case '3':
return 0x03;
case '4':
return 0x04;
case '5':
return 0x05;
case '6':
return 0x06;
case '7':
return 0x07;
case '8':
return 0x08;
case '9':
return 0x09;
case 'a':
return 0x0A;
case 'b':
return 0x0B;
case 'c':
return 0x0C;
case 'd':
return 0x0D;
case 'e':
return 0x0E;
case 'f':
return 0x0F;
}
return 0x00;
}
// *********************************************************************
// * Base64 - a simple base64 encoder and decoder.
// *
// * Copyright (c) 1999, Bob Withers - bwit@pobox.com
// *
// * This code may be freely used for any purpose, either personal
// * or commercial, provided the authors copyright notice remains
// * intact.
// *********************************************************************
/**
* Encodes a String as a base64 String.
*
* @param data
* a String to encode.
* @return a base64 encoded String.
*/
public static String encodeBase64(String data) {
byte[] bytes = null;
try {
bytes = data.getBytes("ISO-8859-1");
} catch (UnsupportedEncodingException uee) {
// Nothing to do
}
return encodeBase64(bytes);
}
/**
* Encodes a byte array into a base64 String.
*
* @param data
* a byte array to encode.
* @return a base64 encode String.
*/
public static String encodeBase64(byte[] data) {
int c;
int len = data.length;
StringBuffer ret = new StringBuffer(((len / 3) + 1) * 4);
for (int i = 0; i < len; ++i) {
c = (data[i] >> 2) & 0x3f;
ret.append(cvt.charAt(c));
c = (data[i] << 4) & 0x3f;
if (++i < len)
c |= (data[i] >> 4) & 0x0f;
ret.append(cvt.charAt(c));
if (i < len) {
c = (data[i] << 2) & 0x3f;
if (++i < len)
c |= (data[i] >> 6) & 0x03;
ret.append(cvt.charAt(c));
} else {
++i;
ret.append((char) fillchar);
}
if (i < len) {
c = data[i] & 0x3f;
ret.append(cvt.charAt(c));
} else {
ret.append((char) fillchar);
}
}
return ret.toString();
}
/**
* Decodes a base64 String.
*
* @param data
* a base64 encoded String to decode.
* @return the decoded String.
*/
public static String decodeBase64(String data) {
byte[] bytes = null;
try {
bytes = data.getBytes("ISO-8859-1");
} catch (UnsupportedEncodingException uee) {
// Nothing to do
}
return decodeBase64(bytes);
}
/**
* Decodes a base64 aray of bytes.
*
* @param data
* a base64 encode byte array to decode.
* @return the decoded String.
*/
public static String decodeBase64(byte[] data) {
int c, c1;
int len = data.length;
StringBuffer ret = new StringBuffer((len * 3) / 4);
for (int i = 0; i < len; ++i) {
c = cvt.indexOf(data[i]);
++i;
c1 = cvt.indexOf(data[i]);
c = ((c << 2) | ((c1 >> 4) & 0x3));
ret.append((char) c);
if (++i < len) {
c = data[i];
if (fillchar == c)
break;
c = cvt.indexOf(c);
c1 = ((c1 << 4) & 0xf0) | ((c >> 2) & 0xf);
ret.append((char) c1);
}
if (++i < len) {
c1 = data[i];
if (fillchar == c1)
break;
c1 = cvt.indexOf(c1);
c = ((c << 6) & 0xc0) | c1;
ret.append((char) c);
}
}
return ret.toString();
}
/**
* The method below is under the following license
* <p/>
* <p/>
* <p/>
* ====================================================================
* <p/>
* <p/>
* <p/>
* The Apache Software License, Version 1.1
* <p/>
* <p/>
* <p/>
* Copyright (c) 2002-2003 The Apache Software Foundation. All rights
* <p/>
* reserved.
* <p/>
* <p/>
* <p/>
* Redistribution and use in source and binary forms, with or without
* <p/>
* modification, are permitted provided that the following conditions
* <p/>
* are met:
* <p/>
* <p/>
* <p/>
* 1. Redistributions of source code must retain the above copyright
* <p/>
* notice, this list of conditions and the following disclaimer.
* <p/>
* <p/>
* <p/>
* 2. Redistributions in binary form must reproduce the above copyright
* <p/>
* notice, this list of conditions and the following disclaimer in
* <p/>
* the documentation and/or other materials provided with the
* <p/>
* distribution.
* <p/>
* <p/>
* <p/>
* 3. The end-user documentation included with the redistribution, if
* <p/>
* any, must include the following acknowlegement:
* <p/>
* "This product includes software developed by the
* <p/>
* Apache Software Foundation (http://www.apache.org/)."
* <p/>
* Alternately, this acknowlegement may appear in the software itself,
* <p/>
* if and wherever such third-party acknowlegements normally appear.
* <p/>
* <p/>
* <p/>
* 4. The names "The Jakarta Project", "Commons", and "Apache Software
* <p/>
* Foundation" must not be used to endorse or promote products derived
* <p/>
* from this software without prior written permission. For written
* <p/>
* permission, please contact apache@apache.org.
* <p/>
* <p/>
* <p/>
* 5. Products derived from this software may not be called "Apache"
* <p/>
* nor may "Apache" appear in their names without prior written
* <p/>
* permission of the Apache Group.
* <p/>
* <p/>
* <p/>
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* <p/>
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* <p/>
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* <p/>
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* <p/>
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* <p/>
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* <p/>
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* <p/>
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* <p/>
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* <p/>
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* <p/>
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* <p/>
* SUCH DAMAGE.
* <p/>
* ====================================================================
* <p/>
* <p/>
* <p/>
* This software consists of voluntary contributions made by many
* <p/>
* individuals on behalf of the Apache Software Foundation. For more
* <p/>
* information on the Apache Software Foundation, please see
* <p/>
* <http://www.apache.org/>.
*/
private static final BitSet allowed_query = new BitSet(256);
static {
for (int i = '0'; i <= '9'; i++) {
allowed_query.set(i);
}
for (int i = 'a'; i <= 'z'; i++) {
allowed_query.set(i);
}
for (int i = 'A'; i <= 'Z'; i++) {
allowed_query.set(i);
}
allowed_query.set('-');
allowed_query.set('_');
allowed_query.set('.');
allowed_query.set('!');
allowed_query.set('~');
allowed_query.set('*');
allowed_query.set('\'');
allowed_query.set('(');
allowed_query.set(')');
}
/**
* Encodes URI string. This is a replacement for the
* java.net.URLEncode#encode(String, String) class which is broken under JDK
* 1.3.
*
* @param original
* the original character sequence
* @param charset
* the protocol charset
* @return URI character sequence
* @throws UnsupportedEncodingException
* unsupported character encoding
*/
public static String URLEncode(String original, String charset)
throws UnsupportedEncodingException {
// encode original to uri characters.
if (original == null) {
return null;
}
// escape octet to uri characters.
byte[] octets;
try {
octets = original.getBytes(charset);
} catch (UnsupportedEncodingException error) {
throw new UnsupportedEncodingException();
}
StringBuffer buf = new StringBuffer(octets.length);
for (byte octet : octets) {
char c = (char) octet;
if (allowed_query.get(c)) {
buf.append(c);
} else {
buf.append('%');
char hexadecimal = Character.forDigit((octet >> 4) & 0xF, 16);
buf.append(Character.toUpperCase(hexadecimal)); // high
hexadecimal = Character.forDigit(octet & 0xF, 16);
buf.append(Character.toUpperCase(hexadecimal)); // low
}
}
return buf.toString();
}
private static final int fillchar = '=';
private static final String cvt = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz" + "0123456789+/";
/**
* Converts a line of text into an array of lower case words using a
* {@link BreakIterator}.wordInstance().
* <p/>
* This method is under the Jive Open Source Software License
*
* @author Mark Imbriaco.
*
* @param text
* a String of text to convert into an array of words
* @return text broken up into an array of words.
*/
public static String[] toLowerCaseWordArray(String text) {
if (text == null || text.length() == 0) {
return new String[0];
}
ArrayList<String> wordList = new ArrayList<String>();
BreakIterator boundary = BreakIterator.getWordInstance();
boundary.setText(text);
int start = 0;
for (int end = boundary.next(); end != BreakIterator.DONE; start = end, end = boundary
.next()) {
String tmp = text.substring(start, end).trim();
// Remove characters that are not needed.
tmp = replace(tmp, "+", "");
tmp = replace(tmp, "/", "");
tmp = replace(tmp, "\\", "");
tmp = replace(tmp, "#", "");
tmp = replace(tmp, "*", "");
tmp = replace(tmp, ")", "");
tmp = replace(tmp, "(", "");
tmp = replace(tmp, "&", "");
if (tmp.length() > 0) {
wordList.add(tmp);
}
}
return wordList.toArray(new String[wordList.size()]);
}
/**
* Pseudo-random number generator object for use with randomString(). The
* Random class is not considered to be cryptographically secure, so only
* use these random Strings for low to medium security applications.
*/
private static Random randGen = new Random();
/**
* Array of numbers and letters of mixed case. Numbers appear in the list
* twice so that there is a more equal chance that a number will be picked.
* We can use the array to get a random number or letter by picking a random
* array index.
*/
private static char[] numbersAndLetters = ("0123456789abcdefghijklmnopqrstuvwxyz"
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ").toCharArray();
/**
* Returns a random String of numbers and letters (lower and upper case) of
* the specified length. The method uses the Random class that is built-in
* to Java which is suitable for low to medium grade security uses. This
* means that the output is only pseudo random, i.e., each number is
* mathematically generated so is not truly random.
* <p>
* <p/>
* <p/>
* The specified length must be at least one. If not, the method will return
* <code>null</code>.
*
* @param length
* the desired length of the random String to return.
* @return a random String of numbers and letters of the specified length.
*/
public static String randomString(int length) {
if (length < 1) {
return null;
}
// Create a char buffer to put random letters and numbers in.
char[] randBuffer = new char[length];
for (int i = 0; i < randBuffer.length; i++) {
randBuffer[i] = numbersAndLetters[randGen.nextInt(71)];
}
return new String(randBuffer);
}
/**
* Intelligently chops a String at a word boundary (whitespace) that occurs
* at the specified index in the argument or before. However, if there is a
* newline character before <code>length</code>, the String will be chopped
* there. If no newline or whitespace is found in <code>string</code> up to
* the index <code>length</code>, the String will chopped at
* <code>length</code>.
* <p/>
* For example, chopAtWord("This is a nice String", 10, -1) will return
* <p/>
* "This is a" which is the first word boundary less than or equal to 10
* characters into the original String.
*
* @param string
* the String to chop.
* @param length
* the index in <code>string</code> to start looking for a
* <p/>
* whitespace boundary at.
* @param minLength
* the minimum length the word should be chopped at. This is
* helpful
* <p/>
* for words with no natural boundaries, ie:
* "thisisareallylonglonglongword".
* <p/>
* This must be smaller than length and can be -1 if no minLength
* is wanted
* @return a substring of <code>string</code> whose length is less than or
* <p/>
* equal to <code>length</code>, and that is chopped at whitespace.
*/
public static String chopAtWord(String string, int length, int minLength) {
// guard clauses
if (length < 2) {
throw new IllegalArgumentException("Length specified (" + length
+ ") must be > 2");
} else if (minLength >= length) {
throw new IllegalArgumentException(
"minLength must be smaller than length");
}
int sLength = (string == null) ? -1 : string.length();
// shortcircuit clauses
if (sLength < 1) {
return string;
}
// minLength specified, string is smaller than the minLength, return the
// string
else if (minLength != -1 && sLength < minLength) {
return string;
}
// no minLength specified, string is smaller than length
else if (minLength == -1 && sLength < length) {
return string;
}
if (string == null)
return null;
char[] charArray = string.toCharArray();
// String is longer than the length specified, attempt to find a newline
// or a space
if (sLength > length) {
sLength = length;
// First check if there is a newline character before length; if so,
// chop word there.
for (int i = 0; i < sLength - 1; i++) {
// Windows
if (charArray[i] == '\r' && charArray[i + 1] == '\n') {
return string.substring(0, i + 1);
}
// Unix
else if (charArray[i] == '\n') {
return string.substring(0, i);
}
}
// Also check boundary case of Unix newline
if (charArray[sLength - 1] == '\n') {
return string.substring(0, sLength - 1);
}
// No newline, so chop at the first whitespace.
for (int i = sLength - 1; i > 0; i--) {
if (charArray[i] == ' ') {
return string.substring(0, i).trim();
}
}
}
// String is shorter than length but longer than minLength,
// make sure there is a space in the string before minLength
else if (minLength != -1 && sLength > minLength) {
for (int i = 0; i < minLength; i++) {
if (charArray[i] == ' ') {
return string;
}
}
}
// Did not find a word boundary, so return a string at the min length,
// if a min
// length was specified:
if (minLength > -1 && minLength <= string.length()) {
return string.substring(0, minLength);
}
// Did not find word boundary or min length so return original String
// chopped at
// specified length.
return string.substring(0, length);
}
/**
* Intelligently chops a String at a word boundary (whitespace) that occurs
* <p/>
* at the specified index in the argument or before. However, if there is a
* <p/>
* newline character before <code>length</code>, the String will be chopped
* <p/>
* there. If no newline or whitespace is found in <code>string</code> up to
* <p/>
* the index <code>length</code>, the String will chopped at
* <code>length</code>.
* <p/>
* <p/>
* <p/>
* For example, chopAtWord("This is a nice String", 10) will return
* <p/>
* "This is a" which is the first word boundary less than or equal to 10
* <p/>
* characters into the original String.
*
* @param string
* the String to chop.
* @param length
* the index in <code>string</code> to start looking for a
* <p/>
* whitespace boundary at.
* @return a substring of <code>string</code> whose length is less than or
* <p/>
* equal to <code>length</code>, and that is chopped at whitespace.
*/
public static String chopAtWord(String string, int length) {
return chopAtWord(string, length, -1);
}
/**
* Returns a substring of the given string which represents the words around
* the given word.
* <p/>
* For example, passing in "This is a quick test a test", "{a,test}" and 5
* would return a string
* <p/>
* of "This is a quick" - that's 5 characters (or to the end of the word,
* whichever
* <p/>
* is greater) on either side of "a". Also, since {a,test} is passed in a
* "a" is found
* <p/>
* first in the string, we base the substring off of the position of "a".
* The wordList is
* <p/>
* really just a list of strings to try - the first one found is used.
* <p>
* <p/>
* <p/>
* <p/>
* Note: The wordList passed in should be lowercase.
*
* @param input
* The string to parse.
* @param wordList
* The words to look for - the first one found in the string is
* used.
* @param numChars
* The number of characters on either side to include in the
* chop.
* @return a substring of the given string matching the criteria, otherwise
* "".
*/
public static String chopAtWordsAround(String input, String[] wordList,
int numChars) {
if (input == null || "".equals(input.trim()) || wordList == null
|| wordList.length == 0 || numChars == 0) {
return "";
}
String lc = input.toLowerCase();
for (String aWordList : wordList) {
int pos = lc.indexOf(aWordList);
if (pos > -1) {
int beginIdx = pos - numChars;
if (beginIdx < 0) {
beginIdx = 0;
}
int endIdx = pos + numChars;
if (endIdx > input.length() - 1) {
endIdx = input.length() - 1;
}
char[] chars = input.toCharArray();
while (beginIdx > 0 && chars[beginIdx] != ' '
&& chars[beginIdx] != '\n' && chars[beginIdx] != '\r') {
beginIdx--;
}
while (endIdx < input.length() && chars[endIdx] != ' '
&& chars[endIdx] != '\n' && chars[endIdx] != '\r') {
endIdx++;
}
return input.substring(beginIdx, endIdx);
}
}
return input.substring(0,
(input.length() >= 200) ? 200 : input.length());
}
/**
* Reformats a string where lines that are longer than <tt>width</tt>
* <p/>
* are split apart at the earliest wordbreak or at maxLength, whichever is
* <p/>
* sooner. If the width specified is less than 5 or greater than the input
* <p/>
* Strings length the string will be returned as is.
* <p/>
* <p/>
* <p/>
* Please note that this method can be lossy - trailing spaces on wrapped
* <p/>
* lines may be trimmed.
*
* @param input
* the String to reformat.
* @param width
* the maximum length of any one line.
* @param locale
* of the string to be wrapped.
* @return a new String with reformatted as needed.
*/
public static String wordWrap(String input, int width, Locale locale) {
// protect ourselves
if (input == null) {
return "";
} else if (width < 5) {
return input;
} else if (width >= input.length()) {
return input;
}
StringBuffer buf = new StringBuffer(input);
boolean endOfLine = false;
int lineStart = 0;
for (int i = 0; i < buf.length(); i++) {
if (buf.charAt(i) == '\n') {
lineStart = i + 1;
endOfLine = true;
}
// handle splitting at width character
if (i > lineStart + width - 1) {
if (!endOfLine) {
int limit = i - lineStart - 1;
BreakIterator breaks = BreakIterator
.getLineInstance(locale);
breaks.setText(buf.substring(lineStart, i));
int end = breaks.last();
// if the last character in the search string isn't a space,
// we can't split on it (looks bad). Search for a previous
// break character
if (end == limit + 1) {
if (!Character
.isWhitespace(buf.charAt(lineStart + end))) {
end = breaks.preceding(end - 1);
}
}
// if the last character is a space, replace it with a \n
if (end != BreakIterator.DONE && end == limit + 1) {
buf.replace(lineStart + end, lineStart + end + 1, "\n");
lineStart = lineStart + end;
}
// otherwise, just insert a \n
else if (end != BreakIterator.DONE && end != 0) {
buf.insert(lineStart + end, '\n');
lineStart = lineStart + end + 1;
} else {
buf.insert(i, '\n');
lineStart = i + 1;
}
} else {
buf.insert(i, '\n');
lineStart = i + 1;
endOfLine = false;
}
}
}
return buf.toString();
}
/**
* Highlights words in a string. Words matching ignores case. The actual
* higlighting method is specified with the start and end higlight tags.
* Those might be beginning and ending HTML bold tags, or anything else.
* This method is under the Jive Open Source Software License and was
* written by Mark Imbriaco.
*
* @param string
* the String to highlight words in.
* @param words
* an array of words that should be highlighted in the string.
* @param startHighlight
* the tag that should be inserted to start highlighting.
* @param endHighlight
* the tag that should be inserted to end highlighting.
* @return a new String with the specified words highlighted.
*/
public static String highlightWords(String string, String[] words,
String startHighlight, String endHighlight) {
if (string == null || words == null || startHighlight == null
|| endHighlight == null) {
return null;
}
StringBuffer regexp = new StringBuffer();
regexp.append("(?i)\\b(");
// Iterate through each word and generate a word list for the regexp.
for (int x = 0; x < words.length; x++) {
// Escape "$", "|", ".", "/", and "?" to keep us out of trouble in
// our regexp.
words[x] = words[x].replaceAll("([\\$\\?\\|\\/\\.])", "\\\\$1");
regexp.append(words[x]);
if (x != words.length - 1) {
regexp.append("|");
}
}
regexp.append(")");
return string.replaceAll(regexp.toString(), startHighlight + "$1"
+ endHighlight);
}
/**
* Escapes all necessary characters in the String so that it can be used
* <p/>
* in an XML doc.
*
* @param string
* the string to escape.
* @return the string with appropriate characters escaped.
*/
public static String escapeForXML(String string) {
if (string == null) {
return null;
}
char ch;
int i = 0;
int last = 0;
char[] input = string.toCharArray();
int len = input.length;
StringBuffer out = new StringBuffer((int) (len * 1.3));
for (; i < len; i++) {
ch = input[i];
if (ch > '>') {
// Nothing to do
} else if (ch == '<') {
if (i > last) {
out.append(input, last, i - last);
}
last = i + 1;
out.append(LT_ENCODE);
} else if (ch == '&') {
if (i > last) {
out.append(input, last, i - last);
}
last = i + 1;
out.append(AMP_ENCODE);
} else if (ch == '"') {
if (i > last) {
out.append(input, last, i - last);
}
last = i + 1;
out.append(QUOTE_ENCODE);
} else if (ch == 10 || ch == 13 || ch == 9) {
// Nothing to do
} else if (ch < 32) {
// Disallow all ASCII control characters, except space,
// enter characters and tabs:
if (i > last) {
out.append(input, last, i - last);
}
last = i + 1;
}
}
if (last == 0) {
return string;
}
if (i > last) {
out.append(input, last, i - last);
}
return out.toString();
}
/**
* Unescapes the String by converting XML escape sequences back into normal
* <p/>
* characters.
*
* @param string
* the string to unescape.
* @return the string with appropriate characters unescaped.
*/
public static String unescapeFromXML(String string) {
string = replace(string, "<", "<");
string = replace(string, ">", ">");
string = replace(string, """, "\"");
return replace(string, "&", "&");
}
private static final char[] zeroArray = "0000000000000000000000000000000000000000000000000000000000000000"
.toCharArray();
/**
* Pads the supplied String with 0's to the specified length and returns
* <p/>
* the result as a new String. For example, if the initial String is
* <p/>
* "9999" and the desired length is 8, the result would be "00009999".
* <p/>
* This type of padding is useful for creating numerical values that need
* <p/>
* to be stored and sorted as character data. Note: the current
* <p/>
* implementation of this method allows for a maximum <tt>length</tt> of
* <p/>
* 64.
*
* @param string
* the original String to pad.
* @param length
* the desired length of the new padded String.
* @return a new String padded with the required number of 0's.
*/
public static String zeroPadString(String string, int length) {
if (string == null || string.length() > length) {
return string;
}
StringBuffer buf = new StringBuffer(length);
buf.append(zeroArray, 0, length - string.length()).append(string);
return buf.toString();
}
/**
* Formats a Date as a String. Depending on how Dates are defined in the
* database
* <p/>
* (character data or numberic), the format return will either be a fifteen
* character long String
* <p/>
* made up of the Date's padded millisecond value, or will simply be the
* Date's millesecond value.
*
* @param date
* Date to convert to milliseconds.
* @return a Date encoded as a String.
*/
public static String dateToMillis(Date date) {
return Long.toString(date.getTime());
}
/**
* Validate an email address. This isn't 100% perfect but should handle just
* about everything
* <p/>
* that is in common use.
*
* @param addr
* the email address to validate
* @return true if the address is valid, false otherwise
*/
public static boolean isValidEmailAddress(String addr) {
if (addr == null) {
return false;
}
addr = addr.trim();
if (addr.length() == 0) {
return false;
}
// basic address check
Matcher matcher = basicAddressPattern.matcher(addr);
if (!matcher.matches()) {
return false;
}
String userPart = matcher.group(1);
String domainPart = matcher.group(2);
// user address check
matcher = validUserPattern.matcher(userPart);
if (!matcher.matches()) {
return false;
}
// ip domain check
matcher = ipDomainPattern.matcher(domainPart);
if (matcher.matches()) {
// if the pattern matched, check to make sure that the ip range is
// valid
for (int i = 1; i < 5; i++) {
String num = matcher.group(i);
if (num == null) {
return false;
}
if (Integer.parseInt(num) > 254) {
return false;
}
}
return true;
}
// symbolic domain check
matcher = domainPattern.matcher(domainPart);
if (matcher.matches()) {
String tld = matcher.group(matcher.groupCount());
// Permit top-level-domains of 3 (includes dot separator) because
// these could be
// country codes which we are not going to check for.
matcher = tldPattern.matcher(tld);
if (tld.length() != 3 && !matcher.matches()) {
return false;
}
} else {
return false;
}
// all tests passed
return true;
}
// Testing method
/*
* public static void main(String[] args) { { String test1 =
* "The quick brown fox jumped"; int chop11 = test1.length(); int chop12 =
* test1.length() - 1; int chop13 = test1.length() - 3; int chop14 =
* test1.length() - "jumped".length(); int chop15 = test1.length() -
* "ox jumped".length(); // run test 1 String result11 = chopAtWord(test1,
* chop11); String result12 = chopAtWord(test1, chop12); String result13 =
* chopAtWord(test1, chop13); String result14 = chopAtWord(test1, chop14);
* String result15 = chopAtWord(test1, chop15); // print results if
* (test1.equals(result11)) { System.err.println("Test 1.1 passed, result: "
* + result11); } else { System.err.println("Test 1.1 failed, result: " +
* result11); }
*
* if ("The quick brown fox".equals(result12)) {
* System.err.println("Test 1.2 passed, result: " + result12); } else {
* System.err.println("Test 1.2 failed, result: " + result12); }
*
* if ("The quick brown fox".equals(result13)) {
* System.err.println("Test 1.3 passed, result: " + result13); } else {
* System.err.println("Test 1.3 failed, result: " + result13); }
*
* if ("The quick brown fox".equals(result14)) {
* System.err.println("Test 1.4 passed, result: " + result14); } else {
* System.err.println("Test 1.4 failed, result: " + result14); }
*
* if ("The quick brown".equals(result15)) {
* System.err.println("Test 1.5 passed, result: " + result15); } else {
* System.err.println("Test 1.5 failed, result: " + result15); } }
*
* System.err.println("");
*
* { String test2 = "The quick brown fox jumped"; int chop21 =
* test2.length(); int chop22 = test2.length() - 1; int chop23 =
* test2.length() - 3; int chop24 = test2.length() - "jumped".length(); int
* chop25 = test2.length() - "ox jumped".length(); // run test 1 String
* result21 = chopAtWord(test2, chop21, 0); String result22 =
* chopAtWord(test2, chop22, 0); String result23 = chopAtWord(test2, chop23,
* 0); String result24 = chopAtWord(test2, chop24, 0); String result25 =
* chopAtWord(test2, chop25, 0); // print results if
* (test2.equals(result21)) { System.err.println("Test 2.1 passed, result: "
* + result21); } else { System.err.println("Test 2.1 failed, result: " +
* result21); }
*
* if ("The quick brown fox".equals(result22)) {
* System.err.println("Test 2.2 passed, result: " + result22); } else {
* System.err.println("Test 2.2 failed, result: " + result22); }
*
* if ("The quick brown fox".equals(result23)) {
* System.err.println("Test 2.3 passed, result: " + result23); } else {
* System.err.println("Test 2.3 failed, result: " + result23); }
*
* if ("The quick brown fox".equals(result24)) {
* System.err.println("Test 2.4 passed, result: " + result24); } else {
* System.err.println("Test 2.4 failed, result: " + result24); }
*
* if ("The quick brown".equals(result25)) {
* System.err.println("Test 2.5 passed, result: " + result25); } else {
* System.err.println("Test 2.5 failed, result: " + result25); } }
*
* System.err.println("");
*
* { String test3 = "Thequickbrownfoxjumped"; int chop31 = test3.length();
* int chop32 = test3.length() - 1; int chop33 = test3.length() - 3; int
* chop34 = test3.length() - "jumped".length(); int chop35 = test3.length()
* - "ox jumped".length(); // run test 1 String result31 = chopAtWord(test3,
* chop31, "Thequickbrownfoxjumped".length()); String result32 =
* chopAtWord(test3, chop32, "Thequick".length()); String result33 =
* chopAtWord(test3, chop33, "Thequick".length()); String result34 =
* chopAtWord(test3, chop34, "Thequick".length()); String result35 =
* chopAtWord(test3, chop35, "Thequick".length()); // print results if
* ("Thequick".equals(result31)) {
* System.err.println("Test 3.1 passed, result: " + result31); } else {
* System.err.println("Test 3.1 failed, result: " + result31); }
*
* if ("Thequick".equals(result32)) {
* System.err.println("Test 3.2 passed, result: " + result32); } else {
* System.err.println("Test 3.2 failed, result: " + result32); }
*
* if ("Thequick".equals(result33)) {
* System.err.println("Test 3.3 passed, result: " + result33); } else {
* System.err.println("Test 3.3 failed, result: " + result33); }
*
* if ("Thequick".equals(result34)) {
* System.err.println("Test 3.4 passed, result: " + result34); } else {
* System.err.println("Test 3.4 failed, result: " + result34); }
*
* if ("Thequick".equals(result35)) {
* System.err.println("Test 3.5 passed, result: " + result35); } else {
* System.err.println("Test 3.5 failed, result: " + result35); } }
*
* System.err.println("");
*
* { String test4 = "Java.Lang.ClassNotFoundException:com.Citrix"; int
* length = test4.length()-3; int min = 20; String result =
* chopAtWord(test4, length, min); System.err.println("result: " + result);
* } }
*/
public static String keyStroke2String(KeyStroke key) {
StringBuffer s = new StringBuffer(50);
int m = key.getModifiers();
if ((m & (InputEvent.SHIFT_DOWN_MASK | InputEvent.SHIFT_MASK)) != 0) {
s.append("shift ");
}
if ((m & (InputEvent.CTRL_DOWN_MASK | InputEvent.CTRL_MASK)) != 0) {
s.append("ctrl ");
}
if ((m & (InputEvent.META_DOWN_MASK | InputEvent.META_MASK)) != 0) {
s.append("meta ");
}
if ((m & (InputEvent.ALT_DOWN_MASK | InputEvent.ALT_MASK)) != 0) {
s.append("alt ");
}
if ((m & (InputEvent.BUTTON1_DOWN_MASK | InputEvent.BUTTON1_MASK)) != 0) {
s.append("button1 ");
}
if ((m & (InputEvent.BUTTON2_DOWN_MASK | InputEvent.BUTTON2_MASK)) != 0) {
s.append("button2 ");
}
if ((m & (InputEvent.BUTTON3_DOWN_MASK | InputEvent.BUTTON3_MASK)) != 0) {
s.append("button3 ");
}
switch (key.getKeyEventType()) {
case KeyEvent.KEY_TYPED:
s.append("typed ");
s.append(key.getKeyChar()).append(" ");
break;
case KeyEvent.KEY_PRESSED:
s.append("pressed ");
s.append(getKeyText(key.getKeyCode())).append(" ");
break;
case KeyEvent.KEY_RELEASED:
s.append("released ");
s.append(getKeyText(key.getKeyCode())).append(" ");
break;
default:
s.append("unknown-event-type ");
break;
}
return s.toString();
}
public static String getKeyText(int keyCode) {
if (keyCode >= KeyEvent.VK_0 && keyCode <= KeyEvent.VK_9
|| keyCode >= KeyEvent.VK_A && keyCode <= KeyEvent.VK_Z) {
return String.valueOf((char) keyCode);
}
switch (keyCode) {
case KeyEvent.VK_COMMA:
return "COMMA";
case KeyEvent.VK_PERIOD:
return "PERIOD";
case KeyEvent.VK_SLASH:
return "SLASH";
case KeyEvent.VK_SEMICOLON:
return "SEMICOLON";
case KeyEvent.VK_EQUALS:
return "EQUALS";
case KeyEvent.VK_OPEN_BRACKET:
return "OPEN_BRACKET";
case KeyEvent.VK_BACK_SLASH:
return "BACK_SLASH";
case KeyEvent.VK_CLOSE_BRACKET:
return "CLOSE_BRACKET";
case KeyEvent.VK_ENTER:
return "ENTER";
case KeyEvent.VK_BACK_SPACE:
return "BACK_SPACE";
case KeyEvent.VK_TAB:
return "TAB";
case KeyEvent.VK_CANCEL:
return "CANCEL";
case KeyEvent.VK_CLEAR:
return "CLEAR";
case KeyEvent.VK_SHIFT:
return "SHIFT";
case KeyEvent.VK_CONTROL:
return "CONTROL";
case KeyEvent.VK_ALT:
return "ALT";
case KeyEvent.VK_PAUSE:
return "PAUSE";
case KeyEvent.VK_CAPS_LOCK:
return "CAPS_LOCK";
case KeyEvent.VK_ESCAPE:
return "ESCAPE";
case KeyEvent.VK_SPACE:
return "SPACE";
case KeyEvent.VK_PAGE_UP:
return "PAGE_UP";
case KeyEvent.VK_PAGE_DOWN:
return "PAGE_DOWN";
case KeyEvent.VK_END:
return "END";
case KeyEvent.VK_HOME:
return "HOME";
case KeyEvent.VK_LEFT:
return "LEFT";
case KeyEvent.VK_UP:
return "UP";
case KeyEvent.VK_RIGHT:
return "RIGHT";
case KeyEvent.VK_DOWN:
return "DOWN";
// numpad numeric keys handled below
case KeyEvent.VK_MULTIPLY:
return "MULTIPLY";
case KeyEvent.VK_ADD:
return "ADD";
case KeyEvent.VK_SEPARATOR:
return "SEPARATOR";
case KeyEvent.VK_SUBTRACT:
return "SUBTRACT";
case KeyEvent.VK_DECIMAL:
return "DECIMAL";
case KeyEvent.VK_DIVIDE:
return "DIVIDE";
case KeyEvent.VK_DELETE:
return "DELETE";
case KeyEvent.VK_NUM_LOCK:
return "NUM_LOCK";
case KeyEvent.VK_SCROLL_LOCK:
return "SCROLL_LOCK";
case KeyEvent.VK_F1:
return "F1";
case KeyEvent.VK_F2:
return "F2";
case KeyEvent.VK_F3:
return "F3";
case KeyEvent.VK_F4:
return "F4";
case KeyEvent.VK_F5:
return "F5";
case KeyEvent.VK_F6:
return "F6";
case KeyEvent.VK_F7:
return "F7";
case KeyEvent.VK_F8:
return "F8";
case KeyEvent.VK_F9:
return "F9";
case KeyEvent.VK_F10:
return "F10";
case KeyEvent.VK_F11:
return "F11";
case KeyEvent.VK_F12:
return "F12";
case KeyEvent.VK_F13:
return "F13";
case KeyEvent.VK_F14:
return "F14";
case KeyEvent.VK_F15:
return "F15";
case KeyEvent.VK_F16:
return "F16";
case KeyEvent.VK_F17:
return "F17";
case KeyEvent.VK_F18:
return "F18";
case KeyEvent.VK_F19:
return "F19";
case KeyEvent.VK_F20:
return "F20";
case KeyEvent.VK_F21:
return "F21";
case KeyEvent.VK_F22:
return "F22";
case KeyEvent.VK_F23:
return "F23";
case KeyEvent.VK_F24:
return "F24";
case KeyEvent.VK_PRINTSCREEN:
return "PRINTSCREEN";
case KeyEvent.VK_INSERT:
return "INSERT";
case KeyEvent.VK_HELP:
return "HELP";
case KeyEvent.VK_META:
return "META";
case KeyEvent.VK_BACK_QUOTE:
return "BACK_QUOTE";
case KeyEvent.VK_QUOTE:
return "QUOTE";
case KeyEvent.VK_KP_UP:
return "KP_UP";
case KeyEvent.VK_KP_DOWN:
return "KP_DOWN";
case KeyEvent.VK_KP_LEFT:
return "KP_LEFT";
case KeyEvent.VK_KP_RIGHT:
return "KP_RIGHT";
case KeyEvent.VK_DEAD_GRAVE:
return "DEAD_GRAVE";
case KeyEvent.VK_DEAD_ACUTE:
return "DEAD_ACUTE";
case KeyEvent.VK_DEAD_CIRCUMFLEX:
return "DEAD_CIRCUMFLEX";
case KeyEvent.VK_DEAD_TILDE:
return "DEAD_TILDE";
case KeyEvent.VK_DEAD_MACRON:
return "DEAD_MACRON";
case KeyEvent.VK_DEAD_BREVE:
return "DEAD_BREVE";
case KeyEvent.VK_DEAD_ABOVEDOT:
return "DEAD_ABOVEDOT";
case KeyEvent.VK_DEAD_DIAERESIS:
return "DEAD_DIAERESIS";
case KeyEvent.VK_DEAD_ABOVERING:
return "DEAD_ABOVERING";
case KeyEvent.VK_DEAD_DOUBLEACUTE:
return "DEAD_DOUBLEACUTE";
case KeyEvent.VK_DEAD_CARON:
return "DEAD_CARON";
case KeyEvent.VK_DEAD_CEDILLA:
return "DEAD_CEDILLA";
case KeyEvent.VK_DEAD_OGONEK:
return "DEAD_OGONEK";
case KeyEvent.VK_DEAD_IOTA:
return "DEAD_IOTA";
case KeyEvent.VK_DEAD_VOICED_SOUND:
return "DEAD_VOICED_SOUND";
case KeyEvent.VK_DEAD_SEMIVOICED_SOUND:
return "DEAD_SEMIVOICED_SOUND";
case KeyEvent.VK_AMPERSAND:
return "AMPERSAND";
case KeyEvent.VK_ASTERISK:
return "ASTERISK";
case KeyEvent.VK_QUOTEDBL:
return "QUOTEDBL";
case KeyEvent.VK_LESS:
return "LESS";
case KeyEvent.VK_GREATER:
return "GREATER";
case KeyEvent.VK_BRACELEFT:
return "BRACELEFT";
case KeyEvent.VK_BRACERIGHT:
return "BRACERIGHT";
case KeyEvent.VK_AT:
return "AT";
case KeyEvent.VK_COLON:
return "COLON";
case KeyEvent.VK_CIRCUMFLEX:
return "CIRCUMFLEX";
case KeyEvent.VK_DOLLAR:
return "DOLLAR";
case KeyEvent.VK_EURO_SIGN:
return "EURO_SIGN";
case KeyEvent.VK_EXCLAMATION_MARK:
return "EXCLAMATION_MARK";
case KeyEvent.VK_INVERTED_EXCLAMATION_MARK:
return "INVERTED_EXCLAMATION_MARK";
case KeyEvent.VK_LEFT_PARENTHESIS:
return "LEFT_PARENTHESIS";
case KeyEvent.VK_NUMBER_SIGN:
return "NUMBER_SIGN";
case KeyEvent.VK_MINUS:
return "MINUS";
case KeyEvent.VK_PLUS:
return "PLUS";
case KeyEvent.VK_RIGHT_PARENTHESIS:
return "RIGHT_PARENTHESIS";
case KeyEvent.VK_UNDERSCORE:
return "UNDERSCORE";
case KeyEvent.VK_FINAL:
return "FINAL";
case KeyEvent.VK_CONVERT:
return "CONVERT";
case KeyEvent.VK_NONCONVERT:
return "NONCONVERT";
case KeyEvent.VK_ACCEPT:
return "ACCEPT";
case KeyEvent.VK_MODECHANGE:
return "MODECHANGE";
case KeyEvent.VK_KANA:
return "KANA";
case KeyEvent.VK_KANJI:
return "KANJI";
case KeyEvent.VK_ALPHANUMERIC:
return "ALPHANUMERIC";
case KeyEvent.VK_KATAKANA:
return "KATAKANA";
case KeyEvent.VK_HIRAGANA:
return "HIRAGANA";
case KeyEvent.VK_FULL_WIDTH:
return "FULL_WIDTH";
case KeyEvent.VK_HALF_WIDTH:
return "HALF_WIDTH";
case KeyEvent.VK_ROMAN_CHARACTERS:
return "ROMAN_CHARACTERS";
case KeyEvent.VK_ALL_CANDIDATES:
return "ALL_CANDIDATES";
case KeyEvent.VK_PREVIOUS_CANDIDATE:
return "PREVIOUS_CANDIDATE";
case KeyEvent.VK_CODE_INPUT:
return "CODE_INPUT";
case KeyEvent.VK_JAPANESE_KATAKANA:
return "JAPANESE_KATAKANA";
case KeyEvent.VK_JAPANESE_HIRAGANA:
return "JAPANESE_HIRAGANA";
case KeyEvent.VK_JAPANESE_ROMAN:
return "JAPANESE_ROMAN";
case KeyEvent.VK_KANA_LOCK:
return "KANA_LOCK";
case KeyEvent.VK_INPUT_METHOD_ON_OFF:
return "INPUT_METHOD_ON_OFF";
case KeyEvent.VK_AGAIN:
return "AGAIN";
case KeyEvent.VK_UNDO:
return "UNDO";
case KeyEvent.VK_COPY:
return "COPY";
case KeyEvent.VK_PASTE:
return "PASTE";
case KeyEvent.VK_CUT:
return "CUT";
case KeyEvent.VK_FIND:
return "FIND";
case KeyEvent.VK_PROPS:
return "PROPS";
case KeyEvent.VK_STOP:
return "STOP";
case KeyEvent.VK_COMPOSE:
return "COMPOSE";
case KeyEvent.VK_ALT_GRAPH:
return "ALT_GRAPH";
}
if (keyCode >= KeyEvent.VK_NUMPAD0 && keyCode <= KeyEvent.VK_NUMPAD9) {
char c = (char) (keyCode - KeyEvent.VK_NUMPAD0 + '0');
return "NUMPAD" + c;
}
return "unknown(0x" + Integer.toString(keyCode, 16) + ")";
}
/**
* Converts the first Character of a String to its Uppercase Instance<br>
* test -> Test
* @param word
* @return String, with first char uppercased
*/
public static String makeFirstWordCaptial(String word) {
if (word.length() < 2) {
return word;
}
String firstWord = word.substring(0, 1);
String restOfWord = word.substring(1);
return firstWord.toUpperCase() + restOfWord;
}
/**
* Modifies Wildcards such as <b>%random%</b>,<b>%system%</b>,
* <b>%version%</b>,<b>%time%</b> into what they represent
* <p>
* for properties see System.getProperties()
*
* @param resource
* String to modify
* @return modified String
* @author wolf.posdorfer
*/
public static String modifyWildcards(String resource) {
if(resource==null)
return "";
resource = resource.replace("%random%",
"" + Math.round((Math.random() * 1000)));
resource = resource.replace("%system%", System.getProperty("os.name")
.replace(" ", ""));
resource = resource.replace("%version%",
System.getProperty("os.version").replace(" ", ""));
final String DATE_FORMAT_NOW = "HH:mm";
Calendar cal = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT_NOW);
resource = resource.replace("%time%", sdf.format(cal.getTime()));
while (resource.contains("%property{")) {
if (resource.contains("%property{") && resource.contains("}/%")) {
int indexofbeginning = resource.indexOf("%property{");
int indexofending = resource.indexOf("}/%");
String begin = resource.substring(0, indexofbeginning);
String middle = System.getProperty(resource.substring(
indexofbeginning+10, indexofending));
String end = resource.substring(indexofending + 3);
resource = begin + middle + end;
}
}
return resource;
}
/**
* Creates an MD5 Checksum of a File, given the Filepath
* @param filepath
* @return md5 checksum
* @throws IOException
* @throws NoSuchAlgorithmException
* @throws Exception
*/
public static String getMD5Checksum(String filepath) throws NoSuchAlgorithmException, IOException {
byte[] b = createChecksum(filepath);
String result = "";
for (int i = 0; i < b.length; i++) {
result += Integer.toString((b[i] & 0xff) + 0x100, 16).substring(1);
}
return result;
}
/**
* creates an MD5 checksum of a File, given the Filepath
* @param filename
* @return byte[] md5 sum
* @throws NoSuchAlgorithmException
* @throws IOException
* @throws Exception
*/
public static byte[] createChecksum(String filename) throws NoSuchAlgorithmException, IOException {
InputStream fis = new FileInputStream(filename);
byte[] buffer = new byte[1024];
MessageDigest complete = MessageDigest.getInstance("MD5");
int numRead;
do {
numRead = fis.read(buffer);
if (numRead > 0) {
complete.update(buffer, 0, numRead);
}
} while (numRead != -1);
fis.close();
return complete.digest();
}
/**
* Counts the Number of Occurences of a specified char c in string
*
* @param string
* @param c
* @return {@link Integer}
*/
public static int countNumberOfOccurences(String string, char c) {
int result = 0;
for (int i = 0; i < string.length(); i++) {
if (string.charAt(i) == c)
result++;
}
return result;
}
}