001: // $Id: ClassConfigurator.java,v 1.20 2006/09/11 13:54:42 belaban Exp $
002:
003: package org.jgroups.conf;
004:
005: import org.apache.commons.logging.Log;
006: import org.apache.commons.logging.LogFactory;
007: import org.jgroups.ChannelException;
008: import org.jgroups.Global;
009: import org.jgroups.util.Util;
010:
011: import java.io.ObjectStreamClass;
012: import java.util.*;
013:
014: /**
015: * This class will be replaced with the class that read info
016: * from the magic number configurator that reads info from the xml file.
017: * The name and the relative path of the magic number map file can be specified
018: * as value of the property <code>org.jgroups.conf.magicNumberFile</code>.
019: * It must be relative to one of the classpath elements, to allow the
020: * classloader to locate the file. If a value is not specified,
021: * <code>MagicNumberReader.MAGIC_NUMBER_FILE</code> is used, which defaults
022: * to "jg-magic-map.xml".
023: *
024: * @author Filip Hanik
025: * @author Bela Ban
026: * @see MagicNumberReader
027: */
028: public class ClassConfigurator {
029: static volatile ClassConfigurator instance = null; // works under the new JSR 133 memory model in JDK 5
030:
031: //this is where we store magic numbers
032: private final Map classMap = new HashMap(); // key=Class, value=magic number
033: private final Map magicMap = new HashMap(); // key=magic number, value=Class
034:
035: /** Map<Integer,ObjectStreamClass> */
036: private final Map streamMapId = new HashMap();
037:
038: /** Map<ObjectStreamClass, Integer> */
039: private final Map streamMapClass = new HashMap();
040:
041: protected final Log log = LogFactory.getLog(getClass());
042:
043: private ClassConfigurator() {
044: }
045:
046: public void init() throws ChannelException {
047: //populate the map
048: try {
049: // make sure we have a class for DocumentBuilderFactory
050: // getClass().getClassLoader().loadClass("javax.xml.parsers.DocumentBuilderFactory");
051: Util.loadClass("javax.xml.parsers.DocumentBuilderFactory",
052: this .getClass());
053:
054: MagicNumberReader reader = new MagicNumberReader();
055:
056: // PropertyPermission not granted if running in an untrusted environment with JNLP.
057: try {
058: String mnfile = Util.getProperty(new String[] {
059: Global.MAGIC_NUMBER_FILE,
060: "org.jgroups.conf.magicNumberFile" }, null,
061: null, false, null);
062: if (mnfile != null) {
063: if (log.isDebugEnabled())
064: log.debug("Using " + mnfile
065: + " as magic number file");
066: reader.setFilename(mnfile);
067: }
068: } catch (SecurityException ex) {
069: }
070:
071: ObjectStreamClass objStreamClass;
072: ClassMap[] mapping = reader.readMagicNumberMapping();
073: if (mapping != null) {
074: Integer m;
075: for (int i = 0; i < mapping.length; i++) {
076: m = new Integer(mapping[i].getMagicNumber());
077: try {
078: Class clazz = mapping[i].getClassForMap();
079: objStreamClass = ObjectStreamClass
080: .lookup(clazz);
081: if (objStreamClass == null)
082: throw new ChannelException(
083: "ObjectStreamClass for " + clazz
084: + " not found");
085: if (magicMap.containsKey(m)) {
086: throw new ChannelException(
087: "magic key "
088: + m
089: + " ("
090: + clazz.getName()
091: + ')'
092: + " is already in map; please make sure that "
093: + "all magic keys are unique");
094: } else {
095: magicMap.put(m, clazz);
096: classMap.put(clazz, m);
097:
098: streamMapId.put(m, objStreamClass);
099: streamMapClass.put(objStreamClass, m);
100: }
101: } catch (ClassNotFoundException cnf) {
102: throw new ChannelException(
103: "failed loading class", cnf);
104: }
105: }
106: if (log.isDebugEnabled())
107: log.debug("mapping is:\n" + printMagicMap());
108: }
109: } catch (ChannelException ex) {
110: throw ex;
111: } catch (Throwable x) {
112: // if(log.isErrorEnabled()) log.error("failed reading the magic number mapping file, reason: " + Util.print(x));
113: throw new ChannelException(
114: "failed reading the magic number mapping file", x);
115: }
116: }
117:
118: public static ClassConfigurator getInstance(boolean init)
119: throws ChannelException {
120: if (instance == null) {
121: instance = new ClassConfigurator();
122: if (init)
123: instance.init();
124: }
125: return instance;
126: }
127:
128: /**
129: * Returns a class for a magic number.
130: * Returns null if no class is found
131: *
132: * @param magic the magic number that maps to the class
133: * @return a Class object that represents a class that implements java.io.Externalizable
134: */
135: public Class get(int magic) {
136: return (Class) magicMap.get(new Integer(magic));
137: }
138:
139: /**
140: * Loads and returns the class from the class name
141: *
142: * @param clazzname a fully classified class name to be loaded
143: * @return a Class object that represents a class that implements java.io.Externalizable
144: */
145: public Class get(String clazzname) {
146: try {
147: // return ClassConfigurator.class.getClassLoader().loadClass(clazzname);
148: return Util.loadClass(clazzname, this .getClass());
149: } catch (Exception x) {
150: if (log.isErrorEnabled())
151: log.error("failed loading class " + clazzname, x);
152: }
153: return null;
154: }
155:
156: /**
157: * Returns the magic number for the class.
158: *
159: * @param clazz a class object that we want the magic number for
160: * @return the magic number for a class, -1 if no mapping is available
161: */
162: public int getMagicNumber(Class clazz) {
163: Integer i = (Integer) classMap.get(clazz);
164: if (i == null)
165: return -1;
166: else
167: return i.intValue();
168: }
169:
170: public int getMagicNumberFromObjectStreamClass(
171: ObjectStreamClass objStream) {
172: Integer i = (Integer) streamMapClass.get(objStream);
173: if (i == null)
174: return -1;
175: else
176: return i.intValue();
177: }
178:
179: public ObjectStreamClass getObjectStreamClassFromMagicNumber(
180: int magic_number) {
181: ObjectStreamClass retval = null;
182: retval = (ObjectStreamClass) streamMapId.get(new Integer(
183: magic_number));
184: return retval;
185: }
186:
187: public String toString() {
188: return printMagicMap();
189: }
190:
191: public String printMagicMap() {
192: StringBuffer sb = new StringBuffer();
193: Integer key;
194: SortedSet keys = new TreeSet(magicMap.keySet());
195:
196: for (Iterator it = keys.iterator(); it.hasNext();) {
197: key = (Integer) it.next();
198: sb.append(key).append(":\t").append(magicMap.get(key))
199: .append('\n');
200: }
201: return sb.toString();
202: }
203:
204: public String printClassMap() {
205: StringBuffer sb = new StringBuffer();
206: Map.Entry entry;
207:
208: for (Iterator it = classMap.entrySet().iterator(); it.hasNext();) {
209: entry = (Map.Entry) it.next();
210: sb.append(entry.getKey()).append(": ").append(
211: entry.getValue()).append('\n');
212: }
213: return sb.toString();
214: }
215:
216: /* --------------------------------- Private methods ------------------------------------ */
217:
218: /* ------------------------------ End of Pivate methods --------------------------------- */
219: public static void main(String[] args) throws Exception {
220:
221: ClassConfigurator test = getInstance(true);
222: System.out.println('\n' + test.printMagicMap());
223: }
224: }
|