Return-Path: X-Original-To: apmail-bval-commits-archive@www.apache.org Delivered-To: apmail-bval-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 84D73105A6 for ; Wed, 14 Aug 2013 15:36:03 +0000 (UTC) Received: (qmail 42095 invoked by uid 500); 14 Aug 2013 15:36:00 -0000 Delivered-To: apmail-bval-commits-archive@bval.apache.org Received: (qmail 41034 invoked by uid 500); 14 Aug 2013 15:35:54 -0000 Mailing-List: contact commits-help@bval.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@bval.apache.org Delivered-To: mailing list commits@bval.apache.org Received: (qmail 40980 invoked by uid 99); 14 Aug 2013 15:35:52 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 14 Aug 2013 15:35:52 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 14 Aug 2013 15:35:49 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id B0CD02388860; Wed, 14 Aug 2013 15:35:27 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1513933 - in /bval/branches/bval-11: bval-core/src/main/java/org/apache/bval/MetaBeanManager.java bval-jsr303/src/main/java/org/apache/bval/jsr303/ClassValidator.java Date: Wed, 14 Aug 2013 15:35:27 -0000 To: commits@bval.apache.org From: rmannibucau@apache.org X-Mailer: svnmailer-1.0.9 Message-Id: <20130814153527.B0CD02388860@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: rmannibucau Date: Wed Aug 14 15:35:27 2013 New Revision: 1513933 URL: http://svn.apache.org/r1513933 Log: better locking when concurrently trying to create the same metadata in MetaBeanManager Modified: bval/branches/bval-11/bval-core/src/main/java/org/apache/bval/MetaBeanManager.java bval/branches/bval-11/bval-jsr303/src/main/java/org/apache/bval/jsr303/ClassValidator.java Modified: bval/branches/bval-11/bval-core/src/main/java/org/apache/bval/MetaBeanManager.java URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-core/src/main/java/org/apache/bval/MetaBeanManager.java?rev=1513933&r1=1513932&r2=1513933&view=diff ============================================================================== --- bval/branches/bval-11/bval-core/src/main/java/org/apache/bval/MetaBeanManager.java (original) +++ bval/branches/bval-11/bval-core/src/main/java/org/apache/bval/MetaBeanManager.java Wed Aug 14 15:35:27 2013 @@ -19,7 +19,12 @@ package org.apache.bval; import org.apache.bval.model.MetaBean; import org.apache.bval.model.MetaProperty; -import static org.apache.bval.model.Features.Property.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +import static org.apache.bval.model.Features.Property.REF_BEAN_ID; +import static org.apache.bval.model.Features.Property.REF_BEAN_TYPE; +import static org.apache.bval.model.Features.Property.REF_CASCADE; /** * Description: Default implementation for the interface to find, register and @@ -36,6 +41,8 @@ public class MetaBeanManager implements /** Complete flag */ protected boolean complete = false; + protected final ConcurrentMap cacheLocks = new ConcurrentHashMap(); + /** * Create a new MetaBeanManager instance. */ @@ -73,40 +80,69 @@ public class MetaBeanManager implements /** * {@inheritDoc} */ - public MetaBean findForId(String beanInfoId) { + public MetaBean findForId(final String beanInfoId) { MetaBean beanInfo = cache.findForId(beanInfoId); - if (beanInfo != null) + if (beanInfo != null) { return beanInfo; - try { - beanInfo = builder.buildForId(beanInfoId); - cache.cache(beanInfo); - computeRelationships(beanInfo); - return beanInfo; - } catch (RuntimeException e) { - throw e; // do not wrap runtime exceptions - } catch (Exception e) { - throw new IllegalArgumentException("error creating beanInfo with id: " + beanInfoId, e); + } + + synchronized (getLockFor(beanInfoId)) { + beanInfo = cache.findForId(beanInfoId); + if (beanInfo != null) { + return beanInfo; + } + + try { + beanInfo = builder.buildForId(beanInfoId); + cache.cache(beanInfo); + computeRelationships(beanInfo); + return beanInfo; + } catch (final RuntimeException e) { + throw e; // do not wrap runtime exceptions + } catch (final Exception e) { + throw new IllegalArgumentException("error creating beanInfo with id: " + beanInfoId, e); + } } } + private Object getLockFor(final Object key) { + final Object newLock = new Object(); + Object lock = cacheLocks.putIfAbsent(key, newLock); + if (lock == null) { + lock = newLock; + } + return lock; + } + /** * {@inheritDoc} */ - public MetaBean findForClass(Class clazz) { - if (clazz == null) + public MetaBean findForClass(final Class clazz) { + if (clazz == null) { return null; + } + MetaBean beanInfo = cache.findForClass(clazz); - if (beanInfo != null) + if (beanInfo != null) { return beanInfo; - try { - beanInfo = builder.buildForClass(clazz); - cache.cache(beanInfo); - computeRelationships(beanInfo); - return beanInfo; - } catch (RuntimeException e) { - throw e; // do not wrap runtime exceptions - } catch (Exception e) { - throw new IllegalArgumentException("error creating beanInfo for " + clazz, e); + } + + synchronized (getLockFor(clazz)) { + beanInfo = cache.findForClass(clazz); + if (beanInfo != null) { + return beanInfo; + } + + try { + beanInfo = builder.buildForClass(clazz); + cache.cache(beanInfo); + computeRelationships(beanInfo); + return beanInfo; + } catch (final RuntimeException e) { + throw e; // do not wrap runtime exceptions + } catch (final Exception e) { + throw new IllegalArgumentException("error creating beanInfo for " + clazz, e); + } } } @@ -118,8 +154,8 @@ public class MetaBeanManager implements * - the bean for which to compute relationships */ protected void computeRelationships(MetaBean beanInfo) { - for (MetaProperty prop : beanInfo.getProperties()) { - String beanRef = (String) prop.getFeature(REF_BEAN_ID); + for (final MetaProperty prop : beanInfo.getProperties()) { + final String beanRef = prop.getFeature(REF_BEAN_ID); computeRelatedMetaBean(prop, beanRef); } } Modified: bval/branches/bval-11/bval-jsr303/src/main/java/org/apache/bval/jsr303/ClassValidator.java URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-jsr303/src/main/java/org/apache/bval/jsr303/ClassValidator.java?rev=1513933&r1=1513932&r2=1513933&view=diff ============================================================================== --- bval/branches/bval-11/bval-jsr303/src/main/java/org/apache/bval/jsr303/ClassValidator.java (original) +++ bval/branches/bval-11/bval-jsr303/src/main/java/org/apache/bval/jsr303/ClassValidator.java Wed Aug 14 15:35:27 2013 @@ -100,6 +100,8 @@ public class ClassValidator implements C */ protected final GroupsComputer groupsComputer = new GroupsComputer(); + private final MetaBeanFinder metaBeanFinder; + /** * Create a new ClassValidator instance. * @@ -107,16 +109,7 @@ public class ClassValidator implements C */ public ClassValidator(ApacheFactoryContext factoryContext) { this.factoryContext = factoryContext; - } - - /** - * Get the metabean finder associated with this validator. - * - * @return a MetaBeanFinder - * @see org.apache.bval.MetaBeanManagerFactory#getFinder() - */ - protected MetaBeanFinder getMetaBeanFinder() { - return factoryContext.getMetaBeanFinder(); + metaBeanFinder = factoryContext.getMetaBeanFinder(); } // Validator implementation @@ -144,7 +137,7 @@ public class ClassValidator implements C try { final Class objectClass = (Class) object.getClass(); - final MetaBean objectMetaBean = getMetaBeanFinder().findForClass(objectClass); + final MetaBean objectMetaBean = metaBeanFinder.findForClass(objectClass); final GroupValidationContext context = createContext(objectMetaBean, object, objectClass, groups); return validateBeanWithGroups(context, context.getGroups()); } catch (final RuntimeException ex) { @@ -266,7 +259,7 @@ public class ClassValidator implements C throw new IllegalArgumentException("Class cannot be null"); } try { - MetaBean metaBean = getMetaBeanFinder().findForClass(clazz); // don't throw an exception because of a missing validator here + MetaBean metaBean = metaBeanFinder.findForClass(clazz); // don't throw an exception because of a missing validator here BeanDescriptorImpl edesc = metaBean.getFeature(Jsr303Features.Bean.BEAN_DESCRIPTOR); if (edesc == null) { edesc = createBeanDescriptor(metaBean); @@ -1248,7 +1241,7 @@ public class ClassValidator implements C checkGroups(groups); try { - final MetaBean initialMetaBean = new DynamicMetaBean(getMetaBeanFinder()); + final MetaBean initialMetaBean = new DynamicMetaBean(metaBeanFinder); initialMetaBean.setBeanClass(beanType); GroupValidationContext context = createContext(initialMetaBean, object, beanType, groups); ValidationContextTraversal contextTraversal = createValidationContextTraversal(context); @@ -1259,7 +1252,7 @@ public class ClassValidator implements C if (value != VALIDATE_PROPERTY) { assert !context.getPropertyPath().isRootPath(); if (prop == null && value != null) { - context.setMetaBean(getMetaBeanFinder().findForClass(value.getClass())); + context.setMetaBean(metaBeanFinder.findForClass(value.getClass())); } if (!cascade) { //TCK doesn't care what type a property is if there are no constraints to validate: