1 4 package org.enhydra.util; 5 6 import java.util.Enumeration ; 7 import java.util.Hashtable ; 8 import java.util.Iterator ; 9 import java.util.StringTokenizer ; 10 import java.util.Vector ; 11 12 import javax.management.Attribute ; 13 import javax.management.AttributeChangeNotification ; 14 import javax.management.AttributeList ; 15 import javax.management.AttributeNotFoundException ; 16 import javax.management.DynamicMBean ; 17 import javax.management.InvalidAttributeValueException ; 18 import javax.management.MBeanAttributeInfo ; 19 import javax.management.MBeanConstructorInfo ; 20 import javax.management.MBeanException ; 21 import javax.management.MBeanInfo ; 22 import javax.management.MBeanNotificationInfo ; 23 import javax.management.MBeanOperationInfo ; 24 import javax.management.MBeanParameterInfo ; 25 import javax.management.Notification ; 26 import javax.management.NotificationBroadcasterSupport ; 27 import javax.management.ObjectName ; 28 import javax.management.ReflectionException ; 29 import javax.management.RuntimeOperationsException ; 30 31 import com.lutris.appserver.server.Application; 32 import com.lutris.logging.LogChannel; 33 import com.lutris.logging.Logger; 34 import com.lutris.util.Config; 35 import com.lutris.util.KeywordValueException; 36 37 import java.lang.reflect.Method ; 38 39 44 public abstract class EafConfigMBean extends NotificationBroadcasterSupport 45 implements DynamicMBean { 46 47 protected String dClassName = this.getClass().getName(); 48 protected MBeanInfo dMBeanInfo = null; 49 50 protected ObjectName objectName = null; 51 protected Hashtable hashAttrib = new Hashtable (); 52 protected Hashtable initHashAttrib = new Hashtable (); 53 54 protected Config config = null; 55 protected String prefix = null; 56 57 protected Vector addedAttributes = null; 58 59 public static String DOT = "_"; 60 61 protected long sequence = 0; 62 protected String noteTypesChange[] = { 63 "jmx.attribute.change" 64 }; 65 protected String noteTypesSave[] = { 66 "jmx.attribute.save" 67 }; 68 protected String noteTypesReset[] = { 69 "jmx.attribute.reset" 70 }; 71 protected String noteTypesAdd[] = { 72 "jmx.attribute.add" 73 }; 74 protected String noteTypesRemove[] = { 75 "jmx.attribute.remove" 76 }; 77 78 LogChannel logChannel = null; 79 80 protected Application application = null; 81 82 85 public EafConfigMBean() { 86 } 87 88 public EafConfigMBean(Application application, 89 ObjectName objectName, String prefix, String [] includes, String [] excludes) { 90 init(application,objectName,prefix,includes,excludes); 91 } 92 93 protected String toValidIdentifier (String value){ 94 return value.replaceAll(".",DOT); 95 } 96 97 protected String toOriginal (String value){ 98 return value.replaceAll(DOT,"."); 99 } 100 101 102 public void init(Application app, 103 ObjectName objectName, String prefix, String [] includes, String [] excludes) { 104 this.objectName = objectName; 105 this.prefix = prefix; 106 this.application = app; 107 108 if ("".equals(prefix)){ 109 prefix=null; 110 } 111 112 addedAttributes = new Vector (); 113 114 config = application.getConfig(); 115 logChannel = application.getLogChannel(); 116 117 Hashtable originalHashtable = null; 118 119 try{ 120 originalHashtable = config.allConfigParams(null); 121 }catch(KeywordValueException kwe){ 122 originalHashtable = new Hashtable (); 123 logChannel.write(Logger.DEBUG, kwe.toString()); 124 } 125 126 Hashtable includesHashtable = null; 127 Hashtable excludesHashtable = null; 128 129 if (includes!=null){ 130 includesHashtable = new Hashtable (); 131 int length = originalHashtable.size(); 132 Enumeration keys = originalHashtable.keys(); 133 for (int i = length-1; i >= 0; i--) { 134 String keyName = (String ) keys.nextElement(); 135 boolean include = false; 136 for (int j=0; j<includes.length;j++){ 137 if (keyName.startsWith(includes[j])){ 138 include = true; 139 } 140 } 141 if (include){ 142 includesHashtable.put(keyName, (String )originalHashtable.get(keyName)); 143 } 144 } 145 } else { 146 includesHashtable = originalHashtable; 147 } 148 149 if (excludes!=null){ 150 excludesHashtable = new Hashtable (); 151 int length = includesHashtable.size(); 152 Enumeration keys = includesHashtable.keys(); 153 for (int i = 0; i < length; i++) { 154 String keyName = (String ) keys.nextElement(); 155 boolean exclude = false; 156 for (int j=0; j<excludes.length;j++){ 157 if (keyName.startsWith(excludes[j])){ 158 exclude = true; 159 } 160 } 161 if (exclude){ 162 excludesHashtable.put(keyName,(String )includesHashtable.get(keyName)); 163 } 164 } 165 } else { 166 excludesHashtable = new Hashtable (); 167 } 168 169 int length = includesHashtable.size(); 170 Enumeration keys = includesHashtable.keys(); 171 for (int i = 0; i < length; i++) { 172 String keyName = (String ) keys.nextElement(); 173 174 if (!excludesHashtable.containsKey(keyName)){ 175 String keyValue = (String ) includesHashtable.get(keyName); 176 177 if (prefix!=null){ 178 keyName=keyName.substring(prefix.length()+1); 179 } 180 181 hashAttrib.put(keyName, keyValue); 182 initHashAttrib.put(keyName, keyValue); 183 } 184 } 185 } 187 188 189 190 public void buildDynamicMBeanInfo(){ 191 dMBeanInfo = new MBeanInfo (dClassName, getDescription(), 193 getMBeanAttributesInfo(), getMBeanConstructorInfo(), 194 getMBeanOperationsInfo(), getMBeanNotificationInfo()); 195 } 196 197 202 203 207 protected MBeanAttributeInfo [] getMBeanAttributesInfo () { 208 int length = hashAttrib.size(); 209 MBeanAttributeInfo [] dAttributes = new MBeanAttributeInfo [length]; 210 Enumeration keys = hashAttrib.keys(); 211 for (int i = 0; i < length; i++) { 212 String attName = (String ) keys.nextElement(); 213 String attDesc = new String (attName + " configuration parameter!"); 214 dAttributes[i] = new MBeanAttributeInfo (attName, "java.lang.String", 215 attDesc, true, true, false); 216 } 217 return dAttributes; 218 } 219 220 224 protected MBeanOperationInfo [] getMBeanOperationsInfo () { 225 MBeanParameterInfo [] params = null; 226 MBeanOperationInfo [] dOperations = new MBeanOperationInfo [5]; 227 dOperations[0] = new MBeanOperationInfo ("reset", 228 "reset(): reset attributes to their initial values", 229 params, "void", 230 MBeanOperationInfo.ACTION); 231 dOperations[1] = new MBeanOperationInfo ("saveAttributes", 232 "saveAttributes(): save the attribute values into the configuration file", 233 params, "void", 234 MBeanOperationInfo.ACTION); 235 dOperations[2] = new MBeanOperationInfo ("getAppInfo", 236 "getAppInfo(): get application information", 237 params, "String", 238 MBeanOperationInfo.ACTION); 239 240 params = new MBeanParameterInfo [2]; 241 params[0] = new MBeanParameterInfo ("attKey","java.lang.String","Attribute name! Please, " + 242 "use UNDERLINE (_) as attribute group separator."); 243 params[1] = new MBeanParameterInfo ("attValue","java.lang.String","Attribute value!"); 244 245 dOperations[3] = new MBeanOperationInfo ("addAttribute", 246 "addAttribute(String key, String value): add new application parameter", 247 params, "void", 248 MBeanOperationInfo.ACTION); 249 250 params = new MBeanParameterInfo [1]; 251 params[0] = new MBeanParameterInfo ("attKey","java.lang.String","Attribute name! Please, " + 252 "use UNDERLINE (_) as attribute group separator."); 253 254 dOperations[4] = new MBeanOperationInfo ("removeAttribute", 255 "removeAttribute(String key): remove application parameter", 256 params, "void", 257 MBeanOperationInfo.ACTION); 258 259 return dOperations; 260 } 261 262 266 protected MBeanNotificationInfo [] getMBeanNotificationInfo () { 267 MBeanNotificationInfo [] dNotifications = new MBeanNotificationInfo [5]; 268 dNotifications[0] = new MBeanNotificationInfo (noteTypesChange, 269 "javax.management.AttributeChangeNotification", 270 "Notifies listener of the attribute change"); 271 dNotifications[1] = new MBeanNotificationInfo (noteTypesSave, 272 "javax.management.Notification", 273 "Notifies listnere that attributes have been saved to the config file"); 274 dNotifications[2] = new MBeanNotificationInfo (noteTypesReset, 275 "javax.management.Notification", 276 "Notifies listnere that attributes have been reset to the initial value"); 277 dNotifications[3] = new MBeanNotificationInfo (noteTypesAdd, 278 "javax.management.Notification", 279 "Notifies listener of the attribute change"); 280 dNotifications[4] = new MBeanNotificationInfo (noteTypesRemove, 281 "javax.management.Notification", 282 "Notifies listener of the attribute change"); 283 284 return dNotifications; 285 } 286 287 291 protected MBeanConstructorInfo [] getMBeanConstructorInfo () { 292 MBeanParameterInfo [] dParameters = new MBeanParameterInfo [5]; 293 dParameters[0] = new MBeanParameterInfo ("application","com.lutris.appserver.server.Application","Application Object"); 294 dParameters[1] = new MBeanParameterInfo ("objectName","javax.management.ObjectName","MBean Name Object"); 295 dParameters[2] = new MBeanParameterInfo ("prefix","java.lang.String","Configuration Parameter Prefix"); 296 dParameters[3] = new MBeanParameterInfo ("includes","java.lang.reflect.Array","Array of internal parameter prefixes to include"); 297 dParameters[4] = new MBeanParameterInfo ("excludes","java.lang.reflect.Array","Array of internal parameter prefixes to exclude"); 298 299 MBeanConstructorInfo [] dConstructors = new MBeanConstructorInfo [1]; 300 dConstructors[0] = new MBeanConstructorInfo ("ConfigMBean", 301 "ConfigMBean Object Constructor", 302 dParameters); 303 304 return dConstructors; 305 } 306 307 311 protected String getDescription (){ 312 String dDescription = "Dynamic MBean manages application configuration"; 313 return dDescription; 314 } 315 316 321 322 325 public Object getAttribute(String attribute_name) throws 326 AttributeNotFoundException , 327 MBeanException , ReflectionException { 328 if (attribute_name == null) { 330 throw new RuntimeOperationsException (new IllegalArgumentException ( 331 "Attribute name cannot be null"), 332 "Cannot invoke a getter of " + dClassName + 333 " with null attribute name"); 334 } 335 try { 337 return hashAttrib.get(attribute_name); 338 } 339 catch (Exception e) { 340 throw (new AttributeNotFoundException ("Cannot find " + 342 attribute_name + " attribute in " + dClassName)); 343 } 344 } 345 346 349 public void setAttribute(Attribute attribute) throws 350 AttributeNotFoundException , 351 InvalidAttributeValueException , MBeanException , ReflectionException { 352 353 if (attribute == null) { 355 throw new RuntimeOperationsException (new IllegalArgumentException ( 356 "Attribute cannot be null"), 357 "Cannot invoke a setter of " + dClassName + 358 " with null attribute"); 359 } 360 361 String name = attribute.getName(); 362 String value = (String ) attribute.getValue(); 363 364 try { 365 373 374 String oldValue = (String ) hashAttrib.get(name); 375 376 hashAttrib.put(name, value); 377 378 String [] stringArray = null; 379 if (name.endsWith("_Array")) { 380 int len = name.length(); 381 name = name.substring(0, len-6); 382 StringTokenizer tok = new StringTokenizer (value, new String (",")); 383 stringArray = new String [tok.countTokens()]; 384 int i = 0; 385 while (tok.hasMoreTokens()) { 386 stringArray[i] = tok.nextToken().trim(); 387 i++; 388 } 389 390 try{ 391 if (prefix==null){ 392 config.set(toOriginal(name), stringArray); 393 config.getConfigFile().addEntry(toOriginal(name),stringArray,""); 394 } else { 395 config.set(toOriginal(prefix+DOT+name), stringArray); 396 config.getConfigFile().addEntry(toOriginal(prefix+DOT+name),stringArray,""); 397 } 398 } catch (Exception e) { 399 logChannel.write(Logger.DEBUG, e.toString()); 400 } 401 } 402 else { 403 try { 404 if (prefix==null){ 405 config.set(toOriginal(name), value); 406 config.getConfigFile().addEntry(toOriginal(name),value,""); 407 } else { 408 config.set(toOriginal(prefix+DOT+name), value); 409 config.getConfigFile().addEntry(toOriginal(prefix+DOT+name),value,""); 410 } 411 } catch (Exception e) { 412 logChannel.write(Logger.DEBUG, e.toString()); 413 } 414 } 415 416 String notificationString = "Attribute " + name + " has been set from " + oldValue + " to " + value; 417 Notification note = new AttributeChangeNotification (objectName, 418 ++sequence, 419 System.currentTimeMillis(), notificationString, name, "String", 420 oldValue, value); 421 sendNotification(note); 422 } 423 catch (Exception e) { 424 throw (new AttributeNotFoundException ("Cannot find " + name + 425 " attribute in " 426 + dClassName)); 427 } 428 } 429 430 434 public AttributeList setAttributes(AttributeList attributes) { 435 if (attributes == null) { 437 throw new RuntimeOperationsException (new IllegalArgumentException ( 438 "AttributeList attributes cannot be null"), 439 "Cannot invoke a setter of " + dClassName); 440 } 441 AttributeList resultList = new AttributeList (); 442 443 if (attributes.isEmpty()) { 445 return resultList; 446 } 447 448 for (Iterator i = attributes.iterator(); i.hasNext(); ) { 450 Attribute attr = (Attribute ) i.next(); 451 try { 452 setAttribute(attr); 453 String name = attr.getName(); 454 Object value = getAttribute(name); 455 resultList.add(new Attribute (name, value)); 456 } 457 catch (Exception e) { 458 logChannel.write(Logger.DEBUG, e.toString()); 459 } 460 } 461 return resultList; 462 } 463 464 467 public AttributeList getAttributes(String [] attributeNames) { 468 469 if (attributeNames == null) { 471 throw new RuntimeOperationsException (new IllegalArgumentException ( 472 "attributeNames[] cannot be null"), 473 "Cannot invoke a getter of " + dClassName); 474 } 475 476 AttributeList resultList = new AttributeList (); 477 478 if (attributeNames.length == 0) { 480 return resultList; 481 } 482 483 for (int i = 0; i < attributeNames.length; i++) { 485 try { 486 Object value = getAttribute((String )attributeNames[i]); 487 resultList.add(new Attribute (attributeNames[i], value)); 488 } 489 catch (Exception e) { 490 logChannel.write(Logger.DEBUG, e.toString()); 491 } 492 } 493 return resultList; 494 } 495 496 500 public MBeanInfo getMBeanInfo() { 501 return dMBeanInfo; 504 } 505 506 507 512 513 516 public void saveAttributes() { 517 try { 518 ConfigFileInterface configFile = config.getConfigFile(); 519 520 configFile.write(); 521 522 Notification note = new Notification (noteTypesSave[0], objectName, 523 ++sequence, 524 System.currentTimeMillis()); 525 sendNotification(note); 526 } catch (Exception e) { 527 logChannel.write(Logger.DEBUG, e.toString()); 528 } 529 } 530 531 534 public void addAttribute(String name, String value) { 535 try { 536 if (name!=null && value!=null){ 537 538 name = name.trim(); 539 540 boolean newOne = true; 541 String tempName = name; 542 if (tempName.endsWith("_Array")) { 543 int len = tempName.length(); 544 tempName = tempName.substring(0, len-6); 545 } 546 547 if (prefix==null && config.containsKey(toOriginal(tempName))){ 548 newOne = false; 549 } else if (config.containsKey(toOriginal(prefix+DOT+tempName))) { 550 newOne = false; 551 } 552 553 Attribute att = new Attribute (name, (String )value); 554 setAttribute(att); 555 556 if (newOne){ 557 addedAttributes.add(tempName); 558 } 559 560 buildDynamicMBeanInfo(); 561 562 Notification note = new Notification (noteTypesAdd[0], (NotificationBroadcasterSupport )this, 563 ++sequence, 564 System.currentTimeMillis()); 565 sendNotification(note); 566 } 567 } 568 catch (Exception e) { 569 logChannel.write(Logger.DEBUG, e.toString()); 570 } 571 } 572 573 576 public void reset() throws AttributeNotFoundException { 577 578 try { 579 int length = 0; 580 Enumeration keys = null; 581 582 length = initHashAttrib.size(); 584 keys = initHashAttrib.keys(); 585 hashAttrib.clear(); 586 for (int i = 0; i < length; i++) { 587 String keyName = (String ) keys.nextElement(); 588 String keyValue = (String ) initHashAttrib.get(keyName); 589 hashAttrib.put(keyName,keyValue); 590 } 591 592 length = hashAttrib.size(); 593 keys = hashAttrib.keys(); 594 595 for (int i = 0; i < length; i++) { 597 String keyName = (String ) keys.nextElement(); 598 String keyValue = (String ) hashAttrib.get(keyName); 599 600 if (keyName.endsWith("_Array")) { 601 int len = keyName.length(); 602 keyName = keyName.substring(0, len-6); 603 StringTokenizer tok = new StringTokenizer (keyValue, new String (",")); 604 String [] stringArray = new String [tok.countTokens()]; 605 int j = 0; 606 while (tok.hasMoreTokens()) { 607 stringArray[j] = tok.nextToken().trim(); 608 j++; 609 } 610 611 try{ 612 if (prefix==null){ 613 config.set(toOriginal(keyName), stringArray); 614 config.getConfigFile().addEntry(toOriginal(keyName),stringArray,""); 615 } else { 616 config.set(toOriginal(prefix+DOT+keyName), stringArray); 617 config.getConfigFile().addEntry(toOriginal(prefix+DOT+keyName),stringArray,""); 618 } 619 } catch (Exception e) { 620 logChannel.write(Logger.DEBUG, e.toString()); 621 } 622 } else { 623 try { 624 if (prefix==null){ 625 config.set(toOriginal(keyName), keyValue); 626 config.getConfigFile().addEntry(toOriginal(keyName),keyValue,""); 627 } else { 628 config.set(toOriginal(prefix+DOT+keyName), keyValue); 629 config.getConfigFile().addEntry(toOriginal(prefix+DOT+keyName),keyValue,""); 630 } 631 } catch (Exception e) { 632 logChannel.write(Logger.DEBUG, e.toString()); 633 } 634 } 635 636 } 637 638 length = addedAttributes.size(); 640 for (int i = 0; i < length; i++) { 641 String keyName = (String ) addedAttributes.elementAt(i); 642 if (!hashAttrib.contains(keyName)){ 643 if (prefix==null){ 644 config.remove(toOriginal(keyName)); 645 config.getConfigFile().removeEntry(toOriginal(keyName)); 646 } else { 647 config.remove(toOriginal(prefix+DOT+keyName)); 648 config.getConfigFile().removeEntry(toOriginal(prefix+DOT+keyName)); 649 } 650 } 651 } 652 addedAttributes.clear(); 653 } 654 catch (Exception e) { 655 logChannel.write(Logger.DEBUG, e.toString()); 656 } 657 658 buildDynamicMBeanInfo(); 659 Notification note = new Notification (noteTypesReset[0], objectName, 660 ++sequence, 661 System.currentTimeMillis()); 662 sendNotification(note); 663 } 664 665 670 public void removeAttribute(String name) { 671 try { 672 if (name!=null){ 673 name = name.trim(); 674 if (hashAttrib.containsKey(name)){ 675 hashAttrib.remove(name); 676 677 if (name.endsWith("_Array")) { 678 int len = name.length(); 679 name = name.substring(0, len-6); 680 } 681 682 if (prefix==null){ 683 config.remove(toOriginal(name)); 684 config.getConfigFile().removeEntry(toOriginal(name)); 685 } else { 686 config.remove(toOriginal(prefix+DOT+name)); 687 config.getConfigFile().removeEntry(toOriginal(prefix+DOT+name)); 688 } 689 690 buildDynamicMBeanInfo(); 691 692 Notification note = new Notification (noteTypesAdd[0], (NotificationBroadcasterSupport )this, 693 ++sequence, 694 System.currentTimeMillis()); 695 sendNotification(note); 696 } 697 } 698 } 699 catch (Exception e) { 700 logChannel.write(Logger.DEBUG, e.toString()); 701 } 702 } 703 704 707 public Object invoke(String operationName, Object params[], 708 String signature[]) throws MBeanException , 709 ReflectionException { 710 if (operationName == null) { 712 throw new RuntimeOperationsException (new IllegalArgumentException ( 713 "Operation name cannot be null"), 714 "Cannot invoke a null operation in " + dClassName); 715 } 716 if (operationName.equals("reset")) { 718 try { 719 reset(); 720 } 721 catch (Exception e) { 722 throw new MBeanException (e); 723 } 724 return null; 725 } 726 else if (operationName.equals("saveAttributes")) { 727 saveAttributes(); 728 return null; 729 } else if (operationName.equals("addAttribute")) { 730 if (params!=null && params.length==2){ 731 addAttribute((String )params[0],(String )params[1]); 732 } 733 return null; 734 } else if (operationName.equals("removeAttribute")) { 735 if (params!=null && params.length==1){ 736 removeAttribute((String )params[0]); 737 } 738 return null; 739 } else if (operationName.equals("getAppInfo")) { 740 return getAppInfo(); 741 }else { 742 throw new ReflectionException (new NoSuchMethodException (operationName), 744 "Cannot find the operation " + 745 operationName + " in " + dClassName); 746 } 747 } 748 749 public String getAppInfo() { 750 String appInfo = null; 751 Class appClass = application.getClass(); 752 try { 753 Method toHtmlMethod = appClass.getMethod("toHtml", null); 754 appInfo = (String )toHtmlMethod.invoke(application, null); 755 }catch (Exception exc){ 756 appInfo = application.toString(); 757 } 758 return appInfo; 759 } 760 761 } 762 | Popular Tags |