001: /* JFox, the OpenSource J2EE Application Server
002: *
003: * Copyright (C) 2002 huihoo.com
004: * Distributable under GNU LGPL license
005: * See the GNU Lesser General Public License for more details.
006: */
007:
008: package org.huihoo.jfox.xmlet;
009:
010: import java.io.File;
011: import java.io.InputStream;
012: import java.util.List;
013: import java.util.Set;
014: import java.util.Arrays;
015: import java.util.HashSet;
016: import java.util.Iterator;
017: import java.util.ArrayList;
018: import java.net.URLClassLoader;
019: import java.net.URL;
020: import java.net.URLStreamHandlerFactory;
021: import java.net.MalformedURLException;
022:
023: import javax.xml.bind.JAXBContext;
024: import javax.xml.bind.Unmarshaller;
025: import javax.xml.bind.JAXBException;
026: import javax.management.loading.ClassLoaderRepository;
027: import javax.management.MBeanRegistration;
028: import javax.management.MBeanServer;
029: import javax.management.ObjectName;
030: import javax.management.MBeanServerFactory;
031: import javax.management.ServiceNotFoundException;
032: import javax.management.JMRuntimeException;
033: import javax.management.ObjectInstance;
034: import javax.management.Attribute;
035:
036: import org.huihoo.jfox.jmx.loading.PrimitiveClassLoader;
037: import org.huihoo.jfox.jmx.loading.MLetException;
038: import org.huihoo.jfox.jmx.loading.ObjectInputStreamLoader;
039: import org.huihoo.jfox.xmlet.jaxb.XMLetType;
040: import org.huihoo.jfox.xmlet.jaxb.XMLetsType;
041: import org.huihoo.jfox.xmlet.jaxb.ArgType;
042: import org.huihoo.jfox.xmlet.jaxb.AttrType;
043:
044: /**
045: *
046: * @author <a href="mailto:young_yy@hotmail.com">Young Yang</a>
047: */
048:
049: public class XMLet extends URLClassLoader implements XMLetMBean,
050: MBeanRegistration {
051:
052: private String liberaryDirectory = System.getProperty("user.dir");
053:
054: protected MBeanServer server = null;
055: private ObjectName objectName = null;
056: private ClassLoaderRepository clrepo = null;
057:
058: protected PrimitiveClassLoader paramLoader = PrimitiveClassLoader
059: .getInstance();
060:
061: public XMLet() {
062: this (new URL[0]);
063: }
064:
065: public XMLet(URL[] urls) {
066: super (urls);
067: }
068:
069: public XMLet(URL[] urls, ClassLoader parent) {
070: super (urls, parent);
071: }
072:
073: public XMLet(URL[] urls, ClassLoader parent,
074: URLStreamHandlerFactory factory) {
075: super (urls, parent, factory);
076: }
077:
078: public ObjectName preRegister(MBeanServer server, ObjectName objName)
079: throws Exception {
080: this .server = server;
081: if (objName == null)
082: objName = new ObjectName(server.getDefaultDomain() + ":"
083: + "service=" + this .toString());
084: this .objectName = objName;
085: clrepo = MBeanServerFactory.getClassLoaderRepository(server);
086: return objectName;
087: }
088:
089: public void postRegister(Boolean success) {
090: if (!success.booleanValue())
091: server = null;
092: }
093:
094: public void preDeregister() throws Exception {
095:
096: }
097:
098: public void postDeregister() {
099:
100: }
101:
102: public Set getMBeansFromURL(URL url)
103: throws ServiceNotFoundException {
104: if (server == null)
105: throw new IllegalStateException(
106: "This MLet MBean is not registered with an MBeanServer.");
107: if (url == null)
108: throw new ServiceNotFoundException(
109: "Can not load MBeans from null URL");
110: Set mbeanInstances = new HashSet();
111: String urlString = url.toString();
112: String defaultCodeBase = urlString.substring(0, urlString
113: .lastIndexOf('/') + 1);
114: try {
115: Iterator mlets = this .parse(url);
116: while (mlets.hasNext()) {
117: XMLetType mlet = (XMLetType) mlets.next();
118: URL[] urls = this .getMLetURLs(mlet, defaultCodeBase);
119: for (int i = 0; i < urls.length; i++) {
120: this .addURL(urls[i]);
121: }
122: ObjectInstance oi = createMBean(mlet);
123:
124: setAttributes(mlet);
125:
126: // not support operation now
127: // invokeOperations(mlet);
128:
129: mbeanInstances.add(oi);
130:
131: }
132:
133: } catch (MLetException e) {
134: e.printStackTrace();
135: throw new JMRuntimeException(e.getMessage());
136: }
137: return mbeanInstances;
138: }
139:
140: public Set getMBeansFromURL(String url)
141: throws ServiceNotFoundException {
142: try {
143: URL urlObj = new URL(url);
144: return this .getMBeansFromURL(urlObj);
145: } catch (MalformedURLException e) {
146: throw new ServiceNotFoundException(
147: "The specified URL is malformed");
148: }
149:
150: }
151:
152: public void addURL(URL url) {
153: if (!Arrays.asList(getURLs()).contains(url))
154: super .addURL(url);
155: }
156:
157: public void addURL(String url) throws ServiceNotFoundException {
158: try {
159: URL urlObj = new URL(url);
160: this .addURL(urlObj);
161: } catch (MalformedURLException e) {
162: throw new ServiceNotFoundException(
163: "The specified URL is malformed");
164: }
165:
166: }
167:
168: public String getLibraryDirectory() {
169: return liberaryDirectory;
170: }
171:
172: public void setLibraryDirectory(String dir) {
173: liberaryDirectory = dir;
174: }
175:
176: public Class loadClass(String name) throws ClassNotFoundException {
177: Class cla = null;
178: try {
179: cla = super .loadClass(name);
180: } catch (ClassNotFoundException e) {
181: try {
182: clrepo.loadClassWithout(this , name);
183: } catch (ClassNotFoundException ex) {
184: throw ex;
185: }
186: }
187: return cla;
188: }
189:
190: /**
191: * 用 jaxb 把 XMLet Config 文件解析成 Java object
192: * @param url
193: * @return
194: * @throws MLetException
195: */
196: private Iterator parse(URL url) throws MLetException {
197: try {
198: JAXBContext jcontect = JAXBContext.newInstance(getClass()
199: .getPackage().getName()
200: + ".jaxb");
201: Unmarshaller unmarshaller = jcontect.createUnmarshaller();
202: unmarshaller.setValidating(true);
203: XMLetsType _mlets = (XMLetsType) unmarshaller
204: .unmarshal(url);
205: List mlets = _mlets.getXMLET();
206: for (int i = 0; i < mlets.size(); i++) {
207: XMLetType mlet = (XMLetType) mlets.get(i);
208: checkMLet(mlet);
209: }
210: return mlets.iterator();
211: } catch (JAXBException e) {
212: e.printStackTrace();
213: throw new MLetException(e.getMessage());
214: }
215: }
216:
217: /**
218: * 必须要设置 NAME, ARCHIVE 可以不设
219: * @param mlet
220: * @throws MLetException
221: */
222: private static void checkMLet(XMLetType mlet) throws MLetException {
223: if (mlet.getNAME() == null) {
224: throw new MLetException(
225: "The MLet NAME attribute must be set");
226: }
227:
228: if (mlet.getCODE() == null && mlet.getOBJECT() == null) {
229: throw new MLetException(
230: "The MLet CODE attribute and OBJECT must be set either");
231: }
232:
233: if (mlet.getCODE() != null && mlet.getOBJECT() != null) {
234: throw new MLetException(
235: "The MLet CODE attribute and OBJECT must only be set one");
236: }
237: }
238:
239: /**
240: * get the jar urls, so can add it the the classloader path
241: */
242: private URL[] getMLetURLs(XMLetType mlet, String defaultCodeBase) {
243: List urls = new ArrayList();
244: String codeBase = mlet.getCODEBASE();
245: codeBase = codeBase == null ? defaultCodeBase : defaultCodeBase
246: + codeBase;
247: if (!codeBase.endsWith("/"))
248: codeBase += "/";
249: String archive = mlet.getARCHIVE(); // maybe "a.jar,b.jar"
250:
251: // xmlet 中,ARCHIVE 可以不设置
252: if (archive == null)
253: return new URL[0];
254:
255: String[] archives = decompoundArchive(archive);
256:
257: for (int i = 0; i < archives.length; i++) {
258: String arch = archives[i];
259: if (!arch.startsWith("/"))
260: arch = codeBase + arch;
261: URL url = null;
262: try {
263: url = new URL(arch);
264: } catch (MalformedURLException e) {
265: // maybe cause by not specified the file:/ protocal
266: File file = new File(arch);
267: try {
268: if (file.exists())
269: url = file.toURL();
270: } catch (Exception ignore) {
271: ignore.printStackTrace();
272: }
273: }
274: if (url != null)
275: urls.add(url);
276: }
277: return (URL[]) urls.toArray(new URL[0]);
278: }
279:
280: // decompound multi archives "a.jar,b.jar" to array
281: private static String[] decompoundArchive(String archive) {
282: List archives = new ArrayList();
283: int start = 0;
284: int commaIndex = -1;
285: int pointer = -1;
286:
287: while ((pointer = archive.indexOf(",", start)) > 0) { // find comma
288: archives.add(archive.substring(start, pointer).trim());
289: commaIndex = pointer;
290: start = pointer + 1;
291: }
292: if (commaIndex == -1) { // not found comma
293: archives.add(archive);
294: } else {
295: archives.add(archive.substring(commaIndex + 1).trim());
296: }
297: return (String[]) archives.toArray(new String[0]);
298: }
299:
300: /**
301: * doCreate a MBean by the offered mlet
302: *
303: * @param mlet
304: * @return ObjectInstance of the created MBean
305: */
306: protected ObjectInstance createMBean(XMLetType mlet) {
307: ObjectInstance instance = null;
308: Object mbean = null;
309: String className = mlet.getCODE();
310: try {
311: if (className != null) { // specified classname
312:
313: XMLetType.ARGUMENTSType argsType = mlet.getARGUMENTS();
314: // System.out.println("Arguments: " + argsType);
315: if (argsType == null) {
316: mbean = server.instantiate(className, objectName);
317: } else {
318: List args = argsType.getARG();
319: Object[] params = new Object[args.size()];
320: String[] signatures = new String[args.size()];
321: for (int i = 0; i < args.size(); i++) {
322: ArgType arg = (ArgType) args.get(i);
323: // doCreate param object
324: signatures[i] = arg.getTYPE();
325: params[i] = paramLoader.createObject(arg
326: .getVALUE(), signatures[i]);
327: }
328:
329: mbean = server.instantiate(className, objectName,
330: params, signatures);
331: }
332: } else { // must specified the serialized object
333: String serFile = mlet.getOBJECT();
334: InputStream is = getResourceAsStream(serFile);
335: if (is == null)
336: throw new ServiceNotFoundException(
337: "Cannot find MBean " + serFile
338: + " in this ClassLoader classpath");
339: ObjectInputStreamLoader loader = new ObjectInputStreamLoader(
340: is, this );
341: mbean = loader.readObject();
342:
343: }
344: ObjectName objName = null;
345: // if objName is null,the mbean must implements MBeanRegistry,provide the DEFAULT_OBJECTNAME bye preRegister
346: String oname = mlet.getNAME();
347: if (oname != null && oname.trim().length() != 0)
348: objName = new ObjectName(oname);
349: instance = server.registerMBean(mbean, objName);
350: } catch (Exception e) {
351: e.printStackTrace();
352: }
353:
354: return instance;
355: }
356:
357: private void setAttributes(XMLetType mlet) {
358: String _objectName = mlet.getNAME();
359: XMLetType.ATTRIBUTESType attrsType = mlet.getATTRIBUTES();
360: if (attrsType == null)
361: return;
362:
363: List attrs = attrsType.getATTR();
364: for (int i = 0; i < attrs.size(); i++) {
365: AttrType attr = (AttrType) attrs.get(i);
366: setAttribute(_objectName, attr);
367: }
368:
369: }
370:
371: private void setAttribute(String on, AttrType attr) {
372: try {
373: ObjectName objectName = new ObjectName(on);
374: String attributeName = attr.getNAME();
375: String attributeType = attr.getTYPE();
376: String attributeValue = attr.getVALUE();
377:
378: Class attrClass = null;
379: attrClass = Class.forName(attributeType);
380: Object value = attrClass.getConstructor(
381: new Class[] { java.lang.String.class })
382: .newInstance(new Object[] { attributeValue });
383: Attribute attribute = new Attribute(attributeName, value);
384: server.setAttribute(objectName, attribute);
385: } catch (Exception e) {
386: e.printStackTrace();
387: }
388: }
389:
390: public static void main(String[] args) throws Exception {
391: JAXBContext jcontect = JAXBContext.newInstance(XMLet.class
392: .getPackage().getName()
393: + ".jaxb");
394: Unmarshaller unmarshaller = jcontect.createUnmarshaller();
395: unmarshaller.setValidating(true);
396: XMLetsType _mlets = (XMLetsType) unmarshaller
397: .unmarshal(new File("conf/xmlet.xml"));
398: List mlets = _mlets.getXMLET();
399: for (int i = 0; i < mlets.size(); i++) {
400: XMLetType mlet = (XMLetType) mlets.get(i);
401: System.out.println(mlet.getNAME());
402:
403: XMLetType.ARGUMENTSType arggs = mlet.getARGUMENTS();
404:
405: if (arggs != null) {
406: List li = arggs.getARG();
407: for (int j = 0; j < li.size(); j++) {
408: ArgType arg = (ArgType) li.get(j);
409: System.out.print(arg.getTYPE() + ": ");
410: System.out.println(arg.getVALUE());
411: }
412: }
413: }
414: }
415: }
|