You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by tr...@apache.org on 2006/01/20 14:48:55 UTC

svn commit: r370807 [17/22] - in /directory/sandbox/trustin/mina-spi: ./ core/src/main/java/org/apache/mina/common/ core/src/main/java/org/apache/mina/common/support/ core/src/main/java/org/apache/mina/common/support/discovery/ core/src/main/java/org/a...

Added: directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/exception/NestableDelegate.java
URL: http://svn.apache.org/viewcvs/directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/exception/NestableDelegate.java?rev=370807&view=auto
==============================================================================
--- directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/exception/NestableDelegate.java (added)
+++ directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/exception/NestableDelegate.java Fri Jan 20 05:47:50 2006
@@ -0,0 +1,410 @@
+/*
+ * Copyright 2002-2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.mina.common.support.lang.exception;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.io.Serializable;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * <p>A shared implementation of the nestable exception functionality.</p>
+ * <p>
+ * The code is shared between 
+ * {@link org.apache.mina.common.support.lang.exception.NestableError NestableError},
+ * {@link org.apache.mina.common.support.lang.exception.NestableException NestableException} and
+ * {@link org.apache.mina.common.support.lang.exception.NestableRuntimeException NestableRuntimeException}.
+ * </p>
+ * 
+ * @author <a href="mailto:Rafal.Krzewski@e-point.pl">Rafal Krzewski</a>
+ * @author <a href="mailto:dlr@collab.net">Daniel Rall</a>
+ * @author <a href="mailto:knielsen@apache.org">Kasper Nielsen</a>
+ * @author <a href="mailto:steven@caswell.name">Steven Caswell</a>
+ * @author Sean C. Sullivan
+ * @author Stephen Colebourne
+ * @since 1.0
+ * @version $Id$
+ */
+public class NestableDelegate implements Serializable {
+
+    /**
+     * Constructor error message.
+     */
+    private transient static final String MUST_BE_THROWABLE =
+        "The Nestable implementation passed to the NestableDelegate(Nestable) "
+            + "constructor must extend java.lang.Throwable";
+
+    /**
+     * Holds the reference to the exception or error that we're
+     * wrapping (which must be a {@link
+     * org.apache.mina.common.support.lang.exception.Nestable} implementation).
+     */
+    private Throwable nestable = null;
+    
+    /**
+     * Whether to print the stack trace top-down.
+     * This public flag may be set by calling code, typically in initialisation.
+     * This exists for backwards compatability, setting it to false will return
+     * the library to v1.0 behaviour (but will affect all users of the library
+     * in the classloader).
+     * @since 2.0
+     */
+    public static boolean topDown = true;
+    
+    /**
+     * Whether to trim the repeated stack trace.
+     * This public flag may be set by calling code, typically in initialisation.
+     * This exists for backwards compatability, setting it to false will return
+     * the library to v1.0 behaviour (but will affect all users of the library
+     * in the classloader).
+     * @since 2.0
+     */
+    public static boolean trimStackFrames = true;
+    
+    /**
+     * Whether to match subclasses via indexOf.
+     * This public flag may be set by calling code, typically in initialisation.
+     * This exists for backwards compatability, setting it to false will return
+     * the library to v2.0 behaviour (but will affect all users of the library
+     * in the classloader).
+     * @since 2.1
+     */
+    public static boolean matchSubclasses = true;
+
+    /**
+     * Constructs a new <code>NestableDelegate</code> instance to manage the
+     * specified <code>Nestable</code>.
+     *
+     * @param nestable the Nestable implementation (<i>must</i> extend
+     * {@link java.lang.Throwable})
+     * @since 2.0
+     */
+    public NestableDelegate(Nestable nestable) {
+        if (nestable instanceof Throwable) {
+            this.nestable = (Throwable) nestable;
+        } else {
+            throw new IllegalArgumentException(MUST_BE_THROWABLE);
+        }
+    }
+
+    /**
+     * Returns the error message of the <code>Throwable</code> in the chain
+     * of <code>Throwable</code>s at the specified index, numbered from 0.
+     *
+     * @param index the index of the <code>Throwable</code> in the chain of
+     * <code>Throwable</code>s
+     * @return the error message, or null if the <code>Throwable</code> at the
+     * specified index in the chain does not contain a message
+     * @throws IndexOutOfBoundsException if the <code>index</code> argument is
+     * negative or not less than the count of <code>Throwable</code>s in the
+     * chain
+     * @since 2.0
+     */
+    public String getMessage(int index) {
+        Throwable t = this.getThrowable(index);
+        if (Nestable.class.isInstance(t)) {
+            return ((Nestable) t).getMessage(0);
+        } else {
+            return t.getMessage();
+        }
+    }
+
+    /**
+     * Returns the full message contained by the <code>Nestable</code>
+     * and any nested <code>Throwable</code>s.
+     *
+     * @param baseMsg the base message to use when creating the full
+     * message. Should be generally be called via
+     * <code>nestableHelper.getMessage(super.getMessage())</code>,
+     * where <code>super</code> is an instance of {@link
+     * java.lang.Throwable}.
+     * @return The concatenated message for this and all nested
+     * <code>Throwable</code>s
+     * @since 2.0
+     */
+    public String getMessage(String baseMsg) {
+        StringBuffer msg = new StringBuffer();
+        if (baseMsg != null) {
+            msg.append(baseMsg);
+        }
+
+        Throwable nestedCause = ExceptionUtils.getCause(this.nestable);
+        if (nestedCause != null) {
+            String causeMsg = nestedCause.getMessage();
+            if (causeMsg != null) {
+                if (baseMsg != null) {
+                    msg.append(": ");
+                }
+                msg.append(causeMsg);
+            }
+
+        }
+        return msg.length() > 0 ? msg.toString() : null;
+    }
+
+    /**
+     * Returns the error message of this and any nested <code>Throwable</code>s
+     * in an array of Strings, one element for each message. Any
+     * <code>Throwable</code> not containing a message is represented in the
+     * array by a null. This has the effect of cause the length of the returned
+     * array to be equal to the result of the {@link #getThrowableCount()}
+     * operation.
+     *
+     * @return the error messages
+     * @since 2.0
+     */
+    public String[] getMessages() {
+        Throwable[] throwables = this.getThrowables();
+        String[] msgs = new String[throwables.length];
+        for (int i = 0; i < throwables.length; i++) {
+            msgs[i] =
+                (Nestable.class.isInstance(throwables[i])
+                    ? ((Nestable) throwables[i]).getMessage(0)
+                    : throwables[i].getMessage());
+        }
+        return msgs;
+    }
+
+    /**
+     * Returns the <code>Throwable</code> in the chain of
+     * <code>Throwable</code>s at the specified index, numbered from 0.
+     *
+     * @param index the index, numbered from 0, of the <code>Throwable</code> in
+     * the chain of <code>Throwable</code>s
+     * @return the <code>Throwable</code>
+     * @throws IndexOutOfBoundsException if the <code>index</code> argument is
+     * negative or not less than the count of <code>Throwable</code>s in the
+     * chain
+     * @since 2.0
+     */
+    public Throwable getThrowable(int index) {
+        if (index == 0) {
+            return this.nestable;
+        }
+        Throwable[] throwables = this.getThrowables();
+        return throwables[index];
+    }
+
+    /**
+     * Returns the number of <code>Throwable</code>s contained in the
+     * <code>Nestable</code> contained by this delegate.
+     *
+     * @return the throwable count
+     * @since 2.0
+     */
+    public int getThrowableCount() {
+        return ExceptionUtils.getThrowableCount(this.nestable);
+    }
+
+    /**
+     * Returns this delegate's <code>Nestable</code> and any nested
+     * <code>Throwable</code>s in an array of <code>Throwable</code>s, one
+     * element for each <code>Throwable</code>.
+     *
+     * @return the <code>Throwable</code>s
+     * @since 2.0
+     */
+    public Throwable[] getThrowables() {
+        return ExceptionUtils.getThrowables(this.nestable);
+    }
+
+    /**
+     * Returns the index, numbered from 0, of the first <code>Throwable</code>
+     * that matches the specified type, or a subclass, in the chain of <code>Throwable</code>s
+     * with an index greater than or equal to the specified index.
+     * The method returns -1 if the specified type is not found in the chain.
+     * <p>
+     * NOTE: From v2.1, we have clarified the <code>Nestable</code> interface
+     * such that this method matches subclasses.
+     * If you want to NOT match subclasses, please use
+     * {@link ExceptionUtils#indexOfThrowable(Throwable, Class, int)}
+     * (which is avaiable in all versions of lang).
+     * An alternative is to use the public static flag {@link #matchSubclasses}
+     * on <code>NestableDelegate</code>, however this is not recommended.
+     *
+     * @param type  the type to find, subclasses match, null returns -1
+     * @param fromIndex the index, numbered from 0, of the starting position in
+     * the chain to be searched
+     * @return index of the first occurrence of the type in the chain, or -1 if
+     * the type is not found
+     * @throws IndexOutOfBoundsException if the <code>fromIndex</code> argument
+     * is negative or not less than the count of <code>Throwable</code>s in the
+     * chain
+     * @since 2.0
+     */
+    public int indexOfThrowable(Class type, int fromIndex) {
+        if (type == null) {
+            return -1;
+        }
+        if (fromIndex < 0) {
+            throw new IndexOutOfBoundsException("The start index was out of bounds: " + fromIndex);
+        }
+        Throwable[] throwables = ExceptionUtils.getThrowables(this.nestable);
+        if (fromIndex >= throwables.length) {
+            throw new IndexOutOfBoundsException("The start index was out of bounds: "
+                + fromIndex + " >= " + throwables.length);
+        }
+        if (matchSubclasses) {
+            for (int i = fromIndex; i < throwables.length; i++) {
+                if (type.isAssignableFrom(throwables[i].getClass())) {
+                    return i;
+                }
+            }
+        } else {
+            for (int i = fromIndex; i < throwables.length; i++) {
+                if (type.equals(throwables[i].getClass())) {
+                    return i;
+                }
+            }
+        }
+        return -1;
+    }
+
+    /**
+     * Prints the stack trace of this exception the the standar error
+     * stream.
+     */
+    public void printStackTrace() {
+        printStackTrace(System.err);
+    }
+
+    /**
+     * Prints the stack trace of this exception to the specified
+     * stream.
+     *
+     * @param out <code>PrintStream</code> to use for output.
+     * @see #printStackTrace(PrintWriter)
+     */
+    public void printStackTrace(PrintStream out) {
+        synchronized (out) {
+            PrintWriter pw = new PrintWriter(out, false);
+            printStackTrace(pw);
+            // Flush the PrintWriter before it's GC'ed.
+            pw.flush();
+        }
+    }
+
+    /**
+     * Prints the stack trace of this exception to the specified
+     * writer. If the Throwable class has a <code>getCause</code>
+     * method (i.e. running on jre1.4 or higher), this method just 
+     * uses Throwable's printStackTrace() method. Otherwise, generates
+     * the stack-trace, by taking into account the 'topDown' and 
+     * 'trimStackFrames' parameters. The topDown and trimStackFrames 
+     * are set to 'true' by default (produces jre1.4-like stack trace).
+     *
+     * @param out <code>PrintWriter</code> to use for output.
+     */
+    public void printStackTrace(PrintWriter out) {
+        Throwable throwable = this.nestable;
+        // if running on jre1.4 or higher, use default printStackTrace
+        if (ExceptionUtils.isThrowableNested()) {
+            if (throwable instanceof Nestable) {
+                ((Nestable)throwable).printPartialStackTrace(out);
+            } else {
+                throwable.printStackTrace(out);
+            }
+            return;
+        }
+
+        // generating the nested stack trace
+        List stacks = new ArrayList();
+        while (throwable != null) {
+            String[] st = getStackFrames(throwable);
+            stacks.add(st);
+            throwable = ExceptionUtils.getCause(throwable);
+        }
+
+        // If NOT topDown, reverse the stack
+        String separatorLine = "Caused by: ";
+        if (!topDown) {
+            separatorLine = "Rethrown as: ";
+            Collections.reverse(stacks);
+        }
+
+        // Remove the repeated lines in the stack
+        if (trimStackFrames) {
+          trimStackFrames(stacks);
+        }
+
+        synchronized (out) {
+            for (Iterator iter=stacks.iterator(); iter.hasNext();) {
+                String[] st = (String[]) iter.next();
+                for (int i=0, len=st.length; i < len; i++) {
+                    out.println(st[i]);
+                }
+                if (iter.hasNext()) {
+                    out.print(separatorLine);
+                }
+            }
+        }
+    }
+
+    /**
+     * Captures the stack trace associated with the specified
+     * <code>Throwable</code> object, decomposing it into a list of
+     * stack frames.
+     *
+     * @param t The <code>Throwable</code>.
+     * @return  An array of strings describing each stack frame.
+     * @since 2.0
+     */
+    protected String[] getStackFrames(Throwable t) {
+        StringWriter sw = new StringWriter();
+        PrintWriter pw = new PrintWriter(sw, true);
+
+        // Avoid infinite loop between decompose() and printStackTrace().
+        if (t instanceof Nestable) {
+            ((Nestable) t).printPartialStackTrace(pw);
+        } else {
+            t.printStackTrace(pw);
+        }
+        return ExceptionUtils.getStackFrames(sw.getBuffer().toString());
+    }
+    
+    /**
+     * Trims the stack frames. The first set is left untouched. The rest
+     * of the frames are truncated from the bottom by comparing with
+     * one just on top.
+     *
+     * @param stacks The list containing String[] elements
+     * @since 2.0
+     */
+    protected void trimStackFrames(List stacks) {
+         for (int size=stacks.size(), i=size-1; i > 0; i--) {
+             String[] curr = (String[]) stacks.get(i);
+             String[] next = (String[]) stacks.get(i-1); 
+             
+             List currList = new ArrayList(Arrays.asList(curr));
+             List nextList = new ArrayList(Arrays.asList(next));
+             ExceptionUtils.removeCommonFrames(currList, nextList);
+
+             int trimmed = curr.length - currList.size();
+             if (trimmed > 0) {
+                 currList.add("\t... "+trimmed+" more");
+                 stacks.set(
+                     i, 
+                     currList.toArray(new String[currList.size()])
+                 );
+             }
+         }
+     }
+}

Propchange: directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/exception/NestableDelegate.java
------------------------------------------------------------------------------
    svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision

Added: directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/exception/NestableError.java
URL: http://svn.apache.org/viewcvs/directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/exception/NestableError.java?rev=370807&view=auto
==============================================================================
--- directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/exception/NestableError.java (added)
+++ directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/exception/NestableError.java Fri Jan 20 05:47:50 2006
@@ -0,0 +1,154 @@
+/*
+ * Copyright 2002-2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.mina.common.support.lang.exception;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+
+/**
+ * The base class of all errors which can contain other exceptions.
+ *
+ * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
+ * @see org.apache.mina.common.support.lang.exception.NestableException
+ * @since 1.0
+ * @version $Id$
+ */
+public class NestableError extends Error implements Nestable {
+
+    /**
+     * The helper instance which contains much of the code which we
+     * delegate to.
+     */
+    protected NestableDelegate delegate = new NestableDelegate(this);
+
+    /**
+     * Holds the reference to the exception or error that caused
+     * this exception to be thrown.
+     */
+    private Throwable cause = null;
+
+    /**
+     * Constructs a new <code>NestableError</code> without specified
+     * detail message.
+     */
+    public NestableError() {
+        super();
+    }
+
+    /**
+     * Constructs a new <code>NestableError</code> with specified
+     * detail message.
+     *
+     * @param msg The error message.
+     */
+    public NestableError(String msg) {
+        super(msg);
+    }
+
+    /**
+     * Constructs a new <code>NestableError</code> with specified
+     * nested <code>Throwable</code>.
+     *
+     * @param cause the exception or error that caused this exception to be
+     * thrown
+     */
+    public NestableError(Throwable cause) {
+        super();
+        this.cause = cause;
+    }
+
+    /**
+     * Constructs a new <code>NestableError</code> with specified
+     * detail message and nested <code>Throwable</code>.
+     *
+     * @param msg    the error message
+     * @param cause  the exception or error that caused this exception to be
+     * thrown
+     */
+    public NestableError(String msg, Throwable cause) {
+        super(msg);
+        this.cause = cause;
+    }
+
+    public Throwable getCause() {
+        return cause;
+    }
+
+    /**
+     * Returns the detail message string of this throwable. If it was
+     * created with a null message, returns the following:
+     * (cause==null ? null : cause.toString()).
+     *
+     * @return String message string of the throwable
+     */
+    public String getMessage() {
+        if (super.getMessage() != null) {
+            return super.getMessage();
+        } else if (cause != null) {
+            return cause.toString();
+        } else {
+            return null;
+        }
+    }
+
+    public String getMessage(int index) {
+        if (index == 0) {
+            return super.getMessage();
+        } else {
+            return delegate.getMessage(index);
+        }
+    }
+
+    public String[] getMessages() {
+        return delegate.getMessages();
+    }
+
+    public Throwable getThrowable(int index) {
+        return delegate.getThrowable(index);
+    }
+
+    public int getThrowableCount() {
+        return delegate.getThrowableCount();
+    }
+
+    public Throwable[] getThrowables() {
+        return delegate.getThrowables();
+    }
+
+    public int indexOfThrowable(Class type) {
+        return delegate.indexOfThrowable(type, 0);
+    }
+
+    public int indexOfThrowable(Class type, int fromIndex) {
+        return delegate.indexOfThrowable(type, fromIndex);
+    }
+
+    public void printStackTrace() {
+        delegate.printStackTrace();
+    }
+
+    public void printStackTrace(PrintStream out) {
+        delegate.printStackTrace(out);
+    }
+
+    public void printStackTrace(PrintWriter out) {
+        delegate.printStackTrace(out);
+    }
+
+    public final void printPartialStackTrace(PrintWriter out) {
+        super.printStackTrace(out);
+    }
+}

Propchange: directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/exception/NestableError.java
------------------------------------------------------------------------------
    svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision

Added: directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/exception/NestableException.java
URL: http://svn.apache.org/viewcvs/directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/exception/NestableException.java?rev=370807&view=auto
==============================================================================
--- directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/exception/NestableException.java (added)
+++ directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/exception/NestableException.java Fri Jan 20 05:47:50 2006
@@ -0,0 +1,215 @@
+/*
+ * Copyright 2002-2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.mina.common.support.lang.exception;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+
+/**
+ * The base class of all exceptions which can contain other exceptions.
+ *
+ * It is intended to ease the debugging by carrying on the information
+ * about the exception which was caught and provoked throwing the
+ * current exception. Catching and rethrowing may occur multiple
+ * times, and provided that all exceptions except the first one
+ * are descendants of <code>NestedException</code>, when the
+ * exception is finally printed out using any of the <code>
+ * printStackTrace()</code> methods, the stack trace will contain
+ * the information about all exceptions thrown and caught on
+ * the way.
+ * <p> Running the following program
+ * <p><blockquote><pre>
+ *  1 import org.apache.mina.common.support.lang.exception.NestableException;
+ *  2
+ *  3 public class Test {
+ *  4     public static void main( String[] args ) {
+ *  5         try {
+ *  6             a();
+ *  7         } catch(Exception e) {
+ *  8             e.printStackTrace();
+ *  9         }
+ * 10      }
+ * 11
+ * 12      public static void a() throws Exception {
+ * 13          try {
+ * 14              b();
+ * 15          } catch(Exception e) {
+ * 16              throw new NestableException("foo", e);
+ * 17          }
+ * 18      }
+ * 19
+ * 20      public static void b() throws Exception {
+ * 21          try {
+ * 22              c();
+ * 23          } catch(Exception e) {
+ * 24              throw new NestableException("bar", e);
+ * 25          }
+ * 26      }
+ * 27
+ * 28      public static void c() throws Exception {
+ * 29          throw new Exception("baz");
+ * 30      }
+ * 31 }
+ * </pre></blockquote>
+ * <p>Yields the following stack trace:
+ * <p><blockquote><pre>
+ * org.apache.mina.common.support.lang.exception.NestableException: foo
+ *         at Test.a(Test.java:16)
+ *         at Test.main(Test.java:6)
+ * Caused by: org.apache.mina.common.support.lang.exception.NestableException: bar
+ *         at Test.b(Test.java:24)
+ *         at Test.a(Test.java:14)
+ *         ... 1 more
+ * Caused by: java.lang.Exception: baz
+ *         at Test.c(Test.java:29)
+ *         at Test.b(Test.java:22)
+ *         ... 2 more
+ * </pre></blockquote><br>
+ *
+ * @author <a href="mailto:Rafal.Krzewski@e-point.pl">Rafal Krzewski</a>
+ * @author <a href="mailto:dlr@collab.net">Daniel Rall</a>
+ * @author <a href="mailto:knielsen@apache.org">Kasper Nielsen</a>
+ * @author <a href="mailto:steven@caswell.name">Steven Caswell</a>
+ * @since 1.0
+ * @version $Id$
+ */
+public class NestableException extends Exception implements Nestable {
+    
+    /**
+     * The helper instance which contains much of the code which we
+     * delegate to.
+     */
+    protected NestableDelegate delegate = new NestableDelegate(this);
+
+    /**
+     * Holds the reference to the exception or error that caused
+     * this exception to be thrown.
+     */
+    private Throwable cause = null;
+
+    /**
+     * Constructs a new <code>NestableException</code> without specified
+     * detail message.
+     */
+    public NestableException() {
+        super();
+    }
+
+    /**
+     * Constructs a new <code>NestableException</code> with specified
+     * detail message.
+     *
+     * @param msg The error message.
+     */
+    public NestableException(String msg) {
+        super(msg);
+    }
+
+    /**
+     * Constructs a new <code>NestableException</code> with specified
+     * nested <code>Throwable</code>.
+     *
+     * @param cause the exception or error that caused this exception to be
+     * thrown
+     */
+    public NestableException(Throwable cause) {
+        super();
+        this.cause = cause;
+    }
+
+    /**
+     * Constructs a new <code>NestableException</code> with specified
+     * detail message and nested <code>Throwable</code>.
+     *
+     * @param msg    the error message
+     * @param cause  the exception or error that caused this exception to be
+     * thrown
+     */
+    public NestableException(String msg, Throwable cause) {
+        super(msg);
+        this.cause = cause;
+    }
+
+    public Throwable getCause() {
+        return cause;
+    }
+
+    /**
+     * Returns the detail message string of this throwable. If it was
+     * created with a null message, returns the following:
+     * (cause==null ? null : cause.toString()).
+     *
+     * @return String message string of the throwable
+     */
+    public String getMessage() {
+        if (super.getMessage() != null) {
+            return super.getMessage();
+        } else if (cause != null) {
+            return cause.toString();
+        } else {
+            return null;
+        }
+    }
+
+    public String getMessage(int index) {
+        if (index == 0) {
+            return super.getMessage();
+        } else {
+            return delegate.getMessage(index);
+        }
+    }
+
+    public String[] getMessages() {
+        return delegate.getMessages();
+    }
+
+    public Throwable getThrowable(int index) {
+        return delegate.getThrowable(index);
+    }
+
+    public int getThrowableCount() {
+        return delegate.getThrowableCount();
+    }
+
+    public Throwable[] getThrowables() {
+        return delegate.getThrowables();
+    }
+
+    public int indexOfThrowable(Class type) {
+        return delegate.indexOfThrowable(type, 0);
+    }
+
+    public int indexOfThrowable(Class type, int fromIndex) {
+        return delegate.indexOfThrowable(type, fromIndex);
+    }
+
+    public void printStackTrace() {
+        delegate.printStackTrace();
+    }
+
+    public void printStackTrace(PrintStream out) {
+        delegate.printStackTrace(out);
+    }
+
+    public void printStackTrace(PrintWriter out) {
+        delegate.printStackTrace(out);
+    }
+
+    public final void printPartialStackTrace(PrintWriter out) {
+        super.printStackTrace(out);
+    }
+
+}

Propchange: directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/exception/NestableException.java
------------------------------------------------------------------------------
    svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision

Added: directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/exception/NestableRuntimeException.java
URL: http://svn.apache.org/viewcvs/directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/exception/NestableRuntimeException.java?rev=370807&view=auto
==============================================================================
--- directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/exception/NestableRuntimeException.java (added)
+++ directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/exception/NestableRuntimeException.java Fri Jan 20 05:47:50 2006
@@ -0,0 +1,159 @@
+/*
+ * Copyright 2002-2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.mina.common.support.lang.exception;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+
+/**
+ * The base class of all runtime exceptions which can contain other
+ * exceptions.
+ *
+ * @see org.apache.mina.common.support.lang.exception.NestableException
+ * @author <a href="mailto:Rafal.Krzewski@e-point.pl">Rafal Krzewski</a>
+ * @author <a href="mailto:dlr@collab.net">Daniel Rall</a>
+ * @author <a href="mailto:knielsen@apache.org">Kasper Nielsen</a>
+ * @author <a href="mailto:steven@caswell.name">Steven Caswell</a>
+ * @since 1.0
+ * @version $Id$
+ */
+public class NestableRuntimeException extends RuntimeException implements Nestable {
+    
+    /**
+     * The helper instance which contains much of the code which we
+     * delegate to.
+     */
+    protected NestableDelegate delegate = new NestableDelegate(this);
+
+    /**
+     * Holds the reference to the exception or error that caused
+     * this exception to be thrown.
+     */
+    private Throwable cause = null;
+
+    /**
+     * Constructs a new <code>NestableRuntimeException</code> without specified
+     * detail message.
+     */
+    public NestableRuntimeException() {
+        super();
+    }
+
+    /**
+     * Constructs a new <code>NestableRuntimeException</code> with specified
+     * detail message.
+     *
+     * @param msg the error message
+     */
+    public NestableRuntimeException(String msg) {
+        super(msg);
+    }
+
+    /**
+     * Constructs a new <code>NestableRuntimeException</code> with specified
+     * nested <code>Throwable</code>.
+     *
+     * @param cause the exception or error that caused this exception to be
+     * thrown
+     */
+    public NestableRuntimeException(Throwable cause) {
+        super();
+        this.cause = cause;
+    }
+
+    /**
+     * Constructs a new <code>NestableRuntimeException</code> with specified
+     * detail message and nested <code>Throwable</code>.
+     *
+     * @param msg    the error message
+     * @param cause  the exception or error that caused this exception to be
+     * thrown
+     */
+    public NestableRuntimeException(String msg, Throwable cause) {
+        super(msg);
+        this.cause = cause;
+    }
+
+    public Throwable getCause() {
+        return cause;
+    }
+
+    /**
+     * Returns the detail message string of this throwable. If it was
+     * created with a null message, returns the following:
+     * (cause==null ? null : cause.toString()).
+     *
+     * @return String message string of the throwable
+     */
+    public String getMessage() {
+        if (super.getMessage() != null) {
+            return super.getMessage();
+        } else if (cause != null) {
+            return cause.toString();
+        } else {
+            return null;
+        }
+    }
+
+    public String getMessage(int index) {
+        if (index == 0) {
+            return super.getMessage();
+        } else {
+            return delegate.getMessage(index);
+        }
+    }
+
+    public String[] getMessages() {
+        return delegate.getMessages();
+    }
+
+    public Throwable getThrowable(int index) {
+        return delegate.getThrowable(index);
+    }
+
+    public int getThrowableCount() {
+        return delegate.getThrowableCount();
+    }
+
+    public Throwable[] getThrowables() {
+        return delegate.getThrowables();
+    }
+
+    public int indexOfThrowable(Class type) {
+        return delegate.indexOfThrowable(type, 0);
+    }
+
+    public int indexOfThrowable(Class type, int fromIndex) {
+        return delegate.indexOfThrowable(type, fromIndex);
+    }
+
+    public void printStackTrace() {
+        delegate.printStackTrace();
+    }
+
+    public void printStackTrace(PrintStream out) {
+        delegate.printStackTrace(out);
+    }
+
+    public void printStackTrace(PrintWriter out) {
+        delegate.printStackTrace(out);
+    }
+
+    public final void printPartialStackTrace(PrintWriter out) {
+        super.printStackTrace(out);
+    }
+
+}

Propchange: directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/exception/NestableRuntimeException.java
------------------------------------------------------------------------------
    svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision

Added: directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/exception/package.html
URL: http://svn.apache.org/viewcvs/directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/exception/package.html?rev=370807&view=auto
==============================================================================
--- directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/exception/package.html (added)
+++ directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/exception/package.html Fri Jan 20 05:47:50 2006
@@ -0,0 +1,26 @@
+<!--
+Copyright 2002-2005 The Apache Software Foundation.
+ 
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+<html>
+<body>
+Provides JDK 1.4 style Nested Exception functionality for those on prior Java 
+versions.
+<p>Includes a static utility to create version independent Nested 
+Exception which can handle JDK 1.4 Exceptions as well as others. </p>
+<p>Lastly, {@link org.apache.commons.lang.exception.ExceptionUtils} 
+also contains <code>Throwable</code> manipulation and examination routines.</p>
+@since 1.0
+</body>
+</html>

Propchange: directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/exception/package.html
------------------------------------------------------------------------------
    svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision

Added: directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/math/DoubleRange.java
URL: http://svn.apache.org/viewcvs/directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/math/DoubleRange.java?rev=370807&view=auto
==============================================================================
--- directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/math/DoubleRange.java (added)
+++ directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/math/DoubleRange.java Fri Jan 20 05:47:50 2006
@@ -0,0 +1,410 @@
+/*
+ * Copyright 2002-2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.mina.common.support.lang.math;
+
+import java.io.Serializable;
+
+/**
+ * <p><code>DoubleRange</code> represents an inclusive range of <code>double</code>s.</p>
+ *
+ * @author Stephen Colebourne
+ * @since 2.0
+ * @version $Id$
+ */
+public final class DoubleRange extends Range implements Serializable {
+    
+    private static final long serialVersionUID = 71849363892740L;
+
+    /**
+     * The minimum number in this range (inclusive).
+     */
+    private final double min;
+    /**
+     * The maximum number in this range (inclusive).
+     */
+    private final double max;
+    
+    /**
+     * Cached output minObject (class is immutable).
+     */
+    private transient Double minObject = null;
+    /**
+     * Cached output maxObject (class is immutable).
+     */
+    private transient Double maxObject = null;
+    /**
+     * Cached output hashCode (class is immutable).
+     */
+    private transient int hashCode = 0;
+    /**
+     * Cached output toString (class is immutable).
+     */
+    private transient String toString = null;
+    
+    /**
+     * <p>Constructs a new <code>DoubleRange</code> using the specified
+     * number as both the minimum and maximum in this range.</p>
+     *
+     * @param number  the number to use for this range
+     * @throws IllegalArgumentException if the number is <code>NaN</code>
+     */
+    public DoubleRange(double number) {
+        super();
+        if (Double.isNaN(number)) {
+            throw new IllegalArgumentException("The number must not be NaN");
+        }
+        this.min = number;
+        this.max = number;
+    }
+
+    /**
+     * <p>Constructs a new <code>DoubleRange</code> using the specified
+     * number as both the minimum and maximum in this range.</p>
+     *
+     * @param number  the number to use for this range, must not
+     *  be <code>null</code>
+     * @throws IllegalArgumentException if the number is <code>null</code>
+     * @throws IllegalArgumentException if the number is <code>NaN</code>
+     */
+    public DoubleRange(Number number) {
+        super();
+        if (number == null) {
+            throw new IllegalArgumentException("The number must not be null");
+        }
+        this.min = number.doubleValue();
+        this.max = number.doubleValue();
+        if (Double.isNaN(min) || Double.isNaN(max)) {
+            throw new IllegalArgumentException("The number must not be NaN");
+        }
+        if (number instanceof Double) {
+            this.minObject = (Double) number;
+            this.maxObject = (Double) number;
+        }
+    }
+
+    /**
+     * <p>Constructs a new <code>DoubleRange</code> with the specified
+     * minimum and maximum numbers (both inclusive).</p>
+     * 
+     * <p>The arguments may be passed in the order (min,max) or (max,min). The
+     * getMinimum and getMaximum methods will return the correct values.</p>
+     * 
+     * @param number1  first number that defines the edge of the range, inclusive
+     * @param number2  second number that defines the edge of the range, inclusive
+     * @throws IllegalArgumentException if either number is <code>NaN</code>
+     */
+    public DoubleRange(double number1, double number2) {
+        super();
+        if (Double.isNaN(number1) || Double.isNaN(number2)) {
+            throw new IllegalArgumentException("The numbers must not be NaN");
+        }
+        if (number2 < number1) {
+            this.min = number2;
+            this.max = number1;
+        } else {
+            this.min = number1;
+            this.max = number2;
+        }
+    }
+
+    /**
+     * <p>Constructs a new <code>DoubleRange</code> with the specified
+     * minimum and maximum numbers (both inclusive).</p>
+     * 
+     * <p>The arguments may be passed in the order (min,max) or (max,min). The
+     * getMinimum and getMaximum methods will return the correct values.</p>
+     *
+     * @param number1  first number that defines the edge of the range, inclusive
+     * @param number2  second number that defines the edge of the range, inclusive
+     * @throws IllegalArgumentException if either number is <code>null</code>
+     * @throws IllegalArgumentException if either number is <code>NaN</code>
+     */
+    public DoubleRange(Number number1, Number number2) {
+        super();
+        if (number1 == null || number2 == null) {
+            throw new IllegalArgumentException("The numbers must not be null");
+        }
+        double number1val = number1.doubleValue();
+        double number2val = number2.doubleValue();
+        if (Double.isNaN(number1val) || Double.isNaN(number2val)) {
+            throw new IllegalArgumentException("The numbers must not be NaN");
+        }
+        if (number2val < number1val) {
+            this.min = number2val;
+            this.max = number1val;
+            if (number2 instanceof Double) {
+                this.minObject = (Double) number2;
+            }
+            if (number1 instanceof Double) {
+                this.maxObject = (Double) number1;
+            }
+        } else {
+            this.min = number1val;
+            this.max = number2val;
+            if (number1 instanceof Double) {
+                this.minObject = (Double) number1;
+            }
+            if (number2 instanceof Double) {
+                this.maxObject = (Double) number2;
+            }
+        }
+    }
+
+    // Accessors
+    //--------------------------------------------------------------------
+
+    /**
+     * <p>Returns the minimum number in this range.</p>
+     *
+     * @return the minimum number in this range
+     */
+    public Number getMinimumNumber() {
+        if (minObject == null) {
+            minObject = new Double(min);            
+        }
+        return minObject;
+    }
+
+    /**
+     * <p>Gets the minimum number in this range as a <code>long</code>.</p>
+     * 
+     * <p>This conversion can lose information for large values or decimals.</p>
+     *
+     * @return the minimum number in this range
+     */
+    public long getMinimumLong() {
+        return (long) min;
+    }
+
+    /**
+     * <p>Gets the minimum number in this range as a <code>int</code>.</p>
+     * 
+     * <p>This conversion can lose information for large values or decimals.</p>
+     *
+     * @return the minimum number in this range
+     */
+    public int getMinimumInteger() {
+        return (int) min;
+    }
+
+    /**
+     * <p>Gets the minimum number in this range as a <code>double</code>.</p>
+     *
+     * @return the minimum number in this range
+     */
+    public double getMinimumDouble() {
+        return min;
+    }
+
+    /**
+     * <p>Gets the minimum number in this range as a <code>float</code>.</p>
+     * 
+     * <p>This conversion can lose information for large values.</p>
+     *
+     * @return the minimum number in this range
+     */
+    public float getMinimumFloat() {
+        return (float) min;
+    }
+
+    /**
+     * <p>Returns the maximum number in this range.</p>
+     *
+     * @return the maximum number in this range
+     */
+    public Number getMaximumNumber() {
+        if (maxObject == null) {
+            maxObject = new Double(max);            
+        }
+        return maxObject;
+    }
+
+    /**
+     * <p>Gets the maximum number in this range as a <code>long</code>.</p>
+     * 
+     * <p>This conversion can lose information for large values or decimals.</p>
+     *
+     * @return the maximum number in this range
+     */
+    public long getMaximumLong() {
+        return (long) max;
+    }
+
+    /**
+     * <p>Gets the maximum number in this range as a <code>int</code>.</p>
+     * 
+     * <p>This conversion can lose information for large values or decimals.</p>
+     *
+     * @return the maximum number in this range
+     */
+    public int getMaximumInteger() {
+        return (int) max;
+    }
+
+    /**
+     * <p>Gets the maximum number in this range as a <code>double</code>.</p>
+     *
+     * @return the maximum number in this range
+     */
+    public double getMaximumDouble() {
+        return max;
+    }
+
+    /**
+     * <p>Gets the maximum number in this range as a <code>float</code>.</p>
+     * 
+     * <p>This conversion can lose information for large values.</p>
+     *
+     * @return the maximum number in this range
+     */
+    public float getMaximumFloat() {
+        return (float) max;
+    }
+
+    // Tests
+    //--------------------------------------------------------------------
+    
+    /**
+     * <p>Tests whether the specified <code>number</code> occurs within
+     * this range using <code>double</code> comparison.</p>
+     * 
+     * <p><code>null</code> is handled and returns <code>false</code>.</p>
+     *
+     * @param number  the number to test, may be <code>null</code>
+     * @return <code>true</code> if the specified number occurs within this range
+     */
+    public boolean containsNumber(Number number) {
+        if (number == null) {
+            return false;
+        }
+        return containsDouble(number.doubleValue());
+    }
+
+    /**
+     * <p>Tests whether the specified <code>double</code> occurs within
+     * this range using <code>double</code> comparison.</p>
+     * 
+     * <p>This implementation overrides the superclass for performance as it is
+     * the most common case.</p>
+     * 
+     * @param value  the double to test
+     * @return <code>true</code> if the specified number occurs within this
+     *  range by <code>double</code> comparison
+     */
+    public boolean containsDouble(double value) {
+        return value >= min && value <= max;
+    }
+
+    // Range tests
+    //--------------------------------------------------------------------
+
+    /**
+     * <p>Tests whether the specified range occurs entirely within this range
+     * using <code>double</code> comparison.</p>
+     * 
+     * <p><code>null</code> is handled and returns <code>false</code>.</p>
+     *
+     * @param range  the range to test, may be <code>null</code>
+     * @return <code>true</code> if the specified range occurs entirely within this range
+     * @throws IllegalArgumentException if the range is not of this type
+     */
+    public boolean containsRange(Range range) {
+        if (range == null) {
+            return false;
+        }
+        return containsDouble(range.getMinimumDouble())
+            && containsDouble(range.getMaximumDouble());
+    }
+
+    /**
+     * <p>Tests whether the specified range overlaps with this range
+     * using <code>double</code> comparison.</p>
+     * 
+     * <p><code>null</code> is handled and returns <code>false</code>.</p>
+     *
+     * @param range  the range to test, may be <code>null</code>
+     * @return <code>true</code> if the specified range overlaps with this range
+     */
+    public boolean overlapsRange(Range range) {
+        if (range == null) {
+            return false;
+        }
+        return range.containsDouble(min)
+            || range.containsDouble(max)
+            || containsDouble(range.getMinimumDouble());
+    }
+
+    // Basics
+    //--------------------------------------------------------------------
+
+    /**
+     * <p>Compares this range to another object to test if they are equal.</p>.
+     * 
+     * <p>To be equal, the class, minimum and maximum must be equal.</p>
+     *
+     * @param obj the reference object with which to compare
+     * @return <code>true</code> if this object is equal
+     */
+    public boolean equals(Object obj) {
+        if (obj == this) {
+            return true;
+        }
+        if (obj instanceof DoubleRange == false) {
+            return false;
+        }
+        DoubleRange range = (DoubleRange) obj;
+        return (Double.doubleToLongBits(min) == Double.doubleToLongBits(range.min) &&
+                Double.doubleToLongBits(max) == Double.doubleToLongBits(range.max));
+    }
+
+    /**
+     * <p>Gets a hashCode for the range.</p>
+     *
+     * @return a hash code value for this object
+     */
+    public int hashCode() {
+        if (hashCode == 0) {
+            hashCode = 17;
+            hashCode = 37 * hashCode + getClass().hashCode();
+            long lng = Double.doubleToLongBits(min);
+            hashCode = 37 * hashCode + ((int) (lng ^ (lng >> 32)));
+            lng = Double.doubleToLongBits(max);
+            hashCode = 37 * hashCode + ((int) (lng ^ (lng >> 32)));
+        }
+        return hashCode;
+    }
+
+    /**
+     * <p>Gets the range as a <code>String</code>.</p>
+     *
+     * <p>The format of the String is 'Range[<i>min</i>,<i>max</i>]'.</p>
+     *
+     * @return the <code>String</code> representation of this range
+     */
+    public String toString() {
+        if (toString == null) {
+            StringBuffer buf = new StringBuffer(32);
+            buf.append("Range[");
+            buf.append(min);
+            buf.append(',');
+            buf.append(max);
+            buf.append(']');
+            toString = buf.toString();
+        }
+        return toString;
+    }
+
+}

Propchange: directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/math/DoubleRange.java
------------------------------------------------------------------------------
    svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision

Added: directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/math/FloatRange.java
URL: http://svn.apache.org/viewcvs/directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/math/FloatRange.java?rev=370807&view=auto
==============================================================================
--- directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/math/FloatRange.java (added)
+++ directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/math/FloatRange.java Fri Jan 20 05:47:50 2006
@@ -0,0 +1,404 @@
+/*
+ * Copyright 2002-2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.mina.common.support.lang.math;
+
+import java.io.Serializable;
+
+/**
+ * <p><code>FloatRange</code> represents an inclusive range of <code>float</code>s.</p>
+ *
+ * @author Stephen Colebourne
+ * @since 2.0
+ * @version $Id$
+ */
+public final class FloatRange extends Range implements Serializable {
+    
+    private static final long serialVersionUID = 71849363892750L;
+
+    /**
+     * The minimum number in this range (inclusive).
+     */
+    private final float min;
+    /**
+     * The maximum number in this range (inclusive).
+     */
+    private final float max;
+    
+    /**
+     * Cached output minObject (class is immutable).
+     */
+    private transient Float minObject = null;
+    /**
+     * Cached output maxObject (class is immutable).
+     */
+    private transient Float maxObject = null;
+    /**
+     * Cached output hashCode (class is immutable).
+     */
+    private transient int hashCode = 0;
+    /**
+     * Cached output toString (class is immutable).
+     */
+    private transient String toString = null;
+    
+    /**
+     * <p>Constructs a new <code>FloatRange</code> using the specified
+     * number as both the minimum and maximum in this range.</p>
+     *
+     * @param number  the number to use for this range
+     * @throws IllegalArgumentException if the number is <code>NaN</code>
+     */
+    public FloatRange(float number) {
+        super();
+        if (Float.isNaN(number)) {
+            throw new IllegalArgumentException("The number must not be NaN");
+        }
+        this.min = number;
+        this.max = number;
+    }
+
+    /**
+     * <p>Constructs a new <code>FloatRange</code> using the specified
+     * number as both the minimum and maximum in this range.</p>
+     *
+     * @param number  the number to use for this range, must not
+     *  be <code>null</code>
+     * @throws IllegalArgumentException if the number is <code>null</code>
+     * @throws IllegalArgumentException if the number is <code>NaN</code>
+     */
+    public FloatRange(Number number) {
+        super();
+        if (number == null) {
+            throw new IllegalArgumentException("The number must not be null");
+        }
+        this.min = number.floatValue();
+        this.max = number.floatValue();
+        if (Float.isNaN(min) || Float.isNaN(max)) {
+            throw new IllegalArgumentException("The number must not be NaN");
+        }
+        if (number instanceof Float) {
+            this.minObject = (Float) number;
+            this.maxObject = (Float) number;
+        }
+    }
+
+    /**
+     * <p>Constructs a new <code>FloatRange</code> with the specified
+     * minimum and maximum numbers (both inclusive).</p>
+     * 
+     * <p>The arguments may be passed in the order (min,max) or (max,min). The
+     * getMinimum and getMaximum methods will return the correct values.</p>
+     * 
+     * @param number1  first number that defines the edge of the range, inclusive
+     * @param number2  second number that defines the edge of the range, inclusive
+     * @throws IllegalArgumentException if either number is <code>NaN</code>
+     */
+    public FloatRange(float number1, float number2) {
+        super();
+        if (Float.isNaN(number1) || Float.isNaN(number2)) {
+            throw new IllegalArgumentException("The numbers must not be NaN");
+        }
+        if (number2 < number1) {
+            this.min = number2;
+            this.max = number1;
+        } else {
+            this.min = number1;
+            this.max = number2;
+        }
+    }
+
+    /**
+     * <p>Constructs a new <code>FloatRange</code> with the specified
+     * minimum and maximum numbers (both inclusive).</p>
+     * 
+     * <p>The arguments may be passed in the order (min,max) or (max,min). The
+     * getMinimum and getMaximum methods will return the correct values.</p>
+     *
+     * @param number1  first number that defines the edge of the range, inclusive
+     * @param number2  second number that defines the edge of the range, inclusive
+     * @throws IllegalArgumentException if either number is <code>null</code>
+     * @throws IllegalArgumentException if either number is <code>NaN</code>
+     */
+    public FloatRange(Number number1, Number number2) {
+        super();
+        if (number1 == null || number2 == null) {
+            throw new IllegalArgumentException("The numbers must not be null");
+        }
+        float number1val = number1.floatValue();
+        float number2val = number2.floatValue();
+        if (Float.isNaN(number1val) || Float.isNaN(number2val)) {
+            throw new IllegalArgumentException("The numbers must not be NaN");
+        }
+        if (number2val < number1val) {
+            this.min = number2val;
+            this.max = number1val;
+            if (number2 instanceof Float) {
+                this.minObject = (Float) number2;
+            }
+            if (number1 instanceof Float) {
+                this.maxObject = (Float) number1;
+            }
+        } else {
+            this.min = number1val;
+            this.max = number2val;
+            if (number1 instanceof Float) {
+                this.minObject = (Float) number1;
+            }
+            if (number2 instanceof Float) {
+                this.maxObject = (Float) number2;
+            }
+        }
+    }
+
+    // Accessors
+    //--------------------------------------------------------------------
+
+    /**
+     * <p>Returns the minimum number in this range.</p>
+     *
+     * @return the minimum number in this range
+     */
+    public Number getMinimumNumber() {
+        if (minObject == null) {
+            minObject = new Float(min);            
+        }
+        return minObject;
+    }
+
+    /**
+     * <p>Gets the minimum number in this range as a <code>long</code>.</p>
+     * 
+     * <p>This conversion can lose information for large values or decimals.</p>
+     *
+     * @return the minimum number in this range
+     */
+    public long getMinimumLong() {
+        return (long) min;
+    }
+
+    /**
+     * <p>Gets the minimum number in this range as a <code>int</code>.</p>
+     * 
+     * <p>This conversion can lose information for large values or decimals.</p>
+     *
+     * @return the minimum number in this range
+     */
+    public int getMinimumInteger() {
+        return (int) min;
+    }
+
+    /**
+     * <p>Gets the minimum number in this range as a <code>double</code>.</p>
+     *
+     * @return the minimum number in this range
+     */
+    public double getMinimumDouble() {
+        return min;
+    }
+
+    /**
+     * <p>Gets the minimum number in this range as a <code>float</code>.</p>
+     *
+     * @return the minimum number in this range
+     */
+    public float getMinimumFloat() {
+        return min;
+    }
+
+    /**
+     * <p>Returns the maximum number in this range.</p>
+     *
+     * @return the maximum number in this range
+     */
+    public Number getMaximumNumber() {
+        if (maxObject == null) {
+            maxObject = new Float(max);            
+        }
+        return maxObject;
+    }
+
+    /**
+     * <p>Gets the maximum number in this range as a <code>long</code>.</p>
+     * 
+     * <p>This conversion can lose information for large values or decimals.</p>
+     *
+     * @return the maximum number in this range
+     */
+    public long getMaximumLong() {
+        return (long) max;
+    }
+
+    /**
+     * <p>Gets the maximum number in this range as a <code>int</code>.</p>
+     * 
+     * <p>This conversion can lose information for large values or decimals.</p>
+     *
+     * @return the maximum number in this range
+     */
+    public int getMaximumInteger() {
+        return (int) max;
+    }
+
+    /**
+     * <p>Gets the maximum number in this range as a <code>double</code>.</p>
+     *
+     * @return the maximum number in this range
+     */
+    public double getMaximumDouble() {
+        return max;
+    }
+
+    /**
+     * <p>Gets the maximum number in this range as a <code>float</code>.</p>
+     *
+     * @return the maximum number in this range
+     */
+    public float getMaximumFloat() {
+        return max;
+    }
+
+    // Tests
+    //--------------------------------------------------------------------
+    
+    /**
+     * <p>Tests whether the specified <code>number</code> occurs within
+     * this range using <code>float</code> comparison.</p>
+     * 
+     * <p><code>null</code> is handled and returns <code>false</code>.</p>
+     *
+     * @param number  the number to test, may be <code>null</code>
+     * @return <code>true</code> if the specified number occurs within this range
+     */
+    public boolean containsNumber(Number number) {
+        if (number == null) {
+            return false;
+        }
+        return containsFloat(number.floatValue());
+    }
+
+    /**
+     * <p>Tests whether the specified <code>float</code> occurs within
+     * this range using <code>float</code> comparison.</p>
+     * 
+     * <p>This implementation overrides the superclass for performance as it is
+     * the most common case.</p>
+     * 
+     * @param value  the float to test
+     * @return <code>true</code> if the specified number occurs within this
+     *  range by <code>float</code> comparison
+     */
+    public boolean containsFloat(float value) {
+        return value >= min && value <= max;
+    }
+
+    // Range tests
+    //--------------------------------------------------------------------
+
+    /**
+     * <p>Tests whether the specified range occurs entirely within this range
+     * using <code>float</code> comparison.</p>
+     * 
+     * <p><code>null</code> is handled and returns <code>false</code>.</p>
+     *
+     * @param range  the range to test, may be <code>null</code>
+     * @return <code>true</code> if the specified range occurs entirely within this range
+     * @throws IllegalArgumentException if the range is not of this type
+     */
+    public boolean containsRange(Range range) {
+        if (range == null) {
+            return false;
+        }
+        return containsFloat(range.getMinimumFloat()) &&
+               containsFloat(range.getMaximumFloat());
+    }
+
+    /**
+     * <p>Tests whether the specified range overlaps with this range
+     * using <code>float</code> comparison.</p>
+     * 
+     * <p><code>null</code> is handled and returns <code>false</code>.</p>
+     *
+     * @param range  the range to test, may be <code>null</code>
+     * @return <code>true</code> if the specified range overlaps with this range
+     */
+    public boolean overlapsRange(Range range) {
+        if (range == null) {
+            return false;
+        }
+        return range.containsFloat(min) ||
+               range.containsFloat(max) || 
+               containsFloat(range.getMinimumFloat());
+    }
+
+    // Basics
+    //--------------------------------------------------------------------
+
+    /**
+     * <p>Compares this range to another object to test if they are equal.</p>.
+     * 
+     * <p>To be equal, the class, minimum and maximum must be equal.</p>
+     *
+     * @param obj the reference object with which to compare
+     * @return <code>true</code> if this object is equal
+     */
+    public boolean equals(Object obj) {
+        if (obj == this) {
+            return true;
+        }
+        if (obj instanceof FloatRange == false) {
+            return false;
+        }
+        FloatRange range = (FloatRange) obj;
+        return (Float.floatToIntBits(min) == Float.floatToIntBits(range.min) &&
+                Float.floatToIntBits(max) == Float.floatToIntBits(range.max));
+    }
+
+    /**
+     * <p>Gets a hashCode for the range.</p>
+     *
+     * @return a hash code value for this object
+     */
+    public int hashCode() {
+        if (hashCode == 0) {
+            hashCode = 17;
+            hashCode = 37 * hashCode + getClass().hashCode();
+            hashCode = 37 * hashCode + Float.floatToIntBits(min);
+            hashCode = 37 * hashCode + Float.floatToIntBits(max);
+        }
+        return hashCode;
+    }
+
+    /**
+     * <p>Gets the range as a <code>String</code>.</p>
+     *
+     * <p>The format of the String is 'Range[<i>min</i>,<i>max</i>]'.</p>
+     *
+     * @return the <code>String</code> representation of this range
+     */
+    public String toString() {
+        if (toString == null) {
+            StringBuffer buf = new StringBuffer(32);
+            buf.append("Range[");
+            buf.append(min);
+            buf.append(',');
+            buf.append(max);
+            buf.append(']');
+            toString = buf.toString();
+        }
+        return toString;
+    }
+
+}

Propchange: directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/math/FloatRange.java
------------------------------------------------------------------------------
    svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision