You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flex.apache.org by cd...@apache.org on 2017/04/16 22:32:33 UTC
[42/72] [abbrv] [partial] flex-blazeds git commit: - Major code scrub
http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/8315f8fa/common/src/main/java/flex/messaging/log/LineFormattedTarget.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/flex/messaging/log/LineFormattedTarget.java b/common/src/main/java/flex/messaging/log/LineFormattedTarget.java
new file mode 100644
index 0000000..1864bb0
--- /dev/null
+++ b/common/src/main/java/flex/messaging/log/LineFormattedTarget.java
@@ -0,0 +1,286 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 flex.messaging.log;
+
+import flex.messaging.config.ConfigMap;
+import flex.messaging.util.ExceptionUtil;
+import flex.messaging.util.StringUtils;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+/**
+ *
+ */
+public class LineFormattedTarget extends AbstractTarget
+{
+ /**
+ * Indicates if the date should be added to the trace.
+ */
+ protected boolean includeDate;
+
+ /**
+ * Indicates if the time should be added to the trace.
+ */
+ protected boolean includeTime;
+
+ /**
+ * Indicates if the level for the event should added to the trace.
+ */
+ protected boolean includeLevel;
+
+ /**
+ * Indicates if the category for this target should added to the trace.
+ */
+ protected boolean includeCategory;
+
+ /**
+ * A prefix to prepend onto each logged message.
+ */
+ protected String prefix = null;
+
+ /**
+ * The formatter to write the date as part of the logging statement.
+ * Defaults to MM/dd/yyyy format.
+ */
+ protected DateFormat dateFormater = new SimpleDateFormat("MM/dd/yyyy");
+
+ /**
+ * The formatter to write the time as part of the logging statement.
+ * Defaults to HH:mm:ss.SSS format.
+ */
+ protected DateFormat timeFormatter = new SimpleDateFormat("HH:mm:ss.SSS");
+
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Default constructor.
+ */
+ public LineFormattedTarget()
+ {
+ super();
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Initialize, validate, start, and stop methods.
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Initializes the target with id and properties. Subclasses can overwrite.
+ *
+ * @param id id for the target which is ignored.
+ * @param properties ConfigMap of properties for the target.
+ */
+ public void initialize(String id, ConfigMap properties)
+ {
+ super.initialize(id, properties);
+
+ includeTime = properties.getPropertyAsBoolean("includeTime", false);
+ includeDate = properties.getPropertyAsBoolean("includeDate", false);
+ includeCategory = properties.getPropertyAsBoolean("includeCategory", false);
+ includeLevel = properties.getPropertyAsBoolean("includeLevel", false);
+ prefix = properties.getPropertyAsString("prefix", null);
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Public Getters and Setters for AbstractService properties
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Returns includeCategory property.
+ *
+ * @return <code>true</code> if category is included; <code>false</code> otherwise.
+ */
+ public boolean isIncludeCategory()
+ {
+ return includeCategory;
+ }
+
+ /**
+ * Sets includeCategory property.
+ *
+ * @param includeCategory the include category
+ */
+ public void setIncludeCategory(boolean includeCategory)
+ {
+ this.includeCategory = includeCategory;
+ }
+
+ /**
+ * Returns includeDate property.
+ *
+ * @return <code>true</code> if date is included; <code>false</code> otherwise.
+ */
+ public boolean isIncludeDate()
+ {
+ return includeDate;
+ }
+
+ /**
+ * Sets includeDate property.
+ *
+ * @param includeDate the include date
+ */
+ public void setIncludeDate(boolean includeDate)
+ {
+ this.includeDate = includeDate;
+ }
+
+ /**
+ * Returns includeLevel property.
+ *
+ * @return <code>true</code> if level is included; <code>false</code> otherwise.
+ */
+ public boolean isIncludeLevel()
+ {
+ return includeLevel;
+ }
+
+ /**
+ * Sets includeLevel property.
+ *
+ * @param includeLevel the include level
+ */
+ public void setIncludeLevel(boolean includeLevel)
+ {
+ this.includeLevel = includeLevel;
+ }
+
+ /**
+ * Returns includeTime property.
+ *
+ * @return <code>true</code> if time is included; <code>false</code> otherwise.
+ */
+ public boolean isIncludeTime()
+ {
+ return includeTime;
+ }
+
+ /**
+ * Sets includeTime property.
+ *
+ * @param includeTime the include time
+ */
+ public void setIncludeTime(boolean includeTime)
+ {
+ this.includeTime = includeTime;
+ }
+
+ /**
+ * Returns prefix property.
+ *
+ * @return The prefix for log messages.
+ */
+ public String getPrefix()
+ {
+ return prefix;
+ }
+
+ /**
+ * Sets prefix property.
+ *
+ * @param prefix the prefix string
+ */
+ public void setPrefix(String prefix)
+ {
+ this.prefix = prefix;
+ }
+
+ /**
+ * This method handles a <code>LogEvent</code> from an associated logger.
+ * A target uses this method to translate the event into the appropriate
+ * format for transmission, storage, or display.
+ * This method will be called only if the event's level is in range of the
+ * target's level.
+ * @param event the log event
+ */
+ public void logEvent(LogEvent event)
+ {
+ String pre = "";
+ if (prefix != null)
+ {
+ pre = prefix + " "; // any space is stripped from config
+ }
+
+ String date = "";
+ if (includeDate || includeTime)
+ {
+ StringBuffer buffer = new StringBuffer();
+ Date d = new Date();
+ if (includeDate)
+ {
+ buffer.append(dateFormater.format(d));
+ buffer.append(" ");
+ }
+ if (includeTime)
+ {
+ buffer.append(timeFormatter.format(d));
+ buffer.append(" ");
+ }
+ date = buffer.toString();
+ }
+
+ String cat = includeCategory ?
+ ("[" + event.logger.getCategory() + "] ") : "";
+ String level = "";
+ if (includeLevel)
+ {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("[");
+ buffer.append(LogEvent.getLevelString(event.level));
+ buffer.append("]");
+ buffer.append(" ");
+ level = buffer.toString();
+ }
+ StringBuffer result = new StringBuffer(pre);
+ result.append(date).append(level).append(cat).append(event.message);
+
+ if (event.throwable != null)
+ result.append(StringUtils.NEWLINE).append(ExceptionUtil.toString(event.throwable));
+
+ internalLog(result.toString());
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Protected/private methods.
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Descendants of this class should override this method to direct the
+ * specified message to the desired output.
+ *
+ * @param message String containing preprocessed log message which may
+ * include time, date, category, etc. based on property settings,
+ * such as <code>includeDate</code>, <code>includeCategory</code>,
+ * etc.
+ */
+ protected void internalLog(String message)
+ {
+ // override this method to perform the redirection to the desired output
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/8315f8fa/common/src/main/java/flex/messaging/log/Log.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/flex/messaging/log/Log.java b/common/src/main/java/flex/messaging/log/Log.java
new file mode 100644
index 0000000..570911a
--- /dev/null
+++ b/common/src/main/java/flex/messaging/log/Log.java
@@ -0,0 +1,708 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 flex.messaging.log;
+
+import flex.messaging.LocalizedException;
+import flex.messaging.config.ConfigMap;
+import flex.messaging.util.PrettyPrinter;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.HashSet;
+
+/**
+ *
+ */
+public class Log
+{
+
+ public static final String INVALID_CHARS = "[]~$^&\\/(){}<>+=`!#%?,:;\'\"@";
+
+ // Errors
+ private static final int INVALID_TARGET = 10013;
+ private static final int INVALID_CATEGORY = 10014;
+ private static final int INVALID_CATEGORY_CHARS = 10015;
+
+ private static Log log;
+ private static PrettyPrinter prettyPrinter;
+ private static String prettyPrinterClass = "flex.messaging.util.BasicPrettyPrinter";
+
+ private static final HashSet excludedProperties = new HashSet();
+ public static final String VALUE_SUPRESSED = "** [Value Suppressed] **";
+
+ private volatile short targetLevel;
+ private final Map loggers;
+ private final List targets;
+ private final Map targetMap;
+ private static final Object staticLock = new Object();
+
+
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Private constructor.
+ */
+ private Log()
+ {
+ targetLevel = LogEvent.NONE;
+ loggers = new HashMap();
+ targets = new ArrayList();
+ targetMap = new LinkedHashMap();
+ }
+
+
+ /**
+ * Creates the log on first access, returns already created log on
+ * subsequent calls.
+ *
+ * @return log.
+ */
+ public static Log createLog()
+ {
+ synchronized (staticLock)
+ {
+ if (log == null)
+ log = new Log();
+
+ return log;
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Initialize, validate, start, and stop methods.
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Initializes Log with id and properties.
+ *
+ * @param id Id for the Log which is ignored, though is used by the ManageableComponent superclass
+ * @param properties ConfigMap of properties for the Log.
+ */
+ public static synchronized void initialize(String id, ConfigMap properties)
+ {
+ String value = properties.getPropertyAsString("pretty-printer", null);
+ if (value != null)
+ prettyPrinterClass = value;
+
+ // Create a HashSet with the properties that we want to exclude from the
+ // list of properties given by 'getPropertiesAsList'
+ ConfigMap excludeMap = properties.getPropertyAsMap("exclude-properties", null);
+ if (excludeMap != null)
+ {
+ if (excludeMap.getPropertyAsList("property", null) != null)
+ excludedProperties.addAll(excludeMap.getPropertyAsList("property", null));
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Public Getters and Setters for Log properties
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Indicates whether a fatal level log event will be processed by a log target.
+ * @return boolean true if it is Fatal level
+ */
+ public static boolean isFatal()
+ {
+ return log == null ? false : log.targetLevel <= LogEvent.FATAL;
+ }
+
+ /**
+ * Indicates whether an error level log event will be processed by a log target.
+ * @return boolean true if it is Error level
+ */
+ public static boolean isError()
+ {
+ return log == null ? false : log.targetLevel <= LogEvent.ERROR;
+ }
+
+ /**
+ * Indicates whether a warn level log event will be processed by a log target.
+ * @return boolean true if it is Warn level
+ */
+ public static boolean isWarn()
+ {
+ return log == null ? false : log.targetLevel <= LogEvent.WARN;
+ }
+
+ /**
+ * Indicates whether an info level log event will be processed by a log target.
+ * @return boolean true if it is Info level
+ */
+ public static boolean isInfo()
+ {
+ return log == null ? false : log.targetLevel <= LogEvent.INFO;
+ }
+
+ /**
+ * Indicates whether a debug level log event will be processed by a log target.
+ * @return boolean true if it is debug level
+ */
+ public static boolean isDebug()
+ {
+ return log == null ? false : log.targetLevel <= LogEvent.DEBUG;
+ }
+
+ /**
+ * Indicates whether a log property should be excluded.
+ * @param property the property to check
+ * @return boolean true if the property should be excluded
+ */
+ public static boolean isExcludedProperty(String property)
+ {
+ return !excludedProperties.isEmpty() && excludedProperties.contains(property);
+ }
+
+
+ /**
+ * Given a category, returns the logger associated with the category.
+ *
+ * @param category Categogry for the logger.
+ * @return Logger associated with the category.
+ */
+ public static Logger getLogger(String category)
+ {
+ if (log != null)
+ return getLogger(log, category);
+
+ // Return a dummy logger?
+ return new Logger(category);
+ }
+
+ /**
+ * @param log base logger.
+ * @param category category to log to.
+ * @return Logger instance for the given category.
+ */
+ public static Logger getLogger(Log log, String category)
+ {
+ checkCategory(category);
+
+ synchronized (staticLock)
+ {
+ Logger result = (Logger) log.loggers.get(category);
+ if (result == null)
+ {
+ result = new Logger(category);
+
+ // Check to see if there are any targets for this logger.
+ for (Iterator iter = log.targets.iterator(); iter.hasNext();)
+ {
+ Target target = (Target) iter.next();
+ if (categoryMatchInFilterList(category, target.getFilters()))
+ target.addLogger(result);
+ }
+
+ log.loggers.put(category, result);
+ }
+ return result;
+ }
+ }
+
+ /**
+ * Returns an unmodifiable snapshot of the targets registered with this Log when the
+ * method is invoked.
+ * @return List the list of targets
+ */
+ public static List getTargets()
+ {
+ if (log != null)
+ {
+ List currentTargets;
+ // Snapshot the current target list (shallow copy) and return it.
+ synchronized (staticLock)
+ {
+ currentTargets = Collections.unmodifiableList(new ArrayList(log.targets));
+ }
+ return currentTargets;
+ }
+ return null;
+ }
+
+ /**
+ * Return the Log's map of targets keyed on their human-readable ids (e.g. ConsoleTarget0, ConsoleTarget1, etc.)
+ * @return Map the target map
+ */
+ public static Map getTargetMap()
+ {
+ if (log != null)
+ {
+ Map currentTargets;
+ synchronized (staticLock)
+ {
+ currentTargets = new LinkedHashMap(log.targetMap);
+ }
+ return currentTargets;
+ }
+ return null;
+ }
+
+ /**
+ * Returns the target associated with the unique ID searchId. Returns null if no
+ * such target exists.
+ * @param searchId the search ID
+ * @return Target the associated target
+ */
+ public static Target getTarget(String searchId)
+ {
+ if (log != null)
+ {
+ synchronized (staticLock)
+ {
+ return (Target) log.targetMap.get(searchId);
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Return the categories for all of the loggers
+ * @return String[] the categories for all of the loggers
+ */
+ public String[] getLoggers()
+ {
+ String[] currentCategories;
+ if (log != null)
+ {
+ synchronized (staticLock)
+ {
+ Object[] currentCategoryObjects = loggers.keySet().toArray();
+ currentCategories = new String[currentCategoryObjects.length];
+ for (int i = 0; i < currentCategoryObjects.length; i++)
+ {
+ currentCategories[i] = (String)(currentCategoryObjects[i]);
+ }
+ }
+ }
+ else
+ {
+ currentCategories = new String[0];
+ }
+
+ return currentCategories;
+ }
+
+ /**
+ * Adds a target to the log.
+ *
+ * @param target Target to be added.
+ */
+ public static void addTarget(Target target)
+ {
+ if (log != null)
+ {
+ if (target != null)
+ {
+ synchronized (staticLock)
+ {
+ List filters = target.getFilters();
+
+ // need to find what filters this target matches and set the specified
+ // target as a listener for that logger.
+ Iterator it = log.loggers.keySet().iterator();
+ while (it.hasNext())
+ {
+ String key = (String) it.next();
+ if (categoryMatchInFilterList(key, filters))
+ target.addLogger((Logger) log.loggers.get(key));
+ }
+ // if we found a match all is good, otherwise we need to
+ // put the target in a waiting queue in the event that a logger
+ // is created that this target cares about.
+ if (!log.targets.contains(target))
+ log.targets.add(target);
+
+ if (!log.targetMap.containsValue(target))
+ {
+ String name = target.getClass().getName();
+
+ if (name.indexOf(".") > -1)
+ {
+ String[] classes = name.split("\\.");
+ name = classes[classes.length - 1];
+ }
+
+ log.targetMap.put(new String(name + log.targetMap.size()), target);
+ }
+
+ // update our global target log level if this target is more verbose.
+ short targetLevel = target.getLevel();
+ if (log.targetLevel == LogEvent.NONE)
+ log.targetLevel = targetLevel;
+ else if (targetLevel < log.targetLevel)
+ {
+ log.targetLevel = targetLevel;
+ }
+ }
+ }
+ else
+ {
+ // Invalid target specified. Target must not be null.
+ LocalizedException ex = new LocalizedException();
+ ex.setMessage(INVALID_TARGET);
+ throw ex;
+ }
+ }
+ }
+
+ /**
+ * Removes a target from the log.
+ *
+ * @param target The target to be removed.
+ */
+ public static void removeTarget(Target target)
+ {
+ if (log != null)
+ {
+ if (target != null)
+ {
+ synchronized (staticLock)
+ {
+ // Remove the target from any associated loggers.
+ List filters = target.getFilters();
+ Iterator it = log.loggers.keySet().iterator();
+ while (it.hasNext())
+ {
+ String key = (String) it.next();
+ if (categoryMatchInFilterList(key, filters))
+ target.removeLogger((Logger) log.loggers.get(key));
+ }
+ // Remove the target from the Log set.
+ log.targets.remove(target);
+ resetTargetLevel();
+ }
+ }
+ else
+ {
+ // Invalid target specified. Target must not be null.
+ LocalizedException ex = new LocalizedException();
+ ex.setMessage(INVALID_TARGET);
+ throw ex;
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Other Public APIs
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * This method removes all of the current loggers and targets from the cache.
+ * and resets target level.
+ */
+ public static synchronized void reset()
+ {
+ flush();
+ }
+
+ /**
+ *
+ */
+ public static void flush()
+ {
+ if (log != null)
+ {
+ log.loggers.clear();
+ log.targets.clear();
+ log.targetLevel = LogEvent.NONE;
+ }
+ }
+
+ /**
+ * @param l string representation of the log level.
+ * @return a short value representing the log level.
+ */
+ public static short readLevel(String l)
+ {
+ short lvl = LogEvent.ERROR;
+ if ((l != null) && (l.length() > 0))
+ {
+ l = l.trim().toLowerCase();
+ char c = l.charAt(0);
+ switch (c)
+ {
+ case 'n':
+ lvl = LogEvent.NONE;
+ break;
+ case 'e':
+ lvl = LogEvent.ERROR;
+ break;
+ case 'w':
+ lvl = LogEvent.WARN;
+ break;
+ case 'i':
+ lvl = LogEvent.INFO;
+ break;
+ case 'd':
+ lvl = LogEvent.DEBUG;
+ break;
+ case 'a':
+ lvl = LogEvent.ALL;
+ break;
+ default:
+ lvl = LogEvent.ERROR;
+ }
+ }
+
+ return lvl;
+ }
+
+ /**
+ *
+ * This method checks the specified string value for illegal characters.
+ *
+ * @param value to check for illegal characters.
+ * The following characters are not valid:
+ * []~$^&\/(){}<>+=`!#%?,:;'"&#64;
+ * @return <code>true</code> if there are any illegal characters found,
+ * <code>false</code> otherwise
+ */
+ public static boolean hasIllegalCharacters(String value)
+ {
+ char[] chars = value.toCharArray();
+ for (int i = 0; i < chars.length; i++)
+ {
+ char c = chars[i];
+ if (INVALID_CHARS.indexOf(c) != -1)
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns the PrettyPrinter used by the Log.
+ *
+ * @return the PrettyPrinter used by the Log.
+ */
+ public static PrettyPrinter getPrettyPrinter()
+ {
+ if (prettyPrinter == null ||
+ !prettyPrinter.getClass().getName().equals(prettyPrinterClass))
+ {
+ try
+ {
+ Class c = Class.forName(prettyPrinterClass);
+ prettyPrinter = (PrettyPrinter)c.newInstance();
+ }
+ catch (Throwable t)
+ {
+ throw new RuntimeException("Error creating instance of default pretty printer.", t);
+ }
+ }
+ return (PrettyPrinter)prettyPrinter.copy();
+ }
+
+ /**
+ * Returns the current target level for the Log.
+ *
+ * @return the current target level for the Log.
+ */
+ public static short getTargetLevel()
+ {
+ return log == null ? LogEvent.NONE : log.targetLevel;
+ }
+
+ /**
+ *
+ * Sets the pretty printer class name used by the log.
+ *
+ * @param value Name of the pretty printer class.
+ */
+ public static void setPrettyPrinterClass(String value)
+ {
+ prettyPrinterClass = value;
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Protected/private methods.
+ //
+ //--------------------------------------------------------------------------
+
+ /* package */ static void resetTargetLevel()
+ {
+ if (log != null)
+ {
+ synchronized (staticLock)
+ {
+ short maxTargetLevel = LogEvent.NONE;
+ for (Iterator iter = log.targets.iterator(); iter.hasNext();)
+ {
+ short targetLevel = ((Target) iter.next()).getLevel();
+ if (maxTargetLevel == LogEvent.NONE || targetLevel < maxTargetLevel)
+ maxTargetLevel = targetLevel;
+ }
+ log.targetLevel = maxTargetLevel;
+ }
+ }
+ }
+
+ /* package */ static void processTargetFilterAdd(Target target, String filter)
+ {
+ if (log != null)
+ {
+ synchronized (staticLock)
+ {
+ List filters = new ArrayList();
+ filters.add(filter);
+
+ // Find the loggers this target matches and add the
+ // target as a listener for log events from these loggers.
+ Iterator it = log.loggers.keySet().iterator();
+ while (it.hasNext())
+ {
+ String key = (String) it.next();
+ if (categoryMatchInFilterList(key, filters))
+ target.addLogger((Logger) log.loggers.get(key));
+ }
+ }
+ }
+ }
+
+ /* package */ static void processTargetFilterRemove(Target target, String filter)
+ {
+ if (log != null)
+ {
+ synchronized (staticLock)
+ {
+ // Remove the target from any matching loggers.
+ List filters = new ArrayList();
+ filters.add(filter);
+ Iterator it = log.loggers.keySet().iterator();
+ while (it.hasNext())
+ {
+ String key = (String) it.next();
+ if (categoryMatchInFilterList(key, filters))
+ target.removeLogger((Logger) log.loggers.get(key));
+ }
+ }
+ }
+ }
+
+ /**
+ * This method checks that the specified category matches any of the filter
+ * expressions provided in the filters array.
+ *
+ * @param category to match against
+ * @param filters - list of strings to check category against.
+ * @return <code>true</code> if the specified category matches any of the
+ * filter expressions found in the filters list, <code>false</code>
+ * otherwise.
+ */
+ private static boolean categoryMatchInFilterList(String category, List filters)
+ {
+ if (filters == null)
+ return false;
+
+ for (int i = 0; i < filters.size(); i++)
+ {
+ String filter = (String) filters.get(i);
+ // match category to filter based on the presence of a wildcard
+ if (checkFilterToCategory(filter,category))
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Check whether the category match with the filter.
+ * @param filter The filter string to check against a specific category
+ * @param category The category which the filter could match
+ * @return whether the filter matches a specific category
+ */
+ public static boolean checkFilterToCategory(String filter, String category)
+ {
+ int index = -1;
+ index = filter.indexOf("*");
+
+ if (index == 0) // match all
+ {
+ return true;
+ }
+ else if (index < 0) // match full category to filter
+ {
+ if (category.equals(filter))
+ {
+ return true;
+ }
+ }
+ else // match partial category to filter
+ {
+ if ((category.length() >= index) && category.substring(0, index).equals(filter.substring(0, index)))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * This method will ensure that a valid category string has been specified.
+ * If the category is not valid an exception will be thrown.
+ *
+ * Categories can not contain any blanks or any of the following characters:
+ * []`*~,!#$%^&()]{}+=\|'";?><./&#64; or be less than 1 character in length.
+ */
+ private static void checkCategory(String category)
+ {
+ if (category == null || category.length() == 0)
+ {
+ // Categories must be at least one character in length.
+ LocalizedException ex = new LocalizedException();
+ ex.setMessage(INVALID_CATEGORY);
+ throw ex;
+ }
+
+ if (hasIllegalCharacters(category) || (category.indexOf("*") != -1))
+ {
+ // Categories can not contain any of the following characters: 'INVALID_CHARS'
+ LocalizedException ex = new LocalizedException();
+ ex.setMessage(INVALID_CATEGORY_CHARS, new Object[]{INVALID_CHARS});
+ throw ex;
+ }
+ }
+
+ /**
+ * Clean up static member variables.
+ */
+ public static void clear()
+ {
+ log = null;
+ prettyPrinter = null;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/8315f8fa/common/src/main/java/flex/messaging/log/LogCategories.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/flex/messaging/log/LogCategories.java b/common/src/main/java/flex/messaging/log/LogCategories.java
new file mode 100644
index 0000000..2cb6094
--- /dev/null
+++ b/common/src/main/java/flex/messaging/log/LogCategories.java
@@ -0,0 +1,112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 flex.messaging.log;
+
+/**
+ *
+ *
+ * This class contains all the log categories used in our classes. When adding
+ * a new log category, make sure the sample configuration file is updated
+ * as well.
+ *
+ */
+public interface LogCategories
+{
+ String CLIENT_FLEXCLIENT = "Client.FlexClient";
+ String CLIENT_FLEXCLIENT_ADAPTIVE = "Client.FlexClient.Adaptive";
+ String CLIENT_MESSAGECLIENT = "Client.MessageClient";
+
+ String CONFIGURATION = "Configuration";
+ String CONFIGURATION_SPRING = "Configuration.Spring";
+
+ String ENDPOINT_GENERAL = "Endpoint.General";
+ String ENDPOINT_AMF = "Endpoint.AMF";
+ String ENDPOINT_NIO_AMF = "Endpoint.NIOAMF";
+ String ENDPOINT_FLEXSESSION = "Endpoint.FlexSession";
+ String ENDPOINT_GATEWAY = "Endpoint.Gateway";
+ String ENDPOINT_HTTP = "Endpoint.HTTP";
+ String ENDPOINT_NIO_HTTP = "Endpoint.NIOHTTP";
+ String ENDPOINT_RTMP = "Endpoint.RTMP";
+ String ENDPOINT_STREAMING_AMF = "Endpoint.StreamingAMF";
+ String ENDPOINT_STREAMING_NIO_AMF = "Endpoint.StreamingNIOAMF";
+ String ENDPOINT_STREAMING_HTTP = "Endpoint.StreamingHTTP";
+ String ENDPOINT_STREAMING_NIO_HTTP = "Endpoint.StreamingNIOHTTP";
+ String ENDPOINT_WEBSOCKET_NIO_AMF = "Endpoint.WebSocketNIOAMF";
+ String ENDPOINT_TYPE = "Endpoint.Type";
+
+ String EXECUTOR = "Executor";
+
+ String MANAGEMENT_GENERAL = "Management.General";
+ String MANAGEMENT_MBEANSERVER = "Management.MBeanServer";
+
+ String MESSAGE_GENERAL = "Message.General";
+ String MESSAGE_COMMAND = "Message.Command";
+ String MESSAGE_DATA = "Message.Data";
+ String MESSAGE_FILTER = "Message.Filter";
+ String MESSAGE_REMOTING = "Message.Remoting";
+ String MESSAGE_RPC = "Message.RPC";
+ String MESSAGE_SELECTOR = "Message.Selector";
+ String MESSAGE_TIMING = "Message.Timing";
+
+ String PROTOCOL_AMFSOCKET = "Protocol.AMFSocket";
+ String PROTOCOL_HTTP = "Protocol.HTTP";
+ String PROTOCOL_RTMP = "Protocol.RTMP";
+ String PROTOCOL_RTMPT = "Protocol.RTMPT";
+
+ String RESOURCE = "Resource";
+
+ String SERVICE_GENERAL = "Service.General";
+ String SERVICE_CLUSTER = "Service.Cluster";
+ String SERVICE_COLLABORATION = "Service.Collaboration";
+ String SERVICE_DATA = "Service.Data"; // Not a category but used by TargetSettings to replace DataService
+ String SERVICE_DATA_GENERAL = "Service.Data.General";
+ String SERVICE_DATA_HIBERNATE = "Service.Data.Hibernate";
+ String SERVICE_DATA_SQL = "Service.Data.SQL";
+ String SERVICE_DATA_TRANSACTION = "Service.Data.Transaction";
+ String SERVICE_ADVANCED_MESSAGING = "Service.AdvancedMessaging";
+ String SERVICE_NOTIFICATION = "Service.Notification";
+ String SERVICE_GATEWAY = "Service.Gateway";
+ String SERVICE_GATEWAY_CONNECTOR = "Service.Gateway.Connector";
+ String SERVICE_HTTP = "Service.HTTP";
+ String SERVICE_MESSAGE = "Service.Message";
+ String SERVICE_MESSAGE_JMS = "Service.Message.JMS";
+ String SERVICE_REMOTING = "Service.Remoting";
+
+ String SECURITY = "Security";
+
+ String SOCKET_SERVER_GENERAL = "SocketServer.General";
+ String SOCKET_SERVER_BYTE_BUFFER_MANAGEMENT = "SocketServer.ByteBufferManagement";
+
+ String SSL = "SSL";
+
+ String STARTUP_MESSAGEBROKER = "Startup.MessageBroker";
+ String STARTUP_SERVICE = "Startup.Service";
+ String STARTUP_DESTINATION = "Startup.Destination";
+
+ String TIMEOUT = "Timeout";
+
+ String TRANSPORT_RELIABLE = "Transport.Reliable";
+ String TRANSPORT_THROTTLE = "Transport.Throttle";
+ String TRANSPORT_THROTTLE_BUFFER = "Transport.Throttle.Buffer";
+ String TRANSPORT_THROTTLE_CONFLATE = "Transport.Throttle.Conflate";
+
+ String WSRP_GENERAL = "WSRP.General";
+
+ String RDS = "RDS";
+
+ String FBSERVICES_INTROSPECTION = "FBServices.Introspection";
+}
http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/8315f8fa/common/src/main/java/flex/messaging/log/LogEvent.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/flex/messaging/log/LogEvent.java b/common/src/main/java/flex/messaging/log/LogEvent.java
new file mode 100644
index 0000000..7492352
--- /dev/null
+++ b/common/src/main/java/flex/messaging/log/LogEvent.java
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 flex.messaging.log;
+
+/**
+ *
+ */
+public class LogEvent
+{
+ public static final short NONE = 2000;
+ public static final short FATAL = 1000;
+ public static final short ERROR = 8;
+ public static final short WARN = 6;
+ public static final short INFO = 4;
+ public static final short DEBUG = 2;
+ public static final short ALL = 0;
+
+ /**
+ * Provides access to the level for this log event.
+ * Valid values are:
+ * <ul>
+ * <li><code>LogEvent.DEBUG</code> designates informational
+ * level messages that are fine grained and most helpful when
+ * debugging an application.</li>
+ *
+ * <li><code>LogEvent.INFO</code> designates informational messages
+ * that highlight the progress of the application at
+ * coarse-grained level.</li>
+ *
+ * <li><code>LogEvent.WARN</code> designates events that could be
+ * harmful to the application operation.</li>
+ *
+ * <li><code>LogEvent.ERROR</code> designates error events that might
+ * still allow the application to continue running.</li>
+ *
+ * <li><code>LogEvent.FATAL</code> designates events that are very
+ * harmful and will eventually lead to application failure.</li>
+ *
+ * </ul>
+ */
+ public short level;
+
+ /**
+ * Provides access to the message that was logged.
+ */
+ public String message;
+
+ /**
+ * Logger instance that raised the log event.
+ */
+ public Logger logger;
+
+ /**
+ * Related exception, if applicable.
+ */
+ public Throwable throwable;
+
+ /**
+ * Constructor.
+ *
+ * @param lgr Logger instance that raised the log event.
+ * @param msg Message that was logged.
+ * @param lvl The level for the log event.
+ * @param t Related exception, if applicable.
+ */
+ public LogEvent(Logger lgr, String msg, short lvl, Throwable t)
+ {
+ logger = lgr;
+ message = msg;
+ level = lvl;
+ throwable = t;
+ }
+
+ /**
+ * Returns a string value representing the level specified.
+ *
+ * @param value the level a string is desired for.
+ * @return the level specified in english
+ */
+ public static String getLevelString(short value)
+ {
+ switch (value)
+ {
+ case NONE:
+ return ("NONE");
+ case FATAL:
+ return ("FATAL");
+ case ERROR:
+ return ("ERROR");
+ case WARN:
+ return ("WARN");
+ case INFO:
+ return ("INFO");
+ case DEBUG:
+ return ("DEBUG");
+ case ALL:
+ return ("ALL");
+ default:
+ return ("UNKNOWN");
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/8315f8fa/common/src/main/java/flex/messaging/log/Logger.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/flex/messaging/log/Logger.java b/common/src/main/java/flex/messaging/log/Logger.java
new file mode 100644
index 0000000..8684a3e
--- /dev/null
+++ b/common/src/main/java/flex/messaging/log/Logger.java
@@ -0,0 +1,402 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 flex.messaging.log;
+
+import flex.messaging.util.PrettyPrinter;
+import flex.messaging.util.StringUtils;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+/**
+ * The <code>Logger</code> class is used to log out information. It provides named
+ * methods to log information out at the desired level. Each <code>Logger</code>
+ * will log information out for a log category that is settable.
+ *
+ *
+ */
+public class Logger
+{
+ /**
+ * The category this logger send messages for.
+ */
+ private volatile String category;
+
+ /**
+ * The list of targets that this logger will dispatch log events to.
+ */
+ private final ArrayList targets;
+
+ /**
+ * Constructs a <code>Logger</code> instance that will log
+ * information out to the specified category.
+ *
+ * @param category The category to log information for.
+ */
+ public Logger(String category)
+ {
+ this.category = category;
+ targets = new ArrayList();
+ }
+
+ /**
+ * Returns the category this <code>Logger</code> logs information for.
+ *
+ * @return The category this <code>Logger</code> logs information for.
+ */
+ public String getCategory()
+ {
+ return category;
+ }
+
+ /**
+ * Determines whether the <code>Logger</code> has at least one target.
+ *
+ * @return True if the <code>Logger</code> has one or more targets.
+ */
+ public boolean hasTarget()
+ {
+ synchronized (targets)
+ {
+ return !targets.isEmpty();
+ }
+ }
+ /**
+ * Adds a <code>Target</code> that will format and output log events
+ * generated by this <code>Logger</code>.
+ *
+ * @param target The <code>Target</code> to add.
+ */
+ void addTarget(Target target)
+ {
+ synchronized (targets)
+ {
+ if (!targets.contains(target))
+ targets.add(target);
+ }
+ }
+
+ /**
+ * Removes a <code>Target</code> from this <code>Logger</code>.
+ *
+ * @param target The <code>Target</code> to remove.
+ */
+ void removeTarget(Target target)
+ {
+ synchronized (targets)
+ {
+ targets.remove(target);
+ }
+ }
+
+ /*
+ * DEBUG
+ */
+ /**
+ * Logs out a debug message.
+ *
+ * @param message The message to log.
+ */
+ public void debug(String message)
+ {
+ log(LogEvent.DEBUG, message, null, null);
+ }
+
+ /**
+ * Logs out a debug message associated with a <code>Throwable</code>.
+ *
+ * @param message The message to log.
+ * @param t The associated <code>Throwable</code>.
+ */
+ public void debug(String message, Throwable t)
+ {
+ log(LogEvent.DEBUG, message, null, t);
+ }
+
+ /**
+ * Logs out a debug message supporting positional parameter substitutions.
+ *
+ * @param message The message to log.
+ * @param parameters Parameters to substitute into the message.
+ */
+ public void debug(String message, Object[] parameters)
+ {
+ log(LogEvent.DEBUG, message, parameters, null);
+ }
+
+ /**
+ * Logs out a debug message supporting positional parameter substitutions and an
+ * associated <code>Throwable</code>.
+ *
+ * @param message The message to log.
+ * @param parameters Parameters to substitute into the message.
+ * @param t The associated <code>Throwable</code>.
+ */
+ public void debug(String message, Object[] parameters, Throwable t)
+ {
+ log(LogEvent.DEBUG, message, parameters, t);
+ }
+
+ /*
+ * INFO
+ */
+ /**
+ * Logs out an info message.
+ *
+ * @param message The message to log.
+ */
+ public void info(String message)
+ {
+ log(LogEvent.INFO, message, null, null);
+ }
+
+ /**
+ * Logs out an info message associated with a <code>Throwable</code>.
+ *
+ * @param message The message to log.
+ * @param t The associated <code>Throwable</code>.
+ */
+ public void info(String message, Throwable t)
+ {
+ log(LogEvent.INFO, message, null, t);
+ }
+
+ /**
+ * Logs out an info message supporting positional parameter substitutions.
+ *
+ * @param message The message to log.
+ * @param parameters Parameters to substitute into the message.
+ */
+ public void info(String message, Object[] parameters)
+ {
+ log(LogEvent.INFO, message, parameters, null);
+ }
+
+ /**
+ * Logs out an info message supporting positional parameter substitutions and an
+ * associated <code>Throwable</code>.
+ *
+ * @param message The message to log.
+ * @param parameters Parameters to substitute into the message.
+ * @param t The associated <code>Throwable</code>.
+ */
+ public void info(String message, Object[] parameters, Throwable t)
+ {
+ log(LogEvent.INFO, message, parameters, t);
+ }
+
+ /*
+ * WARN
+ */
+ /**
+ * Logs out a warn message.
+ *
+ * @param message The message to log.
+ */
+ public void warn(String message)
+ {
+ log(LogEvent.WARN, message, null, null);
+ }
+
+ /**
+ * Logs out a warn message associated with a <code>Throwable</code>.
+ *
+ * @param message The message to log.
+ * @param t The associated <code>Throwable</code>.
+ */
+ public void warn(String message, Throwable t)
+ {
+ log(LogEvent.WARN, message, null, t);
+ }
+
+ /**
+ * Logs out a warn message supporting positional parameter substitutions.
+ *
+ * @param message The message to log.
+ * @param parameters Parameters to substitute into the message.
+ */
+ public void warn(String message, Object[] parameters)
+ {
+ log(LogEvent.WARN, message, parameters, null);
+ }
+
+ /**
+ * Logs out a warn message supporting positional parameter substitutions and an
+ * associated <code>Throwable</code>.
+ *
+ * @param message The message to log.
+ * @param parameters Parameters to substitute into the message.
+ * @param t The associated <code>Throwable</code>.
+ */
+ public void warn(String message, Object[] parameters, Throwable t)
+ {
+ log(LogEvent.WARN, message, parameters, t);
+ }
+
+ /*
+ * ERROR
+ */
+ /**
+ * Logs out an error message.
+ *
+ * @param message The message to log.
+ */
+ public void error(String message)
+ {
+ log(LogEvent.ERROR, message, null, null);
+ }
+
+ /**
+ * Logs out an error message associated with a <code>Throwable</code>.
+ *
+ * @param message The message to log.
+ * @param t The associated <code>Throwable</code>.
+ */
+ public void error(String message, Throwable t)
+ {
+ log(LogEvent.ERROR, message, null, t);
+ }
+
+ /**
+ * Logs out an error message supporting positional parameter substitutions.
+ *
+ * @param message The message to log.
+ * @param parameters Parameters to substitute into the message.
+ */
+ public void error(String message, Object[] parameters)
+ {
+ log(LogEvent.ERROR, message, parameters, null);
+ }
+
+ /**
+ * Logs out an error message supporting positional parameter substitutions and an
+ * associated <code>Throwable</code>.
+ *
+ * @param message The message to log.
+ * @param parameters Parameters to substitute into the message.
+ * @param t The associated <code>Throwable</code>.
+ */
+ public void error(String message, Object[] parameters, Throwable t)
+ {
+ log(LogEvent.ERROR, message, parameters, t);
+ }
+
+ /*
+ * FATAL
+ */
+ /**
+ * Logs out a fatal message.
+ *
+ * @param message The message to log.
+ */
+ public void fatal(String message)
+ {
+ log(LogEvent.FATAL, message, null, null);
+ }
+
+ /**
+ * Logs out a fatal message associated with a <code>Throwable</code>.
+ *
+ * @param message The message to log.
+ * @param t The associated <code>Throwable</code>.
+ */
+ public void fatal(String message, Throwable t)
+ {
+ log(LogEvent.FATAL, message, null, t);
+ }
+
+ /**
+ * Logs out a fatal message supporting positional parameter substitutions.
+ *
+ * @param message The message to log.
+ * @param parameters Parameters to substitute into the message.
+ */
+ public void fatal(String message, Object[] parameters)
+ {
+ log(LogEvent.FATAL, message, parameters, null);
+ }
+
+ /**
+ * Logs out a fatal message supporting positional parameter substitutions and an
+ * associated <code>Throwable</code>.
+ *
+ * @param message The message to log.
+ * @param parameters Parameters to substitute into the message.
+ * @param t The associated <code>Throwable</code>.
+ */
+ public void fatal(String message, Object[] parameters, Throwable t)
+ {
+ log(LogEvent.FATAL, message, parameters, t);
+ }
+
+ /**
+ *
+ * The methods named according to log level delegate to this method to log.
+ *
+ * @param level The log level.
+ * @param message The message to log.
+ * @param parameters Substitution parameters (may be null).
+ * @param t The associated <code>Throwable</code> (may be null).
+ */
+ public void log(short level, String message, Object[] parameters, Throwable t)
+ {
+ log(level, message, parameters, t, true);
+ }
+
+ /**
+ *
+ * Logs a passed message if its level verifies as high enough.
+ *
+ * @param level The log level.
+ * @param message The message to log.
+ * @param parameters Substitution parameters (may be null).
+ * @param t The associated <code>Throwable</code>.
+ * @param verifyLevel <code>true</code> to verify the log level; otherwise log without verifying the level.
+ */
+ public void log(short level, String message, Object[] parameters, Throwable t, boolean verifyLevel)
+ {
+ if (targets.size() > 0 && (!verifyLevel || (level >= Log.getTargetLevel())))
+ {
+ if (parameters != null)
+ {
+ PrettyPrinter prettyPrinter = Log.getPrettyPrinter();
+
+ // replace all of the parameters in the msg string
+ for(int i = 0; i < parameters.length; i++)
+ {
+ String replacement = parameters[i] != null ? prettyPrinter.prettify(parameters[i]) : "null";
+
+ //this guy runs into problems if the replacement has a \ or $ in it
+ //message = message.replaceAll("\\{" + i + "\\}", replacement);
+ message = StringUtils.substitute(message, "{" + i + "}", replacement);
+ }
+ }
+ LogEvent event = new LogEvent(this, message, level, t);
+ Target tgt;
+ synchronized (targets)
+ {
+ for (Iterator iter = targets.iterator(); iter.hasNext();)
+ {
+ tgt = (Target) iter.next();
+ if (!verifyLevel || (level >= tgt.getLevel()))
+ tgt.logEvent(event);
+ }
+ }
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/8315f8fa/common/src/main/java/flex/messaging/log/Target.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/flex/messaging/log/Target.java b/common/src/main/java/flex/messaging/log/Target.java
new file mode 100644
index 0000000..7a39fb5
--- /dev/null
+++ b/common/src/main/java/flex/messaging/log/Target.java
@@ -0,0 +1,112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 flex.messaging.log;
+
+import java.util.List;
+
+import flex.messaging.config.ConfigMap;
+
+/**
+ * All logger target implementations within the logging framework must
+ * implement this interface. <code>Target</code> implementations receive log events
+ * and output information from these events to the appropriate output
+ * destination which may be a console, log file or some other custom
+ * destination.
+ */
+public interface Target
+{
+ /**
+ * Initializes the target with id and properties.
+ *
+ * @param id id for the target.
+ * @param properties ConfigMap of properties for the target.
+ */
+ void initialize(String id, ConfigMap properties);
+
+ /**
+ * Returns the category filters defined for the <code>Target</code>.
+ *
+ * @return The category filters defined for the <code>Target</code>.
+ */
+ List getFilters();
+
+ /**
+ * Sets the category filters that the <code>Target</code> will process
+ * log events for.
+ *
+ * @param value The category filters that the <code>Target</code> will process
+ */
+ void setFilters(List value);
+
+ /**
+ * Adds the category filteer that the <code>Target</code> will process
+ * log events for.
+ *
+ * @param value The new category filter to add to the <code>Target</code>'s list of filters.
+ */
+ void addFilter(String value);
+
+ /**
+ * Removes a category filter from the list of filters the <code>Target</code> will
+ * process log events for.
+ *
+ * @param value The category filter to remove from the <code>Target</code>'s list of filters.
+ */
+ void removeFilter(String value);
+
+ /**
+ * Returns the log level that the <code>Target</code> will process log
+ * events for. Log events at this level, or at a higher priority level
+ * will be processed.
+ *
+ * @return The log level that the <code>Target</code> will process log events for.
+ */
+ short getLevel();
+
+ /**
+ * Sets the log level that the <code>Target</code> will process log events
+ * for. Log events at this level, or at a higher priority level will be
+ * processed.
+ *
+ * @param value The log level that the <code>Target</code> will process log events for.
+ */
+ void setLevel(short value);
+
+ /**
+ * Adds a <code>Logger</code> whose category matches the filters list for
+ * the <code>Target</code>. The <code>Logger</code> will dispatch log events
+ * to this <code>Target</code> to be output.
+ *
+ * @param logger The <code>Logger</code> to add.
+ */
+ void addLogger(Logger logger);
+
+ /**
+ * Removes a <code>Logger</code> from the <code>Target</code>.
+ *
+ * @param logger The <code>Logger</code> to remove.
+ */
+ void removeLogger(Logger logger);
+
+ /**
+ * Logs a log event out to the <code>Target</code>s output destination,
+ * which may be the console or a log file.
+ *
+ * @param event The <code>LogEvent</code> containing the information to output.
+ */
+ void logEvent(LogEvent event);
+}
http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/8315f8fa/common/src/main/java/flex/messaging/util/BasicPrettyPrinter.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/flex/messaging/util/BasicPrettyPrinter.java b/common/src/main/java/flex/messaging/util/BasicPrettyPrinter.java
new file mode 100644
index 0000000..19fa547
--- /dev/null
+++ b/common/src/main/java/flex/messaging/util/BasicPrettyPrinter.java
@@ -0,0 +1,164 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 flex.messaging.util;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.Method;
+import java.util.Calendar;
+import java.util.Collection;
+import java.util.Date;
+import java.util.Map;
+
+/**
+ * Prettifies the representation of an Object as a String. Complex
+ * types are not traversed.
+ *
+ *
+ */
+public class BasicPrettyPrinter implements PrettyPrinter
+{
+ protected ObjectTrace trace;
+
+ public BasicPrettyPrinter()
+ {
+ }
+
+ /**
+ * Prettifies the representation of an Object as a String.
+ * <ul>
+ * <li>Simple types are simply toString'ed.</li>
+ * <li>XML strings are formatted with line feeds and indentations.</li>
+ * <li>Complex types report their class names.</li>
+ * <li>Collections, Maps and native Arrays also report their size/length.</li>
+ * </ul>
+ * @return A prettified version of an Object as a String.
+ */
+ public String prettify(Object o)
+ {
+ try
+ {
+ trace = new ObjectTrace();
+ internalPrettify(o);
+ return trace.toString();
+ }
+ catch (Throwable t)
+ {
+ return trace.toString();
+ }
+ finally
+ {
+ trace = null;
+ }
+ }
+
+ protected void internalPrettify(Object o)
+ {
+ if (o == null)
+ {
+ trace.writeNull();
+ }
+ else if (o instanceof String)
+ {
+ String string = (String)o;
+ if (string.startsWith("<?xml"))
+ {
+ trace.write(StringUtils.prettifyXML(string));
+ }
+ else
+ {
+ trace.write(string);
+ }
+ }
+ else if (o instanceof Number || o instanceof Boolean || o instanceof Date
+ || o instanceof Calendar || o instanceof Character)
+ {
+ trace.write(o);
+ }
+ else
+ {
+ prettifyComplexType(o);
+ }
+ }
+
+ protected void prettifyComplexType(Object o)
+ {
+ StringBuffer header = new StringBuffer();
+
+ if (o instanceof PrettyPrintable)
+ {
+ PrettyPrintable pp = (PrettyPrintable)o;
+ header.append(pp.toStringHeader());
+ }
+
+ Class c = o.getClass();
+ String className = c.getName();
+
+ if (o instanceof Collection)
+ {
+ header.append(className).append(" (Collection size:").append(((Collection)o).size()).append(")");
+ }
+ else if (o instanceof Map)
+ {
+ header.append(className).append(" (Map size:").append(((Map)o).size()).append(")");
+ }
+ else if (c.isArray() && c.getComponentType() != null)
+ {
+ Class componentType = c.getComponentType();
+ className = componentType.getName();
+ header.append(className).append("[] (Array length:").append(Array.getLength(o)).append(")");
+ }
+ else
+ {
+ header.append(className);
+ }
+
+ trace.startObject(header.toString());
+ trace.endObject();
+ }
+
+ /**
+ * If the definition of toString is not from java.lang.Object or any class in the
+ * java.util.* package then we consider it a custom implementation in which case
+ * we'll use it instead of introspecting the class.
+ *
+ * @param c The class to check for a custom toString definition.
+ * @return Whether this class declares a custom toString() method.
+ */
+ protected boolean hasCustomToStringMethod(Class c)
+ {
+ try
+ {
+ Method toStringMethod = c.getMethod("toString", (Class[])null);
+ Class declaringClass = toStringMethod.getDeclaringClass();
+ if (declaringClass != Object.class
+ && !declaringClass.getName().startsWith("java.util"))
+ {
+ return true;
+ }
+ }
+ catch (Throwable t)
+ {
+ }
+
+ return false;
+ }
+
+ public Object copy()
+ {
+ return new BasicPrettyPrinter();
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/8315f8fa/common/src/main/java/flex/messaging/util/ExceptionUtil.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/flex/messaging/util/ExceptionUtil.java b/common/src/main/java/flex/messaging/util/ExceptionUtil.java
new file mode 100644
index 0000000..595077a
--- /dev/null
+++ b/common/src/main/java/flex/messaging/util/ExceptionUtil.java
@@ -0,0 +1,250 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 flex.messaging.util;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.NoSuchElementException;
+import java.util.StringTokenizer;
+
+/**
+ *
+ */
+public class ExceptionUtil
+{
+ /**
+ * List of no-arg methods that are known to return a wrapped throwable.
+ **/
+ public static String[] unwrapMethods = { "getRootCause", "getTargetException",
+ "getTargetError", "getException",
+ "getCausedByException", "getLinkedException" };
+
+ /**
+ * Get the wrapped Exception object from the Throwable object.
+ * @param t the Throwable object
+ * @return Throwable the wrapped exception object if any
+ */
+ public static Throwable wrappedException(Throwable t)
+ {
+ // Handle these statically since they are core to Java
+ return (t instanceof InvocationTargetException)?
+ ((InvocationTargetException)t).getTargetException() : getRootCauseWithReflection(t);
+ }
+
+ /**
+ * Get to the base exception (if any).
+ * @param t the Throwable object
+ * @return the base Exception object
+ */
+ public static Throwable baseException(Throwable t)
+ {
+ Throwable wrapped = wrappedException(t);
+ return wrapped != null? baseException(wrapped) : t;
+ }
+
+ /**
+ * Return the stack trace in a String.
+ * @param t the Throwable object
+ * @return String the String presentation of the Throwable object
+ */
+ public static String toString(Throwable t)
+ {
+ StringWriter strWrt = new StringWriter();
+ t.printStackTrace(new PrintWriter(strWrt));
+
+ return strWrt.toString();
+ }
+
+ /**
+ * Return the stack trace up to the first line that starts with prefix.
+ *
+ * <p>Example: ExceptionUtil.getStackTraceUpTo(exception, "jrunx.");</p>
+ * @param t the Throwable object
+ * @param prefix the prefix message that we are looking for
+ * @return String the String of stack trace lines till the prefix message is located
+ */
+ public static String getStackTraceUpTo(Throwable t, String prefix)
+ {
+ StringTokenizer tokens = new StringTokenizer(toString(t), "\n\r");
+ StringBuffer trace = new StringBuffer();
+ boolean done = false;
+
+ String lookingFor = "at " + prefix;
+ while (!done && tokens.hasMoreElements())
+ {
+ String token = tokens.nextToken();
+ if (token.indexOf(lookingFor) == -1)
+ trace.append(token);
+ else
+ done = true;
+ trace.append(StringUtils.NEWLINE);
+ }
+
+ return trace.toString();
+ }
+
+ /**
+ * return the top n lines of this stack trace.
+ *
+ * <p>Example: ExceptionUtil.getStackTraceLines(exception, 10);</p>
+ * @param t the Throwable object
+ * @param numLines number of lines we should trace down
+ * @return String the String of stack trace lines
+ */
+ public static String getStackTraceLines(Throwable t, int numLines)
+ {
+ StringTokenizer tokens = new StringTokenizer(toString(t), "\n\r");
+
+ StringBuffer trace = new StringBuffer();
+
+ for (int i=0; i<numLines; i++)
+ {
+ String token = tokens.nextToken();
+ trace.append(token);
+ trace.append(StringUtils.NEWLINE);
+ }
+
+ return trace.toString();
+ }
+
+ /**
+ * Return the "nth" method call from the stack trace of "t", where 0 is
+ * the top.
+ * @param t the Throwable object
+ * @param nth the line number of the message should we skip
+ * @return String the callAt String
+ */
+ public static String getCallAt(Throwable t, int nth)
+ {
+ StringTokenizer tokens = new StringTokenizer(toString(t), "\n\r");
+ try
+ {
+ // Skip the first line - the exception message
+ for(int i = 0; i <= nth; ++i)
+ tokens.nextToken();
+
+ // get the method name from the next token
+ String token = tokens.nextToken();
+ int index1 = token.indexOf(' ');
+ int index2 = token.indexOf('(');
+ StringBuffer call = new StringBuffer();
+ call.append(token.substring(index1 < 0 ? 0 : index1 + 1, index2 < 0 ? call.length() : index2));
+
+ int index3 = token.indexOf(':', index2 < 0 ? 0 : index2);
+ if(index3 >= 0)
+ {
+ int index4 = token.indexOf(')', index3);
+ call.append(token.substring(index3, index4 < 0 ? token.length() : index4));
+ }
+ return call.toString();
+ }
+ catch(NoSuchElementException e) {}
+
+ return "unknown";
+ }
+
+
+ /**
+ * Utility method for converting an exception into a string. This
+ * method unwinds all wrapped exceptions
+ * @param t The throwable exception
+ * @return The printable exception
+ */
+ public static String exceptionToString(Throwable t)
+ {
+ StringWriter sw = new StringWriter();
+ PrintWriter out = new PrintWriter(sw);
+
+ //print out the exception stack.
+ printExceptionStack(t, out, 0);
+ return sw.toString();
+ }
+
+ /**
+ * Utility method for converting an exception and all chained root causes into a
+ * string. Unlike <code>exceptionToString(Throwable)</code> which prints the chain
+ * from most nested root cause down to the top-level exception, this method prints
+ * from the top-level exception down to the most nested root cause.
+ *
+ * @param t The throwable exception.
+ * @return The printable exception.
+ */
+ public static String exceptionFollowedByRootCausesToString(Throwable t)
+ {
+ StringBuffer output = new StringBuffer();
+ Throwable root = t;
+ while (root != null)
+ {
+ output.append((root == t) ? ((root instanceof Exception) ? " Exception: " : " Error: ") : " Root cause: ");
+ output.append(ExceptionUtil.toString(root));
+ // Do not recurse if the root cause has already been printed; this will have happened if the root cause has
+ // been assigned to the current Throwable via initCause() or as a constructor argument.
+ Throwable cause = root.getCause();
+ root = ExceptionUtil.wrappedException(root);
+ if (cause == root)
+ break;
+ }
+ return output.toString();
+ }
+
+ /**
+ * Recursively prints out a stack of wrapped exceptions.
+ *
+ * @param th the Throwable object
+ * @param out the output writer to print to
+ * @param depth the number of levels the stack should be printed
+ */
+ protected static void printExceptionStack(Throwable th, PrintWriter out, int depth){
+ //only print the stack depth if the depth is greater than 0
+ boolean printStackDepth = depth>0;
+
+ Throwable wrappedException = ExceptionUtil.wrappedException(th);
+ if (wrappedException != null)
+ {
+ printStackDepth = true;
+ printExceptionStack(wrappedException, out, depth + 1);
+ }
+
+ if(printStackDepth){
+ out.write("[" + depth + "]");
+ }
+
+ th.printStackTrace(out);
+ }
+
+ private static Throwable getRootCauseWithReflection(Throwable t)
+ {
+ for(int i = 0; i < unwrapMethods.length; i++)
+ {
+ Method m = null;
+
+ try
+ {
+ m = t.getClass().getMethod(unwrapMethods[i], (Class[])null);
+ return (Throwable) m.invoke(t, (Object[])null);
+ }
+ catch(Exception nsme)
+ {
+ // ignore
+ }
+ }
+
+ return null;
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/8315f8fa/common/src/main/java/flex/messaging/util/FileUtils.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/flex/messaging/util/FileUtils.java b/common/src/main/java/flex/messaging/util/FileUtils.java
new file mode 100644
index 0000000..31e8d30
--- /dev/null
+++ b/common/src/main/java/flex/messaging/util/FileUtils.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 flex.messaging.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ *
+ */
+public class FileUtils
+{
+ public static final String UTF_8 = "UTF-8";
+ public static final String UTF_16 = "UTF-16";
+
+ /**
+ * Sets a mark in the InputStream for 3 bytes to check for a BOM. If the BOM
+ * stands for UTF-8 encoded content then the stream will not be reset, otherwise
+ * for UTF-16 with a BOM or any other encoding situation the stream is reset to the
+ * mark (as for UTF-16 the parser will handle the BOM).
+ *
+ * @param in InputStream containing BOM and must support mark().
+ * @param default_encoding The default character set encoding. null or "" => system default
+ * @return The file character set encoding.
+ * @throws IOException an IOException, if something went wrong.
+ */
+ public static final String consumeBOM(InputStream in, String default_encoding) throws IOException
+ {
+ in.mark(3);
+
+ // Determine file encoding...
+ // ASCII - no header (use the supplied encoding)
+ // UTF8 - EF BB BF
+ // UTF16 - FF FE or FE FF (decoder chooses endian-ness)
+ if (in.read() == 0xef && in.read() == 0xbb && in.read() == 0xbf)
+ {
+ // UTF-8 reader does not consume BOM, so do not reset
+ if (System.getProperty("flex.platform.CLR") != null)
+ {
+ return "UTF8";
+ }
+ else
+ {
+ return UTF_8;
+ }
+ }
+ else
+ {
+ in.reset();
+ int b0 = in.read();
+ int b1 = in.read();
+ if (b0 == 0xff && b1 == 0xfe || b0 == 0xfe && b1 == 0xff)
+ {
+ in.reset();
+ // UTF-16 reader will consume BOM
+ if (System.getProperty("flex.platform.CLR") != null)
+ {
+ return "UTF16";
+ }
+ else
+ {
+ return UTF_16;
+ }
+ }
+ else
+ {
+ // no BOM found
+ in.reset();
+ if (default_encoding != null && default_encoding.length() != 0)
+ {
+ return default_encoding;
+ }
+ else
+ {
+ return System.getProperty("file.encoding");
+ }
+ }
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/8315f8fa/common/src/main/java/flex/messaging/util/LocaleUtils.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/flex/messaging/util/LocaleUtils.java b/common/src/main/java/flex/messaging/util/LocaleUtils.java
new file mode 100644
index 0000000..5800433
--- /dev/null
+++ b/common/src/main/java/flex/messaging/util/LocaleUtils.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 flex.messaging.util;
+
+import java.util.Locale;
+
+/**
+ *
+ */
+public class LocaleUtils
+{
+ /**
+ * Builds a <code>Locale</code> instance from the passed string. If the string
+ * is <code>null</code> this method will return the default locale for the JVM.
+ *
+ * @param locale The locale as a string.
+ * @return The Locale instance built from the passed string.
+ */
+ public static Locale buildLocale(String locale)
+ {
+ if (locale == null)
+ {
+ return Locale.getDefault();
+ }
+ else
+ {
+ int index = locale.indexOf('_');
+ if (index == -1)
+ {
+ return new Locale(locale);
+ }
+ String language = locale.substring(0, index);
+ String rest = locale.substring(index + 1);
+ index = rest.indexOf('_');
+ if (index == -1)
+ {
+ return new Locale(language, rest);
+ }
+ String country = rest.substring(0, index);
+ rest = rest.substring(index + 1);
+ return new Locale(language, country, rest);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/8315f8fa/common/src/main/java/flex/messaging/util/ObjectTrace.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/flex/messaging/util/ObjectTrace.java b/common/src/main/java/flex/messaging/util/ObjectTrace.java
new file mode 100644
index 0000000..646d72f
--- /dev/null
+++ b/common/src/main/java/flex/messaging/util/ObjectTrace.java
@@ -0,0 +1,175 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 flex.messaging.util;
+
+import flex.messaging.log.Log;
+
+/**
+ * Simple utility to trace an Object graph out to a StringBuffer.
+ *
+ * Note that new lines are NOT added after the individual values
+ * in complex type properties.
+ *
+ *
+ */
+public class ObjectTrace
+{
+
+
+ /* This boolean is used for suppressing debug output for selected properties.
+ * The logger will check this before printing a property.
+ */
+ public boolean nextElementExclude;
+
+ public ObjectTrace()
+ {
+ buffer = new StringBuffer(4096);
+ }
+
+ public ObjectTrace(int bufferSize)
+ {
+ buffer = new StringBuffer(bufferSize);
+ }
+
+ public String toString()
+ {
+ return buffer.toString();
+ }
+
+ public void write(Object o)
+ {
+ if (m_nested <= 0)
+ buffer.append(indentString());
+
+ buffer.append(String.valueOf(o));
+ }
+
+ public void writeNull()
+ {
+ if (m_nested <= 0)
+ buffer.append(indentString());
+
+ buffer.append("null");
+ }
+
+ public void writeRef(int ref)
+ {
+ if (m_nested <= 0)
+ buffer.append(indentString());
+
+ buffer.append("(Ref #").append(ref).append(")");
+ }
+
+ public void writeString(String s)
+ {
+ if (m_nested <= 0)
+ buffer.append(indentString());
+
+ buffer.append("\"").append(s).append("\"");
+ }
+
+ public void startArray(String header)
+ {
+ if (header != null && header.length() > 0)
+ {
+ if (m_nested <= 0)
+ buffer.append(indentString());
+
+ buffer.append(header).append(newLine);
+ }
+
+ m_indent++;
+ m_nested++;
+ }
+
+ public void arrayElement(int index)
+ {
+ buffer.append(indentString()).append("[").append(index).append("] = ");
+ }
+
+ public void endArray()
+ {
+ m_indent--;
+ m_nested--;
+ }
+
+ public void startObject(String header)
+ {
+ if (header != null && header.length() > 0)
+ {
+ if (m_nested <= 0)
+ buffer.append(indentString());
+
+ buffer.append(header).append(newLine);
+ }
+
+ m_indent++;
+ m_nested++;
+ }
+
+ public void namedElement(String name)
+ {
+ if (Log.isExcludedProperty(name))
+ {
+ nextElementExclude = true;
+ }
+
+ buffer.append(indentString()).append(name).append(" = ");
+ }
+
+ public void endObject()
+ {
+ m_indent--;
+ m_nested--;
+ }
+
+ public void newLine()
+ {
+ boolean alreadyPadded = false;
+ int length = buffer.length();
+
+ if (length > 3)
+ {
+ String tail = buffer.substring(length - 3, length - 1); //Get last two chars in buffer
+ alreadyPadded = tail.equals(newLine);
+ }
+
+ if (!alreadyPadded)
+ buffer.append(newLine);
+ }
+
+ /**
+ * Uses the static member, m_indent to create a string of spaces of
+ * the appropriate indentation.
+ *
+ * @return the ident string.
+ */
+ protected String indentString()
+ {
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < m_indent; ++i)
+ {
+ sb.append(" ");
+ }
+ return sb.toString();
+ }
+
+ protected StringBuffer buffer;
+ protected int m_indent;
+ protected int m_nested;
+ public static String newLine = StringUtils.NEWLINE;
+}
http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/8315f8fa/common/src/main/java/flex/messaging/util/PrettyPrintable.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/flex/messaging/util/PrettyPrintable.java b/common/src/main/java/flex/messaging/util/PrettyPrintable.java
new file mode 100644
index 0000000..68fcc6e
--- /dev/null
+++ b/common/src/main/java/flex/messaging/util/PrettyPrintable.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 flex.messaging.util;
+
+/**
+ * Allows an Object to customize how it is pretty printed in
+ * logging/debugging output.
+ *
+ *
+ */
+public interface PrettyPrintable
+{
+ String toStringHeader();
+
+ String toStringCustomProperty(String name);
+}
http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/8315f8fa/common/src/main/java/flex/messaging/util/PrettyPrinter.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/flex/messaging/util/PrettyPrinter.java b/common/src/main/java/flex/messaging/util/PrettyPrinter.java
new file mode 100644
index 0000000..d0f9de0
--- /dev/null
+++ b/common/src/main/java/flex/messaging/util/PrettyPrinter.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 flex.messaging.util;
+
+/**
+ * Implementations convert Object graphs to Strings for
+ * logging and debugging.
+ *
+ *
+ */
+public interface PrettyPrinter
+{
+ String prettify(Object o);
+
+ Object copy();
+}