JBossWeb SVN: r1895 - tags.
by jbossweb-commits@lists.jboss.org
Author: remy.maucherat(a)jboss.com
Date: 2011-12-15 10:22:11 -0500 (Thu, 15 Dec 2011)
New Revision: 1895
Added:
tags/JBOSSWEB_7_0_6_FINAL/
Log:
Web 7.0.6.
13 years
JBossWeb SVN: r1894 - trunk/webapps/docs.
by jbossweb-commits@lists.jboss.org
Author: remy.maucherat(a)jboss.com
Date: 2011-12-15 10:03:27 -0500 (Thu, 15 Dec 2011)
New Revision: 1894
Modified:
trunk/webapps/docs/changelog.xml
Log:
Update
Modified: trunk/webapps/docs/changelog.xml
===================================================================
--- trunk/webapps/docs/changelog.xml 2011-12-15 12:19:51 UTC (rev 1893)
+++ trunk/webapps/docs/changelog.xml 2011-12-15 15:03:27 UTC (rev 1894)
@@ -24,6 +24,13 @@
</fix>
</changelog>
</subsection>
+ <subsection name="Coyote">
+ <changelog>
+ <update>
+ <jboss-jira>AS7-2695</jboss-jira>: Native library loading updates. (jfclere, mturk)
+ </update>
+ </changelog>
+ </subsection>
</section>
<section name="JBoss Web 7.0.5.Final (remm)">
13 years
JBossWeb SVN: r1893 - trunk/java/org/apache/tomcat/jni.
by jbossweb-commits@lists.jboss.org
Author: mladen.turk(a)jboss.com
Date: 2011-12-15 07:19:51 -0500 (Thu, 15 Dec 2011)
New Revision: 1893
Modified:
trunk/java/org/apache/tomcat/jni/Library.java
Log:
Call LibraryLoader before System.loadLibrary. Otherwise dependecies can be auto bound to libraries inside LD_LIBRARY_PATH instead explicitly from dependecy list
Modified: trunk/java/org/apache/tomcat/jni/Library.java
===================================================================
--- trunk/java/org/apache/tomcat/jni/Library.java 2011-12-15 10:52:00 UTC (rev 1892)
+++ trunk/java/org/apache/tomcat/jni/Library.java 2011-12-15 12:19:51 UTC (rev 1893)
@@ -37,41 +37,40 @@
{
boolean loaded = false;
String err = "";
- for (int i = 0; i < NAMES.length; i++) {
- try {
- System.loadLibrary(NAMES[i]);
- loaded = true;
- }
- catch (Throwable e) {
- if ( i > 0)
- err += ", ";
+ try {
+ LibraryLoader.load(System.getProperty("catalina.home"));
+ loaded = true;
+ }
+ catch (Throwable e) {
+ err += e.getMessage();
+ }
+ if (!loaded) {
+ for (int i = 0; i < NAMES.length; i++) {
+ try {
+ System.loadLibrary(NAMES[i]);
+ loaded = true;
+ }
+ catch (Throwable e) {
+ if ( i > 0)
+ err += ", ";
- String name = System.mapLibraryName(NAMES[i]);
- String path = System.getProperty("java.library.path");
- String sep = System.getProperty("path.separator");
- String [] paths = path.split(sep);
- for (int j=0; j<paths.length; j++) {
- java.io.File fd = new java.io.File(paths[j] + System.getProperty("file.separator") + name);
- if (fd.exists()) {
- err += "(Error on: " + paths[j] + System.getProperty("file.separator") + name +")";
+ String name = System.mapLibraryName(NAMES[i]);
+ String path = System.getProperty("java.library.path");
+ String sep = System.getProperty("path.separator");
+ String [] paths = path.split(sep);
+ for (int j=0; j<paths.length; j++) {
+ java.io.File fd = new java.io.File(paths[j] + System.getProperty("file.separator") + name);
+ if (fd.exists()) {
+ err += "(Error on: " + paths[j] + System.getProperty("file.separator") + name +")";
+ }
}
+ err += e.getMessage();
}
- err += e.getMessage();
+ if (loaded)
+ break;
}
- if (loaded)
- break;
}
if (!loaded) {
- err += " (LibraryLoader.load()): ";
- try {
- LibraryLoader.load(System.getProperty("catalina.home"));
- loaded = true;
- }
- catch (Throwable e) {
- err += e.getMessage();
- }
- }
- if (!loaded) {
err += "(";
err += System.getProperty("java.library.path");
err += ")";
13 years
JBossWeb SVN: r1892 - trunk/java/org/apache/tomcat/jni.
by jbossweb-commits@lists.jboss.org
Author: jfrederic.clere(a)jboss.com
Date: 2011-12-15 05:52:00 -0500 (Thu, 15 Dec 2011)
New Revision: 1892
Modified:
trunk/java/org/apache/tomcat/jni/Library.properties
Log:
Oops forgotten prefix.
Modified: trunk/java/org/apache/tomcat/jni/Library.properties
===================================================================
--- trunk/java/org/apache/tomcat/jni/Library.properties 2011-12-15 09:17:25 UTC (rev 1891)
+++ trunk/java/org/apache/tomcat/jni/Library.properties 2011-12-15 10:52:00 UTC (rev 1892)
@@ -28,7 +28,7 @@
linux2.count=5
linux2.0=apr-1
-linux2.1=?libz
+linux2.1=?z
linux2.2=?crypto
linux2.3=?ssl
linux2.4=tcnative-1
13 years
JBossWeb SVN: r1891 - trunk/java/org/apache/tomcat/jni.
by jbossweb-commits@lists.jboss.org
Author: jfrederic.clere(a)jboss.com
Date: 2011-12-15 04:17:25 -0500 (Thu, 15 Dec 2011)
New Revision: 1891
Modified:
trunk/java/org/apache/tomcat/jni/Library.properties
trunk/java/org/apache/tomcat/jni/LibraryLoader.java
Log:
Fix for AS7-2695.
Modified: trunk/java/org/apache/tomcat/jni/Library.properties
===================================================================
--- trunk/java/org/apache/tomcat/jni/Library.properties 2011-12-15 07:29:10 UTC (rev 1890)
+++ trunk/java/org/apache/tomcat/jni/Library.properties 2011-12-15 09:17:25 UTC (rev 1891)
@@ -1,4 +1,4 @@
-# Copyright(c) 2007 Red Hat Middleware, LLC,
+# Copyright(c) 2011 Red Hat Middleware, LLC,
# and individual contributors as indicated by the @authors tag.
# See the copyright.txt in the distribution for a
# full listing of individual contributors.
@@ -19,49 +19,37 @@
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
#
# @author Mladen Turk
+# @author Jean-Frederic Clere
#
# Library.properties
#
-windows.count=6
+windows.count=1
windows.0=*tcnative-1.dll
-windows.1=libapr-1.dll
-windows.2=libaprutil-1.dll
-windows.3=?libeay32.dll
-windows.4=?ssleay32.dll
-windows.5=libtcnative-1.dll
-linux2.count=7
-linux2.0=libapr-1.so
-linux2.1=?libexpat.so
-linux2.2=?libaprutil-1.so
-linux2.3=?libz.so
-linux2.4=?libcrypto.so
-linux2.5=?libssl.so
-linux2.6=libtcnative-1.so
+linux2.count=5
+linux2.0=apr-1
+linux2.1=?libz
+linux2.2=?crypto
+linux2.3=?ssl
+linux2.4=tcnative-1
-solaris.count=7
-solaris.0=libapr-1.so
-solaris.1=?libexpat.so
-solaris.2=?libaprutil-1.so
-solaris.3=?libz.so
-solaris.4=?libcrypto.so
-solaris.5=?libssl.so
-solaris.6=libtcnative-1.so
+solaris.count=5
+solaris.0=apr-1
+solaris.1=?z
+solaris.2=?crypto
+solaris.3=?ssl
+solaris.4=tcnative-1
-hpux.count=7
-hpux.0=libapr-1.sl
-hpux.1=?libexpat.sl
-hpux.2=?libaprutil-1.sl
-hpux.3=?libz.sl
-hpux.4=?libcrypto.sl
-hpux.5=?libssl.sl
-hpux.6=libtcnative-1.sl
+hpux.count=5
+hpux.0=apr-1
+hpux.1=?z
+hpux.2=?crypto
+hpux.3=?ssl
+hpux.4=tcnative-1
-macosx.count=7
-macosx.0=libapr-1.dylib
-macosx.1=?libexpat.dylib
-macosx.2=?libaprutil-1.dylib
-macosx.3=?libz.dylib
-macosx.4=?libcrypto.dylib
-macosx.5=?libssl.dylib
-macosx.6=libtcnative-1.dylib
+macosx.count=5
+macosx.0=apr-1
+macosx.1=?z
+macosx.2=?crypto
+macosx.3=?ssl
+macosx.4=tcnative-1
Modified: trunk/java/org/apache/tomcat/jni/LibraryLoader.java
===================================================================
--- trunk/java/org/apache/tomcat/jni/LibraryLoader.java 2011-12-15 07:29:10 UTC (rev 1890)
+++ trunk/java/org/apache/tomcat/jni/LibraryLoader.java 2011-12-15 09:17:25 UTC (rev 1891)
@@ -29,8 +29,11 @@
import java.io.InputStream;
import java.util.Properties;
+import org.jboss.logging.Logger;
+
public final class LibraryLoader {
+ private static Logger log = Logger.getLogger(org.apache.catalina.core.AprLifecycleListener.class);
public static String getDefaultPlatformName()
{
@@ -57,61 +60,6 @@
return platform;
}
- public static String getDefaultPlatformNameVersion()
- {
- String platform = getDefaultPlatformName();
-
-
- if (platform.equals("solaris")) {
- // Add the version...
- String version = System.getProperty("os.version");
- if (version.equals("5.10"))
- platform = "solaris10";
- else if (version.equals("5.9"))
- platform = "solaris9";
- else
- platform = "solaris11";
- }
-
- return platform;
- }
-
- public static String getDefaultPlatformCpu()
- {
- String cpu;
- String arch = System.getProperty("os.arch");
-
- if (arch.endsWith("86"))
- cpu = "x86";
- else if (arch.startsWith("PA_RISC")) {
- if (arch.endsWith("W"))
- cpu = "parisc2W";
- else
- cpu = "parisc2";
- } else if (arch.startsWith("IA64"))
- cpu = "i64";
- else if (arch.equals("x86_64"))
- cpu = "x64";
- else if (arch.equals("amd64"))
- cpu = "x64";
- else
- cpu = arch;
- return cpu;
- }
-
- public static String getDefaultLibraryPath()
- {
- String name = getDefaultPlatformNameVersion();
- String arch = getDefaultPlatformCpu();
-
- return name + File.separator + arch;
- }
-
- public static String getDefaultMetaPath()
- {
- return "META-INF" + File.separator + "lib" + File.separator;
- }
-
private LibraryLoader()
{
// Disallow creation
@@ -122,23 +70,8 @@
{
int count = 0;
String name = getDefaultPlatformName();
- String path = getDefaultLibraryPath();
Properties props = new Properties();
- File root = new File(rootPath);
- String basePath = root.getCanonicalPath().toString();
- if (!basePath.endsWith(File.separator)) {
- basePath += File.separator;
- }
- String metaPath = basePath + getDefaultMetaPath();
- File meta = new File(metaPath);
- if (!meta.exists()) {
- /* Try adding bin prefix to rootPath.
- * Used if we pass catalina.base property
- */
- metaPath = basePath + "bin" + File.separator +
- getDefaultMetaPath();
- }
try {
InputStream is = LibraryLoader.class.getResourceAsStream
("/org/apache/tomcat/jni/Library.properties");
@@ -162,23 +95,19 @@
dlibName = dlibName.substring(1);
full = true;
}
- String fullPath = metaPath + path +
- File.separator + dlibName;
+
+ /* AS7 jboss-modules takes care of the names */
try {
- Runtime.getRuntime().load(fullPath);
+ System.loadLibrary(dlibName);
+ log.debug("Loaded: " + dlibName);
+ } catch (Throwable d) {
+ log.debug("Loading " + dlibName + " throws: " + d);
+ if (optional)
+ continue;
+ throw new UnsatisfiedLinkError(" Error: " + d.getMessage() + " " );
}
- catch (Throwable d) {
- if (!optional) {
- java.io.File fd = new java.io.File(fullPath);
- if (fd.exists()) {
- throw new UnsatisfiedLinkError(" Error: " + d.getMessage() + " " );
- } else {
- throw new UnsatisfiedLinkError(" Can't find: " + fullPath + " ");
- }
- }
- }
if (full)
- break;
+ break;
}
}
13 years
JBossWeb SVN: r1890 - branches.
by jbossweb-commits@lists.jboss.org
Author: bmaxwell
Date: 2011-12-15 02:29:10 -0500 (Thu, 15 Dec 2011)
New Revision: 1890
Added:
branches/JBOSSWEB_2_1_10_GA_JBPAPP-7745/
Log:
[JBPAPP-7745] create one off patch branch
13 years
JBossWeb SVN: r1889 - in trunk: webapps/docs and 1 other directory.
by jbossweb-commits@lists.jboss.org
Author: remy.maucherat(a)jboss.com
Date: 2011-12-14 09:20:31 -0500 (Wed, 14 Dec 2011)
New Revision: 1889
Modified:
trunk/java/org/apache/jasper/compiler/Parser.java
trunk/webapps/docs/changelog.xml
Log:
- JBWEB-211: Improve include exception handling.
- Fix bad jira links.
Modified: trunk/java/org/apache/jasper/compiler/Parser.java
===================================================================
--- trunk/java/org/apache/jasper/compiler/Parser.java 2011-12-09 13:06:00 UTC (rev 1888)
+++ trunk/java/org/apache/jasper/compiler/Parser.java 2011-12-14 14:20:31 UTC (rev 1889)
@@ -297,7 +297,7 @@
} catch (FileNotFoundException ex) {
err.jspError(start, "jsp.error.file.not.found", file);
} catch (Exception ex) {
- err.jspError(start, ex.getMessage());
+ err.jspError(parent, "jsp.error.include.exception", file, ex);
}
}
Modified: trunk/webapps/docs/changelog.xml
===================================================================
--- trunk/webapps/docs/changelog.xml 2011-12-09 13:06:00 UTC (rev 1888)
+++ trunk/webapps/docs/changelog.xml 2011-12-14 14:20:31 UTC (rev 1889)
@@ -16,11 +16,21 @@
<body>
+<section name="JBoss Web 7.0.6.Final (remm)">
+ <subsection name="Jasper">
+ <changelog>
+ <fix>
+ <jira>211</jira>: Better exception handling when including. (remm)
+ </fix>
+ </changelog>
+ </subsection>
+</section>
+
<section name="JBoss Web 7.0.5.Final (remm)">
<subsection name="Catalina">
<changelog>
<update>
- <jira>AS7-2844</jira>: Error pages are supposed to complete or dispatch an async operation,
+ <jboss-jira>AS7-2844</jboss-jira>: Error pages are supposed to complete or dispatch an async operation,
but the check was not in the right location. (remm)
</update>
</changelog>
@@ -55,7 +65,7 @@
Filter out multibyte chars when writing a char chunk. (rjung)
</fix>
<fix>
- <jira>AS7-2739</jira>: Allow using the keepalive disable configuration
+ <jboss-jira>AS7-2739</jboss-jira>: Allow using the keepalive disable configuration
when using the async or event modes. (remm)
</fix>
</changelog>
@@ -69,7 +79,7 @@
Improve DIGEST authentication security. (remm)
</fix>
<fix>
- <jira>AS7-2073</jira>: Delegate connector lifecycle handling if in delay mode. (jfclere, remm)
+ <jboss-jira>AS7-2073</jboss-jira>: Delegate connector lifecycle handling if in delay mode. (jfclere, remm)
</fix>
<fix>
For compatibility with managers which don't extend StandardManager, set the session timeout
@@ -115,7 +125,7 @@
<bug>51860</bug>: Fix issues when keyAlias is being used. (markt)
</fix>
<fix>
- <jira>JBWEB-201</jira>JBoss Web Native causes JVM crash with AJP. (jfclere/remm)
+ <jira>201</jira>: JBoss Web Native causes JVM crash with AJP. (jfclere/remm)
</fix>
</changelog>
</subsection>
13 years
JBossWeb SVN: r1888 - tags.
by jbossweb-commits@lists.jboss.org
Author: remy.maucherat(a)jboss.com
Date: 2011-12-09 08:06:00 -0500 (Fri, 09 Dec 2011)
New Revision: 1888
Added:
tags/JBOSSWEB_7_0_5_FINAL/
Log:
Web 7.0.5.
13 years
JBossWeb SVN: r1887 - trunk/webapps/docs.
by jbossweb-commits@lists.jboss.org
Author: remy.maucherat(a)jboss.com
Date: 2011-12-08 12:30:05 -0500 (Thu, 08 Dec 2011)
New Revision: 1887
Modified:
trunk/webapps/docs/changelog.xml
Log:
Update.
Modified: trunk/webapps/docs/changelog.xml
===================================================================
--- trunk/webapps/docs/changelog.xml 2011-12-08 17:29:28 UTC (rev 1886)
+++ trunk/webapps/docs/changelog.xml 2011-12-08 17:30:05 UTC (rev 1887)
@@ -20,11 +20,18 @@
<subsection name="Catalina">
<changelog>
<update>
- <jira>AS7-2844</jira>: Error pages are suppose to complete or dispatch an async operation,
+ <jira>AS7-2844</jira>: Error pages are supposed to complete or dispatch an async operation,
but the check was not in the right location. (remm)
</update>
</changelog>
</subsection>
+ <subsection name="Coyote">
+ <changelog>
+ <fix>
+ Change default to unlimited keepalives for HTTP. (remm)
+ </fix>
+ </changelog>
+ </subsection>
<subsection name="Jasper">
<changelog>
<fix>
13 years
JBossWeb SVN: r1886 - trunk/java/javax/el.
by jbossweb-commits@lists.jboss.org
Author: remy.maucherat(a)jboss.com
Date: 2011-12-08 12:29:28 -0500 (Thu, 08 Dec 2011)
New Revision: 1886
Modified:
trunk/java/javax/el/BeanELResolver.java
Log:
Add the Tomcat version of the bean EL resolver. It is used only locally for building and
testing.
Modified: trunk/java/javax/el/BeanELResolver.java
===================================================================
--- trunk/java/javax/el/BeanELResolver.java 2011-12-07 16:23:56 UTC (rev 1885)
+++ trunk/java/javax/el/BeanELResolver.java 2011-12-08 17:29:28 UTC (rev 1886)
@@ -1,743 +1,493 @@
/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
*
- * Copyright 1997-2008 Sun Microsystems, Inc. All rights reserved.
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * The contents of this file are subject to the terms of either the GNU
- * General Public License Version 2 only ("GPL") or the Common Development
- * and Distribution License("CDDL") (collectively, the "License"). You
- * may not use this file except in compliance with the License. You can obtain
- * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
- * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
- * language governing permissions and limitations under the License.
- *
- * When distributing the software, include this License Header Notice in each
- * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
- * Sun designates this particular file as subject to the "Classpath" exception
- * as provided by Sun in the GPL Version 2 section of the License file that
- * accompanied this code. If applicable, add the following below the License
- * Header, with the fields enclosed by brackets [] replaced by your own
- * identifying information: "Portions Copyrighted [year]
- * [name of copyright owner]"
- *
- * Contributor(s):
- *
- * If you wish your version of this file to be governed by only the CDDL or
- * only the GPL Version 2, indicate your decision by adding "[Contributor]
- * elects to include this software in this distribution under the [CDDL or GPL
- * Version 2] license." If you don't indicate a single choice of license, a
- * recipient has the option to distribute your version of this file under
- * either the CDDL, the GPL Version 2 or to extend the choice of license to
- * its licensees as provided above. However, if you add GPL Version 2 code
- * and therefore, elected the GPL Version 2 license, then the option applies
- * only if the new code is made subject to such option by the copyright
- * holder.
- *
- *
- * This file incorporates work covered by the following copyright and
- * permission notice:
- *
- * 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.
*/
-
package javax.el;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.lang.ref.SoftReference;
-import java.beans.FeatureDescriptor;
import java.beans.BeanInfo;
+import java.beans.FeatureDescriptor;
+import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
-import java.beans.IntrospectionException;
+import java.lang.reflect.Array;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Arrays;
+import java.util.HashMap;
import java.util.Iterator;
-import java.util.ArrayList;
import java.util.Map;
-import java.util.HashMap;
+import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap;
-/**
- * Defines property resolution behavior on objects using the JavaBeans
- * component architecture.
- *
- * <p>This resolver handles base objects of any type, as long as the
- * base is not <code>null</code>. It accepts any object as a property
- * or method, and coerces it to a string.
- *
- * <p>For property resolution, the
- * property string is used to find a JavaBeans compliant property on
- * the base object. The value is accessed using JavaBeans getters and setters.
- * </p>
- *
- * <p>For method resolution, the method string is the name
- * of the method in the bean. The parameter types can be optionally
- * specified to identify the method. If the parameter types are not
- * specified, the parameter objects are used in the method resolution.
- * </p>
- *
- * <p>This resolver can be constructed in read-only mode, which means that
- * {@link #isReadOnly} will always return <code>true</code> and
- * {@link #setValue} will always throw
- * <code>PropertyNotWritableException</code>.</p>
- *
- * <p><code>ELResolver</code>s are combined together using
- * {@link CompositeELResolver}s, to define rich semantics for evaluating
- * an expression. See the javadocs for {@link ELResolver} for details.</p>
- *
- * <p>Because this resolver handles base objects of any type, it should
- * be placed near the end of a composite resolver. Otherwise, it will
- * claim to have resolved a property before any resolvers that come after
- * it get a chance to test if they can do so as well.</p>
- *
- * @see CompositeELResolver
- * @see ELResolver
- * @since JSP 2.1
- */
public class BeanELResolver extends ELResolver {
- private boolean isReadOnly;
+ private static final int CACHE_SIZE;
+ private static final String CACHE_SIZE_PROP =
+ "org.apache.el.BeanELResolver.CACHE_SIZE";
- private static final int CACHE_SIZE = 1024;
- private static final ConcurrentHashMap<Class, BeanProperties> properties =
- new ConcurrentHashMap<Class, BeanProperties>(CACHE_SIZE);
+ static {
+ if (System.getSecurityManager() == null) {
+ CACHE_SIZE = Integer.parseInt(
+ System.getProperty(CACHE_SIZE_PROP, "1000"));
+ } else {
+ CACHE_SIZE = AccessController.doPrivileged(
+ new PrivilegedAction<Integer>() {
- /*
- * Defines a property for a bean.
- */
- protected final static class BeanProperty {
-
- private Method readMethod;
- private Method writeMethod;
- private PropertyDescriptor descriptor;
-
- public BeanProperty(Class<?> baseClass,
- PropertyDescriptor descriptor) {
- this.descriptor = descriptor;
- readMethod = getMethod(baseClass, descriptor.getReadMethod());
- writeMethod = getMethod(baseClass, descriptor.getWriteMethod());
+ @Override
+ public Integer run() {
+ return Integer.valueOf(
+ System.getProperty(CACHE_SIZE_PROP, "1000"));
+ }
+ }).intValue();
}
-
- public Class getPropertyType() {
- return descriptor.getPropertyType();
- }
-
- public boolean isReadOnly() {
- return getWriteMethod() == null;
- }
-
- public Method getReadMethod() {
- return readMethod;
- }
-
- public Method getWriteMethod() {
- return writeMethod;
- }
}
-
- /*
- * Defines the properties for a bean.
- */
- protected final static class BeanProperties {
- private final Map<String, BeanProperty> propertyMap =
- new HashMap<String, BeanProperty>();
-
- public BeanProperties(Class<?> baseClass) {
- PropertyDescriptor[] descriptors;
- try {
- BeanInfo info = Introspector.getBeanInfo(baseClass);
- descriptors = info.getPropertyDescriptors();
- } catch (IntrospectionException ie) {
- throw new ELException(ie);
- }
- for (PropertyDescriptor pd: descriptors) {
- propertyMap.put(pd.getName(),
- new BeanProperty(baseClass, pd));
- }
- }
-
- public BeanProperty getBeanProperty(String property) {
- return propertyMap.get(property);
- }
- }
+ private final boolean readOnly;
- /**
- * Creates a new read/write <code>BeanELResolver</code>.
- */
+ private final ConcurrentCache<String, BeanProperties> cache =
+ new ConcurrentCache<String, BeanProperties>(CACHE_SIZE);
+
public BeanELResolver() {
- this.isReadOnly = false;
+ this.readOnly = false;
}
- /**
- * Creates a new <code>BeanELResolver</code> whose read-only status is
- * determined by the given parameter.
- *
- * @param isReadOnly <code>true</code> if this resolver cannot modify
- * beans; <code>false</code> otherwise.
- */
- public BeanELResolver(boolean isReadOnly) {
- this.isReadOnly = isReadOnly;
+ public BeanELResolver(boolean readOnly) {
+ this.readOnly = readOnly;
}
- /**
- * If the base object is not <code>null</code>, returns the most
- * general acceptable type that can be set on this bean property.
- *
- * <p>If the base is not <code>null</code>, the
- * <code>propertyResolved</code> property of the <code>ELContext</code>
- * object must be set to <code>true</code> by this resolver, before
- * returning. If this property is not <code>true</code> after this
- * method is called, the caller should ignore the return value.</p>
- *
- * <p>The provided property will first be coerced to a <code>String</code>.
- * If there is a <code>BeanInfoProperty</code> for this property and
- * there were no errors retrieving it, the <code>propertyType</code> of
- * the <code>propertyDescriptor</code> is returned. Otherwise, a
- * <code>PropertyNotFoundException</code> is thrown.</p>
- *
- * @param context The context of this evaluation.
- * @param base The bean to analyze.
- * @param property The name of the property to analyze. Will be coerced to
- * a <code>String</code>.
- * @return If the <code>propertyResolved</code> property of
- * <code>ELContext</code> was set to <code>true</code>, then
- * the most general acceptable type; otherwise undefined.
- * @throws NullPointerException if context is <code>null</code>
- * @throws PropertyNotFoundException if <code>base</code> is not
- * <code>null</code> and the specified property does not exist
- * or is not readable.
- * @throws ELException if an exception was thrown while performing
- * the property or variable resolution. The thrown exception
- * must be included as the cause property of this exception, if
- * available.
- */
- public Class<?> getType(ELContext context,
- Object base,
- Object property) {
-
+ @Override
+ public Object getValue(ELContext context, Object base, Object property)
+ throws NullPointerException, PropertyNotFoundException, ELException {
if (context == null) {
throw new NullPointerException();
}
-
- if (base == null || property == null){
+ if (base == null || property == null) {
return null;
}
- BeanProperty bp = getBeanProperty(context, base, property);
context.setPropertyResolved(true);
- return bp.getPropertyType();
+ Method m = this.property(context, base, property).read(context);
+ try {
+ return m.invoke(base, (Object[]) null);
+ } catch (IllegalAccessException e) {
+ throw new ELException(e);
+ } catch (InvocationTargetException e) {
+ Throwable cause = e.getCause();
+ if (cause instanceof ThreadDeath) {
+ throw (ThreadDeath) cause;
+ }
+ if (cause instanceof VirtualMachineError) {
+ throw (VirtualMachineError) cause;
+ }
+ throw new ELException("Property read error", cause);
+ } catch (Exception e) {
+ throw new ELException(e);
+ }
}
- /**
- * If the base object is not <code>null</code>, returns the current
- * value of the given property on this bean.
- *
- * <p>If the base is not <code>null</code>, the
- * <code>propertyResolved</code> property of the <code>ELContext</code>
- * object must be set to <code>true</code> by this resolver, before
- * returning. If this property is not <code>true</code> after this
- * method is called, the caller should ignore the return value.</p>
- *
- * <p>The provided property name will first be coerced to a
- * <code>String</code>. If the property is a readable property of the
- * base object, as per the JavaBeans specification, then return the
- * result of the getter call. If the getter throws an exception,
- * it is propagated to the caller. If the property is not found or is
- * not readable, a <code>PropertyNotFoundException</code> is thrown.</p>
- *
- * @param context The context of this evaluation.
- * @param base The bean on which to get the property.
- * @param property The name of the property to get. Will be coerced to
- * a <code>String</code>.
- * @return If the <code>propertyResolved</code> property of
- * <code>ELContext</code> was set to <code>true</code>, then
- * the value of the given property. Otherwise, undefined.
- * @throws NullPointerException if context is <code>null</code>.
- * @throws PropertyNotFoundException if <code>base</code> is not
- * <code>null</code> and the specified property does not exist
- * or is not readable.
- * @throws ELException if an exception was thrown while performing
- * the property or variable resolution. The thrown exception
- * must be included as the cause property of this exception, if
- * available.
- */
- public Object getValue(ELContext context,
- Object base,
- Object property) {
-
+ @Override
+ public Class<?> getType(ELContext context, Object base, Object property)
+ throws NullPointerException, PropertyNotFoundException, ELException {
if (context == null) {
throw new NullPointerException();
}
-
- if (base == null || property == null){
+ if (base == null || property == null) {
return null;
}
- BeanProperty bp = getBeanProperty(context, base, property);
- Method method = bp.getReadMethod();
- if (method == null) {
- throw new PropertyNotFoundException(
- ELUtil.getExceptionMessageString(context,
- "propertyNotReadable",
- new Object[] { base.getClass().getName(),
- property.toString()}));
- }
-
- Object value;
- try {
- value = method.invoke(base, new Object[0]);
- context.setPropertyResolved(true);
- } catch (ELException ex) {
- throw ex;
- } catch (InvocationTargetException ite) {
- throw new ELException(ite.getCause());
- } catch (Exception ex) {
- throw new ELException(ex);
- }
- return value;
+ context.setPropertyResolved(true);
+ return this.property(context, base, property).getPropertyType();
}
- /**
- * If the base object is not <code>null</code>, attempts to set the
- * value of the given property on this bean.
- *
- * <p>If the base is not <code>null</code>, the
- * <code>propertyResolved</code> property of the <code>ELContext</code>
- * object must be set to <code>true</code> by this resolver, before
- * returning. If this property is not <code>true</code> after this
- * method is called, the caller can safely assume no value was set.</p>
- *
- * <p>If this resolver was constructed in read-only mode, this method will
- * always throw <code>PropertyNotWritableException</code>.</p>
- *
- * <p>The provided property name will first be coerced to a
- * <code>String</code>. If property is a writable property of
- * <code>base</code> (as per the JavaBeans Specification), the setter
- * method is called (passing <code>value</code>). If the property exists
- * but does not have a setter, then a
- * <code>PropertyNotFoundException</code> is thrown. If the property
- * does not exist, a <code>PropertyNotFoundException</code> is thrown.</p>
- *
- * @param context The context of this evaluation.
- * @param base The bean on which to set the property.
- * @param property The name of the property to set. Will be coerced to
- * a <code>String</code>.
- * @param val The value to be associated with the specified key.
- * @throws NullPointerException if context is <code>null</code>.
- * @throws PropertyNotFoundException if <code>base</code> is not
- * <code>null</code> and the specified property does not exist.
- * @throws PropertyNotWritableException if this resolver was constructed
- * in read-only mode, or if there is no setter for the property.
- * @throws ELException if an exception was thrown while performing
- * the property or variable resolution. The thrown exception
- * must be included as the cause property of this exception, if
- * available.
- */
- public void setValue(ELContext context,
- Object base,
- Object property,
- Object val) {
-
+ @Override
+ public void setValue(ELContext context, Object base, Object property,
+ Object value) throws NullPointerException,
+ PropertyNotFoundException, PropertyNotWritableException,
+ ELException {
if (context == null) {
throw new NullPointerException();
}
-
- if (base == null || property == null){
+ if (base == null || property == null) {
return;
}
- if (isReadOnly) {
- throw new PropertyNotWritableException(
- ELUtil.getExceptionMessageString(context,
- "resolverNotwritable",
- new Object[] { base.getClass().getName() }));
- }
+ context.setPropertyResolved(true);
- BeanProperty bp = getBeanProperty(context, base, property);
- Method method = bp.getWriteMethod();
- if (method == null) {
- throw new PropertyNotWritableException(
- ELUtil.getExceptionMessageString(context,
- "propertyNotWritable",
- new Object[] { base.getClass().getName(),
- property.toString()}));
+ if (this.readOnly) {
+ throw new PropertyNotWritableException("Resolver not writable" + base.getClass()
+ .getName());
}
+ Method m = this.property(context, base, property).write(context);
try {
- method.invoke(base, new Object[] {val});
- context.setPropertyResolved(true);
- } catch (ELException ex) {
- throw ex;
- } catch (InvocationTargetException ite) {
- throw new ELException(ite.getCause());
- } catch (Exception ex) {
- if (null == val) {
- val = "null";
+ m.invoke(base, value);
+ } catch (IllegalAccessException e) {
+ throw new ELException(e);
+ } catch (InvocationTargetException e) {
+ Throwable cause = e.getCause();
+ if (cause instanceof ThreadDeath) {
+ throw (ThreadDeath) cause;
}
- String message = ELUtil.getExceptionMessageString(context,
- "setPropertyFailed",
- new Object[] { property.toString(),
- base.getClass().getName(), val });
- throw new ELException(message, ex);
+ if (cause instanceof VirtualMachineError) {
+ throw (VirtualMachineError) cause;
+ }
+ throw new ELException("Property write error", cause);
+ } catch (Exception e) {
+ throw new ELException(e);
}
}
- /**
- * If the base object is not <code>null</code>, invoke the method, with
- * the given parameters on this bean. The return value from the method
- * is returned.
- *
- * <p>If the base is not <code>null</code>, the
- * <code>propertyResolved</code> property of the <code>ELContext</code>
- * object must be set to <code>true</code> by this resolver, before
- * returning. If this property is not <code>true</code> after this
- * method is called, the caller should ignore the return value.</p>
- *
- * <p>The provided method object will first be coerced to a
- * <code>String</code>. The methods in the bean is then examined and
- * an attempt will be made to select one for invocation. If no suitable
- * can be found, a <code>MethodNotFoundException</code> is thrown.
- *
- * If the given paramTypes is not <code>null</code>, select the method
- * with the given name and parameter types.
- *
- * Else select the method with the given name that has the same number
- * of parameters. If there are more than one such method, the method
- * selection process is undefined.
- *
- * Else select the method with the given name that takes a variable
- * number of arguments.
- *
- * Note the resolution for overloaded methods will likely be clarified
- * in a future version of the spec.
- *
- * The provide parameters are coerced to the correcponding parameter
- * types of the method, and the method is then invoked.
- *
- * @param context The context of this evaluation.
- * @param base The bean on which to invoke the method
- * @param method The simple name of the method to invoke.
- * Will be coerced to a <code>String</code>. If method is
- * "<init>"or "<clinit>" a MethodNotFoundException is
- * thrown.
- * @param paramTypes An array of Class objects identifying the
- * method's formal parameter types, in declared order.
- * Use an empty array if the method has no parameters.
- * Can be <code>null</code>, in which case the method's formal
- * parameter types are assumed to be unknown.
- * @param params The parameters to pass to the method, or
- * <code>null</code> if no parameters.
- * @return The result of the method invocation (<code>null</code> if
- * the method has a <code>void</code> return type).
- * @throws MethodNotFoundException if no suitable method can be found.
- * @throws ELException if an exception was thrown while performing
- * (base, method) resolution. The thrown exception must be
- * included as the cause property of this exception, if
- * available. If the exception thrown is an
- * <code>InvocationTargetException</code>, extract its
- * <code>cause</code> and pass it to the
- * <code>ELException</code> constructor.
- * @since EL 2.2
- */
+ @Override
+ public boolean isReadOnly(ELContext context, Object base, Object property)
+ throws NullPointerException, PropertyNotFoundException, ELException {
+ if (context == null) {
+ throw new NullPointerException();
+ }
+ if (base == null || property == null) {
+ return false;
+ }
- public Object invoke(ELContext context,
- Object base,
- Object method,
- Class<?>[] paramTypes,
- Object[] params) {
+ context.setPropertyResolved(true);
+ return this.readOnly
+ || this.property(context, base, property).isReadOnly();
+ }
- if (base == null || method == null) {
+ @Override
+ public Iterator<FeatureDescriptor> getFeatureDescriptors(ELContext context, Object base) {
+ if (context == null) {
+ throw new NullPointerException();
+ }
+
+ if (base == null) {
return null;
}
- Method m = findMethod(base, method.toString(), paramTypes, params);
- Object ret = invokeMethod(m, base, params);
- context.setPropertyResolved(true);
- return ret;
- }
- /**
- * If the base object is not <code>null</code>, returns whether a call
- * to {@link #setValue} will always fail.
- *
- * <p>If the base is not <code>null</code>, the
- * <code>propertyResolved</code> property of the <code>ELContext</code>
- * object must be set to <code>true</code> by this resolver, before
- * returning. If this property is not <code>true</code> after this
- * method is called, the caller can safely assume no value was set.</p>
- *
- * <p>If this resolver was constructed in read-only mode, this method will
- * always return <code>true</code>.</p>
- *
- * <p>The provided property name will first be coerced to a
- * <code>String</code>. If property is a writable property of
- * <code>base</code>, <code>false</code> is returned. If the property is
- * found but is not writable, <code>true</code> is returned. If the
- * property is not found, a <code>PropertyNotFoundException</code>
- * is thrown.</p>
- *
- * @param context The context of this evaluation.
- * @param base The bean to analyze.
- * @param property The name of the property to analyzed. Will be coerced to
- * a <code>String</code>.
- * @return If the <code>propertyResolved</code> property of
- * <code>ELContext</code> was set to <code>true</code>, then
- * <code>true</code> if calling the <code>setValue</code> method
- * will always fail or <code>false</code> if it is possible that
- * such a call may succeed; otherwise undefined.
- * @throws NullPointerException if context is <code>null</code>
- * @throws PropertyNotFoundException if <code>base</code> is not
- * <code>null</code> and the specified property does not exist.
- * @throws ELException if an exception was thrown while performing
- * the property or variable resolution. The thrown exception
- * must be included as the cause property of this exception, if
- * available.
- */
- public boolean isReadOnly(ELContext context,
- Object base,
- Object property) {
+ try {
+ BeanInfo info = Introspector.getBeanInfo(base.getClass());
+ PropertyDescriptor[] pds = info.getPropertyDescriptors();
+ for (int i = 0; i < pds.length; i++) {
+ pds[i].setValue(RESOLVABLE_AT_DESIGN_TIME, Boolean.TRUE);
+ pds[i].setValue(TYPE, pds[i].getPropertyType());
+ }
+ return Arrays.asList((FeatureDescriptor[]) pds).iterator();
+ } catch (IntrospectionException e) {
+ //
+ }
+ return null;
+ }
+
+ @Override
+ public Class<?> getCommonPropertyType(ELContext context, Object base) {
if (context == null) {
throw new NullPointerException();
}
- if (base == null || property == null){
- return false;
+ if (base != null) {
+ return Object.class;
}
- context.setPropertyResolved(true);
- if (isReadOnly) {
- return true;
+ return null;
+ }
+
+ protected static final class BeanProperties {
+ private final Map<String, BeanProperty> properties;
+
+ private final Class<?> type;
+
+ public BeanProperties(Class<?> type) throws ELException {
+ this.type = type;
+ this.properties = new HashMap<String, BeanProperty>();
+ try {
+ BeanInfo info = Introspector.getBeanInfo(this.type);
+ PropertyDescriptor[] pds = info.getPropertyDescriptors();
+ for (int i = 0; i < pds.length; i++) {
+ this.properties.put(pds[i].getName(), new BeanProperty(
+ type, pds[i]));
+ }
+ } catch (IntrospectionException ie) {
+ throw new ELException(ie);
+ }
}
- BeanProperty bp = getBeanProperty(context, base, property);
- return bp.isReadOnly();
+ private BeanProperty get(ELContext ctx, String name) {
+ BeanProperty property = this.properties.get(name);
+ if (property == null) {
+ throw new PropertyNotFoundException("Property not found: " + name );
+ }
+ return property;
+ }
+
+ public BeanProperty getBeanProperty(String name) {
+ return get(null, name);
+ }
+
+ private Class<?> getType() {
+ return type;
+ }
}
- /**
- * If the base object is not <code>null</code>, returns an
- * <code>Iterator</code> containing the set of JavaBeans properties
- * available on the given object. Otherwise, returns <code>null</code>.
- *
- * <p>The <code>Iterator</code> returned must contain zero or more
- * instances of {@link java.beans.FeatureDescriptor}. Each info object
- * contains information about a property in the bean, as obtained by
- * calling the <code>BeanInfo.getPropertyDescriptors</code> method.
- * The <code>FeatureDescriptor</code> is initialized using the same
- * fields as are present in the <code>PropertyDescriptor</code>,
- * with the additional required named attributes "<code>type</code>" and
- * "<code>resolvableAtDesignTime</code>" set as follows:
- * <dl>
- * <li>{@link ELResolver#TYPE} - The runtime type of the property, from
- * <code>PropertyDescriptor.getPropertyType()</code>.</li>
- * <li>{@link ELResolver#RESOLVABLE_AT_DESIGN_TIME} - <code>true</code>.</li>
- * </dl>
- * </p>
- *
- * @param context The context of this evaluation.
- * @param base The bean to analyze.
- * @return An <code>Iterator</code> containing zero or more
- * <code>FeatureDescriptor</code> objects, each representing a property
- * on this bean, or <code>null</code> if the <code>base</code>
- * object is <code>null</code>.
- */
- public Iterator<FeatureDescriptor> getFeatureDescriptors(
- ELContext context,
- Object base) {
- if (base == null){
- return null;
+ protected static final class BeanProperty {
+ private final Class<?> type;
+
+ private final Class<?> owner;
+
+ private final PropertyDescriptor descriptor;
+
+ private Method read;
+
+ private Method write;
+
+ public BeanProperty(Class<?> owner, PropertyDescriptor descriptor) {
+ this.owner = owner;
+ this.descriptor = descriptor;
+ this.type = descriptor.getPropertyType();
}
- BeanInfo info = null;
- try {
- info = Introspector.getBeanInfo(base.getClass());
- } catch (Exception ex) {
+ // Can't use Class<?> because API needs to match specification
+ @SuppressWarnings("rawtypes")
+ public Class getPropertyType() {
+ return this.type;
}
- if (info == null) {
- return null;
+
+ public boolean isReadOnly() {
+ return this.write == null
+ && (null == (this.write = getMethod(this.owner, descriptor.getWriteMethod())));
}
- ArrayList<FeatureDescriptor> list = new ArrayList<FeatureDescriptor>(
- info.getPropertyDescriptors().length);
- for (PropertyDescriptor pd: info.getPropertyDescriptors()) {
- pd.setValue("type", pd.getPropertyType());
- pd.setValue("resolvableAtDesignTime", Boolean.TRUE);
- list.add(pd);
+
+ public Method getWriteMethod() {
+ return write(null);
}
- return list.iterator();
- }
- /**
- * If the base object is not <code>null</code>, returns the most
- * general type that this resolver accepts for the
- * <code>property</code> argument. Otherwise, returns <code>null</code>.
- *
- * <p>Assuming the base is not <code>null</code>, this method will always
- * return <code>Object.class</code>. This is because any object is
- * accepted as a key and is coerced into a string.</p>
- *
- * @param context The context of this evaluation.
- * @param base The bean to analyze.
- * @return <code>null</code> if base is <code>null</code>; otherwise
- * <code>Object.class</code>.
- */
- public Class<?> getCommonPropertyType(ELContext context,
- Object base) {
- if (base == null){
- return null;
+ public Method getReadMethod() {
+ return this.read(null);
}
- return Object.class;
+ private Method write(ELContext ctx) {
+ if (this.write == null) {
+ this.write = getMethod(this.owner, descriptor.getWriteMethod());
+ if (this.write == null) {
+ throw new PropertyNotFoundException("Property not writable: " + descriptor.getName());
+ }
+ }
+ return this.write;
+ }
+
+ private Method read(ELContext ctx) {
+ if (this.read == null) {
+ this.read = getMethod(this.owner, descriptor.getReadMethod());
+ if (this.read == null) {
+ throw new PropertyNotFoundException("Property not readable: " + descriptor.getName());
+ }
+ }
+ return this.read;
+ }
}
- /*
- * Get a public method form a public class or interface of a given method.
- * Note that if a PropertyDescriptor is obtained for a non-public class that
- * implements a public interface, the read/write methods will be for the
- * class, and therefore inaccessible. To correct this, a version of the
- * same method must be found in a superclass or interface.
- **/
+ private final BeanProperty property(ELContext ctx, Object base,
+ Object property) {
+ Class<?> type = base.getClass();
+ String prop = property.toString();
- static private Method getMethod(Class cl, Method method) {
-
- if (method == null) {
- return null;
+ BeanProperties props = this.cache.get(type.getName());
+ if (props == null || type != props.getType()) {
+ props = new BeanProperties(type);
+ this.cache.put(type.getName(), props);
}
- if (Modifier.isPublic (cl.getModifiers ())) {
- return method;
+ return props.get(ctx, prop);
+ }
+
+ private static final Method getMethod(Class<?> type, Method m) {
+ if (m == null || Modifier.isPublic(type.getModifiers())) {
+ return m;
}
- Class [] interfaces = cl.getInterfaces ();
- for (int i = 0; i < interfaces.length; i++) {
- Class c = interfaces[i];
- Method m = null;
+ Class<?>[] inf = type.getInterfaces();
+ Method mp = null;
+ for (int i = 0; i < inf.length; i++) {
try {
- m = c.getMethod(method.getName(), method.getParameterTypes());
- c = m.getDeclaringClass();
- if ((m = getMethod(c, m)) != null)
- return m;
- } catch (NoSuchMethodException ex) {
+ mp = inf[i].getMethod(m.getName(), m.getParameterTypes());
+ mp = getMethod(mp.getDeclaringClass(), mp);
+ if (mp != null) {
+ return mp;
+ }
+ } catch (NoSuchMethodException e) {
+ // Ignore
}
}
- Class c = cl.getSuperclass();
- if (c != null) {
- Method m = null;
+ Class<?> sup = type.getSuperclass();
+ if (sup != null) {
try {
- m = c.getMethod(method.getName(), method.getParameterTypes());
- c = m.getDeclaringClass();
- if ((m = getMethod(c, m)) != null)
- return m;
- } catch (NoSuchMethodException ex) {
+ mp = sup.getMethod(m.getName(), m.getParameterTypes());
+ mp = getMethod(mp.getDeclaringClass(), mp);
+ if (mp != null) {
+ return mp;
+ }
+ } catch (NoSuchMethodException e) {
+ // Ignore
}
}
return null;
}
- private BeanProperty getBeanProperty(ELContext context,
- Object base,
- Object prop) {
+ private static final class ConcurrentCache<K,V> {
- String property = prop.toString();
- Class baseClass = base.getClass();
- BeanProperties bps = properties.get(baseClass);
- if (bps == null) {
- bps = new BeanProperties(baseClass);
- properties.putIfAbsent(baseClass, bps);
+ private final int size;
+ private final Map<K,V> eden;
+ private final Map<K,V> longterm;
+
+ public ConcurrentCache(int size) {
+ this.size = size;
+ this.eden = new ConcurrentHashMap<K,V>(size);
+ this.longterm = new WeakHashMap<K,V>(size);
}
- BeanProperty bp = bps.getBeanProperty(property);
- if (bp == null) {
- throw new PropertyNotFoundException(
- ELUtil.getExceptionMessageString(context,
- "propertyNotFound",
- new Object[] { baseClass.getName(),
- property}));
+
+ public V get(K key) {
+ V value = this.eden.get(key);
+ if (value == null) {
+ synchronized (longterm) {
+ value = this.longterm.get(key);
+ }
+ if (value != null) {
+ this.eden.put(key, value);
+ }
+ }
+ return value;
}
- return bp;
- }
- private void removeFromMap(Map<Class, BeanProperties> map,
- ClassLoader classloader) {
- Iterator<Class> iter = map.keySet().iterator();
- while (iter.hasNext()) {
- Class mbeanClass = iter.next();
- if (classloader.equals(mbeanClass.getClassLoader())) {
- iter.remove();
+ public void put(K key, V value) {
+ if (this.eden.size() >= this.size) {
+ synchronized (longterm) {
+ this.longterm.putAll(this.eden);
+ }
+ this.eden.clear();
}
+ this.eden.put(key, value);
}
}
- /*
- * This method is not part of the API, though it can be used (reflectively)
- * by clients of this class to remove entries from the cache when the beans
- * are being unloaded.
- *
- * A note about why WeakHashMap is not used. Measurements has shown
- * that ConcurrentHashMap is much more scalable than synchronized
- * WeakHashMap. A manual purge seems to be a good compromise.
- *
- * @param classloader The classLoader used to load the beans.
+ /**
+ * @since EL 2.2
*/
- private void purgeBeanClasses(ClassLoader classloader) {
- removeFromMap(properties, classloader);
- }
+ @Override
+ public Object invoke(ELContext context, Object base, Object method,
+ Class<?>[] paramTypes, Object[] params) {
+ if (context == null) {
+ throw new NullPointerException();
+ }
+ if (base == null || method == null) {
+ return null;
+ }
- private Method findMethod(Object base, String method,
- Class<?>[] paramTypes, Object[] params) {
+ ExpressionFactory factory = ExpressionFactory.newInstance();
- Class<?>beanClass = base.getClass();
+ String methodName = (String) factory.coerceToType(method, String.class);
+
+ // Find the matching method
+ Method matchingMethod = null;
+ Class<?> clazz = base.getClass();
if (paramTypes != null) {
try {
- return beanClass.getMethod(method, paramTypes);
- } catch (java.lang.NoSuchMethodException ex) {
- throw new MethodNotFoundException(ex);
+ matchingMethod =
+ getMethod(clazz, clazz.getMethod(methodName, paramTypes));
+ } catch (NoSuchMethodException e) {
+ throw new MethodNotFoundException(e);
}
- }
- for (Method m: base.getClass().getMethods()) {
- if (m.getName().equals(method) && (
- m.isVarArgs() ||
- m.getParameterTypes().length==params.length)){
- return m;
+ } else {
+ int paramCount = 0;
+ if (params != null) {
+ paramCount = params.length;
}
+ Method[] methods = clazz.getMethods();
+ for (Method m : methods) {
+ if (methodName.equals(m.getName())) {
+ if (m.getParameterTypes().length == paramCount) {
+ // Same number of parameters - use the first match
+ matchingMethod = getMethod(clazz, m);
+ break;
+ }
+ if (m.isVarArgs()
+ && paramCount > m.getParameterTypes().length - 2) {
+ matchingMethod = getMethod(clazz, m);
+ }
+ }
+ }
+ if (matchingMethod == null) {
+ throw new MethodNotFoundException(
+ "Unable to find method [" + methodName + "] with ["
+ + paramCount + "] parameters");
+ }
}
- throw new MethodNotFoundException("Method " + method + " not found");
- }
- private Object invokeMethod(Method m, Object base, Object[] params) {
-
- Class[] parameterTypes = m.getParameterTypes();
+ Class<?>[] parameterTypes = matchingMethod.getParameterTypes();
Object[] parameters = null;
if (parameterTypes.length > 0) {
- ExpressionFactory exprFactory = ExpressionFactory.newInstance();
- if (m.isVarArgs()) {
- // TODO
+ parameters = new Object[parameterTypes.length];
+ @SuppressWarnings("null") // params.length >= parameterTypes.length
+ int paramCount = params.length;
+ if (matchingMethod.isVarArgs()) {
+ int varArgIndex = parameterTypes.length - 1;
+ // First argCount-1 parameters are standard
+ for (int i = 0; (i < varArgIndex); i++) {
+ parameters[i] = factory.coerceToType(params[i],
+ parameterTypes[i]);
+ }
+ // Last parameter is the varargs
+ Class<?> varArgClass =
+ parameterTypes[varArgIndex].getComponentType();
+ final Object varargs = Array.newInstance(
+ varArgClass,
+ (paramCount - varArgIndex));
+ for (int i = (varArgIndex); i < paramCount; i++) {
+ Array.set(varargs, i - varArgIndex,
+ factory.coerceToType(params[i], varArgClass));
+ }
+ parameters[varArgIndex] = varargs;
} else {
parameters = new Object[parameterTypes.length];
for (int i = 0; i < parameterTypes.length; i++) {
- parameters[i] = exprFactory.coerceToType(params[i],
- parameterTypes[i]);
+ parameters[i] = factory.coerceToType(params[i],
+ parameterTypes[i]);
}
}
}
+ Object result = null;
try {
- return m.invoke(base, parameters);
- } catch (IllegalAccessException iae) {
- throw new ELException(iae);
- } catch (InvocationTargetException ite) {
- throw new ELException(ite.getCause());
+ result = matchingMethod.invoke(base, parameters);
+ } catch (IllegalArgumentException e) {
+ throw new ELException(e);
+ } catch (IllegalAccessException e) {
+ throw new ELException(e);
+ } catch (InvocationTargetException e) {
+ Throwable cause = e.getCause();
+ if (cause instanceof ThreadDeath) {
+ throw (ThreadDeath) cause;
+ }
+ if (cause instanceof VirtualMachineError) {
+ throw (VirtualMachineError) cause;
+ }
+ throw new ELException(cause);
}
+
+ context.setPropertyResolved(true);
+ return result;
}
-}
+}
13 years