001: /*
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright
003: * notice. All rights reserved.
004: */
005: package com.tc.object.loaders;
006:
007: import com.tc.aspectwerkz.transform.inlining.AsmHelper;
008:
009: import java.lang.ref.WeakReference;
010: import java.util.HashMap;
011: import java.util.Map;
012:
013: /**
014: * Standard ClassProvider, using named classloaders and aware of boot, extension, and system classloaders.
015: */
016: public class StandardClassProvider implements ClassProvider {
017:
018: private static final String BOOT = Namespace
019: .getStandardBootstrapLoaderName();
020: private static final String EXT = Namespace
021: .getStandardExtensionsLoaderName();
022: private static final String SYSTEM = Namespace
023: .getStandardSystemLoaderName();
024:
025: private final Map loaders = new HashMap();
026:
027: public StandardClassProvider() {
028: //
029: }
030:
031: public ClassLoader getClassLoader(String desc) {
032: if (isStandardLoader(desc)) {
033: return SystemLoaderHolder.loader;
034: }
035:
036: ClassLoader rv = lookupLoader(desc);
037: if (rv == null) {
038: throw new AssertionError(
039: "No registered loader for description: " + desc);
040: }
041: return rv;
042: }
043:
044: public Class getClassFor(final String className, String desc)
045: throws ClassNotFoundException {
046: final ClassLoader loader;
047:
048: if (isStandardLoader(desc)) {
049: loader = SystemLoaderHolder.loader;
050: } else {
051: loader = lookupLoader(desc);
052: if (loader == null) {
053: throw new ClassNotFoundException(
054: "No registered loader for description: " + desc
055: + ", trying to load " + className);
056: }
057: }
058:
059: try {
060: return Class.forName(className, false, loader);
061: } catch (ClassNotFoundException e) {
062: if (loader instanceof BytecodeProvider) {
063: BytecodeProvider provider = (BytecodeProvider) loader;
064: byte[] bytes = provider
065: .__tc_getBytecodeForClass(className);
066: if (bytes != null && bytes.length != 0) {
067: return AsmHelper.defineClass(loader, bytes,
068: className);
069: }
070: }
071: throw e;
072: }
073: }
074:
075: public void registerNamedLoader(NamedClassLoader loader) {
076: final String name = getName(loader);
077: synchronized (loaders) {
078: loaders.put(name, new WeakReference(loader));
079: }
080: }
081:
082: private static String getName(NamedClassLoader loader) {
083: String name = loader.__tc_getClassLoaderName();
084: if (name == null || name.length() == 0) {
085: throw new AssertionError("Invalid name [" + name
086: + "] from loader " + loader);
087: }
088: return name;
089: }
090:
091: public String getLoaderDescriptionFor(Class clazz) {
092: return getLoaderDescriptionFor(clazz.getClassLoader());
093: }
094:
095: public String getLoaderDescriptionFor(ClassLoader loader) {
096: if (loader == null) {
097: return BOOT;
098: }
099: if (loader instanceof NamedClassLoader) {
100: return getName((NamedClassLoader) loader);
101: }
102: throw handleMissingLoader(loader);
103: }
104:
105: private RuntimeException handleMissingLoader(ClassLoader loader) {
106: if ("org.apache.jasper.servlet.JasperLoader".equals(loader
107: .getClass().getName())) {
108: // try to guve a better error message if you're trying to share a JSP
109: return new RuntimeException(
110: "JSP instances (and inner classes there of) cannot be distributed, loader = "
111: + loader);
112: }
113: return new RuntimeException("No loader description for "
114: + loader);
115: }
116:
117: private boolean isStandardLoader(String desc) {
118: if (BOOT.equals(desc) || EXT.equals(desc)
119: || SYSTEM.equals(desc)) {
120: return true;
121: }
122: return false;
123: }
124:
125: private ClassLoader lookupLoader(String desc) {
126: final ClassLoader rv;
127: synchronized (loaders) {
128: WeakReference ref = (WeakReference) loaders.get(desc);
129: if (ref != null) {
130: rv = (ClassLoader) ref.get();
131: if (rv == null) {
132: loaders.remove(desc);
133: }
134: } else {
135: rv = null;
136: }
137: }
138: return rv;
139: }
140:
141: public static class SystemLoaderHolder {
142: final static ClassLoader loader = ClassLoader
143: .getSystemClassLoader();
144: }
145:
146: }
|