Browse Source
SPR-6333 + eliminated compile-time dependency on GlassFish custom API for the GlassFish LTW + added support for GlassFish 3 git-svn-id: https://src.springframework.org/svn/spring-framework/trunk@2476 50f2f4bb-b051-0410-bef5-90022cba6387pull/1/head
8 changed files with 159 additions and 84 deletions
@ -0,0 +1,113 @@
@@ -0,0 +1,113 @@
|
||||
/* |
||||
* Copyright 2006-2009 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.instrument.classloading.glassfish; |
||||
|
||||
import java.lang.instrument.ClassFileTransformer; |
||||
import java.lang.reflect.InvocationTargetException; |
||||
import java.lang.reflect.Method; |
||||
|
||||
/** |
||||
* Reflective wrapper around the GlassFish class loader. Used to |
||||
* encapsulate the classloader-specific methods (discovered and |
||||
* called through reflection) from the load-time weaver. |
||||
* |
||||
* <p/> Supports GlassFish V1, V2 and V3 (currently in beta). |
||||
* |
||||
* @author Costin Leau |
||||
* @since 3.0.0 |
||||
*/ |
||||
class GlassFishClassLoaderAdapter { |
||||
|
||||
static final String INSTRUMENTABLE_CLASSLOADER_GLASSFISH_V2 = "com.sun.enterprise.loader.InstrumentableClassLoader"; |
||||
static final String INSTRUMENTABLE_CLASSLOADER_GLASSFISH_V3 = "org.glassfish.api.deployment.InstrumentableClassLoader"; |
||||
private static final String CLASS_TRANSFORMER = "javax.persistence.spi.ClassTransformer"; |
||||
|
||||
private final ClassLoader classLoader; |
||||
private final Method addTransformer; |
||||
private final Method copy; |
||||
private final boolean glassFishV3; |
||||
|
||||
public GlassFishClassLoaderAdapter(ClassLoader classLoader) { |
||||
Class<?> instrumentableLoaderClass = null; |
||||
boolean glassV3 = false; |
||||
try { |
||||
// try the V1/V2 API first
|
||||
instrumentableLoaderClass = classLoader.loadClass(INSTRUMENTABLE_CLASSLOADER_GLASSFISH_V2); |
||||
} catch (ClassNotFoundException ex) { |
||||
// fall back to V3
|
||||
try { |
||||
instrumentableLoaderClass = classLoader.loadClass(INSTRUMENTABLE_CLASSLOADER_GLASSFISH_V3); |
||||
glassV3 = true; |
||||
} catch (ClassNotFoundException cnfe) { |
||||
throw new IllegalStateException( |
||||
"Could not initialize GlassFish LoadTimeWeaver because GlassFish (V1, V2 or V3) API classes are not available", |
||||
ex); |
||||
} |
||||
} |
||||
try { |
||||
Class<?> classTransformerClass = (glassV3 ? ClassFileTransformer.class : classLoader |
||||
.loadClass(CLASS_TRANSFORMER)); |
||||
|
||||
addTransformer = instrumentableLoaderClass.getMethod("addTransformer", classTransformerClass); |
||||
copy = instrumentableLoaderClass.getMethod("copy"); |
||||
|
||||
} catch (Exception ex) { |
||||
throw new IllegalStateException( |
||||
"Could not initialize GlassFish LoadTimeWeaver because GlassFish API classes are not available", ex); |
||||
} |
||||
|
||||
ClassLoader clazzLoader = null; |
||||
// Detect transformation-aware ClassLoader by traversing the hierarchy
|
||||
// (as in GlassFish, Spring can be loaded by the WebappClassLoader).
|
||||
for (ClassLoader cl = classLoader; cl != null && clazzLoader == null; cl = cl.getParent()) { |
||||
if (instrumentableLoaderClass.isInstance(cl)) { |
||||
clazzLoader = cl; |
||||
} |
||||
} |
||||
|
||||
if (clazzLoader == null) { |
||||
throw new IllegalArgumentException(classLoader + " and its parents are not suitable ClassLoaders: " + "A [" |
||||
+ instrumentableLoaderClass.getName() + "] implementation is required."); |
||||
} |
||||
|
||||
this.classLoader = clazzLoader; |
||||
this.glassFishV3 = glassV3; |
||||
} |
||||
|
||||
public void addTransformer(ClassFileTransformer transformer) { |
||||
try { |
||||
addTransformer.invoke(classLoader, (glassFishV3 ? transformer : new ClassTransformerAdapter(transformer))); |
||||
} catch (InvocationTargetException ex) { |
||||
throw new IllegalStateException("GlassFish addTransformer method threw exception ", ex.getCause()); |
||||
} catch (Exception ex) { |
||||
throw new IllegalStateException("Could not invoke GlassFish addTransformer method", ex); |
||||
} |
||||
} |
||||
|
||||
public ClassLoader getClassLoader() { |
||||
return this.classLoader; |
||||
} |
||||
|
||||
public ClassLoader getThrowawayClassLoader() { |
||||
try { |
||||
return (ClassLoader) copy.invoke(classLoader, (Object[]) null); |
||||
} catch (InvocationTargetException ex) { |
||||
throw new IllegalStateException("GlassFish copy method threw exception ", ex.getCause()); |
||||
} catch (Exception ex) { |
||||
throw new IllegalStateException("Could not invoke GlassFish copy method", ex); |
||||
} |
||||
} |
||||
} |
||||
Loading…
Reference in new issue