Andreas, Would you mind to update the dev list (or one of the JIRA issue) about the design in your mind for this implementation ?
Thanks ! On Wed, Sep 7, 2011 at 5:11 PM, <veit...@apache.org> wrote: > Author: veithen > Date: Wed Sep 7 11:41:52 2011 > New Revision: 1166132 > > URL: http://svn.apache.org/viewvc?rev=1166132&view=rev > Log: > AXIS2-4524 / AXIS2-4878 / AXIS2-5118 / AXIS2-5119: Initial implementation of > a BeanInfo cache to speed up POJO services. > > Added: > > axis/axis2/java/core/trunk/modules/kernel/src/org/apache/axis2/classloader/BeanInfoCache.java > (with props) > > axis/axis2/java/core/trunk/modules/kernel/src/org/apache/axis2/classloader/BeanInfoCachingClassLoader.java > (with props) > Modified: > > axis/axis2/java/core/trunk/modules/adb/src/org/apache/axis2/databinding/utils/BeanUtil.java > > axis/axis2/java/core/trunk/modules/kernel/src/org/apache/axis2/deployment/DeploymentClassLoader.java > > Modified: > axis/axis2/java/core/trunk/modules/adb/src/org/apache/axis2/databinding/utils/BeanUtil.java > URL: > http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/adb/src/org/apache/axis2/databinding/utils/BeanUtil.java?rev=1166132&r1=1166131&r2=1166132&view=diff > ============================================================================== > --- > axis/axis2/java/core/trunk/modules/adb/src/org/apache/axis2/databinding/utils/BeanUtil.java > (original) > +++ > axis/axis2/java/core/trunk/modules/adb/src/org/apache/axis2/databinding/utils/BeanUtil.java > Wed Sep 7 11:41:52 2011 > @@ -22,7 +22,6 @@ package org.apache.axis2.databinding.uti > > import java.beans.BeanInfo; > import java.beans.IntrospectionException; > -import java.beans.Introspector; > import java.beans.PropertyDescriptor; > import java.lang.reflect.Array; > import java.lang.reflect.InvocationTargetException; > @@ -58,6 +57,7 @@ import org.apache.axiom.om.impl.dom.DOOM > import org.apache.axiom.om.impl.dom.DocumentImpl; > import org.apache.axiom.om.util.Base64; > import org.apache.axis2.AxisFault; > +import org.apache.axis2.classloader.BeanInfoCache; > import org.apache.axis2.context.MessageContext; > import org.apache.axis2.databinding.typemapping.SimpleTypeMapper; > import org.apache.axis2.databinding.utils.reader.ADBXMLStreamReaderImpl; > @@ -121,19 +121,7 @@ public class BeanUtil { > > > private static BeanInfo getBeanInfo(Class beanClass, Class > beanSuperclass) throws IntrospectionException { > - BeanInfo beanInfo; > - try { > - if (beanSuperclass != null) > - beanInfo = Introspector.getBeanInfo(beanClass, > beanSuperclass); > - else > - beanInfo = Introspector.getBeanInfo(beanClass); > - } > - catch (IntrospectionException e) { > - throw e; > - } > - > - > - return beanInfo; > + return BeanInfoCache.getCachedBeanInfo(beanClass, beanSuperclass); > } > > private static BeanInfo getBeanInfo(Class beanClass) throws > IntrospectionException { > > Added: > axis/axis2/java/core/trunk/modules/kernel/src/org/apache/axis2/classloader/BeanInfoCache.java > URL: > http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/kernel/src/org/apache/axis2/classloader/BeanInfoCache.java?rev=1166132&view=auto > ============================================================================== > --- > axis/axis2/java/core/trunk/modules/kernel/src/org/apache/axis2/classloader/BeanInfoCache.java > (added) > +++ > axis/axis2/java/core/trunk/modules/kernel/src/org/apache/axis2/classloader/BeanInfoCache.java > Wed Sep 7 11:41:52 2011 > @@ -0,0 +1,130 @@ > +/* > + * 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 > + * > + * http://www.apache.org/licenses/LICENSE-2.0 > + * > + * Unless required by applicable law or agreed to in writing, > + * software distributed under the License is distributed on an > + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY > + * KIND, either express or implied. See the License for the > + * specific language governing permissions and limitations > + * under the License. > + */ > +package org.apache.axis2.classloader; > + > +import java.beans.BeanInfo; > +import java.beans.IntrospectionException; > +import java.beans.Introspector; > +import java.util.Map; > +import java.util.concurrent.ConcurrentHashMap; > + > +import org.apache.commons.logging.Log; > +import org.apache.commons.logging.LogFactory; > + > +/** > + * {@link BeanInfo} cache that stores introspection results by bean class > and stop class. This goes > + * beyond the caching provided by the JRE, which only caches the results of > + * {@link Introspector#getBeanInfo(Class)}, but not the results of > + * {@link Introspector#getBeanInfo(Class, Class)} (with non null stop class). > + * <p> > + * To avoid class loader leaks, this class should not be used as a singleton > if the introspected > + * classes are loaded from class loaders that are children of the class > loader which holds the > + * reference to the cache. In such scenarios, use {@link > #getCachedBeanInfo(Class, Class)}. > + */ > +public final class BeanInfoCache { > + private static final class CacheKey { > + private final Class<?> beanClass; > + private final Class<?> stopClass; > + > + CacheKey(Class<?> beanClass, Class<?> stopClass) { > + this.beanClass = beanClass; > + this.stopClass = stopClass; > + } > + > + @Override > + public int hashCode() { > + return 31*beanClass.hashCode() + (stopClass == null ? 0 : > stopClass.hashCode()); > + } > + > + @Override > + public boolean equals(Object obj) { > + if (obj instanceof CacheKey) { > + CacheKey other = (CacheKey)obj; > + return beanClass == other.beanClass && stopClass == > other.stopClass; > + } else { > + return false; > + } > + } > + } > + > + private static final Log log = LogFactory.getLog(BeanInfoCache.class); > + > + /** > + * Local cache instance for Javabeans that are loaded from the same > class loader as this class. > + */ > + private static final BeanInfoCache localCache = new BeanInfoCache(); > + > + private final Map<CacheKey,BeanInfo> cache = new > ConcurrentHashMap<CacheKey,BeanInfo>(); > + > + /** > + * Introspect on a Java bean and return a cached {@link BeanInfo} object. > + * > + * @param beanClass > + * The bean class to be analyzed. > + * @param stopClass > + * The base class at which to stop the analysis; may be > <code>null</code>. > + * @return A {@link BeanInfo} object describing the target bean. > + * @exception IntrospectionException > + * if an exception occurs during introspection. > + * @see Introspector#getBeanInfo(Class, Class) > + */ > + public BeanInfo getBeanInfo(Class<?> beanClass, Class<?> stopClass) > throws IntrospectionException { > + CacheKey key = new CacheKey(beanClass, stopClass); > + BeanInfo beanInfo = cache.get(key); > + if (beanInfo == null) { > + beanInfo = Introspector.getBeanInfo(beanClass, stopClass); > + cache.put(key, beanInfo); > + } > + return beanInfo; > + } > + > + /** > + * Locate an appropriate {@link BeanInfoCache} and return a cached > {@link BeanInfo} object. > + * This method ensures that caching the {@link BeanInfo} object will not > result in a class > + * loader leak. > + * > + * @param beanClass > + * The bean class to be analyzed. > + * @param stopClass > + * The base class at which to stop the analysis; may be > <code>null</code>. > + * @return A {@link BeanInfo} object describing the target bean. > + * @exception IntrospectionException > + * if an exception occurs during introspection. > + */ > + public static BeanInfo getCachedBeanInfo(Class<?> beanClass, Class<?> > stopClass) throws IntrospectionException { > + ClassLoader classLoader = beanClass.getClassLoader(); > + BeanInfoCache cache; > + if (classLoader instanceof BeanInfoCachingClassLoader) { > + cache = > ((BeanInfoCachingClassLoader)classLoader).getBeanInfoCache(); > + } else if (classLoader == BeanInfoCache.class.getClassLoader()) { > + cache = localCache; > + } else { > + cache = null; > + } > + if (cache != null) { > + return cache.getBeanInfo(beanClass, stopClass); > + } else { > + if (log.isWarnEnabled()) { > + log.warn("Unable to locate a BeanInfo cache for " + > beanClass + " (stopClass=" + stopClass > + + "). This will negatively affect performance!"); > + } > + return Introspector.getBeanInfo(beanClass, stopClass); > + } > + } > +} > > Propchange: > axis/axis2/java/core/trunk/modules/kernel/src/org/apache/axis2/classloader/BeanInfoCache.java > ------------------------------------------------------------------------------ > svn:eol-style = native > > Added: > axis/axis2/java/core/trunk/modules/kernel/src/org/apache/axis2/classloader/BeanInfoCachingClassLoader.java > URL: > http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/kernel/src/org/apache/axis2/classloader/BeanInfoCachingClassLoader.java?rev=1166132&view=auto > ============================================================================== > --- > axis/axis2/java/core/trunk/modules/kernel/src/org/apache/axis2/classloader/BeanInfoCachingClassLoader.java > (added) > +++ > axis/axis2/java/core/trunk/modules/kernel/src/org/apache/axis2/classloader/BeanInfoCachingClassLoader.java > Wed Sep 7 11:41:52 2011 > @@ -0,0 +1,33 @@ > +/* > + * 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 > + * > + * http://www.apache.org/licenses/LICENSE-2.0 > + * > + * Unless required by applicable law or agreed to in writing, > + * software distributed under the License is distributed on an > + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY > + * KIND, either express or implied. See the License for the > + * specific language governing permissions and limitations > + * under the License. > + */ > +package org.apache.axis2.classloader; > + > +import java.beans.BeanInfo; > + > +/** > + * Interface implemented by class loaders that keep a {@link BeanInfo} cache. > + */ > +public interface BeanInfoCachingClassLoader { > + /** > + * Get the {@link BeanInfo} cache for this class loader. > + * > + * @return the cache instance; must not be <code>null</code> > + */ > + BeanInfoCache getBeanInfoCache(); > +} > > Propchange: > axis/axis2/java/core/trunk/modules/kernel/src/org/apache/axis2/classloader/BeanInfoCachingClassLoader.java > ------------------------------------------------------------------------------ > svn:eol-style = native > > Modified: > axis/axis2/java/core/trunk/modules/kernel/src/org/apache/axis2/deployment/DeploymentClassLoader.java > URL: > http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/kernel/src/org/apache/axis2/deployment/DeploymentClassLoader.java?rev=1166132&r1=1166131&r2=1166132&view=diff > ============================================================================== > --- > axis/axis2/java/core/trunk/modules/kernel/src/org/apache/axis2/deployment/DeploymentClassLoader.java > (original) > +++ > axis/axis2/java/core/trunk/modules/kernel/src/org/apache/axis2/deployment/DeploymentClassLoader.java > Wed Sep 7 11:41:52 2011 > @@ -20,6 +20,8 @@ > package org.apache.axis2.deployment; > > import org.apache.axiom.attachments.utils.IOUtils; > +import org.apache.axis2.classloader.BeanInfoCache; > +import org.apache.axis2.classloader.BeanInfoCachingClassLoader; > > import java.io.ByteArrayInputStream; > import java.io.IOException; > @@ -36,7 +38,7 @@ import java.util.List; > import java.util.zip.ZipEntry; > import java.util.zip.ZipInputStream; > > -public class DeploymentClassLoader extends URLClassLoader { > +public class DeploymentClassLoader extends URLClassLoader implements > BeanInfoCachingClassLoader { > // List of URL's > private URL[] urls = null; > > @@ -45,6 +47,8 @@ public class DeploymentClassLoader exten > > private boolean isChildFirstClassLoading; > > + private final BeanInfoCache beanInfoCache = new BeanInfoCache(); > + > /** > * DeploymentClassLoader is extended from URLClassLoader. The constructor > * does not override the super constructor, but takes in an addition list > of > @@ -291,4 +295,8 @@ public class DeploymentClassLoader exten > public void setChildFirstClassLoading(boolean childFirstClassLoading) { > isChildFirstClassLoading = childFirstClassLoading; > } > + > + public final BeanInfoCache getBeanInfoCache() { > + return beanInfoCache; > + } > } > > > -- Sagara Gunathunga Blog - http://ssagara.blogspot.com Web - http://people.apache.org/~sagara/ LinkedIn - http://www.linkedin.com/in/ssagara --------------------------------------------------------------------- To unsubscribe, e-mail: java-dev-unsubscr...@axis.apache.org For additional commands, e-mail: java-dev-h...@axis.apache.org