Java tutorial
/* * Copyright 2004 Senunkan Shinryuu * * 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.latticesoft.util.common; import java.lang.NoSuchMethodException; import java.lang.IllegalAccessException; import java.lang.reflect.InvocationTargetException; import java.text.DecimalFormat; import java.text.SimpleDateFormat; import java.util.*; import java.io.*; import java.sql.Timestamp; import java.net.URL; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.commons.beanutils.MethodUtils; import org.apache.commons.beanutils.WrapDynaBean; import org.apache.commons.digester.Digester; import org.apache.commons.digester.xmlrules.DigesterLoader; import org.apache.commons.jexl.JexlHelper; import org.apache.commons.jexl.JexlContext; import org.apache.commons.jexl.Expression; import org.apache.commons.jexl.ExpressionFactory; import org.apache.commons.beanutils.*; import org.xml.sax.SAXException; import org.apache.xml.resolver.tools.CatalogResolver; public final class MiscUtil { private static final Log log = LogFactory.getLog(MiscUtil.class); private static final boolean USE_JEXL = false; public static final String START = "${"; public static final String END = "}"; private MiscUtil() { } /** * Return a submap of properties based a key. * @param map the map object to extract from. * @param groupKey the key to extract the sub map. * @return the sub map of values */ public static Map getSubMap(String groupKey, Map map) { return getSubMap(groupKey, map, false); } /** * Return a submap of properties based a key. * @param map the map object to extract from. * @param groupKey the key to extract the sub map. * @param remove it true it will remove from the original map * @return the sub map of values */ public static Map getSubMap(String groupKey, Map map, boolean remove) { Map retVal = new HashMap(); if (groupKey == null) return retVal; if (map == null) return retVal; Iterator iter = map.keySet().iterator(); ArrayList a = new ArrayList(); while (iter.hasNext()) { String key = (String) iter.next(); if (key == null) continue; int length = groupKey.length(); if (length >= key.length()) { if (log.isDebugEnabled()) { log.debug("key: " + key + " - key length less than GroupKey: continue"); } continue; } else { if (log.isDebugEnabled()) { log.debug("key: " + key); } } if (key.startsWith(groupKey)) { String s = ""; Object value = map.get(key); if (value instanceof String) { s = (String) value; if (s.indexOf(MiscUtil.START) > -1 && s.indexOf(MiscUtil.END) > -1) { value = MiscUtil.resolve(map, START + key + END); } if (value == null) { value = map.get(key); } } char c = key.charAt(length); if (c == '.' || c == '|' || c == '/' || c == '-' || c == '*' || c == '#' || c == '!' || c == '$') { s = key.substring(length + 1, key.length()); } else { s = key.substring(length, key.length()); } retVal.put(s, value); } if (remove) { a.add(key); } } if (log.isDebugEnabled()) { log.debug("====="); } for (int i = 0; i < a.size(); i++) { if (log.isDebugEnabled()) { log.debug("Removing entry from map:" + a.get(i)); } map.remove(a.get(i)); } return retVal; } /** * Get a sublist from a key, the order is in the order of the keys. * @param key the sublist key * @param map the map to extract from * @return the list sort according to the key */ public static List getSubList(String key, Map map) { if (key == null) { return new ArrayList(); } List l = new ArrayList(); Map subMap = MiscUtil.getSubMap(key, map); List keyList = new ArrayList(); keyList.addAll(subMap.keySet()); Collections.sort(keyList); for (int i = 0; i < keyList.size(); i++) { Object o = subMap.get(keyList.get(i)); if (o != null) { l.add(o); } } return l; } /** * Reads a String value from map. * @param map the source map to read the value from. * @param key the key to get the value from. * @param defaultValue assign default value if the value is read is null * @return the value read. */ public static String readString(Map map, String key, String defaultValue) { if (map == null) { if (log.isErrorEnabled()) { log.error("Map is null."); } return null; } if (key == null) { if (log.isErrorEnabled()) { log.error("Key is null"); } return null; } Object o = map.get(key); if (o == null) { if (log.isDebugEnabled()) { log.debug("Assigning default value"); log.debug("Value is null: " + o); } return defaultValue; } if (!(o instanceof String)) { if (log.isErrorEnabled()) { log.error("Value is not a string: " + o); } if (log.isDebugEnabled()) { log.debug("Assigning default value"); } return defaultValue; } return (String) o; } /** * Adds the element to the bean. The bean must implement the * addElement(<ClassName> bean) method where <ClassName> * is the name of the class. * @param bean the Bean to add to. * @param map where the objects reside * @param attributeName attribute name to get the objects * @throws java.lang.NoSuchMethodException * @throws java.lang.IllegalAccessException * @throws java.lang.reflect.InvocationTargetException */ public static void addElement(Object bean, Map map, String attributeName, int startIndex) throws NoSuchMethodException, IllegalAccessException, java.lang.reflect.InvocationTargetException { Object o = null; if (attributeName == null || map == null || bean == null) { if (log.isErrorEnabled()) { log.error("Null Input"); } return; } int index = startIndex; do { o = map.get(attributeName + index); if (log.isDebugEnabled()) { log.debug("Object:" + o); } index++; try { if (o != null) { String methodName = "add"; MethodUtils.invokeMethod(bean, methodName, o); } } catch (NoSuchMethodException nsme) { if (log.isErrorEnabled()) { log.error("NoSuchMethodException", nsme); } throw nsme; } catch (IllegalAccessException iae) { if (log.isErrorEnabled()) { log.error("IllegalAccessException", iae); } throw iae; } catch (InvocationTargetException ite) { if (log.isErrorEnabled()) { log.error("InvocationTargetException", ite); } throw ite; } catch (Exception e) { if (log.isErrorEnabled()) { log.error("Exception", e); } } } while (o != null); } /** * Builds an hierarchy of object(s) from a rule xml file and * a input xml file. The objects are created using digester * library. Default is no catalog resolver * @param rules the digester rules inputstream * @param input the input xml file to be parsed * @return the object created * @see Apache Digester library java doc */ public static Object buildObjectFromXml(URL rules, InputStream input) { return MiscUtil.buildObjectFromXml(rules, input, false); } /** * Builds an hierarchy of object(s) from a rule xml file and * a input xml file. The objects are created using digester * library. * @param rules the digester rules inputstream * @param input the input xml file to be parsed * @param useCatalogResolver whether to use the catalog resolver or not * @return the object created * @see Apache Digester library java doc */ public static Object buildObjectFromXml(URL rules, InputStream input, boolean useCatalogResolver) { Object retVal = null; try { Digester d = DigesterLoader.createDigester(rules); if (useCatalogResolver) { CatalogResolver cr = new CatalogResolver(); d.setEntityResolver(cr); } /*d.setValidating(true); d.setNamespaceAware(true); d.setProperty("http://java.sun.com/xml/jaxp/properties/schemaLanguage", "http://www.w3.org/2001/XMLSchema"); d.setErrorHandler(new org.xml.sax.ErrorHandler() { });//*/ retVal = d.parse(input); } catch (IOException ioe) { if (log.isErrorEnabled()) { log.error("Error!", ioe); } } catch (SAXException saxe) { if (log.isErrorEnabled()) { log.error("Error!", saxe); } } catch (Exception e) { if (log.isErrorEnabled()) { log.error("Error!", e); } } return retVal; } /** * Builds an hierarchy of object(s) from a rule xml file and * a input xml file. The objects are created using digester * library. * @param rules the digester rules inputstream * @param input the input xml file to be parsed * @return the object created * @see Apache Digester library java doc */ public static Object buildObjectFromXml(File rules, File input) { return MiscUtil.buildObjectFromXml(rules, input, false); } /** * Builds an hierarchy of object(s) from a rule xml file and * a input xml file. The objects are created using digester * library. * @param rules the digester rules inputstream * @param input the input xml file to be parsed * @param useCatalogResolver whether to use the catalog resolver or not * @return the object created * @see Apache Digester library java doc */ public static Object buildObjectFromXml(File rules, File input, boolean useCatalogResolver) { Object retVal = null; try { retVal = MiscUtil.buildObjectFromXml(rules.toURI().toURL(), new FileInputStream(input), useCatalogResolver); } catch (Exception e) { if (log.isErrorEnabled()) { log.error("Error!", e); } } return retVal; } /** * Builds an hierarchy of object(s) from a rule xml file and * a input xml file. The objects are created using digester * library. * @param rules the digester rules file name * @param input the input xml file to be parsed * @return the object created * @see Apache Digester library java doc */ public static Object buildObjectFromXml(String rules, String input) { return MiscUtil.buildObjectFromXml(rules, input, false); } /** * Builds an hierarchy of object(s) from a rule xml file and * a input xml file. The objects are created using digester * library. * @param rules the digester rules file name * @param input the input xml file to be parsed * @param useCatalogResolver whether to use the catalog resolver or not * @return the object created * @see Apache Digester library java doc */ public static Object buildObjectFromXml(String rules, String input, boolean useCatalogResolver) { File inputFile = new File(input); File rulesFile = new File(rules); Object retVal = null; try { retVal = MiscUtil.buildObjectFromXml(rulesFile.toURI().toURL(), new FileInputStream(inputFile), useCatalogResolver); } catch (Exception e) { if (log.isErrorEnabled()) { log.error("Error!", e); } } return retVal; } /** * Resolves the key into the object which is represented by the * variable in the key. * Resolving could broadly classify into 2 stages, resolving the * values representing the key into the final key string and * retrieving the values mapped by the final key string. Assumes * the variable is quoted by this form: ${variable} * <pre> * public class TestBean { * private String name; * private String message; * public String getName() { return this.name; } * public String getMessage() { return this.message; } * public void setName(String name) { this.name = name; } * public void setMessage(String message) { this.message = message; } * public String sayHello() { return "Hello there " + name; } * public String sayHello2(String extra) { return "Hello There " + name + " :\"" + extra + ".\""; } * } * // --------------------------- * HashMap map = new HashMap(); * Object o = null; * TestBean bean = new TestBean(); * bean.setName("John"); * bean.setMessage("Hello World"); * Double doubleArray[] = new Double[4]; * doubleArray[0] = new Double(12.3); * doubleArray[1] = new Double(45.6); * doubleArray[2] = new Double(78.9); * doubleArray[3] = new Double(101112.0); * String s[] = {"hello", "world", "how", "are", "you"}; * * map.put("myRedirect", "${myInt}"); * map.put("myString", "Value1"); * map.put("myString2", "Value2"); * map.put("myInt", new Integer(999)); * map.put("myIndex", new Integer(2)); * map.put("myBean", bean); * map.put("myArray", doubleArray); * map.put("a", "${b}"); * map.put("b", "${c}"); * map.put("c", "${a}"); // recursive setup * map.put("myStringArray", s); * map.put("myRedirect2", "${myStringArray}"); * * // retrieving plaing variables ${variable} * o = MiscUtil.resolve(map, "${myString}", "DefaultValue", "${", "}"); * System.out.println(o); // "Value1" will be printed * o = MiscUtil.resolve(map, "${myInt}", "DefaultValue", "${", "}"); * System.out.println(o); // "999" will be printed * * // retrieving variable attributes ${variable.attribute} * o = MiscUtil.resolve(map, "${myBean.name}", "DefaultValue", "${", "}"); * System.out.println(o); // "John" will be printed * * // retrieving variable method ${variable.method()} * // NB: the variable method should not have any input parameter * o = MiscUtil.resolve(map, "${myBean.sayHello()}", "DefaultValue", "${", "}"); * System.out.println(o); // "Hello There John" will be printed * * // retrieving indexed variable ${variable[index]} * // NB: the variable method should not have any input parameter * o = MiscUtil.resolve(map, "${myArray[2]}", "DefaultValue", "${", "}"); * System.out.println(o); // "78.9" will be printed * * // retrieving redirected variable ${variable} * o = MiscUtil.resolve(map, "${myRedirect}", "DefaultValue", "${", "}"); * System.out.println(o); // "999" will be printed as the Integer Object is returned. * * // retrieve partial key variable keyname${variable} * o = MiscUtil.resolve(map, "myString${index}", "DefaultValue", "${", "}"); * System.out.println(o); // "myString2" will be printed instead of * * // nested variable ${variable${nestedVariable}} * o = MiscUtil.resolve(map, "${myString${index}}", "DefaultValue", "${", "}"); * System.out.println(o); // "DefaultValue" will be printed because it is not resolved * * // more than 1 variable ${variable1}${variable2} * o = MiscUtil.resolve(map, "${myString}${myString2}${myInt}${myBean.sayHello()}", "${", "}"); * System.out.println(o); // "Value1Value2999Hello There John" will be printed * * // plain string without variable * o = MiscUtil.resolve(map, "test", "DefaultValue", "${", "}"); * System.out.println(o); // "DefaultValue" will be printed * * // plain object * o = MiscUtil.resolve(map, new Integer(1), "DefaultValue", "${", "}"); * System.out.println(o); // "DefaultValue" will be printed * * // cyclic recursive * o = MiscUtil.resolve(map, "${a}", "DefaultValue", "${", "}"); * System.out.println("DefaultValue==" + o); // "DefaultValue" will be printed * * // multi reference * o = MiscUtil.resolve(map, "${myStringArray[1].length()}", "DefaultValue", "${", "}"); * System.out.println(s[1].length() + "==" + o); // "5" will be printed * o = MiscUtil.resolve(map, "${myArray[3].toString().length()}", "DefaultValue", "${", "}"); * System.out.println(doubleArray[3].toString().length() + "==" + o); // "8" will be printed * </pre> * </p> * * @param map the map which contain all the values * @param key the key object (in most of the case it is a string) * @param paramStart starting string "${" in this case. * @param paramEnd ending string "}" in this case. * @param defaultValue the default value if the key is not found in the map. * @param isObjectFirst parses object 1st before plain string * @param useJEXL use JEXL to resolve the expression (for mathematical) * @return the resolved object. The defaultValue will be returned if any * of the input is invalid. */ public static Object resolve(Map map, Object key, Object defaultValue, String paramStart, String paramEnd, boolean isObjectFirst, boolean useJexl) { // the hashset is to prevent cyclic reference return MiscUtil.resolve(new HashSet(), map, key, defaultValue, paramStart, paramEnd, isObjectFirst, useJexl); } /** @see #resolve */ public static Object resolve(Map map, Object key, Object defaultValue, String paramStart, String paramEnd, boolean isObjectFirst) { // the hashset is to prevent cyclic reference return MiscUtil.resolve(map, key, defaultValue, paramStart, paramEnd, isObjectFirst, true); } /** @see #resolve */ public static Object resolve(Map map, Object key, Object defaultValue, String paramStart, String paramEnd) { return MiscUtil.resolve(map, key, defaultValue, paramStart, paramEnd, false); } /** @see #resolve */ public static Object resolve(Map map, Object key, Object defaultValue) { return MiscUtil.resolve(map, key, defaultValue, MiscUtil.START, MiscUtil.END, false); } /** @see #resolve */ public static Object resolve(Map map, Object key) { return MiscUtil.resolve(map, key, null, MiscUtil.START, MiscUtil.END, false); } /** * Caters for cyclic recursive entry * @see MiscUtil#resolve */ private static Object resolve(HashSet set, Map map, Object key, Object defaultValue, String paramStart, String paramEnd, boolean isObjectFirst, boolean useJexl) { if (log.isDebugEnabled()) { log.debug("===== resolve() ====="); } if (set == null || map == null || key == null || paramStart == null || paramEnd == null) { if (log.isErrorEnabled()) { log.error("set : " + set); log.error("map : " + map); log.error("key : " + key); log.error("start : " + paramStart); log.error("end : " + paramEnd); log.error("Input is invalid"); } return defaultValue; } // check that key is a string. If not it's just // normal map lookup operation if (!(key instanceof String)) { Object o = map.get(key); if (o == null) return defaultValue; else return o; } // get the key in string form. String sKey = (String) key; if (log.isDebugEnabled()) { log.debug("sKey: " + sKey); } // key string is zero length or does not contain variable // if it does not contain variable mark e.g. ${var} // then its just normal lookup operation if (sKey.length() <= 0 || sKey.indexOf(paramStart) < 0 || sKey.indexOf(paramEnd) < 0) { Object o = map.get(key); if (o == null) return defaultValue; else return o; } // extract all the variables in the key Collection c = StringUtil.extractParameter(sKey, paramStart, paramEnd); if (log.isDebugEnabled()) { log.debug("ParamSize: " + c.size()); } Object retVal = null; if (c.size() == 0) { // no valid variable found if (log.isDebugEnabled()) { log.debug("No param to extract"); } return defaultValue; } else if (c.size() == 1) { // one parameter to extract String s = (String) c.iterator().next(); Object o = null; if (useJexl) { o = MiscUtil.getParameterJexl(map, s, isObjectFirst); } else { o = MiscUtil.getParameter(map, s, isObjectFirst); } if (sKey.length() == (paramStart + s + paramEnd).length()) { // if the key contains only the variable // e.g. ${var} retVal = o; } else { // if the key contains variable and other string // e.g. haha${var} String replaceKey = paramStart + s + paramEnd; String replaceValue = null; if (o != null) { replaceValue = o.toString(); } if (replaceValue == null) { // add a check if the defaultValue is same as key we // we use a blank string instead this is to prevent // cyclic resolution if (defaultValue != null && defaultValue.equals(key)) { defaultValue = ""; } replaceValue = (defaultValue != null) ? defaultValue.toString() : ""; } StringBuffer sb = new StringBuffer(sKey); StringUtil.replace(sb, replaceKey, replaceValue, true); retVal = sb.toString(); } } else { // more than 1 parameter => end result is a string StringBuffer sb = new StringBuffer(sKey); Iterator iter = c.iterator(); String s = null; Object o = null; while (iter.hasNext()) { s = (String) iter.next(); if (s != null) { if (USE_JEXL) { o = MiscUtil.getParameterJexl(map, s, isObjectFirst); } else { o = MiscUtil.getParameter(map, s, isObjectFirst); } String replaceKey = paramStart + s + paramEnd; String replaceValue = null; if (o != null) { replaceValue = o.toString(); } if (replaceValue == null) { // add a check if the defaultValue is same as key we // we use a blank string instead this is to prevent // cyclic resolution if (defaultValue != null && defaultValue.equals(key)) { defaultValue = ""; } replaceValue = (defaultValue != null) ? defaultValue.toString() : ""; } if (replaceKey != null && replaceValue != null) { StringUtil.replace(sb, replaceKey, replaceValue, true); } } } retVal = sb.toString(); } // check that the retVal does not contain any variable. // if it does then it calls itself again to resolve the variable if (retVal instanceof String) { String s = (String) retVal; if (s.length() > 0 && s.indexOf(paramStart) > -1 && s.indexOf(paramEnd) > -1) { if (!set.contains(retVal)) { set.add(retVal); retVal = MiscUtil.resolve(set, map, retVal, defaultValue, paramStart, paramEnd, isObjectFirst, useJexl); } else { // cyclic recursive retVal = defaultValue; } } } return retVal; } /** * Get the actual value held in the map using JEXL * @param map the source map * @param param the string parameter * @return the parameter object */ private static Object getParameterJexl(Map map, String expression, boolean isObjectFirst) { Object retVal = null; try { JexlContext jc = JexlHelper.createContext(); jc.getVars().putAll(map); Expression ex = ExpressionFactory.createExpression(expression); retVal = ex.evaluate(jc); } catch (Exception e) { if (log.isErrorEnabled()) { log.error(e); } retVal = expression; } return retVal; } /** * Get the actual value held in the map * @param map the source map * @param param the string parameter * @return the parameter object */ private static Object getParameter(Map map, String param, boolean isObjectFirst) { if (param == null) { if (log.isErrorEnabled()) { log.error("Param is null"); } return null; } Collection c = StringUtil.tokenize(param, "."); if (log.isDebugEnabled()) { log.debug("ElementSizeInParam: " + c.size()); } if (c == null || c.size() == 0) { Object o = map.get(param); if (log.isDebugEnabled()) { log.debug("Can't tokeneise - " + o); } return o; } Object o = null; if (!isObjectFirst) { if (log.isDebugEnabled()) { log.debug("Object evaluated last"); } for (int i = c.size() - 1; i >= 0; i--) { if (log.isDebugEnabled()) { log.debug("[" + i + "]"); } Collection cSrc = combineCollectionElement(c, i); o = evaluateExpression(map, cSrc, isObjectFirst); if (o != null) { if (log.isDebugEnabled()) { log.debug("Object Not Null ending loop: " + o); } break; } } } else { if (log.isDebugEnabled()) { log.debug("Object evaluated first"); } for (int i = 0; i < c.size() - 1; i++) { if (log.isDebugEnabled()) { log.debug("[" + i + "]"); } Collection cSrc = combineCollectionElement(c, i); o = evaluateExpression(map, cSrc, isObjectFirst); if (o != null) { if (log.isDebugEnabled()) { log.debug("Object Not Null ending loop: " + o); } break; } } } return o; } /** * Combines the elements in the collection. * @param c the collection * @param size the size to combine. If the positive the algorithm is * from 1st element to last element. the number is the number of elements * to combine. */ public static Collection combineCollectionElement(Collection c, int size) { if (c.size() == 1) { return c; } ArrayList src = null; ArrayList retVal = new ArrayList(); if (c instanceof ArrayList) { src = (ArrayList) c; } else { src = new ArrayList(); src.addAll(c); } StringBuffer sb = new StringBuffer(); if (size > 0) { int start = 0; int end = start + Math.abs(size) + 1; for (int i = start; i < end; i++) { sb.append(src.get(i)).append("."); } sb.deleteCharAt(sb.length() - 1); retVal.add(sb.toString()); for (int i = end; i < src.size(); i++) { retVal.add(src.get(i)); } } else { int start = src.size() - 1; int end = start - Math.abs(size); for (int i = end; i <= start; i++) { sb.append(src.get(i)).append("."); } sb.deleteCharAt(sb.length() - 1); // add to retVal; retVal.add(sb.toString()); for (int i = end - 1; i >= 0; i--) { retVal.add(src.get(i)); } Collections.reverse(retVal); } if (log.isDebugEnabled()) { log.debug("Combined: " + retVal); } return retVal; } /** * <p>Evaluates the expression. * There are 3 instance of the element combination. * The method will loop throught the collection of elements. * With each loop the element is evaluated. The element can * be either of the the below: * <ol> * <li>It is an attribute: previousObject.currentAttribute</li> * <li>It is an method invocation: previousObject.method()</li> * <li>It is an array index: previousObject.arrayIndex[index]</li> * </ol> * However, the first element must be an object. * </p> * @param map the map to be processed * @param c the collection of elements */ private static Object evaluateExpression(Map map, Collection c, boolean isObjectFirst) { // evaluate the expression Iterator iter = c.iterator(); String s = null; Object o = null; // check for size if (c.size() == 0) { return null; } while (iter.hasNext()) { s = (String) iter.next(); if (log.isDebugEnabled()) { log.debug("ElementName: " + s); } int idxSqOpen = s.indexOf("["); int idxSqClose = s.indexOf("]"); int idxRndOpen = s.indexOf("("); int idxRndClose = s.indexOf(")"); boolean isArray = idxSqOpen >= 0 && idxSqClose >= 0 && idxSqOpen < idxSqClose && idxRndOpen < 0 && idxRndOpen < 0; boolean isMethod = idxRndOpen >= 0 && idxRndClose >= 0 && idxRndOpen < idxRndClose && idxSqOpen < 0 && idxSqClose < 0; boolean isOthers = !isArray && !isMethod; if (isArray) { Object oTemp = MiscUtil.evaluateArrayElement(map, o, s, isObjectFirst, idxSqOpen, idxSqClose); if (oTemp == null) { break; } else { o = oTemp; } } else if (isMethod) { Object oTemp = MiscUtil.evaluateMethodElement(map, o, s, isObjectFirst, idxRndOpen, idxRndClose); if (oTemp == null) { break; } else { o = oTemp; } } else if (isOthers) { Object oTemp = MiscUtil.evaluateOthersElement(map, o, s, isObjectFirst); if (oTemp == null) { break; } else { o = oTemp; } } // else if (o == null) break; } // while return o; } /** * Evaluate an array element */ private static Object evaluateArrayElement(Map map, Object currentObject, String elementName, boolean isObjectFirst, int idxOpen, int idxClose) { if (log.isDebugEnabled()) { log.debug("<<isArrayElement>>"); } Object o = null; // Check if element is an array element[] Collection cIndex = StringUtil.extractParameter(elementName, "[", "]"); if (cIndex == null || cIndex.size() == 0) { if (log.isDebugEnabled()) { log.debug("No index for array" + elementName); } return null; } // should have only one index and it must be an integer String sIndex = (String) cIndex.iterator().next(); int index = -1; try { index = Integer.parseInt(sIndex); } catch (Exception e) { index = -1; } if (log.isDebugEnabled()) { log.debug("Index: " + index); } // check for invalid index if (index < 0) { if (log.isDebugEnabled()) { log.debug("Invalid index: " + sIndex); } return null; } // valid index we try to check if the element // element is an array. String key = elementName.substring(0, idxOpen); if (log.isDebugEnabled()) { log.debug("Key: " + key); } o = map.get(key); Object oArray[] = null; if (o instanceof Object[]) { oArray = (Object[]) o; if (oArray != null && index >= 0 && index < oArray.length) { o = oArray[index]; } } return o; } /** * Evaluate an method element */ private static Object evaluateMethodElement(Map map, Object currentObject, String elementName, boolean isObjectFirst, int idxOpen, int idxClose) { if (log.isDebugEnabled()) { log.debug("<<isMethodInvocation>>"); } // element is an method invoccation element() // invoke via method // 1) no argument is defined in the method e.g. method() // 2) exactly one argument is defined. e.g. method(args) // the argument will be resolved using getParameter. // no direct string is supported. // 3) multi args separated by commas. e.g. method(arg1, args2) // current not implemented if (currentObject == null) { // 1st element have to retrieve from map currentObject = map.get(elementName); } String methodName = elementName.substring(0, idxOpen); String argsString = elementName.substring(idxOpen + 1, idxClose); if (log.isDebugEnabled()) { log.debug("args: [" + argsString + "]"); log.debug("methodName: " + methodName); log.debug("object: [" + currentObject + "]"); } try { Object args = null; if (argsString.length() > 0) { args = MiscUtil.getParameter(map, argsString, isObjectFirst); if (log.isDebugEnabled()) { log.debug("args: " + args + " " + args.getClass().getName()); } currentObject = MethodUtils.invokeMethod(currentObject, methodName, args); } else { currentObject = MethodUtils.invokeMethod(currentObject, methodName, null); } } catch (Exception e) { if (log.isDebugEnabled()) { log.debug(e); } // if the first element is an method invocation // an error will occur } return currentObject; } /** * Evaluate others element */ private static Object evaluateOthersElement(Map map, Object currentObject, String elementName, boolean isObjectFirst) { if (log.isDebugEnabled()) { log.debug("<<isOthers>>"); } // from map directly or attribute // element is an attribute // previousElement.currentAttribute if (currentObject == null) { // 1st element have to retrieve from map currentObject = map.get(elementName); } else { // not the 1st element if (currentObject instanceof Map) { Map m = (Map) currentObject; currentObject = m.get(elementName); } else { try { WrapDynaBean bean = new WrapDynaBean(currentObject); currentObject = bean.get(elementName); } catch (Exception e) { // if it is not an attribute an occur will occur // note that the attribute must have a getter method if (log.isDebugEnabled()) { log.debug(e); } } } // if } return currentObject; } public static void populateObject(Object o, Map map) { try { BeanUtils.populate(o, map); } catch (Exception e) { if (log.isErrorEnabled()) { log.error("", e); } } } public static int getParamCount(Object o, String paramStart, String paramEnd) { int size = 0; if (o instanceof String) { String s = (String) o; Collection c = StringUtil.extractParameter(s, "${", "}"); size = c.size(); } return size; } public static int getParamCount(Object o) { return getParamCount(o, "${", "}"); } public static void extractDifference(List l1, List l2, List in1not2, List in2not1, List inBothFrom1, List inBothFrom2, Comparator c) { int index1 = 0; int index2 = 0; Object o1 = null; Object o2 = null; String curr1 = null; String curr2 = null; String next1 = null; String next2 = null; boolean add1 = false; boolean add2 = false; int compare = 0; // 1st the 2 list must be sorted if (c == null) { Collections.sort(l1); Collections.sort(l2); } else { Collections.sort(l1, c); Collections.sort(l2, c); } // then we loop thru the list while (index1 < (l1.size() - 1) && index2 < (l2.size() - 1)) { o1 = l1.get(index1); o2 = l2.get(index2); if (o1 == null) { index1++; continue; } if (o2 == null) { index2++; continue; } curr1 = o1.toString(); curr2 = o2.toString(); compare = curr1.compareTo(curr2); if (compare == 0) { index1++; index2++; add1 = true; add2 = true; } else if (compare > 0) { // curr1 is bigger than curr2 if (index2 + 1 < l2.size()) { next2 = (String) l2.get(index2 + 1); compare = curr2.compareTo(next2); if (compare > 0) { // check that if the next element of a2 is still // less than the current element of a1 then we will // add the curr2 element add2 = true; add1 = false; } else { // if the next element of a2 is same as or bigger // then current element of a1 we will add curr2 in2not1.add(curr2); add2 = false; add1 = false; } } index2++; } else if (compare < 0) { if (index1 + 1 < l1.size()) { // check that if the next element of a1 is still // less than the current element then we will add the // curr2 element next1 = (String) l1.get(index1 + 1); compare = next1.compareTo(curr2); if (compare < 0) { add1 = true; add2 = false; } else { // if the next element of a1 is same as or bigger // then current element of a2 we will add curr1 in1not2.add(curr1); add2 = false; add1 = false; } } index1++; } if (add1 && add2) { inBothFrom1.add(o1); inBothFrom2.add(o2); } else { if (add1) { in1not2.add(o1); } if (add2) { in2not1.add(o2); } } } // we reach the end of list 2 but not the end of list 1 // or list 2 does nto contain any element // add all the rest of the l1 to collection if (index2 == l2.size() - 1 || l2.size() == 0) { curr2 = null; curr1 = null; o1 = null; o2 = null; if (l2.size() > 0) { o2 = l2.get(l2.size() - 1); curr2 = o2.toString(); for (int i = index1; i < l1.size(); i++) { o1 = l1.get(i); curr1 = o1.toString(); compare = curr1.compareTo(curr2); if (compare == 0) { inBothFrom1.add(o1); } else { in1not2.add(o1); } } // check that last element is not inside the rest of the list boolean addLastElement = true; if (curr2 != null) { for (int i = index1; i < l1.size(); i++) { o1 = l1.get(i); curr1 = o1.toString(); compare = curr1.compareTo(curr2); if (compare == 0) { addLastElement = false; break; } } } if (addLastElement) { in2not1.add(o2); } else { inBothFrom2.add(o2); } } else { // since l2 size is zero we just add l1's element for (int i = index1; i < l1.size(); i++) { o1 = l1.get(i); in1not2.add(o1); } } } // we reach the end of list 1 but not the end of list 2 // or list 1 does nto contain any element // add all the rest of the l2 to collection if ((index1 == l1.size() - 1 && index2 != l2.size() - 1) || l1.size() == 0) { curr2 = null; curr1 = null; o1 = null; o2 = null; if (l1.size() > 0) { o1 = l1.get(l1.size() - 1); curr1 = o1.toString(); for (int i = index2; i < l2.size(); i++) { o2 = l2.get(i); curr2 = o2.toString(); compare = curr1.compareTo(curr2); if (compare == 0) { inBothFrom2.add(o2); } else { in2not1.add(o2); } } // check that last element is not inside the rest of the list boolean addLastElement = true; if (curr1 != null) { for (int i = index2; i < l2.size(); i++) { o2 = l2.get(i); curr2 = o2.toString(); compare = curr2.compareTo(curr1); if (compare == 0) { addLastElement = false; break; } } } if (addLastElement) { in1not2.add(o1); } else { inBothFrom1.add(o1); } } else { for (int i = index2; i < l2.size(); i++) { o2 = l2.get(i); in2not1.add(o2); } } } } /** * Flattens a collections of collection. The new list would be a * collection containing all the collection inside the original * collection * @param collection a parent collection contain child collection * @return the flattened collection */ public static Collection flatten(Collection c) { Collection retVal = new ArrayList(); MiscUtil.getListChild(c, retVal); return retVal; } /** * Get the list of child collections from a parent collection * It is a reentrant method * @param theParent the parent collection * @param c the output collection */ private static void getListChild(Collection theParent, Collection c) { c.add(theParent); if (theParent.size() > 0) { Iterator iter = theParent.iterator(); while (iter.hasNext()) { Object iterObj = iter.next(); if (iterObj != null && iterObj instanceof Collection) { Collection theChild = (Collection) iterObj; MiscUtil.getListChild(theChild, c); } } } } /** * Sets the proxy for internet connection * @param proxyHost the host of the proxy server * @param the port of the proxy server */ public static void setProxy(String proxyHost, int proxyPort) { MiscUtil.setProxy(proxyHost, "" + proxyPort); } /** * Sets the proxy for internet connection * @param proxyHost the host of the proxy server * @param the port of the proxy server */ public static void setProxy(String proxyHost, String proxyPort) { System.getProperties().put("proxySet", "true"); System.getProperties().put("proxyHost", proxyHost); System.getProperties().put("proxyPort", proxyPort); } /** * Generates a random alpha numeric string according to the format. * X: upper case letters * x: lower case letters * n: numeric numbers * @param format the format of the random string */ public static String getRandomString(String format) { int maxSleep = 500 + NumeralUtil.getRandomInt(200) + NumeralUtil.getRandomInt(1000); return getRandomString(format, maxSleep); } /** * Generates a random alpha numeric string according to the format. * X: upper case letters * x: lower case letters * n: numeric numbers * @param format the format of the random string * @param maxSleep the randomness seed of the sleep */ public static String getRandomString(String format, int maxSleep) { char c = ' '; if (format == null || format.length() == 0) { return ""; } StringBuffer sb = new StringBuffer(); int theChar = 0; String s = null; for (int i = 0; i < format.length(); i++) { c = format.charAt(i); s = " "; if (c == 'X' || c == 'A') { theChar = 10 + (NumeralUtil.getRandomInt(26 * 5000) % 26); c = Character.forDigit(theChar, Character.MAX_RADIX); s = "" + Character.toUpperCase(c); sb.append(s); } else if (c == 'x' || c == 'a') { theChar = 10 + (NumeralUtil.getRandomInt(26 * 5000) % 26); c = Character.forDigit(theChar, Character.MAX_RADIX); s = "" + Character.toLowerCase(c); sb.append(s); } else if (c == 'n' || c == 'N' || c == '0') { s = "" + (NumeralUtil.getRandomInt(5000) % 10); sb.append(s); } else if (c == 'y' || c == 'Y') { char c1 = ' '; StringBuffer sb2 = new StringBuffer(); for (int j = i; j < format.length(); j++) { c1 = format.charAt(j); if (c1 == 'y' || c1 == 'Y') { sb2.append(c1); } else { break; } } int size = sb2.length(); Timestamp ts = DateUtil.getCurrentTimestamp(); if (size == 2 || size == 4) { sb.append(DateUtil.formatDate(sb2.toString(), ts)); } else { sb.append(sb2.toString()); } i += size - 1; } else if (c == 'M') { char c1 = ' '; StringBuffer sb2 = new StringBuffer(); for (int j = i; j < format.length(); j++) { c1 = format.charAt(j); if (c1 == 'M') { sb2.append(c1); } else { break; } } int size = sb2.length(); Timestamp ts = DateUtil.getCurrentTimestamp(); if (size == 2 || size == 3) { sb.append(DateUtil.formatDate(sb2.toString(), ts)); } else { sb.append(sb2.toString()); } i += size - 1; } else if (c == 'd') { char c1 = ' '; StringBuffer sb2 = new StringBuffer(); for (int j = i; j < format.length(); j++) { c1 = format.charAt(j); if (c1 == 'd') { sb2.append(c1); } else { break; } } int size = sb2.length(); Timestamp ts = DateUtil.getCurrentTimestamp(); if (size == 2) { sb.append(DateUtil.formatDate(sb2.toString(), ts)); } else { sb.append(sb2.toString()); } i += size - 1; } else if (c == 'H') { char c1 = ' '; StringBuffer sb2 = new StringBuffer(); for (int j = i; j < format.length(); j++) { c1 = format.charAt(j); if (c1 == 'H') { sb2.append(c1); } else { break; } } int size = sb2.length(); Timestamp ts = DateUtil.getCurrentTimestamp(); if (size == 2) { sb.append(DateUtil.formatDate(sb2.toString(), ts)); } else { sb.append(sb2.toString()); } i += size - 1; } else if (c == 'm') { char c1 = ' '; StringBuffer sb2 = new StringBuffer(); for (int j = i; j < format.length(); j++) { c1 = format.charAt(j); if (c1 == 'm') { sb2.append(c1); } else { break; } } int size = sb2.length(); Timestamp ts = DateUtil.getCurrentTimestamp(); if (size == 2) { sb.append(DateUtil.formatDate(sb2.toString(), ts)); } else { sb.append(sb2.toString()); } i += size - 1; } else if (c == 's') { char c1 = ' '; StringBuffer sb2 = new StringBuffer(); for (int j = i; j < format.length(); j++) { c1 = format.charAt(j); if (c1 == 's') { sb2.append(c1); } else { break; } } int size = sb2.length(); Timestamp ts = DateUtil.getCurrentTimestamp(); if (size == 2) { sb.append(DateUtil.formatDate(sb2.toString(), ts)); } else { sb.append(sb2.toString()); } i += size - 1; } else if (c == 'S') { char c1 = ' '; StringBuffer sb2 = new StringBuffer(); for (int j = i; j < format.length(); j++) { c1 = format.charAt(j); if (c1 == 'S') { sb2.append(c1); } else { break; } } int size = sb2.length(); Timestamp ts = DateUtil.getCurrentTimestamp(); if (size == 3) { sb.append(DateUtil.formatDate(sb2.toString(), ts)); } else { sb.append(sb2.toString()); } i += size - 1; } else { s = "" + c; sb.append(s); } ThreadUtil.randomSleep(maxSleep); } return sb.toString(); } public static String getSysId() { StringBuffer sb = new StringBuffer(); try { SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss"); DecimalFormat df = new DecimalFormat("000000"); Random rnd = new Random(System.currentTimeMillis()); int theInt = rnd.nextInt(999999); String s = sdf.format(new Timestamp(System.currentTimeMillis())); sb.append(s); s = df.format(theInt); sb.append(s); } catch (Exception e) { } try { Thread.sleep(15); } catch (Exception e) { } return sb.toString(); } /* public static void main(String args[]){ Collection c = new ArrayList(); c.add("hello"); c.add("world"); System.out.println(MiscUtil.combineCollectionElement(c, 1)); System.out.println(MiscUtil.combineCollectionElement(c, -1)); c.add("there"); System.out.println(MiscUtil.combineCollectionElement(c, 1)); System.out.println(MiscUtil.combineCollectionElement(c, -1)); System.out.println(MiscUtil.combineCollectionElement(c, 2)); System.out.println(MiscUtil.combineCollectionElement(c, -2)); c.add("haha"); System.out.println(MiscUtil.combineCollectionElement(c, 1)); System.out.println(MiscUtil.combineCollectionElement(c, -1)); System.out.println(MiscUtil.combineCollectionElement(c, 2)); System.out.println(MiscUtil.combineCollectionElement(c, -2)); System.out.println(MiscUtil.combineCollectionElement(c, 3)); System.out.println(MiscUtil.combineCollectionElement(c, -3)); } //*/ public static void main(String args[]) { /* // To run this test you will need // a TestBean which is a normal javabean with // 2 attributes: name and message. // The package setting for the TestBean // is to ensure that it will work regardless of // any package. HashMap map = new HashMap(); Object o = null; TestBean bean = new TestBean(); bean.setName("John"); bean.setMessage("Hello World"); Double doubleArray[] = new Double[4]; doubleArray[0] = new Double(12.3); doubleArray[1] = new Double(45.6); doubleArray[2] = new Double(78.9); doubleArray[3] = new Double(101112.0); String s[] = {"hello", "world", "how", "are", "you"}; map.put("myRedirect", "${myInt}"); map.put("myString", "Value1"); map.put("myString2", "Value2"); map.put("myInt", new Integer(999)); map.put("myIndex", new Integer(2)); map.put("myBean", bean); map.put("myArray", doubleArray); map.put("a", "${b}"); map.put("b", "${c}"); map.put("c", "${a}"); // recursive setup map.put("myStringArray", s); map.put("myRedirect2", "${myStringArray}"); map.put("testDir3", "${testDir2}/3"); map.put("testDir", "C:/Temp"); map.put("testDir1", "${testDir}/1"); map.put("testDir2", "${testDir1}/2"); map.put("myBean.name.toString()", "I am the one"); int size = 20; Object[] test = new Object[size]; String[] refr = new String[size]; int testOne = -1; test[0] = "${myString}"; refr[0] = (String)map.get("myString"); test[1] = "${myInt}"; refr[1] = "" + map.get("myInt"); test[2] = "${myBean.name}"; refr[2] = "" + bean.getName(); test[3] = "${myBean.sayHello()}"; refr[3] = "" + bean.sayHello(); test[4] = "${myArray[2]}"; refr[4] = "" + doubleArray[2]; test[5] = "${myRedirect}"; refr[5] = "999"; test[6] = "myString${myIndex}"; refr[6] = "myString2"; test[7] = "${myString${myIndex}}"; refr[7] = "DefaultValue"; test[8] = "${myString}${myString2}${myInt}${myBean.sayHello()}"; refr[8] = "Value1Value2999Hello There John"; test[9] = "test"; refr[9] = "DefaultValue"; test[10] = new Integer(1); refr[10] = "DefaultValue"; test[11] = "${a}"; refr[11] = "DefaultValue"; test[12] = "${myStringArray[1].length()}"; refr[12] = "" + s[1].length(); test[13] = "${myArray[3].toString().length()}"; refr[13] = "" + doubleArray[3].toString().length(); test[14] = "${testDir3}"; refr[14] = "C:/Temp/1/2/3"; //test[15] = "${testDot.attribute.value}"; test[15] = "${myBean.name.toString()}"; refr[15] = "" + bean.getName().toString(); test[16] = "${myBean.sayHello2(myString)}"; refr[16] = "" + bean.sayHello2("Value1"); test[17] = "${3+2+1}"; refr[17] = "" + (3+2+1); test[18] = "${3+4*2}"; refr[18] = "" + (3+4*2); test[19] = "${myInt + myIndex}"; refr[19] = "" + (((Integer)map.get("myInt")).intValue() + ((Integer)map.get("myIndex")).intValue()); Iterator iter = map.entrySet().iterator(); while (iter.hasNext()) { java.util.Map.Entry entry = (java.util.Map.Entry)iter.next(); System.out.print("["); System.out.print(entry.getKey()); System.out.print("] == ["); System.out.print(entry.getValue()); System.out.print("] "); if (entry.getValue() != null) { System.out.print(" ["); System.out.print(entry.getValue().getClass().getName()); System.out.print("]"); } System.out.println(""); } System.out.println("===================="); for (int i=0; i<test.length; i++) { if (testOne < 0 || testOne == (i+1)) { o = MiscUtil.resolve(map, test[i], "DefaultValue", "${", "}"); if (o == null) { continue; } System.out.print("["); if (i+1<10) System.out.print("0"); System.out.print((i+1) + "/" + test.length + "] ["); System.out.print((o.toString().equals(refr[i]))?"passed":"failed"); System.out.print("] { "); System.out.print(refr[i]); System.out.print(" == "); System.out.print(o); System.out.print(" } "); System.out.print(" ["); System.out.print(test[i]); System.out.println("]"); } } System.out.println("===================="); System.out.println("Checking evaluting object 1st or whole parameter 1st"); o = MiscUtil.resolve(map, "${myBean.name.toString()}", "DefaultValue", "${", "}", true); System.out.print(o); System.out.print(" <> "); o = MiscUtil.resolve(map, "${myBean.name.toString()}", "DefaultValue", "${", "}", false); System.out.println(o); //*/ /* Map map = new HashMap(); String s = "This is a test of ${var} null."; System.out.println(MiscUtil.resolve(map, s, "*")); System.out.println(MiscUtil.resolve(map, s, s)); s = "This is a test of ${var} null. ${var2}"; System.out.println(MiscUtil.resolve(map, s, "*")); System.out.println(MiscUtil.resolve(map, s, s)); System.out.println("A:" + Character.getNumericValue('A')); System.out.println("Z:" + Character.getNumericValue('Z')); System.out.println("a:" + Character.getNumericValue('a')); System.out.println("z:" + Character.getNumericValue('z')); System.out.println(Character.forDigit(10, Character.MAX_RADIX)); System.out.println(Character.forDigit(35, Character.MAX_RADIX)); System.out.println("=========="); System.out.println(MiscUtil.getRandomString("XXXxxxnnnn")); for (int i=0; i<10; i++) { System.out.println(MiscUtil.getRandomString("yyyyMMddHHmmssnnnnnn")); }//*/ for (int i = 0; i < 100; i++) { System.out.println(MiscUtil.getSysId()); } } }