You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flex.apache.org by ah...@apache.org on 2014/04/25 07:34:13 UTC

[15/51] [partial] BlazeDS Donation from Adobe Systems Inc

http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/7a58369c/modules/common/src/flex/messaging/log/Logger.java
----------------------------------------------------------------------
diff --git a/modules/common/src/flex/messaging/log/Logger.java b/modules/common/src/flex/messaging/log/Logger.java
new file mode 100755
index 0000000..e8f622f
--- /dev/null
+++ b/modules/common/src/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.
+ *
+ * @exclude
+ */
+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);
+    }
+
+    /**
+     * @exclude
+     * 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);
+    }
+
+    /**
+     * @exclude
+     * 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/7a58369c/modules/common/src/flex/messaging/log/Target.java
----------------------------------------------------------------------
diff --git a/modules/common/src/flex/messaging/log/Target.java b/modules/common/src/flex/messaging/log/Target.java
new file mode 100755
index 0000000..c5c8224
--- /dev/null
+++ b/modules/common/src/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/7a58369c/modules/common/src/flex/messaging/util/BasicPrettyPrinter.java
----------------------------------------------------------------------
diff --git a/modules/common/src/flex/messaging/util/BasicPrettyPrinter.java b/modules/common/src/flex/messaging/util/BasicPrettyPrinter.java
new file mode 100755
index 0000000..6abc550
--- /dev/null
+++ b/modules/common/src/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.
+ *
+ * @exclude
+ */
+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/7a58369c/modules/common/src/flex/messaging/util/ExceptionUtil.java
----------------------------------------------------------------------
diff --git a/modules/common/src/flex/messaging/util/ExceptionUtil.java b/modules/common/src/flex/messaging/util/ExceptionUtil.java
new file mode 100755
index 0000000..f787859
--- /dev/null
+++ b/modules/common/src/flex/messaging/util/ExceptionUtil.java
@@ -0,0 +1,246 @@
+/*
+ * 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;
+
+/**
+ * @exclude
+ */
+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.
+     */
+    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/7a58369c/modules/common/src/flex/messaging/util/FileUtils.java
----------------------------------------------------------------------
diff --git a/modules/common/src/flex/messaging/util/FileUtils.java b/modules/common/src/flex/messaging/util/FileUtils.java
new file mode 100755
index 0000000..8f7146a
--- /dev/null
+++ b/modules/common/src/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;
+
+/**
+ * @exclude
+ */
+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
+     */
+    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/7a58369c/modules/common/src/flex/messaging/util/LocaleUtils.java
----------------------------------------------------------------------
diff --git a/modules/common/src/flex/messaging/util/LocaleUtils.java b/modules/common/src/flex/messaging/util/LocaleUtils.java
new file mode 100755
index 0000000..e398971
--- /dev/null
+++ b/modules/common/src/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;
+
+/**
+ * @exclude
+ */
+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/7a58369c/modules/common/src/flex/messaging/util/ObjectTrace.java
----------------------------------------------------------------------
diff --git a/modules/common/src/flex/messaging/util/ObjectTrace.java b/modules/common/src/flex/messaging/util/ObjectTrace.java
new file mode 100755
index 0000000..6477086
--- /dev/null
+++ b/modules/common/src/flex/messaging/util/ObjectTrace.java
@@ -0,0 +1,173 @@
+/*
+ * 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.
+ *
+ * @exclude
+ */
+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.
+     */
+    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/7a58369c/modules/common/src/flex/messaging/util/PrettyPrintable.java
----------------------------------------------------------------------
diff --git a/modules/common/src/flex/messaging/util/PrettyPrintable.java b/modules/common/src/flex/messaging/util/PrettyPrintable.java
new file mode 100755
index 0000000..3c2933b
--- /dev/null
+++ b/modules/common/src/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.
+ *
+ * @exclude
+ */
+public interface PrettyPrintable
+{
+    String toStringHeader();
+
+    String toStringCustomProperty(String name);
+}

http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/7a58369c/modules/common/src/flex/messaging/util/PrettyPrinter.java
----------------------------------------------------------------------
diff --git a/modules/common/src/flex/messaging/util/PrettyPrinter.java b/modules/common/src/flex/messaging/util/PrettyPrinter.java
new file mode 100755
index 0000000..c4e86c0
--- /dev/null
+++ b/modules/common/src/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.
+ *
+ * @exclude
+ */
+public interface PrettyPrinter
+{
+    String prettify(Object o);
+
+    Object copy();
+}

http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/7a58369c/modules/common/src/flex/messaging/util/PropertyStringResourceLoader.java
----------------------------------------------------------------------
diff --git a/modules/common/src/flex/messaging/util/PropertyStringResourceLoader.java b/modules/common/src/flex/messaging/util/PropertyStringResourceLoader.java
new file mode 100755
index 0000000..39f571d
--- /dev/null
+++ b/modules/common/src/flex/messaging/util/PropertyStringResourceLoader.java
@@ -0,0 +1,379 @@
+/*
+ * 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.InputStream;
+import java.io.IOException;
+import java.text.MessageFormat;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.TreeSet;
+
+import flex.messaging.log.Log;
+import flex.messaging.log.Logger;
+import flex.messaging.log.LogCategories;
+
+/**
+ * Implementation of <code>ResourceLoader</code> that loads string resources
+ * from property files.
+ * <p>
+ * This class uses <code>MessageFormat</code> to perform substitutions
+ * within parameterized strings.
+ * </p>
+ *
+ * @author Seth Hodgson
+ * @see MessageFormat
+ * @exclude
+ */
+public class PropertyStringResourceLoader implements ResourceLoader
+{
+    // The property file bundle that contains localized error strings for BlazeDS.
+    public static final String PROPERTY_BUNDLE = "flex/messaging/errors";
+
+    // The property file bundle that contains localized error strings for BlazeDS 
+    // code specific to vendors (eg. LoginCommands for specific application serves)
+    public static final String VENDORS_BUNDLE = "flex/messaging/vendors";
+    
+    // The property file bundle that contains localized error strings for LCDS.
+    public static final String LCDS_PROPERTY_BUNDLE = "flex/data/errors";
+
+    // The category to write log entries under.
+    private static final String LOG_CATEGORY = LogCategories.RESOURCE;
+
+    // The property bundle names to use in string lookups.
+    private String[] propertyBundles;
+
+    // The default FDS locale.
+    private Locale defaultLocale;
+
+    // The set of locales that have strings loaded.
+    private Set loadedLocales = new TreeSet();
+
+    // A map of all loaded strings.
+    private Map strings = new HashMap();
+
+    // The logger for this instance.
+    private Logger logger;
+
+    /**
+     * Constructs a <code>PropertyStringResourceLoader</code> using the default
+     * property bundles specified by the <code>PROPERTY_BUNDLE</code> and
+     * <code>LCDS_PROPERTY_BUNDLE</code> fields.
+     */
+    public PropertyStringResourceLoader()
+    {
+        this(new String[] {PROPERTY_BUNDLE, LCDS_PROPERTY_BUNDLE});
+    }
+
+    /**
+     * Constructs a <code>PropertyStringResourceLoader</code> that will use the
+     * specified property bundle to use for string lookups.
+     *
+     * @param propertyBundle The property bundles to use for lookups.
+     */
+    public PropertyStringResourceLoader(String propertyBundle)
+    {
+        this(new String[] {propertyBundle});
+    }
+
+    /**
+     * Constructs a <code>PropertyStringResourceLoader</code> that will use the
+     * specified property bundles to use for string lookups.
+     *
+     * @param propertyBundles The list of the property bundles to use for lookups.
+     */
+    public PropertyStringResourceLoader(String[] propertyBundles)
+    {
+        this.propertyBundles = propertyBundles;
+        logger = Log.getLogger(LOG_CATEGORY);
+    }
+
+    // Implements flex.messaging.util.ResourceLoader.init; inherits javadoc specification.
+    public void init(Map properties)
+    {}
+
+    // Implements flex.messaging.util.ResourceLoader.getString; inherits javadoc specification.
+    public String getString(String key)
+    {
+        return getString(key, null, null);
+    }
+
+    // Implements flex.messaging.util.ResourceLoader.getString; inherits javadoc specification.
+    public String getString(String key, Object[] arguments)
+    {
+        return getString(key, null, arguments);
+    }
+
+    // Implements flex.messaging.util.ResourceLoader.getString; inherits javadoc specification.
+    public String getString(String key, Locale locale)
+    {
+        return getString(key, locale, null);
+    }
+
+    // Implements flex.messaging.util.ResourceLoader.getString; inherits javadoc specification.
+    public String getString(String key, Locale locale, Object[] arguments)
+    {
+        synchronized(strings)
+        {
+            if (defaultLocale == null)
+            {
+                defaultLocale = getDefaultLocale();
+            }
+        }
+        String value = null;
+        String stringKey = null;
+        String localeKey = (locale != null) ?
+                           generateLocaleKey(locale) :
+                           generateLocaleKey(defaultLocale);
+        String originalStringKey = generateStringKey(key, localeKey);
+        int trimIndex = 0;
+
+        /*
+         * Attempt to get a string for the target locale - fail back to less specific
+         * versions of the locale.
+         */
+        while (true)
+        {
+            loadStrings(localeKey);
+            stringKey = generateStringKey(key, localeKey);
+            synchronized(strings)
+            {
+                value = (String) strings.get(stringKey);
+                if (value != null)
+                {
+                    if (!stringKey.equals(originalStringKey))
+                    {
+                        strings.put(originalStringKey, value);
+                    }
+                    return substituteArguments(value, arguments);
+                }
+            }
+            trimIndex = localeKey.lastIndexOf('_');
+            if (trimIndex != -1)
+            {
+                localeKey = localeKey.substring(0, trimIndex);
+            }
+            else
+            {
+                break;
+            }
+        }
+
+        /*
+         * Attempt to get the string in our default locale if it is
+         * different than the requested locale.
+         */
+        if ((locale != null) && (!locale.equals(defaultLocale)))
+        {
+            localeKey = generateLocaleKey(defaultLocale);
+            stringKey = generateStringKey(key, localeKey);
+            synchronized(strings)
+            {
+                value = (String) strings.get(stringKey);
+                if (value != null)
+                {
+                    strings.put(originalStringKey, value);
+                    return substituteArguments(value, arguments);
+                }
+            }
+        }
+
+        // As a last resort, try to get a non-locale-specific string.
+        loadStrings("");
+        stringKey = generateStringKey(key, "");
+        synchronized(strings)
+        {
+            value = (String) strings.get(stringKey);
+            if (value != null)
+            {
+                strings.put(originalStringKey, value);
+                return substituteArguments(value, arguments);
+            }
+        }
+
+        // No string is available. Return a formatted missing string value.
+        return ("???" + key + "???");
+    }
+
+    /**
+     * Sets the default locale to be used when locating resources. The
+     * string will be converted into a Locale.
+     *
+     * @param locale The default locale to be used.
+     */
+    public void setDefaultLocale(String locale)
+    {
+        defaultLocale = LocaleUtils.buildLocale(locale);
+    }
+
+    /**
+     * Sets the default locale to be used when locating resources.
+     *
+     * @param locale The default locale to be used.
+     */
+    public void setDefaultLocale(Locale locale)
+    {
+        defaultLocale = locale;
+    }
+
+    /**
+     * The default locale to be used when locating resources.
+     * @return Locale the default Locale object
+     */
+    public Locale getDefaultLocale()
+    {
+        if (defaultLocale == null)
+            defaultLocale = Locale.getDefault();
+
+        return defaultLocale;
+    }
+
+    /**
+     * Loads localized strings for the specified locale from a property file.
+     *
+     * @param localeKey The locale to load strings for.
+     */
+    protected synchronized void loadStrings(String localeKey)
+    {
+        if (loadedLocales.contains(localeKey))
+        {
+            return;
+        }
+
+        if (propertyBundles != null)
+        {
+            for (int i = 0; i < propertyBundles.length; i++)
+            {
+                String propertyBundle = propertyBundles[i];
+                loadProperties(localeKey, propertyBundle);
+            }
+        }
+    }
+
+    protected InputStream loadFile(String filename)
+    {
+        ClassLoader loader = Thread.currentThread().getContextClassLoader();
+        InputStream stream = loader.getResourceAsStream(filename);
+        
+        // Try the properties file in our classloader too - just in case
+        if (stream == null)
+        {
+            stream = PropertyStringResourceLoader.class.getClassLoader().getResourceAsStream(filename);
+        }
+        
+        return stream;
+    }
+    
+    // Helper method for loadStrings.
+    protected void loadProperties(String localeKey, String propertyBundle)
+    {
+        // Build the path to the target property file.
+        String filename = propertyBundle;
+        if (localeKey.length() > 0)
+        {
+            filename += "_" + localeKey;
+        }
+        filename += ".properties";
+        // Load the property file.
+        InputStream stream = loadFile(filename); 
+            
+        Properties props = new Properties();
+        if (stream != null)
+        {
+            try
+            {
+                props.load(stream);
+            }
+            catch (IOException ioe)
+            {
+                logger.warn("There was a problem reading the string resource property file '" + filename + "' stream.", ioe);
+            }
+            catch (IllegalArgumentException iae)
+            {
+                logger.warn("The string resource property file '" + filename + "' contains a malformed Unicode escape sequence.", iae);
+            }
+            finally
+            {
+                try
+                {
+                    stream.close();
+                }
+                catch (IOException ioe)
+                {
+                    logger.warn("The string resource property file '" + filename + "' stream failed to close.", ioe);
+                }
+            }
+        }
+        else
+        {
+            logger.warn("The class loader could not locate the string resource property file '" + filename + "'. This may not be an issue if a property file is available for a less specific locale or the default locale.");
+        }
+        // Move strings into string cache.
+        if (props.size() > 0)
+        {
+            synchronized(strings)
+            {
+                Iterator iter = props.keySet().iterator();
+                while (iter.hasNext())
+                {
+                    String key = (String) iter.next();
+                    strings.put(generateStringKey(key, localeKey), props.getProperty(key));
+                }
+            }
+        }
+    }
+
+    /**
+     * Generates a locale cache key.
+     *
+     * @param locale The locale to generate a cache key for.
+     * @return The generated cache key.
+     */
+    private String generateLocaleKey(Locale locale)
+    {
+        return (locale == null) ? "" : locale.toString();
+    }
+
+    /**
+     * Generates a cache key for a string resource.
+     *
+     * @param key The string to generate a cache key for.
+     * @param locale The locale to retrieve the string for.
+     * @return The generated cache key for the string resource.
+     */
+    private String generateStringKey(String key, String locale)
+    {
+        return (key + "-" + locale);
+    }
+
+    /**
+     * Substitutes the specified arguments into a parameterized string.
+     *
+     * @param parameterized The string containing parameter tokens for substitution.
+     * @param arguments The arguments to substitute into the parameterized string.
+     * @return The resulting substituted string.
+     */
+    private String substituteArguments(String parameterized, Object[] arguments)
+    {
+        return MessageFormat.format(parameterized, arguments).trim();
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/7a58369c/modules/common/src/flex/messaging/util/ResourceLoader.java
----------------------------------------------------------------------
diff --git a/modules/common/src/flex/messaging/util/ResourceLoader.java b/modules/common/src/flex/messaging/util/ResourceLoader.java
new file mode 100755
index 0000000..0ea39b0
--- /dev/null
+++ b/modules/common/src/flex/messaging/util/ResourceLoader.java
@@ -0,0 +1,105 @@
+/*
+ * 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;
+import java.util.Map;
+
+/**
+ * The root interface for classes that provide access to localized resources.
+ *
+ * @author Seth Hodgson
+ * @exclude
+ */
+public interface ResourceLoader
+{
+    /**
+     * Initializes the <code>ResourceLoader</code> using the specified properties.
+     *
+     * @param properties The initialization properties.
+     */
+    void init(Map properties);
+
+    /**
+     * Sets the default locale to be used when locating resources. The
+     * string will be converted into a Locale.
+     *
+     * @param locale The default locale to be used.
+     */
+    void setDefaultLocale(String locale);
+
+    /**
+     * Sets the default locale to be used when locating resources.
+     *
+     * @param locale The default locale to be used.
+     */
+    void setDefaultLocale(Locale locale);
+
+    /**
+     * The default locale to be used when locating resources.
+     *
+     * @return The default locale.
+     */
+    Locale getDefaultLocale();
+
+    /**
+     * Gets a string for the given key.
+     *
+     * @param key The key for the target string.
+     * @return The string for the given key.
+     */
+    String getString(String key);
+
+    /**
+     * Gets a parameterized string for the given key and substitutes
+     * the parameters using the passed array of arguments.
+     *
+     * @param key The key for the target string.
+     * @param arguments The arguments to substitute into the parameterized string.
+     * @return The substituted string for the given key.
+     * @exception IllegalArgumentException If the parameterized string is invalid,
+     *            or if an argument in the <code>arguments</code> array
+     *            is not of the type expected by the format element(s)
+     *            that use it.
+     */
+    String getString(String key, Object[] arguments);
+
+    /**
+     * Gets a string for the given key and locale.
+     *
+     * @param key The key for the target string.
+     * @param locale The target locale for the string.
+     * @return The localized string for the given key.
+     */
+    String getString(String key, Locale locale);
+
+    /**
+     * Gets a parameterized string for the given key and locale and substitutes the
+     * parameters using the passed array of arguments.
+     *
+     * @param key The key for the target string.
+     * @param locale The target locale for the string.
+     * @param arguments The arguments to substitute into the parameterized string.
+     * @return The substituted localized string for the given key.
+     * @exception IllegalArgumentException If the parameterized string is invalid,
+     *            or if an argument in the <code>arguments</code> array
+     *            is not of the type expected by the format element(s)
+     *            that use it.
+     */
+    String getString(String key, Locale locale, Object[] arguments);
+
+}

http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/7a58369c/modules/common/src/flex/messaging/util/StringUtils.java
----------------------------------------------------------------------
diff --git a/modules/common/src/flex/messaging/util/StringUtils.java b/modules/common/src/flex/messaging/util/StringUtils.java
new file mode 100755
index 0000000..7eca7e6
--- /dev/null
+++ b/modules/common/src/flex/messaging/util/StringUtils.java
@@ -0,0 +1,214 @@
+/*
+ * 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.StringReader;
+import java.io.StringWriter;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.TransformerFactoryConfigurationError;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+
+/**
+ * @exclude
+ */
+public class StringUtils
+{
+    /**
+     * The String to use for an OS specific line separator.
+     */
+    public static final String NEWLINE = System.getProperty("line.separator");
+
+    public static String substitute(String str, String from, String to)
+    {
+        if (from == null || from.equals("") || to == null)
+            return str;
+
+        int index = str.indexOf(from);
+
+        if (index == -1)
+            return str;
+
+        StringBuffer buf = new StringBuffer(str.length());
+        int lastIndex = 0;
+
+        while (index != -1)
+        {
+            buf.append(str.substring(lastIndex, index));
+            buf.append(to);
+            lastIndex = index + from.length();
+            index = str.indexOf(from, lastIndex);
+        }
+
+        // add in last chunk
+        buf.append(str.substring(lastIndex));
+
+        return buf.toString();
+    }
+
+    public static boolean findMatchWithWildcard(char[] src, char[] pat)
+    {
+        if (src == null || pat == null)
+            return false;
+
+        // we consider an empty pattern to be a don't-match-anything pattern
+        if (pat.length == 0)
+            return false;
+
+        if (src.length == 0)
+            return (pat.length == 0 || (pat.length == 1 && (pat[0] == '*' || pat[0] == '?')));
+
+        boolean star = false;
+
+        int srcLen = src.length;
+        int patLen = pat.length;
+        int srcIdx = 0;
+        int patIdx = 0;
+
+        for (; srcIdx < srcLen; srcIdx++)
+        {
+            if (patIdx == patLen)
+            {
+                if (patLen < (srcLen - srcIdx))
+                    patIdx = 0; //Start the search again
+                else
+                    return false;
+            }
+
+            char s = src[srcIdx];
+            char m = pat[patIdx];
+
+            switch (m)
+            {
+                case '*':
+                    // star on the end
+                    if (patIdx == pat.length - 1)
+                        return true;
+                    star = true;
+                    ++patIdx;
+                    break;
+
+                case '?':
+                    ++patIdx;
+                    break;
+
+                default:
+                    if (s != m)
+                    {
+                        if (!star)
+                        {
+                            if (patLen < (srcLen - srcIdx))
+                                patIdx = 0; //Start the search again
+                            else
+                                return false;
+                        }
+                    }
+                    else
+                    {
+                        star = false;
+                        ++patIdx;
+                    }
+                    break;
+            }
+        }
+
+        if (patIdx < patLen)
+        {
+            //read off the rest of the pattern and make sure it's all wildcard
+            for (; patIdx < patLen; patLen++)
+            {
+                if (pat[patIdx] != '*')
+                {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+
+        return !star;
+    }
+
+    /**
+     * Returns a prettified version of the XML, with indentations and
+     * linefeeds.  Returns the original string if there was an error.
+     * @param xml the xml string
+     * @return String the prettified xml string
+     */
+    public static String prettifyXML(String xml)
+    {
+        String result = xml;
+        try
+        {
+            StringReader reader = new StringReader(xml);
+            StringWriter writer = new StringWriter();
+            Transformer transformer =
+                TransformerFactory.newInstance().newTransformer();
+            transformer.setOutputProperty(OutputKeys.METHOD, "xml");
+            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+            transformer.transform
+                (new StreamSource(reader), new StreamResult(writer));
+            writer.close();
+
+            result = writer.toString();
+        }
+        catch (TransformerFactoryConfigurationError error)
+        {
+            // Ignore.
+        }
+        catch (TransformerException error)
+        {
+            // Ignore.
+        }
+        catch (IOException error)
+        {
+            // Ignore.
+        }
+        return result;
+    }
+
+    /**
+     * Returns a prettified version of the string, or the original
+     * string if the operation is not possible.
+     * @param string the string to check
+     * @return String the prettified string
+     */
+    public static String prettifyString(String string)
+    {
+        String result = string;
+        if (string.startsWith("<?xml"))
+        {
+            result = prettifyXML(string);
+        }
+        return result;
+    }
+
+    /**
+     * Returns true if a string is null or empty.
+     * @param string the String to check
+     * @return boolean true if the string is an empty string
+     */
+    public static boolean isEmpty(String string)
+    {
+        return string == null || string.length() == 0;
+    }
+}
+

http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/7a58369c/modules/common/src/flex/messaging/util/UUIDUtils.java
----------------------------------------------------------------------
diff --git a/modules/common/src/flex/messaging/util/UUIDUtils.java b/modules/common/src/flex/messaging/util/UUIDUtils.java
new file mode 100755
index 0000000..8df82e3
--- /dev/null
+++ b/modules/common/src/flex/messaging/util/UUIDUtils.java
@@ -0,0 +1,330 @@
+/*
+ * 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.Random;
+import java.util.UUID;
+
+public class UUIDUtils
+{
+    private static Random _weakRand = new Random();
+	
+    /**
+     * The spec indicates that our time value should be based on 100 nano
+     * second increments but our time granularity is in milliseconds.
+     * The spec also says we can approximate the time by doing an increment
+     * when we dole out new ids in the same millisecond.  We can fit 10,000
+     * 100 nanos into a single millisecond.
+     */
+    private static final int MAX_IDS_PER_MILLI = 10000;
+	
+    /**
+     *  Any given time-of-day value can only be used once; remember the last used
+     *  value so we don't reuse them.
+     *  <p>NOTE: this algorithm assumes the clock will not be turned back.
+     */
+    private static long lastUsedTOD = 0;
+    /** Counter to use when we need more than one id in the same millisecond. */
+    private static int numIdsThisMilli = 0;
+	
+    /**  Hex digits, used for padding UUID strings with random characters. */
+    private static final String alphaNum = "0123456789ABCDEF";
+	
+    /** 4 bits per hex character. */
+    private static final int BITS_PER_DIGIT = 4;
+	
+    private static final int BITS_PER_INT = 32;
+    private static final int BITS_PER_LONG = 64;
+    private static final int DIGITS_PER_INT = BITS_PER_INT / BITS_PER_DIGIT;
+    private static final int DIGITS_PER_LONG = BITS_PER_LONG / BITS_PER_DIGIT;
+	
+    /**
+     *  @private
+     */
+    private static char[] UPPER_DIGITS = new char[] {
+	'0', '1', '2', '3', '4', '5', '6', '7',
+	'8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
+    };
+	
+    /**
+     * Private constructor to prevent instances from being created.
+     */
+    private UUIDUtils()
+    {
+    }
+	
+    /**
+     *
+     * Use the createUUID function when you need a unique string that you will
+     * use as a persistent identifier in a distributed environment. To a very
+     * high degree of certainty, this function returns a unique value; no other
+     * invocation on the same or any other system should return the same value.
+     *
+     * @return a Universally Unique Identifier (UUID)
+     * Proper Format: `XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'
+     * where `X' stands for a hexadecimal digit (0-9 or A-F).
+     */
+    public static String createUUID()
+    {
+		return createUUID(false);
+	}
+	
+    public static String createUUID(boolean secure) throws Error
+    {
+        Random rand = _weakRand;
+		if (secure)
+			throw new Error("Secure UUIDs not implemented");
+		
+        StringBuffer s = new StringBuffer(36);
+		
+        appendHexString(uniqueTOD(), false, 11, s);
+		
+        //  Just use random padding characters, but ensure that the high bit
+        //  is set to eliminate chances of collision with an IEEE 802 address.
+        s.append(  alphaNum.charAt( rand.nextInt(16) | 8 ) );
+		
+        //  Add random padding characters.
+        appendRandomHexChars(32 - s.length(), rand, s);
+		
+        //insert dashes in proper position. so the format matches CF
+        s.insert(8,"-");
+        s.insert(13,"-");
+        s.insert(18,"-");
+        s.insert(23,"-");
+		
+        return s.toString();
+    }
+
+    /**
+     * Converts a 128-bit UID encoded as a byte[] to a String representation.
+     * The format matches that generated by createUID. If a suitable byte[]
+     * is not provided, null is returned.
+     *
+     * @param ba byte[] 16 bytes in length representing a 128-bit UID.
+     *
+     * @return String representation of the UID, or null if an invalid
+     * byte[] is provided.
+     */
+    public static String fromByteArray(byte[] ba)
+    {
+        if (ba == null || ba.length != 16)
+            return null;
+
+        StringBuffer result = new StringBuffer(36);
+        for (int i = 0; i < 16; i++)
+        {
+            if (i == 4 || i == 6 || i == 8 || i == 10)
+                result.append('-');
+
+            result.append(UPPER_DIGITS[(ba[i] & 0xF0) >>> 4]);
+            result.append(UPPER_DIGITS[(ba[i] & 0x0F)]);
+        }
+        return result.toString();
+    }
+
+	
+    /**
+     * A utility method to check whether a String value represents a
+     * correctly formatted UID value. UID values are expected to be
+     * in the format generated by createUID(), implying that only
+     * capitalized A-F characters in addition to 0-9 digits are
+     * supported.
+     *
+     * @param uid The value to test whether it is formatted as a UID.
+     *
+     * @return Returns true if the value is formatted as a UID.
+     */
+    public static boolean isUID(String uid)
+    {
+        if (uid == null || uid.length() != 36)
+            return false;
+
+        char[] chars = uid.toCharArray();
+        for (int i = 0; i < 36; i++)
+        {
+            char c = chars[i];
+
+            // Check for correctly placed hyphens
+            if (i == 8 || i == 13 || i == 18 || i == 23)
+            {
+                if (c != '-')
+                    return false;
+            }
+            // We allow capital alpha-numeric hex digits only
+            else if (c < 48 || c > 70 || (c > 57 && c < 65))
+            {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    /**
+     * Converts a UID formatted String to a byte[]. The UID must be in the
+     * format generated by createUID, otherwise null is returned.
+     *
+     * @param uid String representing a 128-bit UID.
+     *
+     * @return byte[] 16 bytes in length representing the 128-bits of the
+     * UID or null if the uid could not be converted.
+     */
+    public static byte[] toByteArray(String uid)
+    {
+        if (!isUID(uid))
+            return null;
+
+        byte[] result = new byte[16];
+        char[] chars = uid.toCharArray();
+        int r = 0;
+
+        for (int i = 0; i < chars.length; i++)
+        {
+            if (chars[i] == '-')
+                continue;
+            int h1 = Character.digit(chars[i], 16);
+            i++;
+            int h2 = Character.digit(chars[i], 16);
+            result[r++] = (byte)(((h1 << 4) | h2) & 0xFF);
+        }
+        return result;
+    }
+
+    private static void appendRandomHexChars(int n, Random rand, StringBuffer result)
+    {
+        int digitsPerInt = DIGITS_PER_INT;
+        while (n > 0)
+        {
+            int digitsToUse = Math.min(n, digitsPerInt);
+            n -= digitsToUse;
+            appendHexString(rand.nextInt(), true, digitsToUse, result);
+        }
+    }
+
+    private static void appendHexString
+        (long value, boolean prependZeroes, int nLeastSignificantDigits,
+         StringBuffer result)
+    {
+        int bitsPerDigit = BITS_PER_DIGIT;
+
+        long mask = (1L << bitsPerDigit) - 1;
+
+        if (nLeastSignificantDigits < DIGITS_PER_LONG)
+        {
+            // Clear the bits that we don't care about.
+            value &= (1L << (bitsPerDigit * nLeastSignificantDigits)) - 1;
+        }
+
+        // Reorder the sequence so that the first set of bits will become the
+        // last set of bits.
+        int i = 0;
+        long reorderedValue = 0;
+        if (value == 0)
+        {
+            // One zero is dumped.
+            i++;
+        }
+        else
+        {
+            do
+            {
+                reorderedValue = (reorderedValue << bitsPerDigit) | (value & mask);
+                value >>>= bitsPerDigit;
+                i++;
+            } while (value != 0);
+        }
+
+        if (prependZeroes)
+        {
+            for (int j = nLeastSignificantDigits - i; j > 0; j--)
+            {
+                result.append('0');
+            }
+        }
+
+
+        // Dump the reordered sequence, with the most significant character
+        // first.
+        for (; i > 0; i--)
+        {
+            result.append(alphaNum.charAt((int) (reorderedValue & mask)));
+            reorderedValue >>>= bitsPerDigit;
+        }
+    }
+
+    private static String createInsecureUUID()
+    {
+        StringBuffer s = new StringBuffer(36);
+
+        appendHexString(uniqueTOD(), false, 11, s);
+
+        //  Just use random padding characters, but ensure that the high bit
+        //  is set to eliminate chances of collision with an IEEE 802 address.
+        s.append(  alphaNum.charAt( _weakRand.nextInt(16) | 8 ) );
+
+        //  Add random padding characters.
+        appendRandomHexChars(32 - s.length(), _weakRand, s);
+
+        //insert dashes in proper position. so the format matches CF
+        s.insert(8,"-");
+        s.insert(13,"-");
+        s.insert(18,"-");
+        s.insert(23,"-");
+
+        return s.toString();
+    }
+
+    /**
+     *  @return a time value, unique for calls to this method loaded by the same classloader.
+     */
+    private static synchronized long uniqueTOD()
+    {
+        long currentTOD = System.currentTimeMillis();
+
+        // Clock was set back... do not hang in this case waiting to catch up.
+        // Instead, rely on the random number part to differentiate the ids.
+        if (currentTOD < lastUsedTOD)
+            lastUsedTOD = currentTOD;
+
+        if (currentTOD == lastUsedTOD)
+        {
+            numIdsThisMilli++;
+            /*
+             * Fall back to the old technique of sleeping if we allocate
+             * too many ids in one time interval.
+             */
+            if (numIdsThisMilli >= MAX_IDS_PER_MILLI)
+            {
+                while ( currentTOD == lastUsedTOD )
+                {
+                    try { Thread.sleep(1); } catch ( Exception interrupt ) { /* swallow, wake up */ }
+                    currentTOD = System.currentTimeMillis();
+                }
+                lastUsedTOD = currentTOD;
+                numIdsThisMilli = 0;
+            }
+        }
+        else
+        {
+            //  We have a new TOD, reset the counter
+            lastUsedTOD = currentTOD;
+            numIdsThisMilli = 0;
+        }
+
+        return lastUsedTOD * MAX_IDS_PER_MILLI + (long)numIdsThisMilli;
+    }
+}

http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/7a58369c/modules/core/AdobeInfo.xml
----------------------------------------------------------------------
diff --git a/modules/core/AdobeInfo.xml b/modules/core/AdobeInfo.xml
new file mode 100755
index 0000000..3504592
--- /dev/null
+++ b/modules/core/AdobeInfo.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+  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.
+
+-->
+    <manifest version="1.0">
+    <versioninfo> 
+        <build AdobeIPNumber="0000494"/>
+    </versioninfo>
+</manifest>
\ No newline at end of file