diff --git a/build.gradle b/build.gradle index 2870f9cafd2..806d03fa39d 100644 --- a/build.gradle +++ b/build.gradle @@ -91,11 +91,19 @@ configure(subprojects) { subproject -> project('spring-core') { description = 'Spring Core' + // As of Spring 3.2 spring-core repackages both asm 4.0 and cglib 3.0 and inlines both + // into the spring-core jar. cglib 3.0 itself depends on asm 4.0, and is therefore + // further transformed by the JarJar task to depend on org.springframework.asm; this + // avoids including two different copies of asm unnecessarily. If however future cglib + // versions drift from the version of asm used by Spring internally, this duplication + // will become necessary. def asmVersion = '4.0' + def cglibVersion = '3.0' configurations { jarjar asm + cglib } task asmRepackJar(type: Jar) { repackJar -> @@ -116,8 +124,32 @@ project('spring-core') { } } + task cglibRepackJar(type: Jar) { repackJar -> + repackJar.baseName = "spring-cglib-repack" + repackJar.version = cglibVersion + + doLast() { + project.ant { + taskdef name: "jarjar", classname: "com.tonicsystems.jarjar.JarJarTask", + classpath: configurations.jarjar.asPath + jarjar(destfile: repackJar.archivePath) { + configurations.cglib.each { originalJar -> + zipfileset(src: originalJar) + } + // repackage net.sf.cglib => org.springframework.cglib + rule(pattern: 'net.sf.cglib.**', result: 'org.springframework.cglib.@1') + // as mentioned above, transform cglib's internal asm dependencies from + // org.objectweb.asm => org.springframework.asm. Doing this counts on the + // the fact that Spring and cglib depend on the same version of asm! + rule(pattern: 'org.objectweb.asm.**', result: 'org.springframework.asm.@1') + } + } + } + } + dependencies { asm "org.ow2.asm:asm:${asmVersion}@jar", "org.ow2.asm:asm-commons:${asmVersion}@jar" + cglib "cglib:cglib:${cglibVersion}@jar" jarjar 'com.googlecode.jarjar:jarjar:1.3' compile files(asmRepackJar) @@ -139,10 +171,13 @@ project('spring-core') { } jar { - // inline all repackaged asm classes directly into the spring-core jar + // inline all repackaged asm and cglib classes directly into the spring-core jar from(asmRepackJar) { exclude 'META-INF/**' } + from(cglibRepackJar) { + exclude 'META-INF/**' + } } } @@ -150,9 +185,9 @@ project('spring-beans') { description = 'Spring Beans' dependencies { compile project(":spring-core") + compile files(project(":spring-core").cglibRepackJar) compile("javax.el:el-api:1.0", provided) compile("javax.inject:javax.inject:1", provided) - compile("cglib:cglib-nodep:2.2", optional) } } @@ -160,6 +195,7 @@ project('spring-aop') { description = 'Spring AOP' dependencies { compile project(":spring-core") + compile files(project(":spring-core").cglibRepackJar) compile project(":spring-beans") compile("aopalliance:aopalliance:1.0") compile("com.jamonapi:jamon:2.4", optional) @@ -200,6 +236,7 @@ project('spring-context') { compile project(":spring-beans") compile project(":spring-expression") compile project(":spring-core") + compile files(project(":spring-core").cglibRepackJar) compile("backport-util-concurrent:backport-util-concurrent:3.0", optional) compile("javax.annotation:jsr250-api:1.0", optional) compile("javax.ejb:ejb-api:3.0", optional) diff --git a/spring-aop/src/main/java/org/springframework/aop/framework/Cglib2AopProxy.java b/spring-aop/src/main/java/org/springframework/aop/framework/CglibAopProxy.java similarity index 91% rename from spring-aop/src/main/java/org/springframework/aop/framework/Cglib2AopProxy.java rename to spring-aop/src/main/java/org/springframework/aop/framework/CglibAopProxy.java index 46ed66b9049..49bfe5fc2b4 100644 --- a/spring-aop/src/main/java/org/springframework/aop/framework/Cglib2AopProxy.java +++ b/spring-aop/src/main/java/org/springframework/aop/framework/CglibAopProxy.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2010 the original author or authors. + * Copyright 2002-2012 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. @@ -25,16 +25,16 @@ import java.util.List; import java.util.Map; import java.util.WeakHashMap; -import net.sf.cglib.core.CodeGenerationException; -import net.sf.cglib.proxy.Callback; -import net.sf.cglib.proxy.CallbackFilter; -import net.sf.cglib.proxy.Dispatcher; -import net.sf.cglib.proxy.Enhancer; -import net.sf.cglib.proxy.Factory; -import net.sf.cglib.proxy.MethodInterceptor; -import net.sf.cglib.proxy.MethodProxy; -import net.sf.cglib.proxy.NoOp; -import net.sf.cglib.transform.impl.UndeclaredThrowableStrategy; +import org.springframework.cglib.core.CodeGenerationException; +import org.springframework.cglib.proxy.Callback; +import org.springframework.cglib.proxy.CallbackFilter; +import org.springframework.cglib.proxy.Dispatcher; +import org.springframework.cglib.proxy.Enhancer; +import org.springframework.cglib.proxy.Factory; +import org.springframework.cglib.proxy.MethodInterceptor; +import org.springframework.cglib.proxy.MethodProxy; +import org.springframework.cglib.proxy.NoOp; +import org.springframework.cglib.transform.impl.UndeclaredThrowableStrategy; import org.aopalliance.aop.Advice; import org.aopalliance.intercept.MethodInvocation; @@ -51,16 +51,16 @@ import org.springframework.util.ClassUtils; import org.springframework.util.ObjectUtils; /** - * CGLIB2-based {@link AopProxy} implementation for the Spring AOP framework. + * CGLIB-based {@link AopProxy} implementation for the Spring AOP framework. * - *

Requires CGLIB 2.1+ on the classpath.. - * As of Spring 2.0, earlier CGLIB versions are not supported anymore. + *

Formerly named {@code Cglib2AopProxy}, as of Spring 3.2, this class depends on + * Spring's own internally repackaged version of CGLIB 3.. * *

Objects of this type should be obtained through proxy factories, * configured by an {@link AdvisedSupport} object. This class is internal * to Spring's AOP framework and need not be used directly by client code. * - *

{@link DefaultAopProxyFactory} will automatically create CGLIB2-based + *

{@link DefaultAopProxyFactory} will automatically create CGLIB-based * proxies if necessary, for example in case of proxying a target class * (see the {@link DefaultAopProxyFactory attendant javadoc} for details). * @@ -71,11 +71,13 @@ import org.springframework.util.ObjectUtils; * @author Rob Harrop * @author Juergen Hoeller * @author Ramnivas Laddad - * @see net.sf.cglib.proxy.Enhancer + * @author Chris Beams + * @see org.springframework.cglib.proxy.Enhancer * @see AdvisedSupport#setProxyTargetClass * @see DefaultAopProxyFactory */ -final class Cglib2AopProxy implements AopProxy, Serializable { +@SuppressWarnings("serial") +final class CglibAopProxy implements AopProxy, Serializable { // Constants for CGLIB callback array indices private static final int AOP_PROXY = 0; @@ -88,10 +90,10 @@ final class Cglib2AopProxy implements AopProxy, Serializable { /** Logger available to subclasses; static to optimize serialization */ - protected final static Log logger = LogFactory.getLog(Cglib2AopProxy.class); + protected final static Log logger = LogFactory.getLog(CglibAopProxy.class); /** Keeps track of the Classes that we have validated for final methods */ - private static final Map validatedClasses = new WeakHashMap(); + private static final Map, Boolean> validatedClasses = new WeakHashMap, Boolean>(); /** The configuration used to configure this proxy */ @@ -99,7 +101,7 @@ final class Cglib2AopProxy implements AopProxy, Serializable { private Object[] constructorArgs; - private Class[] constructorArgTypes; + private Class[] constructorArgTypes; /** Dispatcher used for methods on Advised */ private final transient AdvisedDispatcher advisedDispatcher; @@ -110,12 +112,12 @@ final class Cglib2AopProxy implements AopProxy, Serializable { /** - * Create a new Cglib2AopProxy for the given AOP configuration. + * Create a new CglibAopProxy for the given AOP configuration. * @param config the AOP configuration as AdvisedSupport object * @throws AopConfigException if the config is invalid. We try to throw an informative * exception in this case, rather than let a mysterious failure happen later. */ - public Cglib2AopProxy(AdvisedSupport config) throws AopConfigException { + public CglibAopProxy(AdvisedSupport config) throws AopConfigException { Assert.notNull(config, "AdvisedSupport must not be null"); if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) { throw new AopConfigException("No advisors and no TargetSource specified"); @@ -129,7 +131,7 @@ final class Cglib2AopProxy implements AopProxy, Serializable { * @param constructorArgs the constructor argument values * @param constructorArgTypes the constructor argument types */ - public void setConstructorArguments(Object[] constructorArgs, Class[] constructorArgTypes) { + public void setConstructorArguments(Object[] constructorArgs, Class[] constructorArgTypes) { if (constructorArgs == null || constructorArgTypes == null) { throw new IllegalArgumentException("Both 'constructorArgs' and 'constructorArgTypes' need to be specified"); } @@ -148,18 +150,18 @@ final class Cglib2AopProxy implements AopProxy, Serializable { public Object getProxy(ClassLoader classLoader) { if (logger.isDebugEnabled()) { - logger.debug("Creating CGLIB2 proxy: target source is " + this.advised.getTargetSource()); + logger.debug("Creating CGLIB proxy: target source is " + this.advised.getTargetSource()); } try { - Class rootClass = this.advised.getTargetClass(); + Class rootClass = this.advised.getTargetClass(); Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy"); - Class proxySuperClass = rootClass; + Class proxySuperClass = rootClass; if (ClassUtils.isCglibProxyClass(rootClass)) { proxySuperClass = rootClass.getSuperclass(); - Class[] additionalInterfaces = rootClass.getInterfaces(); - for (Class additionalInterface : additionalInterfaces) { + Class[] additionalInterfaces = rootClass.getInterfaces(); + for (Class additionalInterface : additionalInterfaces) { this.advised.addInterface(additionalInterface); } } @@ -186,7 +188,7 @@ final class Cglib2AopProxy implements AopProxy, Serializable { enhancer.setCallbackFilter(new ProxyCallbackFilter( this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset)); - Class[] types = new Class[callbacks.length]; + Class[] types = new Class[callbacks.length]; for (int x = 0; x < types.length; x++) { types[x] = callbacks[x].getClass(); } @@ -233,7 +235,7 @@ final class Cglib2AopProxy implements AopProxy, Serializable { * Checks to see whether the supplied Class has already been validated and * validates it if not. */ - private void validateClassIfNecessary(Class proxySuperClass) { + private void validateClassIfNecessary(Class proxySuperClass) { if (logger.isWarnEnabled()) { synchronized (validatedClasses) { if (!validatedClasses.containsKey(proxySuperClass)) { @@ -248,7 +250,7 @@ final class Cglib2AopProxy implements AopProxy, Serializable { * Checks for final methods on the Class and writes warnings to the log * for each one found. */ - private void doValidateClass(Class proxySuperClass) { + private void doValidateClass(Class proxySuperClass) { Method[] methods = proxySuperClass.getMethods(); for (Method method : methods) { if (!Object.class.equals(method.getDeclaringClass()) && Modifier.isFinal(method.getModifiers())) { @@ -258,7 +260,7 @@ final class Cglib2AopProxy implements AopProxy, Serializable { } } - private Callback[] getCallbacks(Class rootClass) throws Exception { + private Callback[] getCallbacks(Class rootClass) throws Exception { // Parameters used for optimisation choices... boolean exposeProxy = this.advised.isExposeProxy(); boolean isFrozen = this.advised.isFrozen(); @@ -345,13 +347,13 @@ final class Cglib2AopProxy implements AopProxy, Serializable { @Override public boolean equals(Object other) { - return (this == other || (other instanceof Cglib2AopProxy && - AopProxyUtils.equalsInProxy(this.advised, ((Cglib2AopProxy) other).advised))); + return (this == other || (other instanceof CglibAopProxy && + AopProxyUtils.equalsInProxy(this.advised, ((CglibAopProxy) other).advised))); } @Override public int hashCode() { - return Cglib2AopProxy.class.hashCode() * 13 + this.advised.getTargetSource().hashCode(); + return CglibAopProxy.class.hashCode() * 13 + this.advised.getTargetSource().hashCode(); } @@ -544,7 +546,7 @@ final class Cglib2AopProxy implements AopProxy, Serializable { } public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) { - return Cglib2AopProxy.class.hashCode() * 13 + this.advised.getTargetSource().hashCode(); + return CglibAopProxy.class.hashCode() * 13 + this.advised.getTargetSource().hashCode(); } } @@ -558,9 +560,9 @@ final class Cglib2AopProxy implements AopProxy, Serializable { private final Object target; - private final Class targetClass; + private final Class targetClass; - public FixedChainStaticTargetInterceptor(List adviceChain, Object target, Class targetClass) { + public FixedChainStaticTargetInterceptor(List adviceChain, Object target, Class targetClass) { this.adviceChain = adviceChain; this.target = target; this.targetClass = targetClass; @@ -592,7 +594,7 @@ final class Cglib2AopProxy implements AopProxy, Serializable { public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { Object oldProxy = null; boolean setProxyContext = false; - Class targetClass = null; + Class targetClass = null; Object target = null; try { if (this.advised.exposeProxy) { @@ -670,7 +672,7 @@ final class Cglib2AopProxy implements AopProxy, Serializable { private boolean protectedMethod; public CglibMethodInvocation(Object proxy, Object target, Method method, Object[] arguments, - Class targetClass, List interceptorsAndDynamicMethodMatchers, MethodProxy methodProxy) { + Class targetClass, List interceptorsAndDynamicMethodMatchers, MethodProxy methodProxy) { super(proxy, target, method, arguments, targetClass, interceptorsAndDynamicMethodMatchers); this.methodProxy = methodProxy; this.protectedMethod = Modifier.isProtected(method.getModifiers()); @@ -767,9 +769,9 @@ final class Cglib2AopProxy implements AopProxy, Serializable { logger.debug("Found 'hashCode' method: " + method); return INVOKE_HASHCODE; } - Class targetClass = this.advised.getTargetClass(); + Class targetClass = this.advised.getTargetClass(); // Proxy is not yet available, but that shouldn't matter. - List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); + List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); boolean haveAdvice = !chain.isEmpty(); boolean exposeProxy = this.advised.isExposeProxy(); boolean isStatic = this.advised.getTargetSource().isStatic(); @@ -811,7 +813,7 @@ final class Cglib2AopProxy implements AopProxy, Serializable { if (exposeProxy || !isStatic) { return INVOKE_TARGET; } - Class returnType = method.getReturnType(); + Class returnType = method.getReturnType(); if (targetClass == returnType) { if (logger.isDebugEnabled()) { logger.debug("Method " + method + diff --git a/spring-aop/src/main/java/org/springframework/aop/framework/DefaultAopProxyFactory.java b/spring-aop/src/main/java/org/springframework/aop/framework/DefaultAopProxyFactory.java index 731565c8d79..43293527e6d 100644 --- a/spring-aop/src/main/java/org/springframework/aop/framework/DefaultAopProxyFactory.java +++ b/spring-aop/src/main/java/org/springframework/aop/framework/DefaultAopProxyFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2007 the original author or authors. + * Copyright 2002-2012 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. @@ -19,7 +19,6 @@ package org.springframework.aop.framework; import java.io.Serializable; import org.springframework.aop.SpringProxy; -import org.springframework.util.ClassUtils; /** * Default {@link AopProxyFactory} implementation, @@ -48,10 +47,6 @@ import org.springframework.util.ClassUtils; */ public class DefaultAopProxyFactory implements AopProxyFactory, Serializable { - /** Whether the CGLIB2 library is present on the classpath */ - private static final boolean cglibAvailable = - ClassUtils.isPresent("net.sf.cglib.proxy.Enhancer", DefaultAopProxyFactory.class.getClassLoader()); - public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { @@ -63,11 +58,6 @@ public class DefaultAopProxyFactory implements AopProxyFactory, Serializable { if (targetClass.isInterface()) { return new JdkDynamicAopProxy(config); } - if (!cglibAvailable) { - throw new AopConfigException( - "Cannot proxy target class because CGLIB2 is not available. " + - "Add CGLIB to the class path or specify proxy interfaces."); - } return CglibProxyFactory.createCglibProxy(config); } else { @@ -87,13 +77,13 @@ public class DefaultAopProxyFactory implements AopProxyFactory, Serializable { /** - * Inner factory class used to just introduce a CGLIB2 dependency + * Inner factory class used to just introduce a CGLIB dependency * when actually creating a CGLIB proxy. */ private static class CglibProxyFactory { public static AopProxy createCglibProxy(AdvisedSupport advisedSupport) { - return new Cglib2AopProxy(advisedSupport); + return new CglibAopProxy(advisedSupport); } } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/CglibSubclassingInstantiationStrategy.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/CglibSubclassingInstantiationStrategy.java index c174976a39b..2d3ce41f37d 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/CglibSubclassingInstantiationStrategy.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/CglibSubclassingInstantiationStrategy.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2007 the original author or authors. + * Copyright 2002-2012 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. @@ -19,25 +19,23 @@ package org.springframework.beans.factory.support; import java.lang.reflect.Constructor; import java.lang.reflect.Method; -import net.sf.cglib.proxy.Callback; -import net.sf.cglib.proxy.CallbackFilter; -import net.sf.cglib.proxy.Enhancer; -import net.sf.cglib.proxy.MethodInterceptor; -import net.sf.cglib.proxy.MethodProxy; -import net.sf.cglib.proxy.NoOp; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.BeanFactory; +import org.springframework.cglib.proxy.Callback; +import org.springframework.cglib.proxy.CallbackFilter; +import org.springframework.cglib.proxy.Enhancer; +import org.springframework.cglib.proxy.MethodInterceptor; +import org.springframework.cglib.proxy.MethodProxy; +import org.springframework.cglib.proxy.NoOp; + /** * Default object instantiation strategy for use in BeanFactories. * Uses CGLIB to generate subclasses dynamically if methods need to be * overridden by the container, to implement Method Injection. * - *

Using Method Injection features requires CGLIB on the classpath. - * However, the core IoC container will still run without CGLIB being available. - * * @author Rod Johnson * @author Juergen Hoeller * @since 1.1 @@ -81,7 +79,8 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt /** - * An inner class so we don't have a CGLIB dependency in core. + * An inner class created for historical reasons to avoid external CGLIB dependency + * in Spring versions earlier than 3.2. */ private static class CglibSubclassCreator { diff --git a/spring-beans/src/test/java/org/springframework/beans/factory/BeanFactoryUtilsTests.java b/spring-beans/src/test/java/org/springframework/beans/factory/BeanFactoryUtilsTests.java index 2186da05b43..4094dd39747 100644 --- a/spring-beans/src/test/java/org/springframework/beans/factory/BeanFactoryUtilsTests.java +++ b/spring-beans/src/test/java/org/springframework/beans/factory/BeanFactoryUtilsTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 the original author or authors. + * Copyright 2002-2012 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. @@ -16,20 +16,17 @@ package org.springframework.beans.factory; -import static org.junit.Assert.*; -import static test.util.TestResourceUtils.qualifiedResource; - import java.util.Arrays; import java.util.List; import java.util.Map; -import net.sf.cglib.proxy.NoOp; - import org.junit.Before; import org.junit.Test; + import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.support.StaticListableBeanFactory; import org.springframework.beans.factory.xml.XmlBeanFactory; +import org.springframework.cglib.proxy.NoOp; import org.springframework.core.io.Resource; import org.springframework.util.ObjectUtils; @@ -38,6 +35,9 @@ import test.beans.ITestBean; import test.beans.IndexedTestBean; import test.beans.TestBean; +import static org.junit.Assert.*; +import static test.util.TestResourceUtils.qualifiedResource; + /** * @author Rod Johnson * @author Juergen Hoeller diff --git a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassEnhancer.java b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassEnhancer.java index d2b2ed6d4da..85bda356028 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassEnhancer.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassEnhancer.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2011 the original author or authors. + * Copyright 2002-2012 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. @@ -20,15 +20,16 @@ import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; -import net.sf.cglib.proxy.Callback; -import net.sf.cglib.proxy.CallbackFilter; -import net.sf.cglib.proxy.Enhancer; -import net.sf.cglib.proxy.MethodInterceptor; -import net.sf.cglib.proxy.MethodProxy; -import net.sf.cglib.proxy.NoOp; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + +import org.springframework.cglib.proxy.Callback; +import org.springframework.cglib.proxy.CallbackFilter; +import org.springframework.cglib.proxy.Enhancer; +import org.springframework.cglib.proxy.MethodInterceptor; +import org.springframework.cglib.proxy.MethodProxy; +import org.springframework.cglib.proxy.NoOp; + import org.springframework.aop.scope.ScopedProxyFactoryBean; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.DisposableBean; diff --git a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassPostProcessor.java b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassPostProcessor.java index 9736099c6f5..ac728d9226f 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassPostProcessor.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassPostProcessor.java @@ -88,11 +88,6 @@ import static org.springframework.context.annotation.AnnotationConfigUtils.*; public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor, ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware { - /** Whether the CGLIB2 library is present on the classpath */ - private static final boolean cglibAvailable = ClassUtils.isPresent( - "net.sf.cglib.proxy.Enhancer", ConfigurationClassPostProcessor.class.getClassLoader()); - - private final Log logger = LogFactory.getLog(getClass()); private SourceExtractor sourceExtractor = new PassThroughSourceExtractor(); @@ -323,11 +318,6 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo // nothing to enhance -> return immediately return; } - if (!cglibAvailable) { - throw new IllegalStateException("CGLIB is required to process @Configuration classes. " + - "Either add CGLIB to the classpath or remove the following @Configuration bean definitions: " + - configBeanDefs.keySet()); - } ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer(beanFactory); for (Map.Entry entry : configBeanDefs.entrySet()) { AbstractBeanDefinition beanDef = entry.getValue(); diff --git a/spring-context/src/main/java/org/springframework/instrument/classloading/ShadowingClassLoader.java b/spring-context/src/main/java/org/springframework/instrument/classloading/ShadowingClassLoader.java index 2a987628a51..913b4b00ded 100644 --- a/spring-context/src/main/java/org/springframework/instrument/classloading/ShadowingClassLoader.java +++ b/spring-context/src/main/java/org/springframework/instrument/classloading/ShadowingClassLoader.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 the original author or authors. + * Copyright 2002-2012 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. @@ -48,8 +48,8 @@ public class ShadowingClassLoader extends DecoratingClassLoader { /** Packages that are excluded by default */ public static final String[] DEFAULT_EXCLUDED_PACKAGES = new String[] {"java.", "javax.", "sun.", "oracle.", "com.sun.", "com.ibm.", "COM.ibm.", - "org.w3c.", "org.xml.", "org.dom4j.", "org.eclipse", "org.aspectj.", "net.sf.cglib.", - "org.apache.xerces.", "org.apache.commons.logging."}; + "org.w3c.", "org.xml.", "org.dom4j.", "org.eclipse", "org.aspectj.", "net.sf.cglib", + "org.springframework.cglib", "org.apache.xerces.", "org.apache.commons.logging."}; private final ClassLoader enclosingClassLoader; diff --git a/spring-context/src/main/java/org/springframework/scripting/support/ScriptFactoryPostProcessor.java b/spring-context/src/main/java/org/springframework/scripting/support/ScriptFactoryPostProcessor.java index 2bf5a2e58f5..90626e55435 100644 --- a/spring-context/src/main/java/org/springframework/scripting/support/ScriptFactoryPostProcessor.java +++ b/spring-context/src/main/java/org/springframework/scripting/support/ScriptFactoryPostProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2011 the original author or authors. + * Copyright 2002-2012 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. @@ -20,12 +20,14 @@ import java.util.HashMap; import java.util.Iterator; import java.util.Map; -import net.sf.cglib.asm.Type; -import net.sf.cglib.core.Signature; -import net.sf.cglib.proxy.InterfaceMaker; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.springframework.asm.Type; + +import org.springframework.cglib.core.Signature; +import org.springframework.cglib.proxy.InterfaceMaker; + import org.springframework.aop.TargetSource; import org.springframework.aop.framework.AopInfrastructureBean; import org.springframework.aop.framework.ProxyFactory; @@ -473,7 +475,7 @@ public class ScriptFactoryPostProcessor extends InstantiationAwareBeanPostProces * @param interfaces the interfaces to check against (might define * getters corresponding to the setters we're supposed to generate) * @return the config interface - * @see net.sf.cglib.proxy.InterfaceMaker + * @see org.springframework.cglib.proxy.InterfaceMaker * @see org.springframework.beans.BeanUtils#findPropertyType */ protected Class createConfigInterface(BeanDefinition bd, Class[] interfaces) { diff --git a/spring-context/src/test/java/org/springframework/aop/framework/AbstractAopProxyTests.java b/spring-context/src/test/java/org/springframework/aop/framework/AbstractAopProxyTests.java index 56ef3185d53..1a381f58e10 100644 --- a/spring-context/src/test/java/org/springframework/aop/framework/AbstractAopProxyTests.java +++ b/spring-context/src/test/java/org/springframework/aop/framework/AbstractAopProxyTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2007 the original author or authors. + * Copyright 2002-2012 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. @@ -486,7 +486,7 @@ public abstract class AbstractAopProxyTests { /** * An interceptor throws a checked exception not on the method signature. * For efficiency, we don't bother unifying java.lang.reflect and - * net.sf.cglib UndeclaredThrowableException + * org.springframework.cglib UndeclaredThrowableException */ @Test public void testUndeclaredCheckedException() throws Throwable { @@ -514,9 +514,6 @@ public abstract class AbstractAopProxyTests { catch (UndeclaredThrowableException thrown) { assertEquals("exception matches", unexpectedException, thrown.getUndeclaredThrowable()); } - //catch (net.sf.cglib.proxy.UndeclaredThrowableException thrown) { - // assertEquals("exception matches", unexpectedException, thrown.getUndeclaredThrowable()); - //} catch (Exception ex) { ex.printStackTrace(); fail("Didn't expect exception: " + ex); @@ -549,9 +546,6 @@ public abstract class AbstractAopProxyTests { catch (RuntimeException thrown) { assertEquals("exception matches", unexpectedException, thrown); } - //catch (net.sf.cglib.proxy.UndeclaredThrowableException thrown) { - // assertEquals("exception matches", unexpectedException, thrown.getUndeclaredThrowable()); - //} } /** diff --git a/spring-context/src/test/java/org/springframework/aop/framework/CglibProxyTests.java b/spring-context/src/test/java/org/springframework/aop/framework/CglibProxyTests.java index d59924d16e9..8a2106c58fd 100644 --- a/spring-context/src/test/java/org/springframework/aop/framework/CglibProxyTests.java +++ b/spring-context/src/test/java/org/springframework/aop/framework/CglibProxyTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2007 the original author or authors. + * Copyright 2002-2012 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. @@ -21,11 +21,13 @@ import static org.junit.Assert.*; import java.io.Serializable; -import net.sf.cglib.core.CodeGenerationException; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; + import org.junit.Test; +import org.springframework.cglib.core.CodeGenerationException; + import org.springframework.aop.ClassFilter; import org.springframework.aop.MethodMatcher; import org.springframework.aop.Pointcut; @@ -65,7 +67,7 @@ public final class CglibProxyTests extends AbstractAopProxyTests implements Seri protected AopProxy createAopProxy(AdvisedSupport as) { as.setProxyTargetClass(true); - return new Cglib2AopProxy(as); + return new CglibAopProxy(as); } protected boolean requiresTarget() { @@ -75,7 +77,7 @@ public final class CglibProxyTests extends AbstractAopProxyTests implements Seri @Test public void testNullConfig() { try { - new Cglib2AopProxy(null); + new CglibAopProxy(null); fail("Shouldn't allow null interceptors"); } catch (IllegalArgumentException ex) { @@ -105,7 +107,7 @@ public final class CglibProxyTests extends AbstractAopProxyTests implements Seri AdvisedSupport as = new AdvisedSupport(new Class[]{}); as.setTargetSource(mockTargetSource); as.addAdvice(new NopInterceptor()); - AopProxy aop = new Cglib2AopProxy(as); + AopProxy aop = new CglibAopProxy(as); Object proxy = aop.getProxy(); assertTrue(AopUtils.isCglibProxy(proxy)); @@ -118,7 +120,7 @@ public final class CglibProxyTests extends AbstractAopProxyTests implements Seri mockTargetSource.setTarget(raw); AdvisedSupport pc = new AdvisedSupport(); pc.setTargetSource(mockTargetSource); - AopProxy aop = new Cglib2AopProxy(pc); + AopProxy aop = new CglibAopProxy(pc); Object proxy = aop.getProxy(); assertTrue(AopUtils.isCglibProxy(proxy)); @@ -159,7 +161,7 @@ public final class CglibProxyTests extends AbstractAopProxyTests implements Seri AdvisedSupport as = new AdvisedSupport(new Class[]{}); as.setTarget(bean); as.addAdvice(new NopInterceptor()); - AopProxy aop = new Cglib2AopProxy(as); + AopProxy aop = new CglibAopProxy(as); CglibTestBean proxy = (CglibTestBean) aop.getProxy(); @@ -176,7 +178,7 @@ public final class CglibProxyTests extends AbstractAopProxyTests implements Seri pc.setFrozen(true); pc.setTarget(target); - Cglib2AopProxy aop = new Cglib2AopProxy(pc); + CglibAopProxy aop = new CglibAopProxy(pc); CglibTestBean proxy = (CglibTestBean) aop.getProxy(); @@ -258,7 +260,7 @@ public final class CglibProxyTests extends AbstractAopProxyTests implements Seri mockTargetSource.setTarget(target); AdvisedSupport pc = new AdvisedSupport(new Class[]{}); pc.setTargetSource(mockTargetSource); - Cglib2AopProxy aop = new Cglib2AopProxy(pc); + CglibAopProxy aop = new CglibAopProxy(pc); aop.setConstructorArguments(new Object[] {"Rob Harrop", new Integer(22)}, new Class[] {String.class, int.class}); @@ -276,7 +278,7 @@ public final class CglibProxyTests extends AbstractAopProxyTests implements Seri AdvisedSupport as = new AdvisedSupport(new Class[]{}); as.setTargetSource(mockTargetSource); as.addAdvice(new NopInterceptor()); - Cglib2AopProxy cglib = new Cglib2AopProxy(as); + CglibAopProxy cglib = new CglibAopProxy(as); ITestBean proxy1 = (ITestBean) cglib.getProxy(); @@ -284,7 +286,7 @@ public final class CglibProxyTests extends AbstractAopProxyTests implements Seri as = new AdvisedSupport(new Class[]{}); as.setTargetSource(mockTargetSource); as.addAdvice(new NopInterceptor()); - cglib = new Cglib2AopProxy(as); + cglib = new CglibAopProxy(as); assertThat(cglib.getProxy(), instanceOf(ITestBean.class)); } @@ -298,7 +300,7 @@ public final class CglibProxyTests extends AbstractAopProxyTests implements Seri as.setTargetSource(mockTargetSource); as.addAdvice(new NopInterceptor()); as.addInterface(Serializable.class); - Cglib2AopProxy cglib = new Cglib2AopProxy(as); + CglibAopProxy cglib = new CglibAopProxy(as); ITestBean proxy1 = (ITestBean) cglib.getProxy(); @@ -306,7 +308,7 @@ public final class CglibProxyTests extends AbstractAopProxyTests implements Seri as = new AdvisedSupport(new Class[]{}); as.setTargetSource(mockTargetSource); as.addAdvice(new NopInterceptor()); - cglib = new Cglib2AopProxy(as); + cglib = new CglibAopProxy(as); ITestBean proxy2 = (ITestBean) cglib.getProxy(); assertTrue(proxy2 instanceof Serializable); @@ -320,7 +322,7 @@ public final class CglibProxyTests extends AbstractAopProxyTests implements Seri AdvisedSupport as = new AdvisedSupport(new Class[]{}); as.setTargetSource(mockTargetSource); as.addAdvice(new NopInterceptor()); - AopProxy aop = new Cglib2AopProxy(as); + AopProxy aop = new CglibAopProxy(as); ExceptionThrower proxy = (ExceptionThrower) aop.getProxy(); @@ -494,4 +496,4 @@ class UnsupportedInterceptor implements MethodInterceptor { throw new UnsupportedOperationException(mi.getMethod().getName()); } -} \ No newline at end of file +} diff --git a/spring-core/src/main/java/org/springframework/asm/util/TraceClassVisitor.java b/spring-core/src/main/java/org/springframework/asm/util/TraceClassVisitor.java new file mode 100644 index 00000000000..bf5900fbd1b --- /dev/null +++ b/spring-core/src/main/java/org/springframework/asm/util/TraceClassVisitor.java @@ -0,0 +1,37 @@ +/* + * Copyright 2002-2012 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.asm.util; + +import java.io.PrintWriter; + +import org.springframework.asm.ClassVisitor; +import org.springframework.asm.SpringAsmInfo; + +/** + * Dummy implementation of missing TraceClassVisitor from cglib-nodep's internally + * repackaged ASM library, added to avoid NoClassDefFoundErrors. + * + * @author Chris Beams + * @since 3.2 + */ +public class TraceClassVisitor extends ClassVisitor { + + public TraceClassVisitor(Object object, PrintWriter pw) { + super(SpringAsmInfo.ASM_VERSION); + } + +} diff --git a/spring-core/src/main/java/org/springframework/cglib/SpringCglibInfo.java b/spring-core/src/main/java/org/springframework/cglib/SpringCglibInfo.java new file mode 100644 index 00000000000..0ed64ca52e0 --- /dev/null +++ b/spring-core/src/main/java/org/springframework/cglib/SpringCglibInfo.java @@ -0,0 +1,31 @@ +/* + * Copyright 2002-2012 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.cglib; + +/** + * Empty class used to ensure that the {@code org.springframework.cglib} package is + * processed during Javadoc generation. + * + *

See package-level Javadoc for more + * information on {@code org.springframework.cglib}. + * + * @author Chris Beams + * @since 3.2 + */ +public final class SpringCglibInfo { + +} diff --git a/spring-core/src/main/java/org/springframework/cglib/package-info.java b/spring-core/src/main/java/org/springframework/cglib/package-info.java new file mode 100644 index 00000000000..a7f25ce2a6a --- /dev/null +++ b/spring-core/src/main/java/org/springframework/cglib/package-info.java @@ -0,0 +1,30 @@ +/* + * Copyright 2002-2012 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. + */ + +/** + * Spring's repackaging of net.sf.cglib 3 (for + * internal use only). + *

This repackaging technique avoids any potential conflicts with + * dependencies on CGLIB at the application level or from other third-party + * libraries and frameworks. + *

As this repackaging happens at the classfile level, sources and Javadoc + * are not available here. See the original + * CGLIB 3 Javadoc + * for details when working with these classes. + * + * @since 3.2 + */ +package org.springframework.cglib; diff --git a/spring-core/src/main/java/org/springframework/util/ReflectionUtils.java b/spring-core/src/main/java/org/springframework/util/ReflectionUtils.java index 742126950ac..1ef55a52423 100644 --- a/spring-core/src/main/java/org/springframework/util/ReflectionUtils.java +++ b/spring-core/src/main/java/org/springframework/util/ReflectionUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2011 the original author or authors. + * Copyright 2002-2012 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. @@ -387,7 +387,7 @@ public abstract class ReflectionUtils { * Determine whether the given method is a CGLIB 'renamed' method, following * the pattern "CGLIB$methodName$0". * @param renamedMethod the method to check - * @see net.sf.cglib.proxy.Enhancer#rename + * @see org.springframework.cglib.proxy.Enhancer#rename */ public static boolean isCglibRenamedMethod(Method renamedMethod) { return CGLIB_RENAMED_METHOD_PATTERN.matcher(renamedMethod.getName()).matches(); diff --git a/src/dist/changelog.txt b/src/dist/changelog.txt index adc5615a88d..4324f8f4f44 100644 --- a/src/dist/changelog.txt +++ b/src/dist/changelog.txt @@ -37,6 +37,7 @@ Changes in version 3.2 M2 (2012-08-xx) * introduced JdbcTemplate in tx base classes in the TestContext framework (SPR-8990) * introduced countRowsInTableWhere() and dropTables() in tx base test classes (SPR-9665) * inlined ASM 4.0 into spring-core, removed spring-asm subproject and jar (SPR-9669) +* inlined CGLIB 3.0 into spring-core, eliminating external dependency (SPR-9669) Changes in version 3.2 M1 (2012-05-28) diff --git a/src/dist/license.txt b/src/dist/license.txt index af01a07e6e4..59efc2327a0 100644 --- a/src/dist/license.txt +++ b/src/dist/license.txt @@ -211,7 +211,8 @@ subcomponents referred to below. Your use of the source code for these subcomponents is subject to the terms and conditions of the following licenses. ->>> asm-4.0: + +>>> ASM 4.0 (org.ow2.asm:asm:4.0, org.ow2.asm:asm-commons:4.0): Copyright (c) 2000-2011 INRIA, France Telecom All rights reserved. @@ -245,6 +246,15 @@ THE POSSIBILITY OF SUCH DAMAGE. Copyright (c) 1999-2009, OW2 Consortium + +>>> CGLIB 3.0 (cglib:cglib:3.0): + +Per the LICENSE file in the CGLIB JAR distribution downloaded from +http://sourceforge.net/projects/cglib/files/cglib3/3.0/cglib-3.0.jar/download, +CGLIB 3.0 is licensed under the Apache License, version 2.0, the text of which +is included above. + + ======================================================================= To the extent any open source subcomponents are licensed under the EPL and/or diff --git a/src/reference/docbook/aop-api.xml b/src/reference/docbook/aop-api.xml index 672422d4671..eb60c6c2cb1 100644 --- a/src/reference/docbook/aop-api.xml +++ b/src/reference/docbook/aop-api.xml @@ -1177,8 +1177,10 @@ public interface IntroductionInfo { - You'll need the CGLIB 2 binaries on your classpath; dynamic - proxies are available with the JDK. + There is no need to add CGLIB to your classpath. As of Spring + 3.2, CGLIB is repackaged and included in the spring-core JAR. In + other words, CGLIB-based AOP will work "out of the box" just as do + JDK dynamic proxies. diff --git a/src/reference/docbook/aop.xml b/src/reference/docbook/aop.xml index dd619187967..1b7dd7a8d6d 100644 --- a/src/reference/docbook/aop.xml +++ b/src/reference/docbook/aop.xml @@ -2549,10 +2549,12 @@ public @interface Idempotent { - You will need the CGLIB 2 binaries on your classpath, whereas - dynamic proxies are available with the JDK. Spring will automatically - warn you when it needs CGLIB and the CGLIB library classes are not - found on the classpath. + As of Spring 3.2, it is no longer necessary to add CGLIB to your + project classpath, as CGLIB classes are repackaged under + org.springframework and included directly in the spring-core JAR. This + means that CGLIB-based proxy support 'just works' in the same way that + JDK dynamic proxies always have. + diff --git a/src/reference/docbook/beans-dependencies.xml b/src/reference/docbook/beans-dependencies.xml index f9311d0240c..874dcc188b7 100644 --- a/src/reference/docbook/beans-dependencies.xml +++ b/src/reference/docbook/beans-dependencies.xml @@ -1491,14 +1491,18 @@ public class CommandManager implements ApplicationContextAware { method. - For this dynamic subclassing to work, you must have the CGLIB - jar(s) in your classpath. The class that the Spring container will - subclass cannot be final, and the method to be - overridden cannot be final either. Also, testing a - class that has an abstract method requires you to - subclass the class yourself and to supply a stub implementation of the - abstract method. Finally, objects that have been - the target of method injection cannot be serialized. + For this dynamic subclassing to work, the class that the Spring + container will subclass cannot be final, and the + method to be overridden cannot be final either. Also, + testing a class that has an abstract method requires + you to subclass the class yourself and to supply a stub implementation + of the abstract method. Finally, objects that have + been the target of method injection cannot be serialized. As of Spring + 3.2 it is no longer necessary to add CGLIB to your classpath, because + CGLIB classes are repackaged under org.springframework and distributed + within the spring-core JAR. This is done both for convenience as well + as to avoid potential conflicts with other projects that use differing + versions of CGLIB. Looking at the CommandManager class in the diff --git a/src/reference/docbook/beans-java.xml b/src/reference/docbook/beans-java.xml index 72932da1d95..f81a44fcb23 100644 --- a/src/reference/docbook/beans-java.xml +++ b/src/reference/docbook/beans-java.xml @@ -885,15 +885,14 @@ public class AppConfig { comes in: All @Configuration classes are subclassed at startup-time with CGLIB. In the subclass, the child method checks the container first for any cached (scoped) beans before it - calls the parent method and creates a new instance. + calls the parent method and creates a new instance. Note that as of Spring + 3.2, it is no longer necessary to add CGLIB to your classpath because + CGLIB classes have been repackaged under org.springframework and included + directly within the spring-core JAR. The behavior could be different according to the scope of your bean. We are talking about singletons here. - - Beware that, in order for JavaConfig to work, you must include the - CGLIB jar in your list of dependencies. - There are a few restrictions due to the fact that CGLIB dynamically adds features at startup-time: diff --git a/src/reference/docbook/beans-scopes.xml b/src/reference/docbook/beans-scopes.xml index d909307d387..e70dc651081 100644 --- a/src/reference/docbook/beans-scopes.xml +++ b/src/reference/docbook/beans-scopes.xml @@ -422,10 +422,7 @@ To create such a proxy, you insert a child <aop:scoped-proxy/> element into a scoped bean - definition. - (If - you choose class-based proxying, you also need the CGLIB library in your - classpath. See and .) Why do definitions of beans scoped at the request, session, @@ -502,9 +499,7 @@ By default, when the Spring container creates a proxy for a bean that is marked up with the <aop:scoped-proxy/> element, a - CGLIB-based class proxy is created. This means that you - need to have the CGLIB library in the classpath of your - application. + CGLIB-based class proxy is created. Note: CGLIB proxies only intercept public method calls! Do not call non-public methods on such a proxy; they diff --git a/src/reference/docbook/classic-aop-spring.xml b/src/reference/docbook/classic-aop-spring.xml index 94229c7761b..7954ab3bf40 100644 --- a/src/reference/docbook/classic-aop-spring.xml +++ b/src/reference/docbook/classic-aop-spring.xml @@ -1161,8 +1161,12 @@ public interface IntroductionInfo { - You'll need the CGLIB 2 binaries on your classpath; dynamic - proxies are available with the JDK. + As of Spring 3.2 it is no longer required to add CGLIB to your + project classpath. CGLIB classes have been repackaged under + org.springframework and included directly in the spring-core JAR. This + is both for user convenience as well as to avoid potential conflicts + with other projects that have dependence on a differing version of + CGLIB. diff --git a/src/reference/docbook/dynamic-languages.xml b/src/reference/docbook/dynamic-languages.xml index 4ad5b0c414d..7a6683fb7d9 100644 --- a/src/reference/docbook/dynamic-languages.xml +++ b/src/reference/docbook/dynamic-languages.xml @@ -515,17 +515,11 @@ class GroovyMessenger implements Messenger { The JRuby scripting support in Spring requires the following libraries to be on the classpath of your application. - (The versions listed just happen to be the versions that the - Spring team used in the development of the JRuby scripting support; - you may well be able to use another version of a specific library.) jruby.jar - - cglib-nodep-2.1_3.jar - From the JRuby homepage... @@ -803,9 +797,6 @@ public class Main { bsh-2.0b4.jar - - cglib-nodep-2.1_3.jar - From the BeanShell homepage...