You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@bval.apache.org by rm...@apache.org on 2013/08/16 08:57:44 UTC
svn commit: r1514596 - in
/bval/branches/bval-11/bval-jsr303/src/main/java/org/apache/bval/jsr303:
ConstraintAnnotationAttributes.java xml/AnnotationProxy.java
xml/AnnotationProxyBuilder.java xml/ValidationParser.java
Author: rmannibucau
Date: Fri Aug 16 06:57:43 2013
New Revision: 1514596
URL: http://svn.apache.org/r1514596
Log:
caching built in constraint methods + caching xsd schema
Modified:
bval/branches/bval-11/bval-jsr303/src/main/java/org/apache/bval/jsr303/ConstraintAnnotationAttributes.java
bval/branches/bval-11/bval-jsr303/src/main/java/org/apache/bval/jsr303/xml/AnnotationProxy.java
bval/branches/bval-11/bval-jsr303/src/main/java/org/apache/bval/jsr303/xml/AnnotationProxyBuilder.java
bval/branches/bval-11/bval-jsr303/src/main/java/org/apache/bval/jsr303/xml/ValidationParser.java
Modified: bval/branches/bval-11/bval-jsr303/src/main/java/org/apache/bval/jsr303/ConstraintAnnotationAttributes.java
URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-jsr303/src/main/java/org/apache/bval/jsr303/ConstraintAnnotationAttributes.java?rev=1514596&r1=1514595&r2=1514596&view=diff
==============================================================================
--- bval/branches/bval-11/bval-jsr303/src/main/java/org/apache/bval/jsr303/ConstraintAnnotationAttributes.java (original)
+++ bval/branches/bval-11/bval-jsr303/src/main/java/org/apache/bval/jsr303/ConstraintAnnotationAttributes.java Fri Aug 16 06:57:43 2013
@@ -30,6 +30,8 @@ import java.lang.reflect.Type;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
/**
* Defines the well-known attributes of {@link Constraint} annotations.
@@ -88,8 +90,6 @@ public enum ConstraintAnnotationAttribut
/**
* Get the expected type of the represented attribute.
- *
- * @return Class<?>
*/
public Type getType() {
return type;
@@ -137,7 +137,18 @@ public enum ConstraintAnnotationAttribut
return new Worker<C>(clazz);
}
+ // this is static but related to Worker
+ private static final ConcurrentMap<Class<?>, ConcurrentMap<String, Method>> METHOD_BY_NAME_AND_CLASS = new ConcurrentHashMap<Class<?>, ConcurrentMap<String, Method>>();
+ private static final Method NULL_METHOD;
+ static {
+ try {
+ NULL_METHOD = Object.class.getMethod("hashCode"); // whatever, the only constraint here is to not use a constraint method, this value is used to cache null
+ } catch (NoSuchMethodException e) {
+ throw new RuntimeException("Impossible normally");
+ }
+ }
public class Worker<C extends Annotation> {
+
public final Method method;
public final Object defaultValue;
private RuntimeException error;
@@ -149,8 +160,8 @@ public enum ConstraintAnnotationAttribut
Worker(final Class<C> constraintType) {
Object _defaultValue = null;
try {
- method = Reflection.INSTANCE.getPublicMethod(constraintType, attributeName);
- if (method == null) {
+ method = findMethod(constraintType, attributeName);
+ if (method == null || method == NULL_METHOD) {
error = new ConstraintDefinitionException("Annotation " + constraintType + " has no " + attributeName + " method");
return;
}
@@ -171,6 +182,32 @@ public enum ConstraintAnnotationAttribut
}
}
+ private Method findMethod(final Class<C> constraintType, final String attributeName) {
+ ConcurrentMap<String, Method> cache = METHOD_BY_NAME_AND_CLASS.get(constraintType);
+ if (cache == null) {
+ cache = new ConcurrentHashMap<String, Method>();
+ final ConcurrentMap<String, Method> old = METHOD_BY_NAME_AND_CLASS.putIfAbsent(constraintType, cache);
+ if (old != null) {
+ cache = old;
+ }
+ }
+
+ final Method found = cache.get(attributeName);
+ if (found != null) {
+ return found;
+ }
+ final Method m = Reflection.INSTANCE.getPublicMethod(constraintType, attributeName);
+ if (m == null) {
+ cache.putIfAbsent(attributeName, NULL_METHOD);
+ return null;
+ }
+ final Method oldMtd = cache.putIfAbsent(attributeName, m);
+ if (oldMtd != null) {
+ return oldMtd;
+ }
+ return m;
+ }
+
public boolean isValid() {
return error == null;
}
Modified: bval/branches/bval-11/bval-jsr303/src/main/java/org/apache/bval/jsr303/xml/AnnotationProxy.java
URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-jsr303/src/main/java/org/apache/bval/jsr303/xml/AnnotationProxy.java?rev=1514596&r1=1514595&r2=1514596&view=diff
==============================================================================
--- bval/branches/bval-11/bval-jsr303/src/main/java/org/apache/bval/jsr303/xml/AnnotationProxy.java (original)
+++ bval/branches/bval-11/bval-jsr303/src/main/java/org/apache/bval/jsr303/xml/AnnotationProxy.java Fri Aug 16 06:57:43 2013
@@ -16,8 +16,6 @@
*/
package org.apache.bval.jsr303.xml;
-import org.apache.bval.util.reflection.Reflection;
-
import javax.validation.Valid;
import java.io.Serializable;
import java.lang.annotation.Annotation;
@@ -54,10 +52,9 @@ class AnnotationProxy implements Annotat
}
private <A extends Annotation> Map<String, Object> getAnnotationValues(AnnotationProxyBuilder<A> descriptor) {
- Map<String, Object> result = new HashMap<String, Object>();
+ final Map<String, Object> result = new HashMap<String, Object>();
int processedValuesFromDescriptor = 0;
- final Method[] declaredMethods = Reflection.INSTANCE.getDeclaredMethods(annotationType);
- for (Method m : declaredMethods) {
+ for (final Method m : descriptor.getMethods()) {
if (descriptor.contains(m.getName())) {
result.put(m.getName(), descriptor.getValue(m.getName()));
processedValuesFromDescriptor++;
Modified: bval/branches/bval-11/bval-jsr303/src/main/java/org/apache/bval/jsr303/xml/AnnotationProxyBuilder.java
URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-jsr303/src/main/java/org/apache/bval/jsr303/xml/AnnotationProxyBuilder.java?rev=1514596&r1=1514595&r2=1514596&view=diff
==============================================================================
--- bval/branches/bval-11/bval-jsr303/src/main/java/org/apache/bval/jsr303/xml/AnnotationProxyBuilder.java (original)
+++ bval/branches/bval-11/bval-jsr303/src/main/java/org/apache/bval/jsr303/xml/AnnotationProxyBuilder.java Fri Aug 16 06:57:43 2013
@@ -33,6 +33,8 @@ import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.HashMap;
import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
/**
* Description: Holds the information and creates an annotation proxy during xml
@@ -41,16 +43,32 @@ import java.util.Map;
// TODO move this guy up to org.apache.bval.jsr303 or
// org.apache.bval.jsr303.model
final public class AnnotationProxyBuilder<A extends Annotation> {
+ private static final ConcurrentMap<Class<?>, Method[]> METHODS_CACHE = new ConcurrentHashMap<Class<?>, Method[]>();
+
private final Class<A> type;
private final Map<String, Object> elements = new HashMap<String, Object>();
+ private final Method[] methods;
/**
* Create a new AnnotationProxyBuilder instance.
*
* @param annotationType
*/
- public AnnotationProxyBuilder(Class<A> annotationType) {
+ public AnnotationProxyBuilder(final Class<A> annotationType) {
this.type = annotationType;
+ if (annotationType.getName().startsWith("javax.validation.constraints.")) { // cache built-in constraints only to avoid mem leaks
+ Method[] mtd = METHODS_CACHE.get(annotationType);
+ if (mtd == null) {
+ final Method[] value = Reflection.INSTANCE.getDeclaredMethods(type);
+ mtd = METHODS_CACHE.putIfAbsent(annotationType, value);
+ if (mtd == null) {
+ mtd = value;
+ }
+ }
+ this.methods = mtd;
+ } else {
+ this.methods = Reflection.INSTANCE.getDeclaredMethods(type);
+ }
}
/**
@@ -76,7 +94,6 @@ final public class AnnotationProxyBuilde
public AnnotationProxyBuilder(A annot) {
this((Class<A>) annot.annotationType());
// Obtain the "elements" of the annotation
- final Method[] methods = Reflection.INSTANCE.getDeclaredMethods(annot.annotationType());
for (Method m : methods) {
if (!m.isAccessible()) {
m.setAccessible(true);
@@ -95,6 +112,10 @@ final public class AnnotationProxyBuilde
}
}
+ public Method[] getMethods() {
+ return methods;
+ }
+
/**
* Add an element to the configuration.
*
Modified: bval/branches/bval-11/bval-jsr303/src/main/java/org/apache/bval/jsr303/xml/ValidationParser.java
URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-jsr303/src/main/java/org/apache/bval/jsr303/xml/ValidationParser.java?rev=1514596&r1=1514595&r2=1514596&view=diff
==============================================================================
--- bval/branches/bval-11/bval-jsr303/src/main/java/org/apache/bval/jsr303/xml/ValidationParser.java (original)
+++ bval/branches/bval-11/bval-jsr303/src/main/java/org/apache/bval/jsr303/xml/ValidationParser.java Fri Aug 16 06:57:43 2013
@@ -53,6 +53,8 @@ import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.logging.Level;
@@ -64,9 +66,9 @@ import java.util.logging.Logger;
@SuppressWarnings("restriction")
public class ValidationParser implements Closeable {
private static final String DEFAULT_VALIDATION_XML_FILE = "META-INF/validation.xml";
- private static final String VALIDATION_CONFIGURATION_XSD =
- "META-INF/validation-configuration-1.1.xsd";
+ private static final String VALIDATION_CONFIGURATION_XSD = "META-INF/validation-configuration-1.1.xsd";
private static final Logger log = Logger.getLogger(ValidationParser.class.getName());
+ private static final ConcurrentMap<String, Schema> SCHEMA_CACHE = new ConcurrentHashMap<String, Schema>(1);
private ValidationConfigType xmlConfig;
private BootstrapConfigurationImpl bootstrap;
@@ -191,16 +193,16 @@ public class ValidationParser implements
}
}
- protected static InputStream getInputStream(String path) throws IOException {
- ClassLoader loader = Reflection.INSTANCE.getClassLoader(ValidationParser.class);
- InputStream inputStream = loader.getResourceAsStream(path);
+ protected static InputStream getInputStream(final String path) throws IOException {
+ final ClassLoader loader = Reflection.INSTANCE.getClassLoader(ValidationParser.class);
+ final InputStream inputStream = loader.getResourceAsStream(path);
if (inputStream != null) {
// spec says: If more than one META-INF/validation.xml file
// is found in the classpath, a ValidationException is raised.
- Enumeration<URL> urls = loader.getResources(path);
+ final Enumeration<URL> urls = loader.getResources(path);
if (urls.hasMoreElements()) {
- String url = urls.nextElement().toString();
+ final String url = urls.nextElement().toString();
while (urls.hasMoreElements()) {
if (!url.equals(urls.nextElement().toString())) { // complain when first duplicate found
throw new ValidationException("More than one " + path + " is found in the classpath");
@@ -217,11 +219,21 @@ public class ValidationParser implements
}
static Schema getSchema(final String xsd) {
+ final Schema schema = SCHEMA_CACHE.get(xsd);
+ if (schema != null) {
+ return schema;
+ }
+
final ClassLoader loader = Reflection.INSTANCE.getClassLoader(ValidationParser.class);
final SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
final URL schemaUrl = loader.getResource(xsd);
try {
- return sf.newSchema(schemaUrl);
+ Schema s = sf.newSchema(schemaUrl);
+ final Schema old = SCHEMA_CACHE.putIfAbsent(xsd, s);
+ if (old != null) {
+ s = old;
+ }
+ return s;
} catch (SAXException e) {
log.log(Level.WARNING, String.format("Unable to parse schema: %s", xsd), e);
return null;