Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * Copyright 2002-2008 the original author or authors.
   *
   * 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 org.springframework.beans;
 
 import java.util.Map;
 import java.util.Set;
 
 
Internal class that caches JavaBeans java.beans.PropertyDescriptor information for a Java class. Not intended for direct use by application code.

Necessary for own caching of descriptors within the application's ClassLoader, rather than rely on the JDK's system-wide BeanInfo cache (in order to avoid leaks on ClassLoader shutdown).

Information is cached statically, so we don't need to create new objects of this class for every JavaBean we manipulate. Hence, this class implements the factory design pattern, using a private constructor and a static forClass(java.lang.Class) factory method to obtain instances.

 
 public class CachedIntrospectionResults {
 
 	private static final Log logger = LogFactory.getLog(CachedIntrospectionResults.class);

Set of ClassLoaders that this CachedIntrospectionResults class will always accept classes from, even if the classes do not qualify as cache-safe.
 
 	static final Set acceptedClassLoaders = Collections.synchronizedSet(new HashSet());

Map keyed by class containing CachedIntrospectionResults. Needs to be a WeakHashMap with WeakReferences as values to allow for proper garbage collection in case of multiple class loaders.
 
 	static final Map classCache = Collections.synchronizedMap(new WeakHashMap());


Accept the given ClassLoader as cache-safe, even if its classes would not qualify as cache-safe in this CachedIntrospectionResults class.

This configuration method is only relevant in scenarios where the Spring classes reside in a 'common' ClassLoader (e.g. the system ClassLoader) whose lifecycle is not coupled to the application. In such a scenario, CachedIntrospectionResults would by default not cache any of the application's classes, since they would create a leak in the common ClassLoader.

Any acceptClassLoader call at application startup should be paired with a clearClassLoader(java.lang.ClassLoader) call at application shutdown.

Parameters:
classLoader the ClassLoader to accept
 
 	public static void acceptClassLoader(ClassLoader classLoader) {
 		if (classLoader != null) {
 			.add(classLoader);
 		}
 	}

Clear the introspection cache for the given ClassLoader, removing the introspection results for all classes underneath that ClassLoader, and deregistering the ClassLoader (and any of its children) from the acceptance list.

Parameters:
classLoader the ClassLoader to clear the cache for
	public static void clearClassLoader(ClassLoader classLoader) {
		if (classLoader == null) {
			return;
		}
		synchronized () {
			for (Iterator it = .keySet().iterator(); it.hasNext();) {
				Class beanClass = (Classit.next();
				if (isUnderneathClassLoader(beanClass.getClassLoader(), classLoader)) {
					it.remove();
				}
			}
		}
		synchronized () {
			for (Iterator it = .iterator(); it.hasNext();) {
				ClassLoader registeredLoader = (ClassLoaderit.next();
				if (isUnderneathClassLoader(registeredLoaderclassLoader)) {
					it.remove();
				}
			}
		}
	}

Create CachedIntrospectionResults for the given bean class.

We don't want to use synchronization here. Object references are atomic, so we can live with doing the occasional unnecessary lookup at startup only.

Parameters:
beanClass the bean class to analyze
Returns:
the corresponding CachedIntrospectionResults
Throws:
BeansException in case of introspection failure
		CachedIntrospectionResults results = null;
		Object value = .get(beanClass);
		if (value instanceof Reference) {
			Reference ref = (Referencevalue;
			results = (CachedIntrospectionResultsref.get();
		}
		else {
			results = (CachedIntrospectionResultsvalue;
		}
		if (results == null) {
			// can throw BeansException
			results = new CachedIntrospectionResults(beanClass);
			if (ClassUtils.isCacheSafe(beanClassCachedIntrospectionResults.class.getClassLoader()) ||
				.put(beanClassresults);
			}
			else {
					.debug("Not strongly caching class [" + beanClass.getName() + "] because it is not cache-safe");
				}
				.put(beanClassnew WeakReference(results));
			}
		}
		return results;
	}

Check whether this CachedIntrospectionResults class is configured to accept the given ClassLoader.

Parameters:
classLoader the ClassLoader to check
Returns:
whether the given ClassLoader is accepted
See also:
acceptClassLoader(java.lang.ClassLoader)
	private static boolean isClassLoaderAccepted(ClassLoader classLoader) {
		// Iterate over array copy in order to avoid synchronization for the entire
		// ClassLoader check (avoiding a synchronized acceptedClassLoaders Iterator).
		Object[] acceptedLoaderArray = .toArray();
		for (int i = 0; i < acceptedLoaderArray.lengthi++) {
			ClassLoader registeredLoader = (ClassLoaderacceptedLoaderArray[i];
			if (isUnderneathClassLoader(classLoaderregisteredLoader)) {
				return true;
			}
		}
		return false;
	}

Check whether the given ClassLoader is underneath the given parent, that is, whether the parent is within the candidate's hierarchy.

Parameters:
candidate the candidate ClassLoader to check
parent the parent ClassLoader to check for
	private static boolean isUnderneathClassLoader(ClassLoader candidateClassLoader parent) {
		if (candidate == null) {
			return false;
		}
		if (candidate == parent) {
			return true;
		}
		ClassLoader classLoaderToCheck = candidate;
		while (classLoaderToCheck != null) {
			classLoaderToCheck = classLoaderToCheck.getParent();
			if (classLoaderToCheck == parent) {
				return true;
			}
		}
		return false;
	}


The BeanInfo object for the introspected bean class
	private final BeanInfo beanInfo;

PropertyDescriptor objects keyed by property name String
	private final Map propertyDescriptorCache;


Create a new CachedIntrospectionResults instance for the given class.

Parameters:
beanClass the bean class to analyze
Throws:
BeansException in case of introspection failure
	private CachedIntrospectionResults(Class beanClassthrows BeansException {
		try {
				.trace("Getting BeanInfo for class [" + beanClass.getName() + "]");
			}
			this. = Introspector.getBeanInfo(beanClass);
			// Immediately remove class from Introspector cache, to allow for proper
			// garbage collection on class loader shutdown - we cache it here anyway,
			// in a GC-friendly manner. In contrast to CachedIntrospectionResults,
			// Introspector does not use WeakReferences as values of its WeakHashMap!
			Class classToFlush = beanClass;
			do {
				Introspector.flushFromCaches(classToFlush);
				classToFlush = classToFlush.getSuperclass();
			}
			while (classToFlush != null);
				.trace("Caching PropertyDescriptors for class [" + beanClass.getName() + "]");
			}
			// This call is slow so we do it once.
			for (int i = 0; i < pds.lengthi++) {
				PropertyDescriptor pd = pds[i];
					.trace("Found bean property '" + pd.getName() + "'" +
							(pd.getPropertyType() != null ?
							" of type [" + pd.getPropertyType().getName() + "]" : "") +
							(pd.getPropertyEditorClass() != null ?
							"; editor [" + pd.getPropertyEditorClass().getName() + "]" : ""));
				}
				if (JdkVersion.isAtLeastJava15()) {
					pd = new GenericTypeAwarePropertyDescriptor(beanClasspd.getName(),
				}
			}
		}
		catch (IntrospectionException ex) {
			throw new FatalBeanException("Cannot get BeanInfo for object of class [" + beanClass.getName() + "]"ex);
		}
	}
		return this.;
	}
	}
		return (PropertyDescriptorthis..get(propertyName);
	}
New to GrepCode? Check out our FAQ X