001: /**
002: * The XMOJO Project 5
003: * Copyright © 2003 XMOJO.org. All rights reserved.
004:
005: * NO WARRANTY
006:
007: * BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR
008: * THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
009: * OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
010: * PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
011: * OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
012: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
013: * TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE
014: * LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
015: * REPAIR OR CORRECTION.
016:
017: * IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL
018: * ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE
019: * THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
020: * GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
021: * USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF
022: * DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
023: * PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE),
024: * EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
025: * SUCH DAMAGES.
026: **/package com.adventnet.jmx;
027:
028: import java.io.File;
029: import java.io.FileInputStream;
030: import java.util.Hashtable;
031:
032: import com.adventnet.agent.logging.Log;
033: import com.adventnet.agent.logging.LogFactory;
034:
035: /**
036: * A simple test class loader capable of loading from multiple sources,
037: * such as local files or a URL. Must be subclassed and the abstract method
038: * loadClassBytes() implemented to provide the preferred source.
039: *
040: */
041: public class DefaultClassLoader extends ClassLoader {
042: //---------- Fields --------------------------------------
043: private Hashtable classes = new Hashtable();
044: private char classNameReplacementChar;
045:
046: protected boolean monitorOn = false;
047: protected boolean sourceMonitorOn = true;
048:
049: private String filePrefix = File.separator;
050: private Log log = null;
051:
052: //---------- Initialization ------------------------------
053: public DefaultClassLoader() {
054: try {
055: log = LogFactory.getInstance("JMX");
056: } catch (Exception e) {
057: e.printStackTrace();
058: }
059: }
060:
061: //---------- Public Methods ------------------------------
062:
063: //---------- Superclass Overrides ------------------------
064:
065: /**
066: * This is a simple version for external clients since they
067: * will always want the class resolved before it is returned
068: * to them.
069: */
070: public Class loadClass(String className)
071: throws ClassNotFoundException {
072: return (loadClass(className, true));
073: }
074:
075: //---------- Abstract Implementation ---------------------
076: public synchronized Class loadClass(String className,
077: boolean resolveIt) throws ClassNotFoundException {
078: Class result;
079: byte[] classBytes;
080:
081: //----- Check our local cache of classes
082: result = (Class) classes.get(className);
083: if (result != null) {
084: return result;
085: }
086:
087: //----- Check with the primordial class loader
088: try {
089: result = super .findSystemClass(className);
090:
091: return result;
092: } catch (ClassNotFoundException e) {
093: log.debug(">> Not a system class.");
094: }
095:
096: //----- Try to load it from preferred source
097: // Note loadClassBytes() is an abstract method
098: classBytes = loadClassBytes(className);
099:
100: if (classBytes == null) {
101: throw new ClassNotFoundException();
102: }
103:
104: //----- Define it (parse the class file)
105: result = defineClass(null, classBytes, 0, classBytes.length);
106: if (result == null) {
107: throw new ClassFormatError();
108: }
109:
110: //----- Resolve if necessary
111: if (resolveIt)
112: resolveClass(result);
113:
114: // Done
115: classes.put(className, result);
116: log.debug(">> Returning newly loaded class.");
117:
118: return result;
119: }
120:
121: /**
122: * This optional call allows a class name such as "COM.test.Hello" to be
123: * changed to "COM_test_Hello", which is useful for storing classes from
124: * different packages in the same retrival directory.
125: * In the above example the char would be '_'.
126: */
127: public void setClassNameReplacementChar(char replacement) {
128: classNameReplacementChar = replacement;
129: }
130:
131: private byte[] loadClassBytes(String className) {
132: className = formatClassName(className);
133:
134: byte result[];
135: String fileName = filePrefix + className;
136: //String fileName = className;
137:
138: try {
139: FileInputStream inStream = new FileInputStream(fileName);
140:
141: result = new byte[inStream.available()];
142: inStream.read(result);
143: inStream.close();
144:
145: return result;
146: } catch (Exception e) {
147: // If we caught an exception, either the class
148: // wasn't found or it was unreadable by our process.
149: log.debug("loadClassBytes", e);
150: return null;
151: }
152: }
153:
154: protected String formatClassName(String className) {
155: if (classNameReplacementChar == '\u0000') {
156: // '/' is used to map the package to the path
157: return className.replace('.', '/') + ".class";
158: } else {
159: // Replace '.' with custom char, such as '_'
160: return className.replace('.', classNameReplacementChar)
161: + ".class";
162: }
163: }
164: } // End class
|