1 /*
   2  * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /*
  25  * @test
  26  * @bug 6222961
  27  * @summary Test that the counter/gauge/string monitors
  28  *          support attributes of arbitrary data types.
  29  * @author Luis-Miguel Alventosa
  30  * @modules java.desktop
  31  *          java.management
  32  * @run clean AttributeArbitraryDataTypeTest
  33  * @run build AttributeArbitraryDataTypeTest
  34  * @run main AttributeArbitraryDataTypeTest
  35  */
  36 
  37 import java.beans.BeanInfo;
  38 import java.beans.IntrospectionException;
  39 import java.beans.PropertyDescriptor;
  40 import java.beans.SimpleBeanInfo;
  41 import java.lang.reflect.Array;
  42 import java.lang.reflect.InvocationTargetException;
  43 import javax.management.AttributeNotFoundException;
  44 import javax.management.MBeanServer;
  45 import javax.management.MBeanServerFactory;
  46 import javax.management.Notification;
  47 import javax.management.NotificationListener;
  48 import javax.management.ObjectName;
  49 import javax.management.monitor.CounterMonitor;
  50 import javax.management.monitor.GaugeMonitor;
  51 import javax.management.monitor.MonitorNotification;
  52 import javax.management.monitor.StringMonitor;
  53 import javax.management.openmbean.CompositeData;
  54 import javax.management.openmbean.CompositeDataSupport;
  55 import javax.management.openmbean.CompositeType;
  56 import javax.management.openmbean.OpenDataException;
  57 import javax.management.openmbean.OpenType;
  58 import javax.management.openmbean.SimpleType;
  59 
  60 public class AttributeArbitraryDataTypeTest implements NotificationListener {
  61 
  62     // Flag to notify that a message has been received
  63     private volatile boolean counterMessageReceived = false;
  64     private volatile boolean gaugeMessageReceived = false;
  65     private volatile boolean stringMessageReceived = false;
  66 
  67     // Match enum
  68     public enum Match { do_not_match_0,
  69                         do_not_match_1,
  70                         do_not_match_2,
  71                         do_match_now };
  72 
  73     // MatchBeanInfo class
  74     public static class MatchBeanInfo extends SimpleBeanInfo {
  75         public PropertyDescriptor[] getPropertyDescriptors() {
  76             try {
  77                 return new PropertyDescriptor[] {
  78                     new PropertyDescriptor("name", Match.class, "name", null) };
  79             } catch (IntrospectionException e ) {
  80                 e.printStackTrace();
  81                 return null;
  82             }
  83         }
  84     }
  85 
  86     // ComplexAttribute class
  87     public class ComplexAttribute {
  88 
  89         public Integer getIntegerAttribute() {
  90             return i;
  91         }
  92 
  93         public void setIntegerAttribute(Integer i) {
  94             this.i = i;
  95         }
  96 
  97         public Double getDoubleAttribute() {
  98             return d;
  99         }
 100 
 101         public void setDoubleAttribute(Double d) {
 102             this.d = d;
 103         }
 104 
 105         public String getStringAttribute() {
 106             return s;
 107         }
 108 
 109         public void setStringAttribute(String s) {
 110             this.s = s;
 111         }
 112 
 113         public Integer[] getArrayAttribute() {
 114             return a;
 115         }
 116 
 117         public void setArrayAttribute(Integer[] a) {
 118             this.a = a;
 119         }
 120 
 121         public Match getEnumAttribute() {
 122             return e;
 123         }
 124 
 125         public void setEnumAttribute(Match e) {
 126             this.e = e;
 127         }
 128 
 129         private Integer i;
 130         private Double d;
 131         private String s;
 132         private Integer[] a;
 133         private Match e;
 134     }
 135 
 136     // MBean class
 137     public class ObservedObject implements ObservedObjectMBean {
 138 
 139         // Simple type buried in complex getter
 140         //
 141         public ComplexAttribute getComplexAttribute() {
 142             return ca;
 143         }
 144 
 145         public void setComplexAttribute(ComplexAttribute ca) {
 146             this.ca = ca;
 147         }
 148 
 149         private ComplexAttribute ca = null;
 150 
 151         // Simple type buried in CompositeData
 152         //
 153         public CompositeData getCompositeDataAttribute()
 154             throws OpenDataException {
 155             CompositeType ct = new CompositeType("CompositeDataAttribute",
 156                                                  "Composite Data Attribute",
 157                                                  itemNames,
 158                                                  itemDescriptions,
 159                                                  itemTypes);
 160             Object itemValues[] = { ia, da, sa };
 161             return new CompositeDataSupport(ct, itemNames, itemValues);
 162         }
 163 
 164         public Integer ia;
 165         public Double da;
 166         public String sa;
 167 
 168         private String itemNames[] = { "IntegerAttribute",
 169                                        "DoubleAttribute",
 170                                        "StringAttribute" };
 171         private String itemDescriptions[] = { "Integer Attribute",
 172                                               "Double Attribute",
 173                                               "String Attribute" };
 174         private OpenType itemTypes[] = { SimpleType.INTEGER,
 175                                          SimpleType.DOUBLE,
 176                                          SimpleType.STRING };
 177     }
 178 
 179     // MBean interface
 180     public interface ObservedObjectMBean {
 181         public ComplexAttribute getComplexAttribute();
 182         public void setComplexAttribute(ComplexAttribute ca);
 183         public CompositeData getCompositeDataAttribute()
 184             throws OpenDataException;
 185     }
 186 
 187     // Notification handler
 188     public void handleNotification(Notification notification,
 189                                    Object handback) {
 190         MonitorNotification n = (MonitorNotification) notification;
 191         echo("\tInside handleNotification...");
 192         String type = n.getType();
 193         try {
 194             if (type.equals(MonitorNotification.
 195                             THRESHOLD_VALUE_EXCEEDED)) {
 196                 echo("\t\t" + n.getObservedAttribute() +
 197                      " has reached or exceeded the threshold");
 198                 echo("\t\tDerived Gauge = " + n.getDerivedGauge());
 199                 echo("\t\tTrigger = " + n.getTrigger());
 200 
 201                 synchronized (this) {
 202                     counterMessageReceived = true;
 203                     notifyAll();
 204                 }
 205             } else if (type.equals(MonitorNotification.
 206                                    THRESHOLD_HIGH_VALUE_EXCEEDED)) {
 207                 echo("\t\t" + n.getObservedAttribute() +
 208                      " has reached or exceeded the high threshold");
 209                 echo("\t\tDerived Gauge = " + n.getDerivedGauge());
 210                 echo("\t\tTrigger = " + n.getTrigger());
 211 
 212                 synchronized (this) {
 213                     gaugeMessageReceived = true;
 214                     notifyAll();
 215                 }
 216             } else if (type.equals(MonitorNotification.
 217                                    STRING_TO_COMPARE_VALUE_MATCHED)) {
 218                 echo("\t\t" + n.getObservedAttribute() +
 219                      " matches the string-to-compare value");
 220                 echo("\t\tDerived Gauge = " + n.getDerivedGauge());
 221                 echo("\t\tTrigger = " + n.getTrigger());
 222 
 223                 synchronized (this) {
 224                     stringMessageReceived = true;
 225                     notifyAll();
 226                 }
 227             } else {
 228                 echo("\t\tSkipping notification of type: " + type);
 229             }
 230         } catch (Exception e) {
 231             echo("\tError in handleNotification!");
 232             e.printStackTrace(System.out);
 233         }
 234     }
 235 
 236     /**
 237      * Update the counter and check for notifications
 238      */
 239     public int counterMonitorNotification(int testCase)
 240         throws Exception {
 241 
 242         counterMessageReceived = false;
 243         CounterMonitor counterMonitor = null;
 244         try {
 245             MBeanServer server = MBeanServerFactory.newMBeanServer();
 246 
 247             String domain = server.getDefaultDomain();
 248 
 249             // Create a new CounterMonitor MBean and add it to the MBeanServer.
 250             //
 251             echo(">>> CREATE a new CounterMonitor MBean");
 252             ObjectName counterMonitorName = new ObjectName(
 253                             domain + ":type=" + CounterMonitor.class.getName());
 254             counterMonitor = new CounterMonitor();
 255             server.registerMBean(counterMonitor, counterMonitorName);
 256 
 257             echo(">>> ADD a listener to the CounterMonitor");
 258             counterMonitor.addNotificationListener(this, null, null);
 259 
 260             //
 261             // MANAGEMENT OF A STANDARD MBEAN
 262             //
 263 
 264             echo(">>> CREATE a new ObservedObject MBean");
 265 
 266             ObjectName obsObjName =
 267                 ObjectName.getInstance(domain + ":type=ObservedObject");
 268             ObservedObject obsObj = new ObservedObject();
 269             ComplexAttribute ca = new ComplexAttribute();
 270             switch (testCase) {
 271                 case 1:
 272                     obsObj.ia = 0;
 273                     break;
 274                 case 2:
 275                     ca.setIntegerAttribute(0);
 276                     obsObj.setComplexAttribute(ca);
 277                     break;
 278                 case 3:
 279                     ca.setArrayAttribute(new Integer[0]);
 280                     obsObj.setComplexAttribute(ca);
 281                     break;
 282             }
 283             server.registerMBean(obsObj, obsObjName);
 284 
 285             echo(">>> SET the attributes of the CounterMonitor:");
 286 
 287             counterMonitor.addObservedObject(obsObjName);
 288             echo("\tATTRIBUTE \"ObservedObject\"    = " + obsObjName);
 289 
 290             switch (testCase) {
 291                 case 1:
 292                     counterMonitor.setObservedAttribute(
 293                          "CompositeDataAttribute.IntegerAttribute");
 294                     echo("\tATTRIBUTE \"ObservedAttribute\" = " +
 295                          "CompositeDataAttribute.IntegerAttribute");
 296                     break;
 297                 case 2:
 298                     counterMonitor.setObservedAttribute(
 299                          "ComplexAttribute.integerAttribute");
 300                     echo("\tATTRIBUTE \"ObservedAttribute\" = " +
 301                          "ComplexAttribute.integerAttribute");
 302                     break;
 303                 case 3:
 304                     counterMonitor.setObservedAttribute(
 305                          "ComplexAttribute.arrayAttribute.length");
 306                     echo("\tATTRIBUTE \"ObservedAttribute\" = " +
 307                          "ComplexAttribute.arrayAttribute.length");
 308                     break;
 309             }
 310 
 311             counterMonitor.setNotify(true);
 312             echo("\tATTRIBUTE \"NotifyFlag\"        = true");
 313 
 314             Integer threshold = 2;
 315             counterMonitor.setInitThreshold(threshold);
 316             echo("\tATTRIBUTE \"Threshold\"         = " + threshold);
 317 
 318             int granularityperiod = 500;
 319             counterMonitor.setGranularityPeriod(granularityperiod);
 320             echo("\tATTRIBUTE \"GranularityPeriod\" = " + granularityperiod);
 321 
 322             echo(">>> START the CounterMonitor");
 323             counterMonitor.start();
 324 
 325             // Wait for granularity period (multiplied by 2 for sure)
 326             //
 327             Thread.sleep(granularityperiod * 2);
 328 
 329             switch (testCase) {
 330                 case 1:
 331                     obsObj.ia = 1;
 332                     break;
 333                 case 2:
 334                     ca.setIntegerAttribute(1);
 335                     break;
 336                 case 3:
 337                     ca.setArrayAttribute(new Integer[1]);
 338                     break;
 339             }
 340 
 341             // Wait for granularity period (multiplied by 2 for sure)
 342             //
 343             Thread.sleep(granularityperiod * 2);
 344 
 345             switch (testCase) {
 346                 case 1:
 347                     obsObj.ia = 2;
 348                     break;
 349                 case 2:
 350                     ca.setIntegerAttribute(2);
 351                     break;
 352                 case 3:
 353                     ca.setArrayAttribute(new Integer[2]);
 354                     break;
 355             }
 356 
 357             // Wait for granularity period (multiplied by 2 for sure)
 358             //
 359             Thread.sleep(granularityperiod * 2);
 360 
 361             switch (testCase) {
 362                 case 1:
 363                     obsObj.ia = 3;
 364                     break;
 365                 case 2:
 366                     ca.setIntegerAttribute(3);
 367                     break;
 368                 case 3:
 369                     ca.setArrayAttribute(new Integer[3]);
 370                     break;
 371             }
 372 
 373             // Check if notification was received
 374             //
 375             synchronized (this) {
 376                 while (!counterMessageReceived) {
 377                     try {
 378                         wait();
 379                     } catch (InterruptedException e) {
 380                         System.err.println("Got unexpected exception: " + e);
 381                         e.printStackTrace();
 382                         break;
 383                     }
 384                 }
 385             }
 386             if (counterMessageReceived) {
 387                 echo("\tOK: CounterMonitor notification received");
 388             } else {
 389                 echo("\tKO: CounterMonitor notification missed or not emitted");
 390                 return 1;
 391             }
 392         } finally {
 393             if (counterMonitor != null)
 394                 counterMonitor.stop();
 395         }
 396 
 397         return 0;
 398     }
 399 
 400     /**
 401      * Update the gauge and check for notifications
 402      */
 403     public int gaugeMonitorNotification(int testCase)
 404         throws Exception {
 405 
 406         gaugeMessageReceived = false;
 407         GaugeMonitor gaugeMonitor = null;
 408         try {
 409             MBeanServer server = MBeanServerFactory.newMBeanServer();
 410 
 411             String domain = server.getDefaultDomain();
 412 
 413             // Create a new GaugeMonitor MBean and add it to the MBeanServer.
 414             //
 415             echo(">>> CREATE a new GaugeMonitor MBean");
 416             ObjectName gaugeMonitorName = new ObjectName(
 417                             domain + ":type=" + GaugeMonitor.class.getName());
 418             gaugeMonitor = new GaugeMonitor();
 419             server.registerMBean(gaugeMonitor, gaugeMonitorName);
 420 
 421             echo(">>> ADD a listener to the GaugeMonitor");
 422             gaugeMonitor.addNotificationListener(this, null, null);
 423 
 424             //
 425             // MANAGEMENT OF A STANDARD MBEAN
 426             //
 427 
 428             echo(">>> CREATE a new ObservedObject MBean");
 429 
 430             ObjectName obsObjName =
 431                 ObjectName.getInstance(domain + ":type=ObservedObject");
 432             ObservedObject obsObj = new ObservedObject();
 433             ComplexAttribute ca = new ComplexAttribute();
 434             switch (testCase) {
 435                 case 1:
 436                     obsObj.da = 0.0;
 437                     break;
 438                 case 2:
 439                     ca.setDoubleAttribute(0.0);
 440                     obsObj.setComplexAttribute(ca);
 441                     break;
 442                 case 3:
 443                     ca.setArrayAttribute(new Integer[0]);
 444                     obsObj.setComplexAttribute(ca);
 445                     break;
 446             }
 447             server.registerMBean(obsObj, obsObjName);
 448 
 449             echo(">>> SET the attributes of the GaugeMonitor:");
 450 
 451             gaugeMonitor.addObservedObject(obsObjName);
 452             echo("\tATTRIBUTE \"ObservedObject\"    = " + obsObjName);
 453 
 454             switch (testCase) {
 455                 case 1:
 456                     gaugeMonitor.setObservedAttribute(
 457                          "CompositeDataAttribute.DoubleAttribute");
 458                     echo("\tATTRIBUTE \"ObservedAttribute\" = " +
 459                          "CompositeDataAttribute.DoubleAttribute");
 460                     break;
 461                 case 2:
 462                     gaugeMonitor.setObservedAttribute(
 463                          "ComplexAttribute.doubleAttribute");
 464                     echo("\tATTRIBUTE \"ObservedAttribute\" = " +
 465                          "ComplexAttribute.doubleAttribute");
 466                     break;
 467                 case 3:
 468                     gaugeMonitor.setObservedAttribute(
 469                          "ComplexAttribute.arrayAttribute.length");
 470                     echo("\tATTRIBUTE \"ObservedAttribute\" = " +
 471                          "ComplexAttribute.arrayAttribute.length");
 472                     break;
 473             }
 474 
 475             gaugeMonitor.setNotifyLow(false);
 476             gaugeMonitor.setNotifyHigh(true);
 477             echo("\tATTRIBUTE \"Notify Low  Flag\"  = false");
 478             echo("\tATTRIBUTE \"Notify High Flag\"  = true");
 479 
 480             switch (testCase) {
 481                 case 1:
 482                 case 2:
 483                     Double highThresholdD = 3.0, lowThresholdD = 2.5;
 484                     gaugeMonitor.setThresholds(highThresholdD, lowThresholdD);
 485                     echo("\tATTRIBUTE \"Low  Threshold\"    = " + lowThresholdD);
 486                     echo("\tATTRIBUTE \"High Threshold\"    = " + highThresholdD);
 487                     break;
 488                 case 3:
 489                     Integer highThreshold = 2, lowThreshold = 1;
 490                     gaugeMonitor.setThresholds(highThreshold, lowThreshold);
 491                     echo("\tATTRIBUTE \"Low  Threshold\"    = " + lowThreshold);
 492                     echo("\tATTRIBUTE \"High Threshold\"    = " + highThreshold);
 493                     break;
 494             }
 495 
 496             int granularityperiod = 500;
 497             gaugeMonitor.setGranularityPeriod(granularityperiod);
 498             echo("\tATTRIBUTE \"GranularityPeriod\" = " + granularityperiod);
 499 
 500             echo(">>> START the GaugeMonitor");
 501             gaugeMonitor.start();
 502 
 503             // Wait for granularity period (multiplied by 2 for sure)
 504             //
 505             Thread.sleep(granularityperiod * 2);
 506 
 507             switch (testCase) {
 508                 case 1:
 509                     obsObj.da = 2.0;
 510                     break;
 511                 case 2:
 512                     ca.setDoubleAttribute(2.0);
 513                     break;
 514                 case 3:
 515                     ca.setArrayAttribute(new Integer[2]);
 516                     break;
 517             }
 518 
 519             // Wait for granularity period (multiplied by 2 for sure)
 520             //
 521             Thread.sleep(granularityperiod * 2);
 522 
 523             switch (testCase) {
 524                 case 1:
 525                     obsObj.da = 4.0;
 526                     break;
 527                 case 2:
 528                     ca.setDoubleAttribute(4.0);
 529                     break;
 530                 case 3:
 531                     ca.setArrayAttribute(new Integer[4]);
 532                     break;
 533             }
 534 
 535             // Wait for granularity period (multiplied by 2 for sure)
 536             //
 537             Thread.sleep(granularityperiod * 2);
 538 
 539             switch (testCase) {
 540                 case 1:
 541                     obsObj.da = 6.0;
 542                     break;
 543                 case 2:
 544                     ca.setDoubleAttribute(6.0);
 545                     break;
 546                 case 3:
 547                     ca.setArrayAttribute(new Integer[6]);
 548                     break;
 549             }
 550 
 551             // Check if notification was received
 552             //
 553             synchronized (this) {
 554                 while (!gaugeMessageReceived) {
 555                     try {
 556                         wait();
 557                     } catch (InterruptedException e) {
 558                         System.err.println("Got unexpected exception: " + e);
 559                         e.printStackTrace();
 560                         break;
 561                     }
 562                 }
 563             }
 564             if (gaugeMessageReceived) {
 565                 echo("\tOK: GaugeMonitor notification received");
 566             } else {
 567                 echo("\tKO: GaugeMonitor notification missed or not emitted");
 568                 return 1;
 569             }
 570         } finally {
 571             if (gaugeMonitor != null)
 572                 gaugeMonitor.stop();
 573         }
 574 
 575         return 0;
 576     }
 577 
 578     /**
 579      * Update the string and check for notifications
 580      */
 581     public int stringMonitorNotification(int testCase)
 582         throws Exception {
 583 
 584         stringMessageReceived = false;
 585         StringMonitor stringMonitor = null;
 586         try {
 587             MBeanServer server = MBeanServerFactory.newMBeanServer();
 588 
 589             String domain = server.getDefaultDomain();
 590 
 591             // Create a new StringMonitor MBean and add it to the MBeanServer.
 592             //
 593             echo(">>> CREATE a new StringMonitor MBean");
 594             ObjectName stringMonitorName = new ObjectName(
 595                             domain + ":type=" + StringMonitor.class.getName());
 596             stringMonitor = new StringMonitor();
 597             server.registerMBean(stringMonitor, stringMonitorName);
 598 
 599             echo(">>> ADD a listener to the StringMonitor");
 600             stringMonitor.addNotificationListener(this, null, null);
 601 
 602             //
 603             // MANAGEMENT OF A STANDARD MBEAN
 604             //
 605 
 606             echo(">>> CREATE a new ObservedObject MBean");
 607 
 608             ObjectName obsObjName =
 609                 ObjectName.getInstance(domain + ":type=ObservedObject");
 610             ObservedObject obsObj = new ObservedObject();
 611             ComplexAttribute ca = new ComplexAttribute();
 612             switch (testCase) {
 613                 case 1:
 614                     obsObj.sa = "do_not_match_0";
 615                     break;
 616                 case 2:
 617                     ca.setStringAttribute("do_not_match_0");
 618                     obsObj.setComplexAttribute(ca);
 619                     break;
 620                 case 3:
 621                     ca.setEnumAttribute(Match.do_not_match_0);
 622                     obsObj.setComplexAttribute(ca);
 623                     break;
 624             }
 625             server.registerMBean(obsObj, obsObjName);
 626 
 627             echo(">>> SET the attributes of the StringMonitor:");
 628 
 629             stringMonitor.addObservedObject(obsObjName);
 630             echo("\tATTRIBUTE \"ObservedObject\"    = " + obsObjName);
 631 
 632             switch (testCase) {
 633                 case 1:
 634                     stringMonitor.setObservedAttribute(
 635                          "CompositeDataAttribute.StringAttribute");
 636                     echo("\tATTRIBUTE \"ObservedAttribute\" = " +
 637                          "CompositeDataAttribute.StringAttribute");
 638                     break;
 639                 case 2:
 640                     stringMonitor.setObservedAttribute(
 641                          "ComplexAttribute.stringAttribute");
 642                     echo("\tATTRIBUTE \"ObservedAttribute\" = " +
 643                          "ComplexAttribute.stringAttribute");
 644                     break;
 645                 case 3:
 646                     stringMonitor.setObservedAttribute(
 647                          "ComplexAttribute.enumAttribute.name");
 648                     echo("\tATTRIBUTE \"ObservedAttribute\" = " +
 649                          "ComplexAttribute.enumAttribute.name");
 650                     break;
 651             }
 652 
 653             stringMonitor.setNotifyMatch(true);
 654             echo("\tATTRIBUTE \"NotifyMatch\"       = true");
 655 
 656             stringMonitor.setNotifyDiffer(false);
 657             echo("\tATTRIBUTE \"NotifyDiffer\"      = false");
 658 
 659             stringMonitor.setStringToCompare("do_match_now");
 660             echo("\tATTRIBUTE \"StringToCompare\"   = \"do_match_now\"");
 661 
 662             int granularityperiod = 500;
 663             stringMonitor.setGranularityPeriod(granularityperiod);
 664             echo("\tATTRIBUTE \"GranularityPeriod\" = " + granularityperiod);
 665 
 666             echo(">>> START the StringMonitor");
 667             stringMonitor.start();
 668 
 669             // Wait for granularity period (multiplied by 2 for sure)
 670             //
 671             Thread.sleep(granularityperiod * 2);
 672 
 673             switch (testCase) {
 674                 case 1:
 675                     obsObj.sa = "do_not_match_1";
 676                     break;
 677                 case 2:
 678                     ca.setStringAttribute("do_not_match_1");
 679                     break;
 680                 case 3:
 681                     ca.setEnumAttribute(Match.do_not_match_1);
 682                     break;
 683             }
 684 
 685             // Wait for granularity period (multiplied by 2 for sure)
 686             //
 687             Thread.sleep(granularityperiod * 2);
 688 
 689             switch (testCase) {
 690                 case 1:
 691                     obsObj.sa = "do_match_now";
 692                     break;
 693                 case 2:
 694                     ca.setStringAttribute("do_match_now");
 695                     break;
 696                 case 3:
 697                     ca.setEnumAttribute(Match.do_match_now);
 698                     break;
 699             }
 700 
 701             // Wait for granularity period (multiplied by 2 for sure)
 702             //
 703             Thread.sleep(granularityperiod * 2);
 704 
 705             switch (testCase) {
 706                 case 1:
 707                     obsObj.sa = "do_not_match_2";
 708                     break;
 709                 case 2:
 710                     ca.setStringAttribute("do_not_match_2");
 711                     break;
 712                 case 3:
 713                     ca.setEnumAttribute(Match.do_not_match_2);
 714                     break;
 715             }
 716 
 717             // Check if notification was received
 718             //
 719             synchronized (this) {
 720                 while (!stringMessageReceived) {
 721                     try {
 722                         wait();
 723                     } catch (InterruptedException e) {
 724                         System.err.println("Got unexpected exception: " + e);
 725                         e.printStackTrace();
 726                         break;
 727                     }
 728                 }
 729             }
 730             if (stringMessageReceived) {
 731                 echo("\tOK: StringMonitor notification received");
 732             } else {
 733                 echo("\tKO: StringMonitor notification missed or not emitted");
 734                 return 1;
 735             }
 736         } finally {
 737             if (stringMonitor != null)
 738                 stringMonitor.stop();
 739         }
 740 
 741         return 0;
 742     }
 743 
 744     /**
 745      * Test the monitor notifications.
 746      */
 747     public int monitorNotifications() throws Exception {
 748         echo(">>> ----------------------------------------");
 749         int error = counterMonitorNotification(1);
 750         echo(">>> ----------------------------------------");
 751         error += counterMonitorNotification(2);
 752         echo(">>> ----------------------------------------");
 753         error += counterMonitorNotification(3);
 754         echo(">>> ----------------------------------------");
 755         error += gaugeMonitorNotification(1);
 756         echo(">>> ----------------------------------------");
 757         error += gaugeMonitorNotification(2);
 758         echo(">>> ----------------------------------------");
 759         error += gaugeMonitorNotification(3);
 760         echo(">>> ----------------------------------------");
 761         error += stringMonitorNotification(1);
 762         echo(">>> ----------------------------------------");
 763         error += stringMonitorNotification(2);
 764         echo(">>> ----------------------------------------");
 765         error += stringMonitorNotification(3);
 766         echo(">>> ----------------------------------------");
 767         return error;
 768     }
 769 
 770     /*
 771      * Print message
 772      */
 773     private static void echo(String message) {
 774         System.out.println(message);
 775     }
 776 
 777     public static Object elementFromComplex(Object complex, String element)
 778     throws AttributeNotFoundException {
 779         try {
 780             if (complex.getClass().isArray() && element.equals("length")) {
 781                 return Array.getLength(complex);
 782             } else if (complex instanceof CompositeData) {
 783                 return ((CompositeData) complex).get(element);
 784             } else {
 785                 // Java Beans introspection
 786                 //
 787                 BeanInfo bi = java.beans.Introspector.getBeanInfo(complex.getClass());
 788                 PropertyDescriptor[] pds = bi.getPropertyDescriptors();
 789                 System.out.println("PDs: " + pds.length);
 790                 for (PropertyDescriptor pd : pds) {
 791                     System.out.println("Property: " + pd.getName());
 792                     if (pd.getName().equals(element))
 793                         return pd.getReadMethod().invoke(complex);
 794                 }
 795                 throw new AttributeNotFoundException(
 796                     "Could not find the getter method for the property " +
 797                     element + " using the Java Beans introspector");
 798             }
 799         } catch (InvocationTargetException e) {
 800             throw new IllegalArgumentException(e);
 801         } catch (AttributeNotFoundException e) {
 802             throw e;
 803         } catch (Exception e) {
 804             AttributeNotFoundException anfe =
 805                 new AttributeNotFoundException(e.getMessage());
 806             anfe.initCause(e);
 807             throw anfe;
 808         }
 809     }
 810 
 811     /*
 812      * Standalone entry point.
 813      *
 814      * Run the test and report to stdout.
 815      */
 816     public static void main (String args[]) throws Exception {
 817         Match match = Match.do_match_now;
 818         String name = (String) elementFromComplex(match, "name");
 819         System.out.println("name: " + name);
 820         AttributeArbitraryDataTypeTest test =
 821             new AttributeArbitraryDataTypeTest();
 822         int error = test.monitorNotifications();
 823         if (error > 0) {
 824             echo(">>> Unhappy Bye, Bye!");
 825             throw new IllegalStateException("Test FAILED: Didn't get all " +
 826                                             "the notifications that were " +
 827                                             "expected by the test!");
 828         } else {
 829             echo(">>> Happy Bye, Bye!");
 830         }
 831     }
 832 }