struts-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mr...@apache.org
Subject svn commit: r240168 [22/30] - in /struts/sandbox/trunk/ti: ./ core/src/java/org/apache/ti/ core/src/java/org/apache/ti/config/ core/src/java/org/apache/ti/config/mapper/ core/src/java/org/apache/ti/core/ core/src/java/org/apache/ti/core/factory/ core/s...
Date Fri, 26 Aug 2005 05:46:58 GMT
Added: struts/sandbox/trunk/ti/core/src/java/org/apache/ti/util/internal/FileUtils.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/core/src/java/org/apache/ti/util/internal/FileUtils.java?rev=240168&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/core/src/java/org/apache/ti/util/internal/FileUtils.java (added)
+++ struts/sandbox/trunk/ti/core/src/java/org/apache/ti/util/internal/FileUtils.java Thu Aug 25 22:46:03 2005
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2004 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.
+ *
+ * $Header:$
+ */
+package org.apache.ti.util.internal;
+
+import java.io.File;
+
+public class FileUtils {
+
+    private static final boolean OS_CASE_SENSITIVE = !new File("x").equals(new File("X"));
+
+
+    /**
+     * Tell whether a given URI is absolute, i.e., whether it contains a scheme-part (e.g., "http:").
+     *
+     * @param uri the URI to test.
+     * @return <code>true</code> if the given URI is absolute.
+     */
+    public static boolean isAbsoluteURI(String uri) {
+        //
+        // This method needs to be fast, so it can't use java.net.URI.
+        //
+        if (uri.length() == 0 || uri.charAt(0) == '/') return false;
+
+        for (int i = 0, len = uri.length(); i < len; ++i) {
+            char c = uri.charAt(i);
+
+            if (c == ':') {
+                return true;
+            } else if (c == '/') {
+                return false;
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * Tell whether a URI ends in a given String.
+     */
+    public static boolean uriEndsWith(String uri, String ending) {
+        int queryStart = uri.indexOf('?');
+
+        if (queryStart == -1) {
+            return uri.endsWith(ending);
+        } else {
+            return uri.length() - queryStart >= ending.length()
+                    && uri.substring(queryStart - ending.length(), queryStart).equals(ending);
+        }
+    }
+
+    /**
+     * Get the file extension from a file name.
+     *
+     * @param filename the file name.
+     * @return the file extension (everything after the last '.'), or the empty string if there is no
+     *         file extension.
+     */
+    public static String getFileExtension(String filename) {
+        int lastDot = filename.lastIndexOf('.');
+        return lastDot != -1 ? filename.substring(lastDot + 1) : "";
+    }
+
+    public static String stripFileExtension(String filename) {
+        int lastDot = filename.lastIndexOf('.');
+        return lastDot != -1 ? filename.substring(0, lastDot) : filename;
+    }
+
+    /**
+     * Tell whether the current operating system is case-sensitive with regard to file names.
+     */
+    public static boolean isOSCaseSensitive() {
+        return OS_CASE_SENSITIVE;
+    }
+
+    /**
+     * Compare two strings, with case sensitivity determined by the operating system.
+     *
+     * @param s1 the first String to compare.
+     * @param s2 the second String to compare.
+     * @return <code>true</code> when:
+     *         <ul>
+     *         <li>the strings match exactly (including case), or,</li>
+     *         <li>the operating system is not case-sensitive with regard to file names, and the strings match,
+     *         ignoring case.</li>
+     *         </ul>
+     * @see #isOSCaseSensitive()
+     */
+    public static boolean osSensitiveEquals(String s1, String s2) {
+        if (OS_CASE_SENSITIVE) {
+            return s1.equals(s2);
+        } else {
+            return s1.equalsIgnoreCase(s2);
+        }
+    }
+
+    /**
+     * Tell whether a string ends with a particular suffix, with case sensitivity determined by the operating system.
+     *
+     * @param str    the String to test.
+     * @param suffix the suffix to look for.
+     * @return <code>true</code> when:
+     *         <ul>
+     *         <li><code>str</code> ends with <code>suffix</code>, or,</li>
+     *         <li>the operating system is not case-sensitive with regard to file names, and <code>str</code> ends with
+     *         <code>suffix</code>, ignoring case.</li>
+     *         </ul>
+     * @see #isOSCaseSensitive()
+     */
+    public static boolean osSensitiveEndsWith(String str, String suffix) {
+        if (OS_CASE_SENSITIVE) {
+            return str.endsWith(suffix);
+        } else {
+            int strLen = str.length();
+            int suffixLen = suffix.length();
+
+            if (strLen < suffixLen) {
+                return false;
+            }
+
+            return (str.substring(strLen - suffixLen).equalsIgnoreCase(suffix));
+        }
+    }
+}
+

Added: struts/sandbox/trunk/ti/core/src/java/org/apache/ti/util/internal/InternalStringBuilder.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/core/src/java/org/apache/ti/util/internal/InternalStringBuilder.java?rev=240168&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/core/src/java/org/apache/ti/util/internal/InternalStringBuilder.java (added)
+++ struts/sandbox/trunk/ti/core/src/java/org/apache/ti/util/internal/InternalStringBuilder.java Thu Aug 25 22:46:03 2005
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2004 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.
+ *
+ * $Header:$
+ */
+package org.apache.ti.util.internal;
+
+import java.io.Serializable;
+
+
+/**
+ * Unsynchronized alternative to StringBuffer.
+ */
+public final class InternalStringBuilder
+        implements Serializable {
+
+    private char _buffer[];
+    private int _length = 0;
+    private boolean _shared;
+
+    static final long serialVersionUID = 1;
+
+    public InternalStringBuilder() {
+        this(16);
+    }
+
+    public InternalStringBuilder(int length) {
+        _buffer = new char[length];
+        _shared = false;
+    }
+
+    public InternalStringBuilder(String str) {
+        this(str.length() + 16);
+        append(str);
+    }
+
+    public int length() {
+        return _length;
+    }
+
+    private final void copyWhenShared() {
+        if (_shared) {
+            char newValue[] = new char[_buffer.length];
+            System.arraycopy(_buffer, 0, newValue, 0, _length);
+            _buffer = newValue;
+            _shared = false;
+        }
+    }
+
+    public void ensureCapacity(int minCapacity) {
+        int maxCapacity = _buffer.length;
+
+        if (minCapacity > maxCapacity) {
+            int newCapacity = (maxCapacity + 1) * 2;
+            if (minCapacity > newCapacity) newCapacity = minCapacity;
+            char newValue[] = new char[newCapacity];
+            System.arraycopy(_buffer, 0, newValue, 0, _length);
+            _buffer = newValue;
+            _shared = false;
+        }
+    }
+
+    public void setLength(int length) {
+        if (length < 0) throw new StringIndexOutOfBoundsException(length);
+        ensureCapacity(length);
+
+        if (_length < length) {
+            copyWhenShared();
+            while (_length < length) {
+                _buffer[_length++] = '\0';
+            }
+        }
+        _length = length;
+    }
+
+    public char charAt(int index) {
+        if (index < 0 || index >= _length) throw new StringIndexOutOfBoundsException(index);
+        return _buffer[index];
+    }
+
+    public InternalStringBuilder append(Object obj) {
+        return append(String.valueOf(obj));
+    }
+
+    public InternalStringBuilder append(String str) {
+        if (str == null) str = String.valueOf(str);
+        int len = str.length();
+        ensureCapacity(_length + len);
+        copyWhenShared();
+        str.getChars(0, len, _buffer, _length);
+        _length += len;
+        return this;
+    }
+
+    public InternalStringBuilder append(char c) {
+        ensureCapacity(_length + 1);
+        copyWhenShared();
+        _buffer[_length++] = c;
+        return this;
+    }
+
+    public InternalStringBuilder append(int i) {
+        return append(String.valueOf(i));
+    }
+
+    public String toString() {
+        _shared = true;
+        return new String(_buffer, 0, _length);
+    }
+
+    public InternalStringBuilder deleteCharAt(int index) {
+        if (index < 0 || index >= _length) throw new StringIndexOutOfBoundsException(index);
+        System.arraycopy(_buffer, index + 1, _buffer, index, _length - index - 1);
+        _length--;
+        return this;
+    }
+}

Added: struts/sandbox/trunk/ti/core/src/java/org/apache/ti/util/internal/ServletUtils.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/core/src/java/org/apache/ti/util/internal/ServletUtils.java?rev=240168&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/core/src/java/org/apache/ti/util/internal/ServletUtils.java (added)
+++ struts/sandbox/trunk/ti/core/src/java/org/apache/ti/util/internal/ServletUtils.java Thu Aug 25 22:46:03 2005
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2004 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.
+ *
+ * $Header:$
+ */
+package org.apache.ti.util.internal;
+
+import org.apache.commons.chain.web.WebContext;
+import org.apache.commons.chain.web.servlet.ServletWebContext;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletRequest;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.io.PrintStream;
+import java.util.Enumeration;
+
+public class ServletUtils {
+
+    /**
+     * Print parameters and attributes in the given request.
+     *
+     * @param request the current HttpServletRequest.
+     * @param output  a PrintStream to which to output request parameters and request/session
+     *                attributes; if <code>null</null>, <code>System.err</code> is used.
+     */
+    public static void dumpRequest(ServletRequest request, PrintStream output) {
+        if (output == null) {
+            output = System.err;
+        }
+
+        output.println("*** ServletRequest " + request);
+
+        if (request instanceof HttpServletRequest) {
+            output.println("        uri = " + ((HttpServletRequest) request).getRequestURI());
+        }
+
+        for (Enumeration e = request.getParameterNames(); e.hasMoreElements();) {
+            String name = (String) e.nextElement();
+            output.println("            parameter " + name + " = " + request.getParameter(name));
+        }
+
+        for (Enumeration e = request.getAttributeNames(); e.hasMoreElements();) {
+            String name = (String) e.nextElement();
+            output.println("            attribute " + name + " = " + request.getAttribute(name));
+        }
+
+        if (request instanceof HttpServletRequest) {
+            HttpSession session = ((HttpServletRequest) request).getSession(false);
+
+            if (session != null) {
+                for (Enumeration e = session.getAttributeNames(); e.hasMoreElements();) {
+                    String name = (String) e.nextElement();
+                    output.println("            session attribute " + name + " = " + session.getAttribute(name));
+                }
+            }
+        }
+    }
+
+    /**
+     * Print attributes in the given ServletContext.
+     *
+     * @param context the current ServletContext.
+     * @param output  a PrintStream to which to output ServletContext attributes; if <code>null</null>,
+     *                <code>System.err</code> is used.
+     */
+    public static void dumpServletContext(ServletContext context, PrintStream output) {
+        if (output == null) {
+            output = System.err;
+        }
+
+        output.println("*** ServletContext " + context);
+
+        for (Enumeration e = context.getAttributeNames(); e.hasMoreElements();) {
+            String name = (String) e.nextElement();
+            output.println("            attribute " + name + " = " + context.getAttribute(name));
+        }
+    }
+
+    /**
+     * Set response headers to prevent caching of the response by the browser.
+     */
+    public static void preventCache(HttpServletResponse httpResponse) {
+        httpResponse.setHeader("Pragma", "No-cache");
+        httpResponse.setHeader("Cache-Control", "no-cache,no-store,max-age=0");
+        httpResponse.setDateHeader("Expires", 1);
+    }
+    
+    /*
+    public static void writeHtml(WebContext webContext, String html, boolean preventCache)
+    {
+        response.setContentType( "text/html;charset=UTF-8" );
+        response.getWriter().println( html );        
+    }
+    */
+    
+    public static boolean isSessionExpired(WebContext webContext) {
+        // TODO: make this class (or part of it) into a spring bean (SessionUtils or something like that)
+        if (webContext instanceof ServletWebContext) {
+            HttpServletRequest request = ((ServletWebContext) webContext).getRequest();
+            String requestedSessionID = request.getRequestedSessionId();
+
+            if (requestedSessionID != null) {
+                HttpSession session = request.getSession(false);
+                return session == null || !requestedSessionID.equals(session.getId());
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * Get the base filename of the given URI.
+     *
+     * @param uri the URI from which to get the base filename.
+     * @return a String containing everything after the last slash of the given URI.
+     */
+    public static String getBaseName(String uri) {
+        int lastSlash = uri.lastIndexOf('/');
+        assert lastSlash != -1 : uri;
+        assert lastSlash < uri.length() - 1 : "URI must not end with a slash: " + uri;
+        return uri.substring(lastSlash + 1);
+    }
+
+    /**
+     * Get the directory path of the given URI.
+     *
+     * @param uri the URI from which to get the directory path.
+     * @return a String containing everything before the last slash of the given URI.
+     */
+    public static String getDirName(String uri) {
+        int lastSlash = uri.lastIndexOf('/');
+        assert lastSlash != -1 : uri;
+        assert uri.length() > 1 : uri;
+        assert lastSlash < uri.length() - 1 : "URI must not end with a slash: " + uri;
+        return uri.substring(0, lastSlash);
+    }
+}

Added: struts/sandbox/trunk/ti/core/src/java/org/apache/ti/util/internal/cache/ClassLevelCache.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/core/src/java/org/apache/ti/util/internal/cache/ClassLevelCache.java?rev=240168&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/core/src/java/org/apache/ti/util/internal/cache/ClassLevelCache.java (added)
+++ struts/sandbox/trunk/ti/core/src/java/org/apache/ti/util/internal/cache/ClassLevelCache.java Thu Aug 25 22:46:03 2005
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2004 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.
+ *
+ * $Header:$
+ */
+package org.apache.ti.util.internal.cache;
+
+import org.apache.ti.util.internal.concurrent.InternalConcurrentHashMap;
+
+import java.util.Map;
+
+
+/**
+ * Thread-safe cache that is stored statically per-Class.
+ */
+public final class ClassLevelCache {
+
+    private static InternalConcurrentHashMap _classCaches = new InternalConcurrentHashMap();
+    private InternalConcurrentHashMap _caches = new InternalConcurrentHashMap();
+
+
+    public static ClassLevelCache getCache(Class c) {
+        String className = c.getName();
+        ClassLevelCache cache = (ClassLevelCache) _classCaches.get(className);
+
+        if (cache == null) {
+            cache = new ClassLevelCache();
+            _classCaches.put(className, cache);
+        }
+
+        return cache;
+    }
+
+    protected ClassLevelCache() {
+    }
+
+    public Object get(String majorKey, String minorKey) {
+        InternalConcurrentHashMap cache = (InternalConcurrentHashMap) _caches.get(majorKey);
+        return cache != null ? cache.get(minorKey) : null;
+    }
+
+    public Object getCacheObject(String cacheID) {
+        return _caches.get(cacheID);
+    }
+
+    public void setCacheObject(String cacheID, Object object) {
+        _caches.put(cacheID, object);
+    }
+
+    public Map getCacheMap(String cacheID) {
+        return getCacheMap(cacheID, true);
+    }
+
+    public Map getCacheMap(String cacheID, boolean createIfMissing) {
+        InternalConcurrentHashMap cache = (InternalConcurrentHashMap) _caches.get(cacheID);
+
+        if (cache == null && createIfMissing) {
+            cache = new InternalConcurrentHashMap();
+            _caches.put(cacheID, cache);
+        }
+
+        return cache;
+    }
+
+    public void put(String cacheID, String minorKey, Object value) {
+        //
+        // ConcurrentHashMap can't accept null.  For now we'll just assert; if it becomes necessary to add null,
+        // then we can use a marker value.
+        //
+        assert value != null;
+        getCacheMap(cacheID).put(minorKey, value);
+    }
+
+    public static void clearAll() {
+        _classCaches.clear();
+    }
+}

Added: struts/sandbox/trunk/ti/core/src/java/org/apache/ti/util/internal/cache/FieldCache.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/core/src/java/org/apache/ti/util/internal/cache/FieldCache.java?rev=240168&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/core/src/java/org/apache/ti/util/internal/cache/FieldCache.java (added)
+++ struts/sandbox/trunk/ti/core/src/java/org/apache/ti/util/internal/cache/FieldCache.java Thu Aug 25 22:46:03 2005
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2004 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.
+ *
+ * $Header:$
+ */
+package org.apache.ti.util.internal.cache;
+
+import org.apache.ti.util.internal.concurrent.InternalConcurrentHashMap;
+import org.apache.ti.util.logging.Logger;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.HashMap;
+
+/**
+ * @exclude
+ */
+public class FieldCache {
+
+    private static final Logger _log = Logger.getInstance(FieldCache.class);
+
+    private final InternalConcurrentHashMap _fieldCache;
+    private final InternalConcurrentHashMap _declaredFieldCache;
+
+    public FieldCache() {
+        _fieldCache = new InternalConcurrentHashMap();
+        _declaredFieldCache = new InternalConcurrentHashMap();
+    }
+
+    public final Field getField(Class type, String fieldName) {
+        if (_log.isDebugEnabled()) _log.debug("getFields for: " + type);
+
+        HashMap fields = (HashMap) _fieldCache.get(type);
+
+        if (fields == null) {
+            Field[] fieldArray = type.getFields();
+            fields = new HashMap();
+
+            for (int i = 0; i < fieldArray.length; i++) {
+                Field field = fieldArray[i];
+                fields.put(field.getName(), field);
+            }
+
+            _fieldCache.put(type, fields);
+        }
+
+        return (Field) fields.get(fieldName);
+    }
+
+    public final Field getDeclaredField(Class type, String fieldName) {
+        if (_log.isDebugEnabled()) _log.debug("getDeclaredFields for: " + type);
+
+        HashMap fields = (HashMap) _declaredFieldCache.get(type);
+
+        if (fields == null) {
+            Field[] fieldArray = type.getDeclaredFields();
+            fields = new HashMap();
+
+            for (int i = 0; i < fieldArray.length; i++) {
+                Field field = fieldArray[i];
+                if (!Modifier.isPublic(field.getModifiers())) field.setAccessible(true);
+                fields.put(field.getName(), field);
+            }
+
+            _declaredFieldCache.put(type, fields);
+        }
+
+        return (Field) fields.get(fieldName);
+    }
+}

Added: struts/sandbox/trunk/ti/core/src/java/org/apache/ti/util/internal/cache/MethodCache.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/core/src/java/org/apache/ti/util/internal/cache/MethodCache.java?rev=240168&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/core/src/java/org/apache/ti/util/internal/cache/MethodCache.java (added)
+++ struts/sandbox/trunk/ti/core/src/java/org/apache/ti/util/internal/cache/MethodCache.java Thu Aug 25 22:46:03 2005
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2004 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.
+ *
+ * $Header:$
+ */
+package org.apache.ti.util.internal.cache;
+
+import org.apache.ti.util.internal.concurrent.InternalConcurrentHashMap;
+import org.apache.ti.util.logging.Logger;
+
+import java.lang.reflect.Method;
+
+/**
+ * @exclude
+ */
+public class MethodCache {
+
+    private static final Logger LOGGER = Logger.getInstance(MethodCache.class);
+
+    private final InternalConcurrentHashMap _methodCache;
+
+    /**
+     *
+     */
+    public MethodCache() {
+        _methodCache = new InternalConcurrentHashMap();
+    }
+
+    /**
+     *
+     */
+    public final Method[] getMethods(Class type) {
+        if (LOGGER.isDebugEnabled()) LOGGER.debug("type: " + type + " hash code: " + type.hashCode());
+
+        Object obj = _methodCache.get(type);
+
+        if (obj == null) {
+            obj = type.getMethods();
+            _methodCache.put(type, obj);
+        }
+
+        return (Method[]) obj;
+    }
+
+    /**
+     *
+     */
+    public final Method getMethod(Class type, String methodName, int argCount) {
+        if (LOGGER.isDebugEnabled()) LOGGER.debug("Get method \"" + methodName + "\" from type \"" + type + "\" with " + argCount + " params");
+
+        if (methodName == null)
+            return null;
+
+        Method[] methods = getMethods(type);
+
+        for (int i = 0; i < methods.length; i++) {
+            if (methods[i].getName().equals(methodName) && (argCount == methods[i].getParameterTypes().length))
+                return methods[i];
+        }
+
+        return null;
+    }
+
+    /**
+     *
+     */
+    public final Method getMethod(Class type, String methodName, String[] argTypes) {
+        if (methodName == null)
+            return null;
+
+        Method[] methods = getMethods(type);
+        Class[] parameterTypes = null;
+
+        for (int i = 0; i < methods.length; i++) {
+            // method names don't match
+            if (!methods[i].getName().equals(methodName))
+                continue;
+
+            // never null...
+            parameterTypes = methods[i].getParameterTypes();
+            
+            // zero arg method
+            if ((argTypes == null || argTypes.length == 0) && parameterTypes.length == 0)
+                return methods[i];
+            // looking for zero arg method; found multi arg method
+            else if ((argTypes == null || argTypes.length == 0) && !(parameterTypes.length == 0))
+                continue;
+            // method matching arg count; check argument types
+            else if (parameterTypes != null && parameterTypes.length == argTypes.length) {
+                boolean match = true;
+                for (int j = 0; j < parameterTypes.length; j++) {
+                    if (!parameterTypes[j].getName().equals(argTypes[j])) {
+                        match = false;
+                        break;
+                    }
+                }
+                if (match) return methods[i];
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     *
+     */
+    public final Method getMethod(Class type, String methodName, Class[] argTypes) {
+        if (argTypes == null)
+            return getMethod(type, methodName, (String[]) null);
+
+        String[] typeStrs = new String[argTypes.length];
+        for (int i = 0; i < argTypes.length; i++) {
+            typeStrs[i] = argTypes[i].getName();
+        }
+
+        return getMethod(type, methodName, typeStrs);
+    }
+}

Added: struts/sandbox/trunk/ti/core/src/java/org/apache/ti/util/internal/cache/PropertyCache.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/core/src/java/org/apache/ti/util/internal/cache/PropertyCache.java?rev=240168&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/core/src/java/org/apache/ti/util/internal/cache/PropertyCache.java (added)
+++ struts/sandbox/trunk/ti/core/src/java/org/apache/ti/util/internal/cache/PropertyCache.java Thu Aug 25 22:46:03 2005
@@ -0,0 +1,213 @@
+/*
+ * Copyright 2004 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.
+ *
+ * $Header:$
+ */
+package org.apache.ti.util.internal.cache;
+
+import org.apache.ti.util.internal.concurrent.InternalConcurrentHashMap;
+import org.apache.ti.util.logging.Logger;
+
+import java.beans.IntrospectionException;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.HashMap;
+import java.util.Iterator;
+
+/**
+ * The PropertyCache is used to track the JavaBean properties and public
+ * fields of a set of classes that are stored in the cache.  This implementation
+ * provides a significant speed-up when looking-up reflected metadata
+ * of Java classes.  It is primarily used in the NetUI expression engine
+ * to provide fast access to the properties and fields of classes
+ * against which expressions are being evaluated.
+ */
+public final class PropertyCache {
+
+    private static final Logger LOGGER = Logger.getInstance(PropertyCache.class);
+
+    private final InternalConcurrentHashMap _classCache;
+
+    public PropertyCache() {
+        _classCache = new InternalConcurrentHashMap();
+    }
+
+    /**
+     * Get an array of {@link java.beans.PropertyDescriptor} objects that
+     * describe JavaBean properties of the given <code>_type</code>.  This
+     * array <b>should not</b> be modified.
+     *
+     * @param type the {@link java.lang.Class} whose JavaBean properties to find
+     * @return an array of {@link java.beans.PropertyDescriptor} objects that describe the JavaBean properties
+     */
+    public final PropertyDescriptor[] getPropertyDescriptors(Class type) {
+        CachedClass cc = getCachedClass(type);
+        return (cc != null ? cc.getPropertyDescriptors() : null);
+    }
+
+    public final Method getPropertyGetter(Class type, String property) {
+        CachedClass cc = getCachedClass(type);
+        if (cc == null)
+            return null;
+        CachedProperty cp = cc.getProperty(property);
+        return (cp != null ? cp.getReadMethod() : null);
+    }
+
+    public final Method getPropertySetter(Class type, String property) {
+        CachedClass cc = getCachedClass(type);
+        if (cc == null)
+            return null;
+        CachedProperty cp = cc.getProperty(property);
+        return (cp != null ? cp.getWriteMethod() : null);
+    }
+
+    public final Class getPropertyType(Class type, String property) {
+        CachedClass cc = getCachedClass(type);
+        if (cc == null)
+            return null;
+        CachedProperty cp = cc.getProperty(property);
+        return (cp != null ? cp.getType() : null);
+    }
+
+    private final CachedClass getCachedClass(Class type) {
+        Object obj = _classCache.get(type);
+        if (obj == null) {
+            try {
+                obj = new CachedClass(type);
+                _classCache.put(type, obj);
+            } catch (Exception e) {
+                LOGGER.error("Error introspecting a class of _type \"" + type + "\" when determining its JavaBean property info", e);
+                return null;
+            }
+        }
+
+        return (CachedClass) obj;
+    }
+
+    /**
+     *
+     */
+    private class CachedClass {
+
+        private Class _type = null;
+        private HashMap _properties = null;
+        private PropertyDescriptor[] _propertyDescriptors = null;
+
+        CachedClass(Class type)
+                throws IntrospectionException {
+            this._type = type;
+            init(type);
+        }
+
+        private void init(Class type)
+                throws IntrospectionException {
+            _properties = new HashMap();
+
+            if (Modifier.isPublic(type.getModifiers())) {
+                PropertyDescriptor[] pds = Introspector.getBeanInfo(type).getPropertyDescriptors();
+                for (int i = 0; i < pds.length; i++) {
+                    _properties.put(pds[i].getName(), new CachedProperty(pds[i]));
+                }
+            }
+            // not looking at a public class, get all of the JavaBean PDs off of its interfaces
+            else {
+                // look on the public interfaces on this class and all superclasses
+                for (Class c = type; c != null; c = c.getSuperclass()) {
+                    Class[] interfaces = c.getInterfaces();
+                    for (int i = 0; i < interfaces.length; i++) {
+                        Class iface = interfaces[i];
+                        if (Modifier.isPublic(iface.getModifiers())) {
+                            PropertyDescriptor[] pds = Introspector.getBeanInfo(iface).getPropertyDescriptors();
+                            for (int j = 0; j < pds.length; j++) {
+                                if (!_properties.containsKey(pds[j].getName()))
+                                    _properties.put(pds[j].getName(), new CachedProperty(pds[j]));
+                            }
+                        }
+                    }
+                }
+
+                // look on the nearest public base class
+                Class baseClass = type.getSuperclass();
+                while (!Modifier.isPublic(baseClass.getModifiers())) {
+                    baseClass = baseClass.getSuperclass();
+                }
+
+                PropertyDescriptor[] pds = Introspector.getBeanInfo(baseClass).getPropertyDescriptors();
+                for (int j = 0; j < pds.length; j++) {
+                    if (!_properties.containsKey(pds[j].getName()))
+                        _properties.put(pds[j].getName(), new CachedProperty(pds[j]));
+                }
+            }
+
+            if (_properties.size() > 0) {
+                _propertyDescriptors = new PropertyDescriptor[_properties.size()];
+                Iterator iterator = _properties.values().iterator();
+                for (int i = 0; iterator.hasNext(); i++) {
+                    _propertyDescriptors[i] = ((CachedProperty) iterator.next()).getPropertyDescriptor();
+                }
+            }
+        }
+
+        PropertyDescriptor[] getPropertyDescriptors() {
+            return _propertyDescriptors;
+        }
+
+        CachedProperty getProperty(String name) {
+            return (CachedProperty) _properties.get(name);
+        }
+    }
+
+    /**
+     *
+     */
+    private class CachedProperty {
+
+        private Method _readMethod = null;
+        private Method _writeMethod = null;
+        private String _name = null;
+        private PropertyDescriptor _pd = null;
+        private Class _type = null;
+
+        CachedProperty(PropertyDescriptor pd) {
+            _pd = pd;
+            _name = pd.getName();
+            _readMethod = pd.getReadMethod();
+            _writeMethod = pd.getWriteMethod();
+            _type = pd.getPropertyType();
+        }
+
+        PropertyDescriptor getPropertyDescriptor() {
+            return _pd;
+        }
+
+        Method getReadMethod() {
+            return _readMethod;
+        }
+
+        Method getWriteMethod() {
+            return _writeMethod;
+        }
+
+        String getName() {
+            return _name;
+        }
+
+        Class getType() {
+            return _type;
+        }
+    }
+}

Added: struts/sandbox/trunk/ti/core/src/java/org/apache/ti/util/internal/concurrent/CondVar.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/core/src/java/org/apache/ti/util/internal/concurrent/CondVar.java?rev=240168&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/core/src/java/org/apache/ti/util/internal/concurrent/CondVar.java (added)
+++ struts/sandbox/trunk/ti/core/src/java/org/apache/ti/util/internal/concurrent/CondVar.java Thu Aug 25 22:46:03 2005
@@ -0,0 +1,146 @@
+/*
+  File: ConditionVariable.java
+  Originally written by Doug Lea and released into the public domain.
+  This may be used for any purposes whatsoever without acknowledgment.
+  Thanks for the assistance and support of Sun Microsystems Labs,
+  and everyone contributing, testing, and using this code.
+  History:
+  Date       Who                What
+  11Jun1998  dl               Create public version
+ */
+
+package org.apache.ti.util.internal.concurrent;
+
+import java.util.Date;
+
+class CondVar implements Condition, java.io.Serializable {
+
+    /**
+     * The lock *
+     */
+    protected final LockInfo lock;
+
+    /**
+     * Create a new CondVar that relies on the given mutual
+     * exclusion lock.
+     *
+     * @param lock A non-reentrant mutual exclusion lock.
+     */
+
+    CondVar(LockInfo lock) {
+        this.lock = lock;
+    }
+
+    public void awaitUninterruptibly() {
+        boolean wasInterrupted = false;
+        while (true) {
+            try {
+                await();
+                if (wasInterrupted) {
+                    Thread.currentThread().interrupt();
+                }
+                return;
+            } catch (InterruptedException e) {
+                wasInterrupted = true;
+            }
+        }
+    }
+
+    public void await() throws InterruptedException {
+        if (Thread.interrupted())
+            throw new InterruptedException();
+        try {
+            synchronized (this) {
+                lock.unlock();
+                try {
+                    wait();
+                } catch (InterruptedException ex) {
+                    notify();
+                    throw ex;
+                }
+            }
+        } finally {
+            lock.lock();
+        }
+    }
+
+    public boolean await(long timeout, TimeUnit unit) throws InterruptedException {
+        if (Thread.interrupted()) throw new InterruptedException();
+        long nanos = unit.toNanos(timeout);
+        boolean success = false;
+        try {
+            synchronized (this) {
+                lock.unlock();
+                try {
+                    if (nanos > 0) {
+                        long start = Utils.nanoTime();
+                        TimeUnit.NANOSECONDS.timedWait(this, nanos);
+                        // DK: due to coarse-grained (millis) clock, it seems
+                        // preferable to acknowledge timeout (success == false)
+                        // when the equality holds (timing is exact)
+                        success = Utils.nanoTime() - start < nanos;
+                    }
+                } catch (InterruptedException ex) {
+                    notify();
+                    throw ex;
+                }
+            }
+        } finally {
+            lock.lock();
+        }
+        return success;
+    }
+
+//    public long awaitNanos(long timeout) throws InterruptedException {
+//        throw new UnsupportedOperationException();
+//    }
+//
+    public boolean awaitUntil(Date deadline) throws InterruptedException {
+        if (deadline == null) throw new NullPointerException();
+        long abstime = deadline.getTime();
+        if (Thread.interrupted()) throw new InterruptedException();
+
+        boolean success = false;
+        try {
+            synchronized (this) {
+                lock.unlock();
+                try {
+                    long start = System.currentTimeMillis();
+                    long msecs = abstime - start;
+                    if (msecs > 0) {
+                        wait(msecs);
+                        // DK: due to coarse-grained (millis) clock, it seems
+                        // preferable to acknowledge timeout (success == false)
+                        // when the equality holds (timing is exact)
+                        success = System.currentTimeMillis() - start < msecs;
+                    }
+                } catch (InterruptedException ex) {
+                    notify();
+                    throw ex;
+                }
+            }
+        } finally {
+            lock.lock();
+        }
+        return success;
+    }
+
+    public synchronized void signal() {
+        if (!lock.isHeldByCurrentThread()) {
+            throw new IllegalMonitorStateException();
+        }
+        notify();
+    }
+
+    public synchronized void signalAll() {
+        if (!lock.isHeldByCurrentThread()) {
+            throw new IllegalMonitorStateException();
+        }
+        notifyAll();
+    }
+
+    static interface LockInfo extends Lock {
+
+        boolean isHeldByCurrentThread();
+    }
+}

Added: struts/sandbox/trunk/ti/core/src/java/org/apache/ti/util/internal/concurrent/Condition.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/core/src/java/org/apache/ti/util/internal/concurrent/Condition.java?rev=240168&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/core/src/java/org/apache/ti/util/internal/concurrent/Condition.java (added)
+++ struts/sandbox/trunk/ti/core/src/java/org/apache/ti/util/internal/concurrent/Condition.java Thu Aug 25 22:46:03 2005
@@ -0,0 +1,429 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package org.apache.ti.util.internal.concurrent;
+
+import java.util.Date;
+
+/**
+ * <tt>Condition</tt> factors out the <tt>Object</tt> monitor
+ * methods ({@link Object#wait() wait}, {@link Object#notify notify}
+ * and {@link Object#notifyAll notifyAll}) into distinct objects to
+ * give the effect of having multiple wait-sets per object, by
+ * combining them with the use of arbitrary {@link Lock} implementations.
+ * Where a <tt>Lock</tt> replaces the use of <tt>synchronized</tt> methods
+ * and statements, a <tt>Condition</tt> replaces the use of the Object
+ * monitor methods.
+ * <p/>
+ * <p>Conditions (also known as <em>condition queues</em> or
+ * <em>condition variables</em>) provide a means for one thread to
+ * suspend execution (to &quot;wait&quot;) until notified by another
+ * thread that some state condition may now be true.  Because access
+ * to this shared state information occurs in different threads, it
+ * must be protected, so a lock of some form is associated with the
+ * condition. The key property that waiting for a condition provides
+ * is that it <em>atomically</em> releases the associated lock and
+ * suspends the current thread, just like <tt>Object.wait</tt>.
+ * <p/>
+ * <p>A <tt>Condition</tt> instance is intrinsically bound to a lock.
+ * To obtain a <tt>Condition</tt> instance for a particular {@link Lock}
+ * instance use its {@link Lock#newCondition newCondition()} method.
+ * <p/>
+ * <p>As an example, suppose we have a bounded buffer which supports
+ * <tt>put</tt> and <tt>take</tt> methods.  If a
+ * <tt>take</tt> is attempted on an empty buffer, then the thread will block
+ * until an item becomes available; if a <tt>put</tt> is attempted on a
+ * full buffer, then the thread will block until a space becomes available.
+ * We would like to keep waiting <tt>put</tt> threads and <tt>take</tt>
+ * threads in separate wait-sets so that we can use the optimization of
+ * only notifying a single thread at a time when items or spaces become
+ * available in the buffer. This can be achieved using two
+ * {@link Condition} instances.
+ * <pre>
+ * class BoundedBuffer {
+ *   <b>final Lock lock = new ReentrantLock();</b>
+ *   final Condition notFull  = <b>lock.newCondition(); </b>
+ *   final Condition notEmpty = <b>lock.newCondition(); </b>
+ * <p/>
+ *   final Object[] items = new Object[100];
+ *   int putptr, takeptr, count;
+ * <p/>
+ *   public void put(Object x) throws InterruptedException {
+ *     <b>lock.lock();
+ *     try {</b>
+ *       while (count == items.length)
+ *         <b>notFull.await();</b>
+ *       items[putptr] = x;
+ *       if (++putptr == items.length) putptr = 0;
+ *       ++count;
+ *       <b>notEmpty.signal();</b>
+ *     <b>} finally {
+ *       lock.unlock();
+ *     }</b>
+ *   }
+ * <p/>
+ *   public Object take() throws InterruptedException {
+ *     <b>lock.lock();
+ *     try {</b>
+ *       while (count == 0)
+ *         <b>notEmpty.await();</b>
+ *       Object x = items[takeptr];
+ *       if (++takeptr == items.length) takeptr = 0;
+ *       --count;
+ *       <b>notFull.signal();</b>
+ *       return x;
+ *     <b>} finally {
+ *       lock.unlock();
+ *     }</b>
+ *   }
+ * }
+ * </pre>
+ * <p/>
+ * (The {@link org.apache.ti.util.concurrent.ArrayBlockingQueue} class provides
+ * this functionality, so there is no reason to implement this
+ * sample usage class.)
+ * <p/>
+ * <p>A <tt>Condition</tt> implementation can provide behavior and semantics
+ * that is
+ * different from that of the <tt>Object</tt> monitor methods, such as
+ * guaranteed ordering for notifications, or not requiring a lock to be held
+ * when performing notifications.
+ * If an implementation provides such specialized semantics then the
+ * implementation must document those semantics.
+ * <p/>
+ * <p>Note that <tt>Condition</tt> instances are just normal objects and can
+ * themselves be used as the target in a <tt>synchronized</tt> statement,
+ * and can have their own monitor {@link Object#wait wait} and
+ * {@link Object#notify notification} methods invoked.
+ * Acquiring the monitor lock of a <tt>Condition</tt> instance, or using its
+ * monitor methods, has no specified relationship with acquiring the
+ * {@link Lock} associated with that <tt>Condition</tt> or the use of its
+ * {@link #await waiting} and {@link #signal signalling} methods.
+ * It is recommended that to avoid confusion you never use <tt>Condition</tt>
+ * instances in this way, except perhaps within their own implementation.
+ * <p/>
+ * <p>Except where noted, passing a <tt>null</tt> value for any parameter
+ * will result in a {@link NullPointerException} being thrown.
+ * <p/>
+ * <h3>Implementation Considerations</h3>
+ * <p/>
+ * <p>When waiting upon a <tt>Condition</tt>, a &quot;<em>spurious
+ * wakeup</em>&quot; is permitted to occur, in
+ * general, as a concession to the underlying platform semantics.
+ * This has little practical impact on most application programs as a
+ * <tt>Condition</tt> should always be waited upon in a loop, testing
+ * the state predicate that is being waited for.  An implementation is
+ * free to remove the possibility of spurious wakeups but it is
+ * recommended that applications programmers always assume that they can
+ * occur and so always wait in a loop.
+ * <p/>
+ * <p>The three forms of condition waiting
+ * (interruptible, non-interruptible, and timed) may differ in their ease of
+ * implementation on some platforms and in their performance characteristics.
+ * In particular, it may be difficult to provide these features and maintain
+ * specific semantics such as ordering guarantees.
+ * Further, the ability to interrupt the actual suspension of the thread may
+ * not always be feasible to implement on all platforms.
+ * <p>Consequently, an implementation is not required to define exactly the
+ * same guarantees or semantics for all three forms of waiting, nor is it
+ * required to support interruption of the actual suspension of the thread.
+ * <p>An implementation is required to
+ * clearly document the semantics and guarantees provided by each of the
+ * waiting methods, and when an implementation does support interruption of
+ * thread suspension then it must obey the interruption semantics as defined
+ * in this interface.
+ * <p>As interruption generally implies cancellation, and checks for
+ * interruption are often infrequent, an implementation can favor responding
+ * to an interrupt over normal method return. This is true even if it can be
+ * shown that the interrupt occurred after another action may have unblocked
+ * the thread. An implementation should document this behavior.
+ *
+ * @author Doug Lea
+ * @since 1.5
+ */
+interface Condition {
+
+    /**
+     * Causes the current thread to wait until it is signalled or
+     * {@link Thread#interrupt interrupted}.
+     * <p/>
+     * <p>The lock associated with this <tt>Condition</tt> is atomically
+     * released and the current thread becomes disabled for thread scheduling
+     * purposes and lies dormant until <em>one</em> of four things happens:
+     * <ul>
+     * <li>Some other thread invokes the {@link #signal} method for this
+     * <tt>Condition</tt> and the current thread happens to be chosen as the
+     * thread to be awakened; or
+     * <li>Some other thread invokes the {@link #signalAll} method for this
+     * <tt>Condition</tt>; or
+     * <li>Some other thread {@link Thread#interrupt interrupts} the current
+     * thread, and interruption of thread suspension is supported; or
+     * <li>A &quot;<em>spurious wakeup</em>&quot; occurs
+     * </ul>
+     * <p/>
+     * <p>In all cases, before this method can return the current thread must
+     * re-acquire the lock associated with this condition. When the
+     * thread returns it is <em>guaranteed</em> to hold this lock.
+     * <p/>
+     * <p>If the current thread:
+     * <ul>
+     * <li>has its interrupted status set on entry to this method; or
+     * <li>is {@link Thread#interrupt interrupted} while waiting
+     * and interruption of thread suspension is supported,
+     * </ul>
+     * then {@link InterruptedException} is thrown and the current thread's
+     * interrupted status is cleared. It is not specified, in the first
+     * case, whether or not the test for interruption occurs before the lock
+     * is released.
+     * <p/>
+     * <p><b>Implementation Considerations</b>
+     * <p>The current thread is assumed to hold the lock associated with this
+     * <tt>Condition</tt> when this method is called.
+     * It is up to the implementation to determine if this is
+     * the case and if not, how to respond. Typically, an exception will be
+     * thrown (such as {@link IllegalMonitorStateException}) and the
+     * implementation must document that fact.
+     * <p/>
+     * <p>An implementation can favor responding to an interrupt over normal
+     * method return in response to a signal. In that case the implementation
+     * must ensure that the signal is redirected to another waiting thread, if
+     * there is one.
+     *
+     * @throws InterruptedException if the current thread is interrupted (and
+     *                              interruption of thread suspension is supported).
+     */
+    void await() throws InterruptedException;
+
+    /**
+     * Causes the current thread to wait until it is signalled.
+     * <p/>
+     * <p>The lock associated with this condition is atomically
+     * released and the current thread becomes disabled for thread scheduling
+     * purposes and lies dormant until <em>one</em> of three things happens:
+     * <ul>
+     * <li>Some other thread invokes the {@link #signal} method for this
+     * <tt>Condition</tt> and the current thread happens to be chosen as the
+     * thread to be awakened; or
+     * <li>Some other thread invokes the {@link #signalAll} method for this
+     * <tt>Condition</tt>; or
+     * <li>A &quot;<em>spurious wakeup</em>&quot; occurs
+     * </ul>
+     * <p/>
+     * <p>In all cases, before this method can return the current thread must
+     * re-acquire the lock associated with this condition. When the
+     * thread returns it is <em>guaranteed</em> to hold this lock.
+     * <p/>
+     * <p>If the current thread's interrupted status is set when it enters
+     * this method, or it is {@link Thread#interrupt interrupted}
+     * while waiting, it will continue to wait until signalled. When it finally
+     * returns from this method its interrupted status will still
+     * be set.
+     * <p/>
+     * <p><b>Implementation Considerations</b>
+     * <p>The current thread is assumed to hold the lock associated with this
+     * <tt>Condition</tt> when this method is called.
+     * It is up to the implementation to determine if this is
+     * the case and if not, how to respond. Typically, an exception will be
+     * thrown (such as {@link IllegalMonitorStateException}) and the
+     * implementation must document that fact.
+     */
+    void awaitUninterruptibly();
+
+//    /**
+//     * Causes the current thread to wait until it is signalled or interrupted,
+//     * or the specified waiting time elapses.
+//     *
+//     * <p>The lock associated with this condition is atomically
+//     * released and the current thread becomes disabled for thread scheduling
+//     * purposes and lies dormant until <em>one</em> of five things happens:
+//     * <ul>
+//     * <li>Some other thread invokes the {@link #signal} method for this
+//     * <tt>Condition</tt> and the current thread happens to be chosen as the
+//     * thread to be awakened; or
+//     * <li>Some other thread invokes the {@link #signalAll} method for this
+//     * <tt>Condition</tt>; or
+//     * <li>Some other thread {@link Thread#interrupt interrupts} the current
+//     * thread, and interruption of thread suspension is supported; or
+//     * <li>The specified waiting time elapses; or
+//     * <li>A &quot;<em>spurious wakeup</em>&quot; occurs.
+//     * </ul>
+//     *
+//     * <p>In all cases, before this method can return the current thread must
+//     * re-acquire the lock associated with this condition. When the
+//     * thread returns it is <em>guaranteed</em> to hold this lock.
+//     *
+//     * <p>If the current thread:
+//     * <ul>
+//     * <li>has its interrupted status set on entry to this method; or
+//     * <li>is {@link Thread#interrupt interrupted} while waiting
+//     * and interruption of thread suspension is supported,
+//     * </ul>
+//     * then {@link InterruptedException} is thrown and the current thread's
+//     * interrupted status is cleared. It is not specified, in the first
+//     * case, whether or not the test for interruption occurs before the lock
+//     * is released.
+//     *
+//     * <p>The method returns an estimate of the number of nanoseconds
+//     * remaining to wait given the supplied <tt>nanosTimeout</tt>
+//     * value upon return, or a value less than or equal to zero if it
+//     * timed out. This value can be used to determine whether and how
+//     * long to re-wait in cases where the wait returns but an awaited
+//     * condition still does not hold. Typical uses of this method take
+//     * the following form:
+//     *
+//     * <pre>
+//     * synchronized boolean aMethod(long timeout, TimeUnit unit) {
+//     *   long nanosTimeout = unit.toNanos(timeout);
+//     *   while (!conditionBeingWaitedFor) {
+//     *     if (nanosTimeout &gt; 0)
+//     *         nanosTimeout = theCondition.awaitNanos(nanosTimeout);
+//     *      else
+//     *        return false;
+//     *   }
+//     *   // ...
+//     * }
+//     * </pre>
+//     *
+//     * <p> Design note: This method requires a nanosecond argument so
+//     * as to avoid truncation errors in reporting remaining times.
+//     * Such precision loss would make it difficult for programmers to
+//     * ensure that total waiting times are not systematically shorter
+//     * than specified when re-waits occur.
+//     *
+//     * <p><b>Implementation Considerations</b>
+//     * <p>The current thread is assumed to hold the lock associated with this
+//     * <tt>Condition</tt> when this method is called.
+//     * It is up to the implementation to determine if this is
+//     * the case and if not, how to respond. Typically, an exception will be
+//     * thrown (such as {@link IllegalMonitorStateException}) and the
+//     * implementation must document that fact.
+//     *
+//     * <p>An implementation can favor responding to an interrupt over normal
+//     * method return in response to a signal, or over indicating the elapse
+//     * of the specified waiting time. In either case the implementation
+//     * must ensure that the signal is redirected to another waiting thread, if
+//     * there is one.
+//     *
+//     * @param nanosTimeout the maximum time to wait, in nanoseconds
+//     * @return A value less than or equal to zero if the wait has
+//     * timed out; otherwise an estimate, that
+//     * is strictly less than the <tt>nanosTimeout</tt> argument,
+//     * of the time still remaining when this method returned.
+//     *
+//     * @throws InterruptedException if the current thread is interrupted (and
+//     * interruption of thread suspension is supported).
+//     */
+//    long awaitNanos(long nanosTimeout) throws InterruptedException;
+
+    /**
+     * Causes the current thread to wait until it is signalled or interrupted,
+     * or the specified waiting time elapses. This method is behaviorally
+     * equivalent to:<br>
+     * <pre>
+     *   awaitNanos(unit.toNanos(time)) &gt; 0
+     * </pre>
+     *
+     * @param time the maximum time to wait
+     * @param unit the time unit of the <tt>time</tt> argument.
+     * @return <tt>false</tt> if the waiting time detectably elapsed
+     *         before return from the method, else <tt>true</tt>.
+     * @throws InterruptedException if the current thread is interrupted (and
+     *                              interruption of thread suspension is supported).
+     */
+    boolean await(long time, TimeUnit unit) throws InterruptedException;
+
+    /**
+     * Causes the current thread to wait until it is signalled or interrupted,
+     * or the specified deadline elapses.
+     * <p/>
+     * <p>The lock associated with this condition is atomically
+     * released and the current thread becomes disabled for thread scheduling
+     * purposes and lies dormant until <em>one</em> of five things happens:
+     * <ul>
+     * <li>Some other thread invokes the {@link #signal} method for this
+     * <tt>Condition</tt> and the current thread happens to be chosen as the
+     * thread to be awakened; or
+     * <li>Some other thread invokes the {@link #signalAll} method for this
+     * <tt>Condition</tt>; or
+     * <li>Some other thread {@link Thread#interrupt interrupts} the current
+     * thread, and interruption of thread suspension is supported; or
+     * <li>The specified deadline elapses; or
+     * <li>A &quot;<em>spurious wakeup</em>&quot; occurs.
+     * </ul>
+     * <p/>
+     * <p>In all cases, before this method can return the current thread must
+     * re-acquire the lock associated with this condition. When the
+     * thread returns it is <em>guaranteed</em> to hold this lock.
+     * <p/>
+     * <p/>
+     * <p>If the current thread:
+     * <ul>
+     * <li>has its interrupted status set on entry to this method; or
+     * <li>is {@link Thread#interrupt interrupted} while waiting
+     * and interruption of thread suspension is supported,
+     * </ul>
+     * then {@link InterruptedException} is thrown and the current thread's
+     * interrupted status is cleared. It is not specified, in the first
+     * case, whether or not the test for interruption occurs before the lock
+     * is released.
+     * <p/>
+     * <p/>
+     * <p>The return value indicates whether the deadline has elapsed,
+     * which can be used as follows:
+     * <pre>
+     * synchronized boolean aMethod(Date deadline) {
+     *   boolean stillWaiting = true;
+     *   while (!conditionBeingWaitedFor) {
+     *     if (stillwaiting)
+     *         stillWaiting = theCondition.awaitUntil(deadline);
+     *      else
+     *        return false;
+     *   }
+     *   // ...
+     * }
+     * </pre>
+     * <p/>
+     * <p><b>Implementation Considerations</b>
+     * <p>The current thread is assumed to hold the lock associated with this
+     * <tt>Condition</tt> when this method is called.
+     * It is up to the implementation to determine if this is
+     * the case and if not, how to respond. Typically, an exception will be
+     * thrown (such as {@link IllegalMonitorStateException}) and the
+     * implementation must document that fact.
+     * <p/>
+     * <p>An implementation can favor responding to an interrupt over normal
+     * method return in response to a signal, or over indicating the passing
+     * of the specified deadline. In either case the implementation
+     * must ensure that the signal is redirected to another waiting thread, if
+     * there is one.
+     *
+     * @param deadline the absolute time to wait until
+     * @return <tt>false</tt> if the deadline has
+     *         elapsed upon return, else <tt>true</tt>.
+     * @throws InterruptedException if the current thread is interrupted (and
+     *                              interruption of thread suspension is supported).
+     */
+    boolean awaitUntil(Date deadline) throws InterruptedException;
+
+    /**
+     * Wakes up one waiting thread.
+     * <p/>
+     * <p>If any threads are waiting on this condition then one
+     * is selected for waking up. That thread must then re-acquire the
+     * lock before returning from <tt>await</tt>.
+     */
+    void signal();
+
+    /**
+     * Wakes up all waiting threads.
+     * <p/>
+     * <p>If any threads are waiting on this condition then they are
+     * all woken up. Each thread must re-acquire the lock before it can
+     * return from <tt>await</tt>.
+     */
+    void signalAll();
+
+}

Added: struts/sandbox/trunk/ti/core/src/java/org/apache/ti/util/internal/concurrent/FIFOWaitQueue.java
URL: http://svn.apache.org/viewcvs/struts/sandbox/trunk/ti/core/src/java/org/apache/ti/util/internal/concurrent/FIFOWaitQueue.java?rev=240168&view=auto
==============================================================================
--- struts/sandbox/trunk/ti/core/src/java/org/apache/ti/util/internal/concurrent/FIFOWaitQueue.java (added)
+++ struts/sandbox/trunk/ti/core/src/java/org/apache/ti/util/internal/concurrent/FIFOWaitQueue.java Thu Aug 25 22:46:03 2005
@@ -0,0 +1,77 @@
+package org.apache.ti.util.internal.concurrent;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * Simple linked list queue used in FIFOSemaphore.
+ * Methods are not synchronized; they depend on synch of callers.
+ * Must be public, since it is used by Semaphore (outside this package).
+ * NOTE: this class is NOT present in java.util.concurrent.
+ */
+
+class FIFOWaitQueue extends WaitQueue implements java.io.Serializable {
+
+    protected transient WaitNode head_ = null;
+    protected transient WaitNode tail_ = null;
+
+    public FIFOWaitQueue() {
+    }
+
+    public void insert(WaitNode w) {
+        if (tail_ == null)
+            head_ = tail_ = w;
+        else {
+            tail_.next = w;
+            tail_ = w;
+        }
+    }
+
+    public WaitNode extract() {
+        if (head_ == null)
+            return null;
+        else {
+            WaitNode w = head_;
+            head_ = w.next;
+            if (head_ == null)
+                tail_ = null;
+            w.next = null;
+            return w;
+        }
+    }
+
+    public boolean hasNodes() {
+        return head_ != null;
+    }
+
+    public int getLength() {
+        int count = 0;
+        WaitNode node = head_;
+        while (node != null) {
+            if (node.waiting) count++;
+            node = node.next;
+        }
+        return count;
+    }
+
+    public Collection getWaitingThreads() {
+        List list = new ArrayList();
+        int count = 0;
+        WaitNode node = head_;
+        while (node != null) {
+            if (node.waiting) list.add(node.owner);
+            node = node.next;
+        }
+        return list;
+    }
+
+    public boolean isWaiting(Thread thread) {
+        if (thread == null) throw new NullPointerException();
+        for (WaitNode node = head_; node != null; node = node.next) {
+            if (node.waiting && node.owner == thread) return true;
+        }
+        return false;
+    }
+
+}



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@struts.apache.org
For additional commands, e-mail: dev-help@struts.apache.org


Mime
View raw message