Java tutorial
/** * This file is part of PaxmlCore. * * PaxmlCore is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * PaxmlCore is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with PaxmlCore. If not, see <http://www.gnu.org/licenses/>. */ package org.paxml.el; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.lang.reflect.Array; import java.math.BigDecimal; import java.net.ServerSocket; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.Enumeration; import java.util.GregorianCalendar; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.regex.Pattern; import javax.swing.JFrame; import javax.swing.JOptionPane; import javax.swing.JPasswordField; import javax.xml.bind.DatatypeConverter; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.time.DateUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.paxml.annotation.Util; import org.paxml.core.Context; import org.paxml.core.IEntity; import org.paxml.core.InMemoryResource; import org.paxml.core.PaxmlResource; import org.paxml.core.PaxmlRuntimeException; import org.paxml.launch.Paxml; import org.paxml.security.Secret; import org.paxml.tag.AbstractTag; import org.paxml.util.ReflectUtils; /** * The default util functions. * * @author Xuetao Niu * */ @Util("util") public class UtilFunctions implements IUtilFunctionsFactory { private static final Log log = LogFactory.getLog(UtilFunctions.class); /** * {@inheritDoc} */ @Override public Object getUtilFunctions(Context context) { return this; } /** * {@inheritDoc} */ @Override public Class<?> getXpathUtilFunctions(Context context) { return XpathFunctions.class; } /** * Merge a list of objects into one list. * * @param objs * if an object is a Collection, all its' elements will be used, * not the Collection itself. * @return the list , never null */ public static List list(Object... objs) { if (objs.length == 1 && !(objs[0] instanceof Map)) { List r = new ArrayList(); ReflectUtils.collect(objs[0], r, true); return r; } return new ArrayList(Arrays.asList(objs)); } /** * Compose a map with keys and values. * * @param keysAndValues * each key and value pair should be given consecutively. * @return the map */ public static Map map(Object... keysAndValues) { if (keysAndValues.length % 2 != 0) { throw new PaxmlRuntimeException("Keys and values should be pairs"); } Map map = new LinkedHashMap(); for (int i = 0; i < keysAndValues.length - 1; i += 2) { map.put(keysAndValues[i], keysAndValues[i + 1]); } return map; } /** * Get the apache commons collection utils. * * @return the utils object */ public static CollectionUtils getCollection() { return new CollectionUtils(); } /** * Get the Math utils. * * @return the utils object */ public static Math getMath() { return ReflectUtils.createObject(Math.class); } /** * Select xpath objects. @see Context.xpathSelect(xpath, alwaysList) * * @param xpath * xpath * @param alwaysList * always list * @return the object */ public static Object xpathSelect(String xpath, boolean alwaysList) { return Context.getCurrentContext().xpathSelect(null, xpath, alwaysList); } /** * Select xpath objects. @see Context.xpathSelect(xpath) * * @param xpath * xpath * * @return the object */ public static Object xpathSelect(String xpath) { return Context.getCurrentContext().xpathSelect(null, xpath); } /** * Select xpath objects. @see Context.xpathSelect(from, xpath, alwaysList) * * @param from * from object * @param xpath * xpath * @param alwaysList * always list * @return the object */ public static Object xpathSelectFrom(Object from, String xpath, boolean alwaysList) { return Context.getCurrentContext().xpathSelect(from, xpath, alwaysList); } /** * Select xpath objects. @see Context.xpathSelect(from, xpath) * * @param from * from object * @param xpath * xpath * * @return the object */ public static Object xpathSelectFrom(Object from, String xpath) { return Context.getCurrentContext().xpathSelect(from, xpath); } /** * Check if an id exists in current context. * * @param id * the id * @param searchParent * true to search the parent context, false not to. * @return true if exists, false if not. */ public static boolean hasConst(String id, boolean searchParent) { return Context.getCurrentContext().hasConstId(id, searchParent); } /** * Get a copy of const ids for the current thread context. * * @return the copy */ public static Set<String> getConstIds() { return new HashSet<String>(Context.getCurrentContext().getConstIds()); } /** * Get a value with id from current context. NB, this will not cause * exception if the id doesn't exist! * * @param id * the id * @param searchParent * true to search the parent context, false not to. * @return true the value or null if not found. */ public static Object getConst(String id, boolean searchParent) { return Context.getCurrentContext().getConst(id, searchParent); } /** * Set a const in context. * * @param id * the const id * @param value * the const * @param top * true to set on root context, false to set on its own context * @return the existing const if any. */ public static Object setConst(String id, Object value, boolean top) { Context context = Context.getCurrentContext(); context = top ? context.getRootContext() : context.getCurrentEntityContext(); return context.setConst(id, value == null ? null : value.getClass().getName(), value, true); } /** * Set const in caller's context. * * @param id * the const id * @param value * the const value * @return the existing const in caller's const, null if no existing const. */ public static Object setConstForCaller(String id, Object value) { Context context = Context.getCurrentContext(); context = context.findCallerContext(); if (context == null) { throw new PaxmlRuntimeException("The current file has no caller!"); } return context.setConst(id, value == null ? null : value.getClass().getName(), value, true); } /** * Select values by class name. * * @param className * the class name * @param inheritance * true to also include objects whose parent class matches the * given name, false to do exact name match. * @param excludesParentContext * true not to search in parent contexts, false to search in * parent contexts. * @param mergeWithParentContext * this parameter only has effect when searching from parent * contexts. true to merge the values from parent context, false * to overrule values from parent upon identical id. * @return a list of values, never null * @throws Exception * any Exception */ public static List<Object> classSelect(String className, boolean inheritance, boolean excludesParentContext, boolean mergeWithParentContext) throws Exception { Context context = Context.getCurrentContext(); List<Object> list = new ArrayList<Object>(0); Map<String, Object> map = excludesParentContext ? context.getIdConstsMap() : context.getIdMap(mergeWithParentContext, true); if (inheritance) { Class clazz = Class.forName(className); for (Object value : map.values()) { if (clazz.isInstance(value)) { list.add(value); } } } else { for (Object value : map.values()) { if (value != null && value.getClass().getName().equals(className)) { list.add(value); } } } return list; } /** * Create a random number between two double bounds. * * @param low * the low bound * @param high * the high bound * @return the random number */ public static double random(double low, double high) { if (low == high) { return low; } else if (low > high) { double tmp = low; low = high; high = tmp; } double range = high - low; return low + Math.random() * range; } /** * Create a random number between two long bounds. * * @param low * the low bound * @param high * the high bound * @return the random number */ public static long random(long low, long high) { return Math.round(random(low + 0.0, high)); } /** * Get the current system time. * * @return the system time in ms. */ public static long getSystemTime() { return System.currentTimeMillis(); } /** * Call a static method. If not found, exception will be thrown. * * @param className * the class name * @param method * the method name * @param args * the args name * @return the method return value. * */ public static Object callStaticMethod(String className, String method, Object[] args) { return ReflectUtils.callStaticMethod(className, method, args); } /** * Call a static method. If not found, exception will be thrown. * * @param className * the class name * @param method * the method name * * @return the method return value. * */ public static Object callStaticMethod(String className, String method) { return ReflectUtils.callStaticMethod(className, method, null); } /** * Call a method on an object. * * @param obj * the method owner * @param method * the method name * * @return the return value of the method call */ public static Object callMethod(Object obj, String method) { return ReflectUtils.callMethod(obj, method, null); } /** * Call a method on an object. * * @param obj * the method owner * @param method * the method name * @param args * the args * @return the return value of the method call */ public static Object callMethod(Object obj, String method, Object[] args) { return ReflectUtils.callMethod(obj, method, args); } /** * Check if an object's string value equals to any item's string value in a * collection. * * @param value * the object * @param collection * the collection * @return true if yes, false no */ public static boolean in(Object value, Collection collection) { if (value == null) { return false; } value = value.toString(); for (Object item : collection) { if (String.valueOf(item).equals(value)) { return true; } } return false; } /** * Break a string to parts. * * @param str * the string * @param delimiters * delimiters applicable for StringTokenizer. If null given, * ", \r\n\f\t" will be used. * @return the order set containing the parts */ public static Set<String> breakString(String str, String delimiters) { return AbstractTag.parseDelimitedString(str, delimiters); } /** * Load a class from class name. * * @param clazz * the class name * @return the loaded class, never null */ public static Class loadClass(String clazz) { return ReflectUtils.loadClassStrict(clazz, null); } /** * Quote a pattern literal. * * @param literal * the literal * @return the quoted literal to be used in pattern */ public static String quotePattern(String literal) { return Pattern.quote(literal); } /** * Get today. * * @return today */ public static Date today() { return DateUtils.truncate(new Date(), Calendar.DATE); } /** * Count how many elements is in the given * list/map/iterator/enumeration/array. * * @param obj * list/map/iterator/enumeration/array * @return number of elements */ public static int count(Object obj) { if (obj == null) { return 0; } else if (obj instanceof Collection || obj instanceof Map || obj instanceof Iterator || obj instanceof Enumeration || obj.getClass().isArray()) { return CollectionUtils.size(obj); } else if (obj instanceof Iterable) { return count(((Iterable) obj).iterator()); } else { return 1; } } /** * Call a tag. * * @param name * the tag name * @param args * the arguments map * @return the result */ public static Object call(String name, Map<String, Object> args) { final Context context = Context.getCurrentContext(); final IEntity tag = context.getPaxml().getEntity(name); if (tag == null) { throw new PaxmlRuntimeException("No tag defined as: " + name); } final Context subContext = new Context(context); subContext.setAsCurrentThreadContext(); try { if (args != null) { for (Map.Entry<String, Object> entry : args.entrySet()) { String key = entry.getKey(); Object value = entry.getValue(); subContext.addConst(key, key, value, false); } } return tag.execute(subContext); } finally { context.setAsCurrentThreadContext(); } } /** * Make a string from ascii code. * * @param ascii * ascii codes * @return the string */ public static String makeString(byte... ascii) { StringBuilder sb = new StringBuilder(); for (byte a : ascii) { sb.append((char) a); } return sb.toString(); } /** * Get the caller's paxml resource. * * @return the resource */ public static PaxmlResource getCallerResource() { return Context.getCurrentContext().findCallerEntity().getResource(); } /** * Get the current paxml resource. * * @return the resource */ public static PaxmlResource getCurrentyResource() { return Context.getCurrentContext().getCurrentEntity().getResource(); } /* * public static ITag getCurrentTag() { return * Context.getCurrentContext().getCurrentTag(); } * * public static IpaxmlEntity getCurrentEntity() { return * Context.getCurrentContext().getCurrentEntity(); } * * public static void addpaxmlResource(String[] pathWithPrefixs) { for * (String p : pathWithPrefixs) { * Context.getCurrentContext().getpaxml().addResources * (paxmlResource.createFromPath(p)); } } * * public static void addpaxmlTagLibrary(String[] classNames) { for (String * cn : classNames) { Class<? extends ITagLibrary> clazz = (Class<? extends * ITagLibrary>) ReflectUtils.loadClassStrict(cn, null); * Context.getCurrentContext().getpaxml().addTagLibrary(clazz); } } * * public static void addpaxmlListener(String[] classNames) throws Exception * { paxml paxml = Context.getCurrentContext().getpaxml(); for (String cn : * classNames) { * * Class<?> clazz = ReflectUtils.loadClassStrict(cn, null); if * (ReflectUtils.isImplementingClass(clazz, IpaxmlExecutionListener.class, * true)) { paxml.addpaxmlExecutionListener(((Class<? extends * IpaxmlExecutionListener>) clazz).newInstance()); } else if * (ReflectUtils.isImplementingClass(clazz, IEntityExecutionListener.class, * true)) { paxml.addEntityExecutionListener(((Class<? extends * IEntityExecutionListener>) clazz).newInstance()); } else if * (ReflectUtils.isImplementingClass(clazz, ITagExecutionListener.class, * true)) { paxml.addTagExecutionListener(((Class<? extends * ITagExecutionListener>) clazz).newInstance()); } else { throw new * paxmlRuntimeException("Unknown listener type: " + clazz.getName()); } } } */ /** * Run a random paxml xml string. * * @param paxml * the paxml xml string * @return the execution result */ public static Object runPaxml(String paxml) { if (StringUtils.isBlank(paxml)) { return null; } paxml = "<scenario>" + paxml.trim() + "</scenario>"; Context context = Context.getCurrentContext(); Paxml _paxml = context.getPaxml(); IEntity entity = _paxml.getParser().parse(new InMemoryResource(paxml), true, null); return _paxml.execute(entity, context, false, false); } /** * Check if a tag name is callable. * * @param tagName * the name of the tag * @return true callable, false not */ public static boolean isCallable(String tagName) { return null != Context.getCurrentContext().getPaxml().getResourceLocator().getResource(tagName); } /** * Find const id by given value. * * @param obj * the given value * @param strict * true to do pointer comparison, false to do object equality * comparison * @param searchParent * true to look also in parent contexts, false only look in the * current context * @param excludes * ids to ignore * @return the id or null if no found. */ public static String findConstIdExcept(Object obj, boolean strict, boolean searchParent, String[] excludes) { return Context.getCurrentContext().getParent().findConstId(obj, strict, searchParent, excludes == null ? new String[] {} : excludes); } /** * Find const id by given value. * * @param obj * the given value * @param strict * true to do pointer comparison, false to do object equality * comparison * @param searchParent * true to look also in parent contexts, false only look in the * current context * * @return the id or null if no found. */ public static String findConstId(Object obj, boolean strict, boolean searchParent) { return findConstIdExcept(obj, strict, searchParent, null); } /** * Find const ids by given value collection. * * @param col * the value collection * @param strict * true to do pointer comparison, false to do object equality * comparison * @param searchParent * searchParent true to look also in parent contexts, false only * look in the current context * @return a list of ids corresponding to each element in the given * collection. Not found values will return null id in the list. */ public static List<String> findConstIds(Collection col, boolean strict, boolean searchParent) { List<String> ids = new ArrayList<String>(); for (Object obj : col) { ids.add(findConstId(obj, strict, searchParent)); } return ids; } /** * Check if an object is empty. An object is empty if it is either of the * following case: - null - empty string - empty collection - empty map - * empty array. * * @param obj * the object to examine * @return true empty, false not */ public static boolean isEmpty(Object obj) { if (obj == null) { return true; } else if (obj instanceof String) { return ((String) obj).isEmpty(); } else if (obj instanceof Collection) { return ((Collection) obj).isEmpty(); } else if (obj instanceof Map) { return ((Map) obj).isEmpty(); } else if (obj.getClass().isArray()) { return 0 == Array.getLength(obj); } return false; } /** * Check if a value is logically equivalent to true, where the check logic * is like javascript boolean syntax. * * @param obj * the value * @return */ public static boolean yes(Object obj) { if (obj == null) { return false; } if (obj instanceof Number) { if (0 == new BigDecimal(((Number) obj).toString()).compareTo(new BigDecimal(0))) { return false; } } else if (obj instanceof Collection) { if (((Collection) obj).isEmpty()) { return false; } } else if (obj instanceof Map) { if (((Map) obj).isEmpty()) { return false; } } else if (obj.getClass().isArray()) { if (0 == Array.getLength(obj)) { return false; } } final String str = String.valueOf(obj); if ("".equals(str) || "false".equals(str) || "null".equals(str)) { return false; } return true; } /** * The opposite of yes. * * @param obj * @return */ public static boolean no(Object obj) { return !yes(obj); } /** * Get the current process id. * * @return the pid */ public static long getProcessId() { return Context.getCurrentContext().getProcessId(); } /** * Get the 1st non-empty object. * * @param any * all candidates * @return the 1st non-empty object, or null if none found. */ public static Object any(Object... any) { for (Object obj : any) { if (obj != null && StringUtils.isNotEmpty(obj.toString())) { return obj; } } return null; } /** * Formats a String by replacing the {[0-9]+} placeholder. * * @param formattedString * - String that needs to be formatted with pattern * "string {0} and {1}". * @param stringReplaceables * . an array formating parameters. * @return the formatted String. */ public static String formatString(String formattedString, String[] stringReplaceables) { int i = 0; for (String replaceable : stringReplaceables) { String regexPattern = "\\{" + i + "\\}"; formattedString = formattedString.replaceAll(regexPattern, replaceable); i++; } return formattedString; } /** * Print date/time into xml format. * * @param cal * the calendar or date that represents the datetime. If null * given, it will take the current system time. * @param includeTime * true to include time part, false exclude time part * @return the xml standard date/time string */ public static String printXmlDateTime(Object cal, boolean includeTime) { Calendar c = null; if (cal == null) { c = new GregorianCalendar(); } else if (cal instanceof Calendar) { c = (Calendar) cal; } else if (cal instanceof Date) { c = new GregorianCalendar(); c.setTime((Date) cal); } else { throw new PaxmlRuntimeException( "Unsupported date time of type " + cal.getClass().getName() + ": " + cal); } return includeTime ? DatatypeConverter.printDateTime(c) : DatatypeConverter.printDate(c); } /** * Parse the standard xml date time. * * @param str * the date/time string * @return the calendar obj */ public static Calendar parseXmlDateTime(String str) { return DatatypeConverter.parseDateTime(str); } public static String transform(String template, Object obj) { return null; } public static Secret getSecret(String name) { return Context.getCurrentContext().getSecret(name); } public static void setSecret(String name, String value) { Context.getCurrentContext().setSecret(name, value); } public static String ask(String question, boolean mask) { class DummyFrame extends JFrame { DummyFrame(String title) { super(title); setUndecorated(true); setVisible(true); setLocationRelativeTo(null); } } JPasswordField pf = new JPasswordField(); DummyFrame frame = new DummyFrame(question); int okCxl = JOptionPane.showConfirmDialog(frame, pf, question, JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE); frame.setVisible(false); if (okCxl == JOptionPane.OK_OPTION) { return new String(pf.getPassword()); } return null; } public static List sort(Collection list) { return sort(list, true); } public static List sort(Collection list, boolean asc) { List li = new ArrayList(list); if (asc) { Collections.sort(li); } else { Collections.reverse(li); } return li; } public static Object compress(Collection col) { switch (col.size()) { case 0: return null; case 1: return col.iterator().next(); } return col; } public static List collect(Object... objs) { List list = new ArrayList(); for (Object obj : objs) { ReflectUtils.collect(obj, list, true); } return list; } public static Object compactCollect(Object... objs) { return compress(collect(objs)); } public static boolean confirm(String... args) { String msg; if (args.length == 0) { msg = "Do you want to contibue?"; } else { msg = args[0]; } String[] yes; if (args.length > 1) { yes = new String[args.length - 1]; System.arraycopy(args, 1, yes, 0, yes.length); } else { yes = new String[] { "y", "yes" }; msg += " (y/n)"; } System.out.println(msg); BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); String line; try { line = reader.readLine(); } catch (IOException e) { throw new PaxmlRuntimeException("Cannot read from console", e); } for (String y : yes) { if (y.trim().equalsIgnoreCase(line.trim())) { return true; } } return false; } public static void exit() { Context.getCurrentContext().getStack().exit(); } /** * Get a random available port. * @return the port, or minus if no available port found */ public static int getRandomPort() { ServerSocket s = null; try { s = new ServerSocket(0); return s.getLocalPort(); } catch (IOException e) { log.warn("Cannot get random port", e); return -1; } finally { try { if (s != null) { s.close(); } } catch (Exception e) { log.warn("Cannot close server socket of port: " + s.getLocalPort(), e); } } } }