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