1 8 9 package mx4j.tools.config; 10 11 import java.io.BufferedInputStream ; 12 import java.io.IOException ; 13 import java.io.InputStream ; 14 import java.io.InterruptedIOException ; 15 import java.lang.reflect.Constructor ; 16 import java.lang.reflect.InvocationTargetException ; 17 import java.lang.reflect.Method ; 18 import java.net.InetAddress ; 19 import java.net.ServerSocket ; 20 import java.net.Socket ; 21 import java.util.ArrayList ; 22 import java.util.HashMap ; 23 import java.util.List ; 24 import java.util.Map ; 25 26 import javax.management.Attribute ; 27 import javax.management.MBeanServer ; 28 import javax.management.MalformedObjectNameException ; 29 import javax.management.ObjectName ; 30 31 import mx4j.log.Log; 32 import mx4j.log.Logger; 33 import org.w3c.dom.Element ; 34 import org.w3c.dom.NamedNodeMap ; 35 36 39 public class DefaultConfigurationBuilder implements ConfigurationBuilder 40 { 41 public static final String SHUTDOWN_COMMAND = "shutdown"; 42 public static final String RESTART_COMMAND = "restart"; 43 44 private static final String NULL = "null"; 45 46 public Node createConfigurationNode(Element node) throws ConfigurationException 47 { 48 String loweredName = node.getNodeName().toLowerCase(); 49 StringBuffer buffer = new StringBuffer (loweredName); 50 buffer.replace(0, 1, loweredName.substring(0, 1).toUpperCase()); 51 String className = getClass().getName() + "$" + buffer.toString(); 52 try 53 { 54 Logger logger = getLogger(); 55 if (logger.isEnabledFor(Logger.TRACE)) logger.trace("Creating configuration node " + className); 56 return (ConfigurationBuilder.Node)getClass().getClassLoader().loadClass(className).newInstance(); 57 } 58 catch (Exception x) 59 { 60 throw new ConfigurationException(x); 61 } 62 } 63 64 private static Logger getLogger() 65 { 66 return Log.getLogger(DefaultConfigurationBuilder.class.getName()); 67 } 68 69 public abstract static class AbstractNode implements Node 70 { 71 private String text; 72 private Node parent; 73 private List children; 74 75 public void setText(String text) 76 { 77 this.text = text; 78 } 79 80 public void setParent(Node parent) 81 { 82 this.parent = parent; 83 } 84 85 public void addChild(Node child) 86 { 87 if (children == null) children = new ArrayList (); 88 child.setParent(this); 89 children.add(child); 90 } 91 92 protected String getText() 93 { 94 return text; 95 } 96 97 public Node getParent() 98 { 99 return parent; 100 } 101 102 public List getChildren() 103 { 104 return children; 105 } 106 107 public void setAttributes(NamedNodeMap attributes) throws ConfigurationException 108 { 109 Logger logger = getLogger(); 110 for (int i = 0; i < attributes.getLength(); ++i) 111 { 112 org.w3c.dom.Node attribute = attributes.item(i); 113 String name = attribute.getNodeName(); 114 String value = attribute.getNodeValue(); 115 String setterName = "set" + name.substring(0, 1).toUpperCase() + name.substring(1); 116 try 117 { 118 if (logger.isEnabledFor(Logger.TRACE)) logger.trace("Calling " + setterName + " with " + value + " on " + this); 119 Method setter = getClass().getMethod(setterName, new Class []{String .class}); 120 setter.invoke(this, new java.lang.Object []{value}); 121 } 122 catch (InvocationTargetException x) 123 { 124 throw new ConfigurationException(x.getTargetException()); 125 } 126 catch (Exception x) 127 { 128 throw new ConfigurationException(x); 129 } 130 } 131 } 132 } 133 134 public static class Configuration extends AbstractNode implements ObjectsHolder, Runnable 135 { 136 private Map objects; 137 private int port = -1; 138 private MBeanServer server; 139 private Thread thread; 140 141 public void setPort(String portString) 142 { 143 this.port = Integer.parseInt(portString); 144 } 145 146 public java.lang.Object configure(MBeanServer server) throws ConfigurationException 147 { 148 if (server != null) 149 { 150 this.server = server; 151 return startup(server); 152 } 153 else 154 { 155 return shutdown(this.server); 156 } 157 } 158 159 private java.lang.Object startup(MBeanServer server) throws ConfigurationException 160 { 161 Logger logger = getLogger(); 162 List children = getChildren(); 163 if (children != null) 164 { 165 for (int i = 0; i < children.size(); ++i) 166 { 167 Node child = (Node)children.get(i); 168 if (child instanceof DefaultConfigurationBuilder.Startup) child.configure(server); 169 } 170 } 171 if (port > 0) 172 { 173 thread = new Thread (this, "Configuration Shutdown"); 174 if (logger.isEnabledFor(Logger.TRACE)) logger.trace("Starting " + thread.getName() + " Thread on port " + port); 175 thread.start(); 176 } 177 return null; 178 } 179 180 private java.lang.Object shutdown(MBeanServer server) throws ConfigurationException 181 { 182 Logger logger = getLogger(); 183 List children = getChildren(); 184 if (children != null) 185 { 186 for (int i = 0; i < children.size(); ++i) 187 { 188 Node child = (Node)children.get(i); 189 if (child instanceof DefaultConfigurationBuilder.Shutdown) child.configure(server); 190 } 191 } 192 if (port > 0) 193 { 194 if (logger.isEnabledFor(Logger.TRACE)) logger.trace("Stopping " + thread.getName() + " Thread on port " + port); 195 thread.interrupt(); 196 } 197 return null; 198 } 199 200 public void run() 201 { 202 Logger logger = getLogger(); 203 ServerSocket server = null; 204 try 205 { 206 if (logger.isEnabledFor(Logger.TRACE)) logger.trace("Started " + thread.getName() + " Thread on port " + port); 207 208 server = new ServerSocket (port, 50, InetAddress.getByName(null)); 209 server.setSoTimeout(1000); 210 211 byte[] buffer = new byte[64]; 212 StringBuffer command = new StringBuffer (); 213 while (!thread.isInterrupted()) 214 { 215 Socket client = null; 216 try 217 { 218 client = server.accept(); 219 } 220 catch (InterruptedIOException x) 221 { 222 continue; 223 } 224 if (logger.isEnabledFor(Logger.TRACE)) logger.trace("Client connected " + client); 225 InputStream is = new BufferedInputStream (client.getInputStream()); 226 227 command.setLength(0); 228 int read = -1; 229 while ((read = is.read(buffer)) >= 0) command.append(new String (buffer, 0, read)); 230 231 String cmd = command.toString(); 232 if (logger.isEnabledFor(Logger.TRACE)) logger.trace("Got command '" + cmd + "'"); 233 234 if (SHUTDOWN_COMMAND.equals(cmd)) 235 { 236 try 237 { 238 configure(null); 239 break; 240 } 241 catch (ConfigurationException x) 242 { 243 if (logger.isEnabledFor(Logger.WARN)) logger.warn("Bad configuration for shutdown", x); 244 } 245 } 246 } 247 } 248 catch (Exception x) 249 { 250 if (logger.isEnabledFor(Logger.INFO)) logger.info("Caught Exception in " + thread.getName() + " Thread, exiting", x); 251 } 252 finally 253 { 254 if (logger.isEnabledFor(Logger.TRACE)) logger.trace("Stopped " + thread.getName() + " Thread on port " + port); 255 try 256 { 257 if (server != null) server.close(); 258 } 259 catch (IOException x) 260 { 261 } 262 } 263 } 264 265 public java.lang.Object getObject(String key) 266 { 267 if (objects == null) return null; 268 return objects.get(key); 269 } 270 271 public java.lang.Object putObject(String key, java.lang.Object value) 272 { 273 if (objects == null) objects = new HashMap (); 274 return objects.put(key, value); 275 } 276 277 public boolean containsKey(String key) 278 { 279 if (objects == null) return false; 280 return objects.containsKey(key); 281 } 282 } 283 284 public static class Startup extends AbstractNode 285 { 286 public java.lang.Object configure(MBeanServer server) throws ConfigurationException 287 { 288 List children = getChildren(); 289 if (children != null) 290 { 291 for (int i = 0; i < children.size(); ++i) 292 { 293 Node child = (Node)children.get(i); 294 child.configure(server); 295 } 296 } 297 return null; 298 } 299 } 300 301 public static class Shutdown extends AbstractNode 302 { 303 public java.lang.Object configure(MBeanServer server) throws ConfigurationException 304 { 305 List children = getChildren(); 306 if (children != null) 307 { 308 for (int i = 0; i < children.size(); ++i) 309 { 310 Node child = (Node)children.get(i); 311 child.configure(server); 312 } 313 } 314 return null; 315 } 316 } 317 318 public static class Object extends AbstractNode 319 { 320 private String id; 321 322 public void setObjectid(String id) 323 { 324 this.id = id; 325 } 326 327 public String getObjectid() 328 { 329 return id; 330 } 331 332 public java.lang.Object configure(MBeanServer server) throws ConfigurationException 333 { 334 List children = getChildren(); 335 java.lang.Object result = null; 336 if (children != null && children.size() > 0) 337 { 338 Node child = (Node)children.get(0); 339 result = child.configure(server); 340 } 341 putObject(this, id, result); 342 return result; 343 } 344 } 345 346 public static class New extends AbstractNode 347 { 348 private String classname; 349 350 public void setClassname(String classname) 351 { 352 this.classname = classname; 353 } 354 355 public java.lang.Object configure(MBeanServer server) throws ConfigurationException 356 { 357 try 358 { 359 Class cls = loadClass(classname); 360 Constructor ctor = cls.getConstructor(getMethodSignature(this)); 361 return ctor.newInstance(getMethodArguments(this, server)); 362 } 363 catch (InvocationTargetException x) 364 { 365 throw new ConfigurationException(x.getTargetException()); 366 } 367 catch (ConfigurationException x) 368 { 369 throw x; 370 } 371 catch (Exception x) 372 { 373 throw new ConfigurationException(x); 374 } 375 } 376 } 377 378 public static class Arg extends AbstractNode 379 { 380 private static final String OBJECT_TYPE = "object"; 381 private static final String STRING_TYPE = "string"; 382 private static final String BOOLEAN_TYPE = "boolean"; 383 private static final String BYTE_TYPE = "byte"; 384 private static final String CHAR_TYPE = "char"; 385 private static final String DOUBLE_TYPE = "double"; 386 private static final String FLOAT_TYPE = "float"; 387 private static final String INT_TYPE = "int"; 388 private static final String LONG_TYPE = "long"; 389 private static final String SHORT_TYPE = "short"; 390 391 private String type; 392 private String refobjectid; 393 394 public void setType(String type) 395 { 396 this.type = type; 397 } 398 399 public void setRefobjectid(String refobjectid) 400 { 401 this.refobjectid = refobjectid; 402 } 403 404 public Class getJavaType() throws ConfigurationException 405 { 406 if (STRING_TYPE.equalsIgnoreCase(type)) return String .class; 407 if (OBJECT_TYPE.equalsIgnoreCase(type)) return java.lang.Object .class; 408 if (BOOLEAN_TYPE.equalsIgnoreCase(type)) return boolean.class; 409 if (BYTE_TYPE.equalsIgnoreCase(type)) return byte.class; 410 if (CHAR_TYPE.equalsIgnoreCase(type)) return char.class; 411 if (DOUBLE_TYPE.equalsIgnoreCase(type)) return double.class; 412 if (FLOAT_TYPE.equalsIgnoreCase(type)) return float.class; 413 if (INT_TYPE.equalsIgnoreCase(type)) return int.class; 414 if (LONG_TYPE.equalsIgnoreCase(type)) return long.class; 415 if (SHORT_TYPE.equalsIgnoreCase(type)) return short.class; 416 return loadClass(type); 417 } 418 419 public java.lang.Object configure(MBeanServer server) throws ConfigurationException 420 { 421 if (refobjectid != null) return getObject(this, refobjectid); 422 423 List children = getChildren(); 424 if (children != null && children.size() > 0) 425 { 426 Node child = (Node)children.get(0); 427 return child.configure(server); 428 } 429 430 String text = getText(); 431 if (text == null || NULL.equals(text)) return null; 432 433 if (STRING_TYPE.equalsIgnoreCase(type)) return text; 434 if (OBJECT_TYPE.equalsIgnoreCase(type)) return text; 435 if (BOOLEAN_TYPE.equalsIgnoreCase(type)) return Boolean.valueOf(text); 436 if (BYTE_TYPE.equalsIgnoreCase(type)) return Byte.valueOf(text); 437 if (CHAR_TYPE.equalsIgnoreCase(type)) return new Character (text.length() < 1 ? 0 : text.charAt(0)); 438 if (DOUBLE_TYPE.equalsIgnoreCase(type)) return Double.valueOf(text); 439 if (FLOAT_TYPE.equalsIgnoreCase(type)) return Float.valueOf(text); 440 if (INT_TYPE.equalsIgnoreCase(type)) return Integer.valueOf(text); 441 if (LONG_TYPE.equalsIgnoreCase(type)) return Long.valueOf(text); 442 if (SHORT_TYPE.equalsIgnoreCase(type)) return Short.valueOf(text); 443 444 try 445 { 446 Constructor ctor = getJavaType().getConstructor(new Class []{String .class}); 447 return ctor.newInstance(new java.lang.Object []{text}); 448 } 449 catch (InvocationTargetException x) 450 { 451 throw new ConfigurationException(x.getTargetException()); 452 } 453 catch (ConfigurationException x) 454 { 455 throw x; 456 } 457 catch (Exception x) 458 { 459 throw new ConfigurationException(x); 460 } 461 } 462 } 463 464 public static class Register extends AbstractNode 465 { 466 private ObjectName objectname; 467 468 public void setObjectname(String name) throws MalformedObjectNameException 469 { 470 if (name != null && !NULL.equals(name)) this.objectname = ObjectName.getInstance(name); 471 } 472 473 public java.lang.Object configure(MBeanServer server) throws ConfigurationException 474 { 475 List children = getChildren(); 476 if (children != null && children.size() > 0) 477 { 478 Node child = (Node)children.get(0); 479 try 480 { 481 return server.registerMBean(child.configure(server), objectname); 482 } 483 catch (ConfigurationException x) 484 { 485 throw x; 486 } 487 catch (Exception x) 488 { 489 throw new ConfigurationException(x); 490 } 491 } 492 return null; 493 } 494 } 495 496 public static class Unregister extends AbstractNode 497 { 498 private ObjectName objectname; 499 500 public void setObjectname(String name) throws MalformedObjectNameException 501 { 502 this.objectname = ObjectName.getInstance(name); 503 } 504 505 public java.lang.Object configure(MBeanServer server) throws ConfigurationException 506 { 507 try 508 { 509 server.unregisterMBean(objectname); 510 return null; 511 } 512 catch (Exception x) 513 { 514 throw new ConfigurationException(x); 515 } 516 } 517 } 518 519 public static class Create extends AbstractNode 520 { 521 private String classname; 522 private ObjectName objectname; 523 private String loadername; 524 525 public void setClassname(String classname) 526 { 527 this.classname = classname; 528 } 529 530 public void setObjectname(String name) throws MalformedObjectNameException 531 { 532 if (name != null && !NULL.equals(name)) this.objectname = ObjectName.getInstance(name); 533 } 534 535 public void setLoadername(String name) throws MalformedObjectNameException 536 { 537 this.loadername = name; 538 } 539 540 public java.lang.Object configure(MBeanServer server) throws ConfigurationException 541 { 542 try 543 { 544 if (loadername != null) 545 { 546 ObjectName loader = null; 547 if (!NULL.equals(loadername)) loader = ObjectName.getInstance(loadername); 548 return server.createMBean(classname, objectname, loader, getMethodArguments(this, server), getJMXMethodSignature(this)); 549 } 550 else 551 { 552 return server.createMBean(classname, objectname, getMethodArguments(this, server), getJMXMethodSignature(this)); 553 } 554 } 555 catch (ConfigurationException x) 556 { 557 throw x; 558 } 559 catch (Exception x) 560 { 561 throw new ConfigurationException(x); 562 } 563 } 564 } 565 566 public static class Call extends AbstractNode 567 { 568 private String classname; 569 private ObjectName objectname; 570 private String refobjectid; 571 private String method; 572 private String operation; 573 private String attribute; 574 575 public void setClassname(String classname) 576 { 577 this.classname = classname; 578 } 579 580 public void setObjectname(String name) throws MalformedObjectNameException 581 { 582 if (name != null && !NULL.equals(name)) this.objectname = ObjectName.getInstance(name); 583 } 584 585 public void setRefobjectid(String refid) 586 { 587 this.refobjectid = refid; 588 } 589 590 public void setMethod(String method) 591 { 592 this.method = method; 593 } 594 595 public void setOperation(String operation) 596 { 597 this.operation = operation; 598 } 599 600 public void setAttribute(String attribute) 601 { 602 this.attribute = attribute; 603 } 604 605 public java.lang.Object configure(MBeanServer server) throws ConfigurationException 606 { 607 if (classname != null) 608 { 609 Class cls = loadClass(classname); 611 try 612 { 613 Method mthd = cls.getMethod(method, getMethodSignature(this)); 614 return mthd.invoke(null, getMethodArguments(this, server)); 615 } 616 catch (InvocationTargetException x) 617 { 618 throw new ConfigurationException(x.getTargetException()); 619 } 620 catch (ConfigurationException x) 621 { 622 throw x; 623 } 624 catch (Exception x) 625 { 626 throw new ConfigurationException(x); 627 } 628 } 629 else 630 { 631 if (objectname != null) 632 { 633 if (operation != null) 635 { 636 try 637 { 638 return server.invoke(objectname, operation, getMethodArguments(this, server), getJMXMethodSignature(this)); 639 } 640 catch (ConfigurationException x) 641 { 642 throw x; 643 } 644 catch (Exception x) 645 { 646 throw new ConfigurationException(x); 647 } 648 } 649 else if (attribute != null) 650 { 651 try 652 { 653 List children = getChildren(); 654 if (children == null || children.size() < 1) 655 { 656 return server.getAttribute(objectname, attribute); 657 } 658 else 659 { 660 java.lang.Object arg = getMethodArguments(this, server)[0]; 661 server.setAttribute(objectname, new Attribute (attribute, arg)); 662 return null; 663 } 664 } 665 catch (ConfigurationException x) 666 { 667 throw x; 668 } 669 catch (Exception x) 670 { 671 throw new ConfigurationException(x); 672 } 673 } 674 else 675 { 676 throw new ConfigurationException("Missing 'attribute' or 'operation' attribute in JMX call"); 677 } 678 } 679 else 680 { 681 java.lang.Object target = null; 683 if (refobjectid != null) 684 { 685 target = getObject(this, refobjectid); 686 if (target == null) throw new ConfigurationException("Could not find object with id " + refobjectid); 687 try 688 { 689 Method mthd = target.getClass().getMethod(method, getMethodSignature(this)); 690 return mthd.invoke(target, getMethodArguments(this, server)); 691 } 692 catch (InvocationTargetException x) 693 { 694 throw new ConfigurationException(x.getTargetException()); 695 } 696 catch (ConfigurationException x) 697 { 698 throw x; 699 } 700 catch (Exception x) 701 { 702 throw new ConfigurationException(x); 703 } 704 } 705 else 706 { 707 throw new ConfigurationException("Missing 'refobjectid' attribute in call element"); 708 } 709 } 710 } 711 } 712 } 713 714 private static Class [] getMethodSignature(Node node) throws ConfigurationException 715 { 716 List children = node.getChildren(); 717 if (children == null) return null; 718 ArrayList signature = new ArrayList (); 719 for (int i = 0; i < children.size(); ++i) 720 { 721 Node child = (Node)children.get(i); 722 if (child instanceof Arg) 723 { 724 Arg arg = (Arg)child; 725 signature.add(arg.getJavaType()); 726 } 727 } 728 return (Class [])signature.toArray(new Class [signature.size()]); 729 } 730 731 private static String [] getJMXMethodSignature(Node node) throws ConfigurationException 732 { 733 Class [] signature = getMethodSignature(node); 734 if (signature == null) return null; 735 736 ArrayList jmxSignature = new ArrayList (); 737 for (int i = 0; i < signature.length; ++i) 738 { 739 jmxSignature.add(signature[i].getName()); 740 } 741 return (String [])jmxSignature.toArray(new String [jmxSignature.size()]); 742 } 743 744 private static java.lang.Object [] getMethodArguments(Node node, MBeanServer server) throws ConfigurationException 745 { 746 List children = node.getChildren(); 747 if (children == null) return null; 748 ArrayList arguments = new ArrayList (); 749 for (int i = 0; i < children.size(); ++i) 750 { 751 Node child = (Node)children.get(i); 752 if (child instanceof Arg) 753 { 754 Arg arg = (Arg)child; 755 arguments.add(arg.configure(server)); 756 } 757 } 758 return arguments.toArray(); 759 } 760 761 private static Class loadClass(String className) throws ConfigurationException 762 { 763 try 764 { 765 return Thread.currentThread().getContextClassLoader().loadClass(className); 766 } 767 catch (ClassNotFoundException x) 768 { 769 throw new ConfigurationException(x); 770 } 771 } 772 773 private static java.lang.Object getObject(Node node, String key) 774 { 775 while (node != null) 776 { 777 if (node instanceof ObjectsHolder) 778 { 779 ObjectsHolder holder = (ObjectsHolder)node; 780 if (holder.containsKey(key)) return holder.getObject(key); 781 } 782 node = node.getParent(); 783 } 784 return null; 785 } 786 787 private static void putObject(Node node, String key, java.lang.Object value) 788 { 789 while (node != null) 790 { 791 if (node instanceof ObjectsHolder) 792 { 793 ObjectsHolder holder = (ObjectsHolder)node; 794 holder.putObject(key, value); 795 } 796 node = node.getParent(); 797 } 798 } 799 } 800 | Popular Tags |