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:
+     *              []~$^&amp;\/(){}&lt;&gt;+=`!#%?,:;'"&amp;#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:
+     * []`*~,!#$%^&amp;()]{}+=\|'";?&gt;&lt;./&amp;#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 "" 
=&gt; 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();
+}

Reply via email to