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