public static void main(String[] args) throws Exception {

    long timeBeforeInMillis = System.currentTimeMillis();

    JmxInvokerArguments arguments = new JmxInvokerArguments();
    CmdLineParser parser = new CmdLineParser(arguments);
    try {
      parser.parseArgument(args);
      arguments.cmdLineParser = parser;
      if (Strings2.isEmpty(arguments.pid) && arguments.pidFile == null) {
        throw new CmdLineException(parser, "Options --pid and --pid-file can NOT be both null");
      } else if (!Strings2.isEmpty(arguments.pid) && arguments.pidFile != null) {
        throw new CmdLineException(parser, "Options --pid and --pid-file can NOT be both defined");
      } else if ((arguments.attribute == null || arguments.attribute.length == 0)
          && (arguments.operation == null || arguments.operation.length == 0)
          && arguments.listMbeans == false
          && arguments.describeMbeans == false) {
        throw new CmdLineException(
            parser,
            "Option --attribute or --operation or --list-mbeans or --describe-mbeans must be defined");
      } else if ((arguments.attribute != null && arguments.attribute.length > 0)
          && (arguments.operation != null && arguments.operation.length > 0)) {
        throw new CmdLineException(
            parser, "Options --attribute and --operation can NOT be both defined");
      }

      String logLevel;
      if (arguments.superVerbose) {
        logLevel = "TRACE";
      } else if (arguments.verbose) {
        logLevel = "DEBUG";
      } else {
        logLevel = "WARN";
      }
      System.setProperty(SimpleLogger.DEFAULT_LOG_LEVEL_KEY, logLevel);

      Map<ObjectName, Result> results = new JmxInvoker().process(arguments);
      for (Map.Entry<ObjectName, Result> entry : results.entrySet()) {
        System.out.println(entry.getValue().description);
      }
    } catch (CmdLineException e) {
      System.err.println("INVALID INVOCATION: " + e.getMessage());
      System.err.println("Arguments: " + Strings2.join(args, " "));
      System.err.println("Usage:");
      parser.printUsage(System.err);
      throw e;
    } catch (Exception e) {
      System.err.println("INVALID INVOCATION: " + e.getMessage());
      System.err.println("Arguments: " + Strings2.join(args, " "));
      e.printStackTrace();
      throw e;
    } finally {
      if (arguments.verbose || arguments.superVerbose) {
        System.out.println("Duration: " + (System.currentTimeMillis() - timeBeforeInMillis) + "ms");
      }
    }
  }
Example #2
0
    void checkThreadInfo(ThreadInfo info) {
      if (!getName().equals(info.getThreadName())) {
        throw new RuntimeException(
            "Name: " + info.getThreadName() + " not matched. Expected: " + getName());
      }

      MonitorInfo[] monitors = info.getLockedMonitors();
      if (monitors.length != OWNED_MONITORS) {
        throw new RuntimeException(
            "Number of locked monitors = "
                + monitors.length
                + " not matched. Expected: "
                + OWNED_MONITORS);
      }
      MonitorInfo m = monitors[0];
      StackTraceElement ste = m.getLockedStackFrame();
      int depth = m.getLockedStackDepth();
      StackTraceElement[] stacktrace = info.getStackTrace();
      if (!ste.equals(stacktrace[depth])) {
        System.out.println("LockedStackFrame:- " + ste);
        System.out.println("StackTrace at " + depth + " :-" + stacktrace[depth]);
        throw new RuntimeException(
            "LockedStackFrame does not match " + "stack frame in ThreadInfo.getStackTrace");
      }

      String className = lock.getClass().getName();
      int hcode = System.identityHashCode(lock);
      if (!className.equals(m.getClassName())
          || hcode != m.getIdentityHashCode()
          || !m.getLockedStackFrame().getMethodName().equals("run")) {
        System.out.println(info);
        throw new RuntimeException("MonitorInfo " + m + " doesn't match.");
      }

      LockInfo[] syncs = info.getLockedSynchronizers();
      if (syncs.length != OWNED_SYNCS) {
        throw new RuntimeException(
            "Number of locked syncs = " + syncs.length + " not matched. Expected: " + OWNED_SYNCS);
      }
      AbstractOwnableSynchronizer s = mutex.getSync();
      String lockName = s.getClass().getName();
      hcode = System.identityHashCode(s);
      if (!lockName.equals(syncs[0].getClassName())) {
        throw new RuntimeException(
            "LockInfo : " + syncs[0] + " class name not matched. Expected: " + lockName);
      }
      if (hcode != syncs[0].getIdentityHashCode()) {
        throw new RuntimeException(
            "LockInfo: " + syncs[0] + " IdentityHashCode not matched. Expected: " + hcode);
      }
      LockInfo li = info.getLockInfo();
      if (li == null) {
        throw new RuntimeException("Expected non-null LockInfo");
      }
    }
Example #3
0
  /**
   * Get a pointer to the root context of the directory tree under which this server is supposed to
   * register itself. All LDAP DNs will be considered to be relative to that root.
   *
   * <p>Note that this root is not part of the JSR 160 specification, since the actual location
   * where a JMX Agent will register its connectors is left completely open by the specification.
   * The specification only discuss what the JMX Agent must/may put in the directory - but not
   * where.
   *
   * <p>This method assumes that the root of the directory is will be passed in a the {@link
   * Context#PROVIDER_URL Context.PROVIDER_URL} System property.
   *
   * <p>This method will transfer a fixed set of System Properties to the Hashtable given to the
   * JNDI InitialContext:
   *
   * <ul>
   *   <li>{@link Context#INITIAL_CONTEXT_FACTORY Context.INITIAL_CONTEXT_FACTORY} - default is
   *       <code>"com.sun.jndi.ldap.LdapCtxFactory"</code>
   *   <li>{@link Context#PROVIDER_URL Context.PROVIDER_URL}
   *   <li>{@link Context#SECURITY_PRINCIPAL Context.SECURITY_PRINCIPAL} - default is <code>
   *       "cn=Directory Manager"</code>
   *   <li>{@link Context#SECURITY_CREDENTIALS Context.SECURITY_CREDENTIALS}
   * </ul>
   *
   * @return a pointer to the LDAP Directory.
   */
  public static DirContext getRootContext() throws NamingException {
    // Prepare environment
    //
    final Hashtable env = new Hashtable();

    // The Initial Context Factory must be provided, and
    // must point to an LDAP Context Factory
    //
    final String factory =
        System.getProperty(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");

    // The LDAP Provider URL must be provided, and
    // must point to a running LDAP directory server
    //
    final String ldapServerUrl = System.getProperty(Context.PROVIDER_URL);

    // The LDAP user must be provided, and
    // must have write access to the subpart of the directory
    // where the agent will be registered.
    //
    final String ldapUser = System.getProperty(Context.SECURITY_PRINCIPAL, "cn=Directory Manager");

    // Credentials must be provided, so that the user may
    // write to the directory.
    //
    final String ldapPasswd = System.getProperty(Context.SECURITY_CREDENTIALS);

    // Debug info: print provided values:
    //
    debug(Context.PROVIDER_URL + "=" + ldapServerUrl);
    debug(Context.SECURITY_PRINCIPAL + "=" + ldapUser);
    if (debug) {
      System.out.print(Context.SECURITY_CREDENTIALS + "=");
      final int len = (ldapPasswd == null) ? 0 : ldapPasswd.length();
      for (int i = 0; i < len; i++) System.out.print("*");
      System.out.println();
    }

    // Put provided value in the environment table.
    //
    env.put(Context.INITIAL_CONTEXT_FACTORY, factory);
    env.put(Context.SECURITY_PRINCIPAL, ldapUser);
    if (ldapServerUrl != null) env.put(Context.PROVIDER_URL, ldapServerUrl);
    if (ldapPasswd != null) env.put(Context.SECURITY_CREDENTIALS, ldapPasswd);

    // Create initial context
    //
    InitialContext root = new InitialLdapContext(env, null);

    // Now return the root directory context.
    //
    return (DirContext) (root.lookup(""));
  }
Example #4
0
  public static void main(String[] args) throws Exception {
    Class thisClass = MethodResultTest.class;
    Class exoticClass = Exotic.class;
    String exoticClassName = Exotic.class.getName();
    ClassLoader testClassLoader = thisClass.getClassLoader();
    if (!(testClassLoader instanceof URLClassLoader)) {
      System.out.println("TEST INVALID: Not loaded by a " + "URLClassLoader: " + testClassLoader);
      System.exit(1);
    }

    URLClassLoader tcl = (URLClassLoader) testClassLoader;
    URL[] urls = tcl.getURLs();
    ClassLoader shadowLoader =
        new ShadowLoader(
            urls,
            testClassLoader,
            new String[] {
              exoticClassName, ExoticMBeanInfo.class.getName(), ExoticException.class.getName()
            });
    Class cl = shadowLoader.loadClass(exoticClassName);
    if (cl == exoticClass) {
      System.out.println(
          "TEST INVALID: Shadow class loader loaded " + "same class as test class loader");
      System.exit(1);
    }
    Thread.currentThread().setContextClassLoader(shadowLoader);

    ObjectName on = new ObjectName("a:b=c");
    MBeanServer mbs = MBeanServerFactory.newMBeanServer();
    mbs.createMBean(Thing.class.getName(), on);

    final String[] protos = {"rmi", "iiop", "jmxmp"};

    boolean ok = true;
    for (int i = 0; i < protos.length; i++) {
      try {
        ok &= test(protos[i], mbs, on);
        System.out.println();
      } catch (Exception e) {
        System.out.println("TEST FAILED WITH EXCEPTION:");
        e.printStackTrace(System.out);
        ok = false;
      }
    }

    if (ok) System.out.println("Test passed");
    else {
      System.out.println("TEST FAILED");
      System.exit(1);
    }
  }
 public static void main(String[] args) {
   int errorCount = 0;
   for (int i = 0; i < NTESTS; i++) {
     try {
       System.out.println("Test " + i + ":");
       test(i);
     } catch (Throwable e) {
       errorCount++;
       boolean first = true;
       do {
         System.err.println(first ? "Exception:" : "Caused by:");
         first = false;
         e.printStackTrace();
         Throwable nexte;
         nexte = e.getCause();
         if (nexte == null) { // old JMX
           if (e instanceof MBeanException) nexte = ((MBeanException) e).getTargetException();
         }
         e = nexte;
       } while (e != null);
     }
   }
   if (errorCount == 0) {
     System.out.println("All ModelMBean tests successfuly passed");
     System.out.println("Bye! Bye!");
     // JTReg doesn't like System.exit(0);
     return;
   } else {
     System.err.println("ERROR: " + errorCount + " tests failed");
     System.exit(errorCount);
   }
 }
  public void tableChanged(String Message) {
    String inst = Message;
    Notification n =
        new AttributeChangeNotification(
            this,
            sequenceNumber++,
            System.currentTimeMillis(),
            "Table value changed",
            "Table",
            "String",
            Message,
            LocalServer.table
                .getValueAt(
                    Integer.parseInt(
                        inst.substring(
                            inst.indexOf("Row :") + "Row :".length(), inst.indexOf(","))),
                    Integer.parseInt(inst.substring(inst.indexOf("Column:") + "Column:".length())))
                .toString());

    /* Now send the notification using the sendNotification method
    inherited from the parent class NotificationBroadcasterSupport. */
    sendNotification(n);
    // TODO Auto-generated method stub

  }
Example #7
0
 public void dump(long interval, long samples) {
   try {
     PrintGCStat pstat = new PrintGCStat(server);
     for (int i = 0; i < samples; i++) {
       pstat.printVerboseGc();
       try {
         Thread.sleep(interval);
       } catch (InterruptedException e) {
         System.exit(1);
       }
     }
   } catch (IOException e) {
     System.err.println("\nCommunication error: " + e.getMessage());
     System.exit(1);
   }
 }
Example #8
0
 /**
  * Get a pointer to the Jini Lookup Service. (See Jini documentation for more info).
  *
  * <p>The Jini Lookup Service URL is determined as follows:
  *
  * <p>If the System property <code>"jini.lookup.url"</code> is provided, its value is the Jini
  * Lookup Service URL.
  *
  * <p>Otherwise, the default URL is assumed to be <code>"jini://localhost"</code>
  *
  * @return a pointer to the Jini Lookup Service.
  */
 public static ServiceRegistrar getRegistrar()
     throws IOException, ClassNotFoundException, MalformedURLException {
   final String jurl = System.getProperty("jini.lookup.url", "jini://localhost");
   final LookupLocator lookup = new LookupLocator(jurl);
   final ServiceRegistrar registrar = lookup.getRegistrar();
   if (registrar instanceof Administrable) debug("Registry is administrable.");
   return registrar;
 }
Example #9
0
  public static void main(String[] args) throws Exception {
    System.out.println(
        "Test that target MBean class loader is used " + "before JMX Remote API class loader");

    ClassLoader jmxRemoteClassLoader = JMXServiceURL.class.getClassLoader();
    if (jmxRemoteClassLoader == null) {
      System.out.println(
          "JMX Remote API loaded by bootstrap " + "class loader, this test is irrelevant");
      return;
    }
    if (!(jmxRemoteClassLoader instanceof URLClassLoader)) {
      System.out.println("TEST INVALID: JMX Remote API not loaded by " + "URLClassLoader");
      System.exit(1);
    }

    URLClassLoader jrcl = (URLClassLoader) jmxRemoteClassLoader;
    URL[] urls = jrcl.getURLs();
    PrivateMLet mlet = new PrivateMLet(urls, null, false);
    Class shadowClass = mlet.loadClass(JMXServiceURL.class.getName());
    if (shadowClass == JMXServiceURL.class) {
      System.out.println("TEST INVALID: MLet got original " + "JMXServiceURL not shadow");
      System.exit(1);
    }

    MBeanServer mbs = MBeanServerFactory.newMBeanServer();
    mbs.registerMBean(mlet, mletName);

    final String[] protos = {"rmi", "iiop", "jmxmp"};
    boolean ok = true;
    for (int i = 0; i < protos.length; i++) {
      try {
        ok &= test(protos[i], mbs);
      } catch (Exception e) {
        System.out.println("TEST FAILED WITH EXCEPTION:");
        e.printStackTrace(System.out);
        ok = false;
      }
    }

    if (ok) System.out.println("Test passed");
    else {
      System.out.println("TEST FAILED");
      System.exit(1);
    }
  }
  /**
   * Sends a leave message to the multicast group and leaves it. The <CODE>DiscoveryResponder</CODE>
   * leaves its multicast group. This method has no effect if the <CODE>DiscoveryResponder</CODE> is
   * <CODE>OFFLINE</CODE> or <CODE>STOPPING</CODE> or <CODE>STARTING</CODE>.
   */
  public void stop() {
    if (state == ONLINE) {
      changeState(STOPPING);
      // ------------------------
      // Stop corresponding thread
      // ------------------------

      responder.stopRequested = true;

      synchronized (responder.interrupted) {
        if (!responder.interrupted.booleanValue()) {
          responderThread.interrupt();
        }
      }

      // Fix for cases when the interrupt does not work (Windows NT)
      try {
        MulticastSocket ms = new MulticastSocket(multicastPort);

        // NPCTE fix for bugId 4499338, esc 0, 04 Sept 2001
        if (usrInet != null) {
          ms.setInterface(usrInet);

          if (logger.finerOn()) {
            logger.finer("stop ", "use the interface " + usrInet);
          }
        }
        // end of NPCTE fix for bugId 4499338

        InetAddress group = InetAddress.getByName(multicastGroup);
        ms.joinGroup(group);
        ms.send(new DatagramPacket(new byte[1], 1, group, multicastPort));
        ms.leaveGroup(group);
      } catch (Exception e) {
        if (logger.finerOn()) {
          logger.finer(
              "stop ",
              "Unexpected exception occurred trying to send empty message " + e.getMessage());
        }
      }

      // ------------------------
      // free 'remained' allocated resource
      // ------------------------
      responder = null;
      System.runFinalization();

      // ----------------
      // Update state
      // ----------------
      // changeState(OFFLINE) ;
    } else {
      if (logger.finerOn()) {
        logger.finer("stop ", "Responder is not ONLINE");
      }
    }
  }
Example #11
0
  private void parseCmdLine(String[] args) {
    CommandLineParser parser = new PosixParser();

    Options options = new Options();
    options.addOption("v", "version", false, "Q2's version");
    options.addOption("d", "deploydir", true, "Deployment directory");
    options.addOption("r", "recursive", false, "Deploy subdirectories recursively");
    options.addOption("h", "help", false, "Usage information");
    options.addOption("C", "config", true, "Configuration bundle");
    options.addOption("e", "encrypt", true, "Encrypt configuration bundle");
    options.addOption("i", "cli", false, "Command Line Interface");
    options.addOption("c", "command", true, "Command to execute");

    try {
      CommandLine line = parser.parse(options, args);
      if (line.hasOption("v")) {
        displayVersion();
        System.exit(0);
      }
      if (line.hasOption("h")) {
        HelpFormatter helpFormatter = new HelpFormatter();
        helpFormatter.printHelp("Q2", options);
        System.exit(0);
      }
      if (line.hasOption("c")) {
        cli = new CLI(this, line.getOptionValue("c"), line.hasOption("i"));
      } else if (line.hasOption("i")) cli = new CLI(this, null, true);

      String dir = DEFAULT_DEPLOY_DIR;
      if (line.hasOption("d")) {
        dir = line.getOptionValue("d");
      }
      recursive = line.hasOption("r");
      this.deployDir = new File(dir);
      if (line.hasOption("C")) deployBundle(new File(line.getOptionValue("C")), false);
      if (line.hasOption("e")) deployBundle(new File(line.getOptionValue("e")), true);
    } catch (MissingArgumentException e) {
      System.out.println("ERROR: " + e.getMessage());
      System.exit(1);
    } catch (Exception e) {
      e.printStackTrace();
      System.exit(1);
    }
  }
 public static void main(String[] args) throws Exception {
   MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
   final Boolean isNotificationSupported =
       AccessController.doPrivileged(
           new PrivilegedAction<Boolean>() {
             public Boolean run() {
               try {
                 Class cl = Class.forName("sun.management.VMManagementImpl");
                 Field f = cl.getDeclaredField("gcNotificationSupport");
                 f.setAccessible(true);
                 return f.getBoolean(null);
               } catch (ClassNotFoundException e) {
                 return false;
               } catch (NoSuchFieldException e) {
                 return false;
               } catch (IllegalAccessException e) {
                 return false;
               }
             }
           });
   if (!isNotificationSupported) {
     System.out.println("GC Notification not supported by the JVM, test skipped");
     return;
   }
   final ObjectName gcMXBeanPattern = new ObjectName("java.lang:type=GarbageCollector,*");
   Set<ObjectName> names = mbs.queryNames(gcMXBeanPattern, null);
   if (names.isEmpty()) throw new Exception("Test incorrect: no GC MXBeans");
   number = names.size();
   for (ObjectName n : names) {
     if (mbs.isInstanceOf(n, "javax.management.NotificationEmitter")) {
       listenerInvoked.put(n.getCanonicalName(), null);
       GcListener listener = new GcListener();
       mbs.addNotificationListener(n, listener, null, null);
     }
   }
   // Invocation of System.gc() to trigger major GC
   System.gc();
   // Allocation of many short living and small objects to trigger minor GC
   Object data[] = new Object[32];
   for (int i = 0; i < 100000000; i++) {
     data[i % 32] = new int[8];
   }
   int wakeup = 0;
   synchronized (synchronizer) {
     while (count != number) {
       synchronizer.wait(10000);
       wakeup++;
       if (wakeup > 10) break;
     }
   }
   for (GarbageCollectionNotificationInfo notif : listenerInvoked.values()) {
     checkGarbageCollectionNotificationInfoContent(notif);
   }
   System.out.println("Test passed");
 }
Example #13
0
  /**
   * Program Main
   *
   * <p>Creates a server object, gets the JMX Service URL, and calls the method that will create and
   * register the appropriate JMX Connector Server for that URL.
   *
   * <p>You may wish to use the following properties on the Java command line:
   *
   * <ul>
   *   <li><code>-Durl=&lt;jmxServiceURL&gt;</code>: specifies the URL of the JMX Connector Server
   *       you wish to use. See README file for more details
   *   <li><code>-Dagent.name=&lt;AgentName&gt;</code>: specifies an AgentName to register with.
   *   <li><code>-Djini.lookup.url=&lt;jini-url&gt;</code>: the Jini Lookup Service URL (default is
   *       "jini://localhost"), see {@link #getRegistrar()}.
   *   <li><code>-Ddebug="true|false"</code>: switch the Server debug flag on/off (default is
   *       "false").
   * </ul>
   */
  public static void main(String[] args) {
    try {
      // Jini requires a security manager.
      //
      if (System.getSecurityManager() == null) System.setSecurityManager(new RMISecurityManager());

      // Get the value of the debug flag.
      //
      debug = (Boolean.valueOf(System.getProperty("debug", "false"))).booleanValue();

      // Create a new Server object.
      //
      final Server s = new Server();

      // Get the JMXConnector URL
      //
      final String url = System.getProperty("url", "service:jmx:rmi://");

      // Build a JMXServiceURL
      //
      final JMXServiceURL jurl = new JMXServiceURL(url);

      // Creates a JMX Connector Server
      //
      debug("Creating Connector: " + jurl);
      final String p = jurl.getProtocol();
      if (p.equals("rmi")) // Create an RMI Connector
      s.rmi(url);
      else if (p.equals("iiop")) // Create an RMI/IIOP Connector
      s.rmi(url);
      else // Unsupported protocol
      throw new MalformedURLException("Unsupported protocol: " + p);

      System.out.println("\nService URL successfully registered " + "in the Jini Lookup Service");

    } catch (Exception x) {
      // Something went wrong somewhere....
      //
      System.err.println("Unexpected exception caught in main: " + x);
      x.printStackTrace(System.err);
    }
  }
Example #14
0
 public Q2(String[] args) {
   super();
   this.args = args;
   startTime = System.currentTimeMillis();
   instanceId = UUID.randomUUID();
   parseCmdLine(args);
   libDir = new File(deployDir, "lib");
   dirMap = new TreeMap();
   deployDir.mkdirs();
   mainClassLoader = Thread.currentThread().getContextClassLoader();
 }
Example #15
0
 /** Connect to a JMX agent of a given URL. */
 private void connect(String urlPath) {
   try {
     JMXServiceURL url = new JMXServiceURL("rmi", "", 0, urlPath);
     this.jmxc = JMXConnectorFactory.connect(url);
     this.server = jmxc.getMBeanServerConnection();
   } catch (MalformedURLException e) {
     // should not reach here
   } catch (IOException e) {
     System.err.println("\nCommunication error: " + e.getMessage());
     System.exit(1);
   }
 }
Example #16
0
  private static void checkMap() throws Exception {
    // Add new system properties
    System.setProperty(KEY1, VALUE1);
    System.setProperty(KEY2, VALUE2);

    TabularData props1 = (TabularData) server.getAttribute(runtime, "SystemProperties");

    String value1 = getProperty(props1, KEY1);
    if (value1 == null || !value1.equals(VALUE1)) {
      throw new RuntimeException(
          "TEST FAILED: "
              + KEY1
              + " property found"
              + " with value = "
              + value1
              + " but expected to be "
              + VALUE1);
    }

    String value2 = getProperty(props1, KEY2);
    if (value2 == null || !value2.equals(VALUE2)) {
      throw new RuntimeException(
          "TEST FAILED: "
              + KEY2
              + " property found"
              + " with value = "
              + value2
              + " but expected to be "
              + VALUE2);
    }

    String value3 = getProperty(props1, KEY3);
    if (value3 != null) {
      throw new RuntimeException(
          "TEST FAILED: " + KEY3 + " property found" + " but should not exist");
    }
  }
Example #17
0
  /**
   * Handle a single JMXRequest. The response status is set to 200 if the request was successful
   *
   * @param pJmxReq request to perform
   * @return the already converted answer.
   * @throws InstanceNotFoundException
   * @throws AttributeNotFoundException
   * @throws ReflectionException
   * @throws MBeanException
   */
  public JSONObject handleRequest(JmxRequest pJmxReq)
      throws InstanceNotFoundException, AttributeNotFoundException, ReflectionException,
          MBeanException, IOException {
    lazyInitIfNeeded();

    boolean debug = isDebug();

    long time = 0;
    if (debug) {
      time = System.currentTimeMillis();
    }
    JSONObject json = callRequestDispatcher(pJmxReq);

    // Update global history store
    historyStore.updateAndAdd(pJmxReq, json);
    json.put("status", 200 /* success */);

    if (debug) {
      debug("Execution time: " + (System.currentTimeMillis() - time) + " ms");
      debug("Response: " + json);
    }

    return json;
  }
Example #18
0
  public static void main(String[] args) throws Exception {
    // TODO Auto-generated method stub
    if (args.length != 4) {
      System.err.println("Please provide process id zabbix-host zabbix-port host-guid");
      System.exit(-1);
    }
    String processPid = args[0];
    String zabbixHost = args[1];
    String zabbixPort = args[2];
    String hostGuid = args[3];

    VirtualMachine vm = VirtualMachine.attach(processPid);
    String connectorAddr =
        vm.getAgentProperties().getProperty("com.sun.management.jmxremote.localConnectorAddress");
    if (connectorAddr == null) {
      String agent =
          vm.getSystemProperties().getProperty("java.home")
              + File.separator
              + "lib"
              + File.separator
              + "management-agent.jar";
      vm.loadAgent(agent);
      connectorAddr =
          vm.getAgentProperties().getProperty("com.sun.management.jmxremote.localConnectorAddress");
    }
    JMXServiceURL serviceURL = new JMXServiceURL(connectorAddr);
    JMXConnector connector = JMXConnectorFactory.connect(serviceURL);
    MBeanServerConnection mbsc = connector.getMBeanServerConnection();
    ObjectName objName = new ObjectName(ManagementFactory.THREAD_MXBEAN_NAME);
    Set<ObjectName> mbeans = mbsc.queryNames(objName, null);
    for (ObjectName name : mbeans) {
      ThreadMXBean threadBean;
      threadBean =
          ManagementFactory.newPlatformMXBeanProxy(mbsc, name.toString(), ThreadMXBean.class);
      long threadIds[] = threadBean.getAllThreadIds();
      for (long threadId : threadIds) {
        ThreadInfo threadInfo = threadBean.getThreadInfo(threadId);
        System.out.println(threadInfo.getThreadName() + " / " + threadInfo.getThreadState());
      }
    }
  }
Example #19
0
  public CompositeData getNextEntry(Object[] indexObjects) {

    // User code starts here
    if (!agentName.initAlert()) return null;

    String previousKeys[] = {indexObjects[0].toString(), indexObjects[1].toString()};
    String keys[] = getNextAlert(previousKeys);

    if (keys == null) return null;

    String source = keys[0];

    // String ownerName = keys[1];

    String entity = keys[1];

    Alert alert1 = new Alert();

    alert1.setSource(source);

    //	alert1.setOwnerName(ownerName);

    alert1.setEntity(entity);

    Alert alert2 = new Alert();

    alert2.setModTime(System.currentTimeMillis());

    Vector alerts = null;

    try {
      alerts = agentName.alertAPI.getAlerts(alert1, alert2);

      if (alerts != null) return makeComData((Alert) alerts.elementAt(0));
    } catch (Exception e) {
      return null;
    }

    // User code ends here
    return null;
  }
 /**
  * Creates a new AgentMBeanServerConnectionFactory
  *
  * @param builder The AgentMBeanServerConnectionFactory builder
  */
 protected AgentMBeanServerConnectionFactory(Builder builder) {
   this.channel = builder.channel;
   this.remoteAddress =
       builder.remoteAddress == null ? this.channel.getRemoteAddress() : builder.remoteAddress;
   this.timeout = builder.timeout;
   this.listener = builder.listener;
   this.domain = builder.domain;
   if ("DefaultDomain".equals(domain)) {
     domainInfoData = new byte[] {0};
   } else {
     byte[] domainBytes = domain.getBytes();
     domainInfoData = new byte[domainBytes.length + 1];
     domainInfoData[0] = (byte) domainBytes.length;
     System.arraycopy(domainBytes, 0, domainInfoData, 1, domainBytes.length);
   }
   if (channel.getPipeline().get(getClass().getSimpleName()) == null) {
     this.channel.getPipeline().addFirst(getClass().getSimpleName(), responseHandler);
     //			LoggingHandler logg = new LoggingHandler(InternalLogLevel.ERROR, true);
     //			this.channel.getPipeline().addFirst("logger", logg);
   }
 }
  /* Setter for the CacheSize attribute. To avoid problems with
  stale values in multithreaded situations, it is a good idea
  for setters to be synchronized. */
  public synchronized void setCacheSize(int size) {
    int oldSize = this.cacheSize;
    this.cacheSize = size;

    /* In a real application, changing the attribute would
    typically have effects beyond just modifying the cacheSize
    field.  For example, resizing the cache might mean
    discarding entries or allocating new ones. The logic for
    these effects would be here. */
    System.out.println("Cache size now " + this.cacheSize);

    /* Construct a notification that describes the change. The
    "source" of a notification is the ObjectName of the MBean
    that emitted it. But an MBean can put a reference to
    itself ("this") in the source, and the MBean server will
    replace this with the ObjectName before sending the
    notification on to its clients.

    For good measure, we maintain a sequence number for each
    notification emitted by this MBean.

    The oldValue and newValue parameters to the constructor are
    of type Object, so we are relying on Tiger's autoboxing
    here.  */
    Notification n =
        new AttributeChangeNotification(
            this,
            sequenceNumber++,
            System.currentTimeMillis(),
            "CacheSize changed",
            "CacheSize",
            "int",
            oldSize,
            this.cacheSize);

    /* Now send the notification using the sendNotification method
    inherited from the parent class NotificationBroadcasterSupport. */
    sendNotification(n);
  }
 /**
  * Deserializes an array of arguments from a byte array
  *
  * @param bytes The byte array containing the serialized arguments
  * @return an object array
  */
 public static Object[] getInput(byte[] bytes) {
   if (bytes.length == 0 || (bytes.length == 1 && bytes[0] == 0)) return new Object[0];
   ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
   ObjectInputStream ois = null;
   GZIPInputStream gzis = null;
   Object[] args = null;
   try {
     gzis = new GZIPInputStream(bais);
     ois = new ObjectInputStream(gzis);
     Object obj = ois.readObject();
     if (obj.getClass().isArray()) {
       args = new Object[Array.getLength(obj)];
       System.arraycopy(obj, 0, args, 0, args.length);
     } else {
       args = new Object[] {obj};
     }
     return args;
   } catch (Exception ex) {
     throw new RuntimeException("Failed to decode MBeanServerConnection Invocation arguments", ex);
   } finally {
     try {
       bais.close();
     } catch (Exception ex) {
       /* No Op */
     }
     if (ois != null)
       try {
         ois.close();
       } catch (Exception ex) {
         /* No Op */
       }
     if (gzis != null)
       try {
         gzis.close();
       } catch (Exception ex) {
         /* No Op */
       }
   }
 }
  public void start() {

    if ((this.state == this.STARTING_STATE)
        || (this.state == this.RUNNING_STATE)
        || (this.state == this.STOPPING_STATE)) {
      throw new RuntimeException(
          new Exception("cannot start because the current state is " + this.state));
    }

    try {
      this.state = this.STARTING_STATE;
      this.stateChanged("j2ee.state.starting");
      module.start(this);
      this.state = this.RUNNING_STATE;
      this.startTime = System.currentTimeMillis();
      this.stateChanged("j2ee.state.running");
    } catch (Exception ex) {
      this.state = this.FAILED_STATE;
      this.stateChanged("j2ee.state.failed");
      if (ex instanceof RuntimeException) throw (RuntimeException) ex;
      throw new RuntimeException(ex);
    }
  }
Example #24
0
  /**
   * Creates an RMI Connector Server, starts it, and registers it with the Jini Lookup Service.
   *
   * <p>This method will transfer a fixed set of System Properties to the Map given to the
   * RMIConnectorServer constructor. Some JNDI properties, if defined, are transfered to the Map so
   * that they may be used when LDAP is used as external directory to register the RMI Stub (see
   * {@link javax.management.remote.rmi} Javadoc). Note that even if LDAP is used as external
   * directory the {@link Context#INITIAL_CONTEXT_FACTORY Context.INITIAL_CONTEXT_FACTORY} and
   * {@link Context#PROVIDER_URL Context.PROVIDER_URL} properties usually don't need to be passed.
   *
   * <p>The following System properties, if defined, are transfered to the Map given to the
   * RMIConnectorServer constructor.
   *
   * <ul>
   *   <li>{@link Context#INITIAL_CONTEXT_FACTORY Context.INITIAL_CONTEXT_FACTORY}
   *   <li>{@link Context#PROVIDER_URL Context.PROVIDER_URL}
   *   <li>{@link Context#SECURITY_PRINCIPAL Context.SECURITY_PRINCIPAL}
   *   <li>{@link Context#SECURITY_CREDENTIALS Context.SECURITY_CREDENTIALS}
   *   <li>{@link RMIConnectorServer#JNDI_REBIND_ATTRIBUTE RMIConnectorServer.JNDI_REBIND_ATTRIBUTE}
   *       - default is <code>true</code>.
   * </ul>
   *
   * @param url A string representation of the JMXServiceURL.
   * @return the created RMIConnectorServer.
   */
  public JMXConnectorServer rmi(String url)
      throws IOException, JMException, ClassNotFoundException {

    // Make a JMXServiceURL from the url string.
    //
    JMXServiceURL jurl = new JMXServiceURL(url);

    // Prepare the environment Map
    //
    final HashMap env = new HashMap();
    final String rprop = RMIConnectorServer.JNDI_REBIND_ATTRIBUTE;
    final String rebind = System.getProperty(rprop, "true");
    final String factory = System.getProperty(Context.INITIAL_CONTEXT_FACTORY);
    final String ldapServerUrl = System.getProperty(Context.PROVIDER_URL);
    final String ldapUser = System.getProperty(Context.SECURITY_PRINCIPAL);
    final String ldapPasswd = System.getProperty(Context.SECURITY_CREDENTIALS);

    // Transfer some system properties to the Map
    //
    if (factory != null) // this should not be needed
    env.put(Context.INITIAL_CONTEXT_FACTORY, factory);
    if (ldapServerUrl != null) // this should not be needed
    env.put(Context.PROVIDER_URL, ldapServerUrl);
    if (ldapUser != null) // this is needed when LDAP is used
    env.put(Context.SECURITY_PRINCIPAL, ldapUser);
    if (ldapPasswd != null) // this is needed when LDAP is used
    env.put(Context.SECURITY_CREDENTIALS, ldapPasswd);
    env.put(rprop, rebind); // default is true.

    // Create an RMIConnectorServer
    //
    System.out.println("Creating RMI Connector: " + jurl);
    JMXConnectorServer rmis = JMXConnectorServerFactory.newJMXConnectorServer(jurl, env, mbs);

    // Get the AgentName for registering the Connector in the Lookup Service
    //
    final String agentName = System.getProperty("agent.name", "DefaultAgent");

    // Start the connector and register it with Jini Lookup Service.
    //
    start(rmis, env, agentName);

    return rmis;
  }
 /**
  * The notifications dispatch thread. The dispatch thread sends all pending notifications in the
  * buffer to the client. The dispatch thread exits, whenever an IOException occurs during actual
  * dispatch or whenever this connection is being closed (after a call to close())
  */
 public void run() {
   /* XXX: Even when we are exiting should we send the remaining notifications?
    *      OR just drop the remaining notifications ?
    *
    *     Currently we drop all the remaining notifications!!
    */
   while (!isExiting() && !hasIOExceptionOccurred()) {
     synchronized (que) {
       while (que.isEmpty() && !isExiting() && !hasIOExceptionOccurred()) {
         try {
           que.wait();
         } catch (InterruptedException intre) {
         }
       }
     }
     if (isExiting() || hasIOExceptionOccurred()) break;
     dispatching = true;
     while (!que.isEmpty() && !isExiting() && !hasIOExceptionOccurred()) {
       NotificationWrapper wrapr = (NotificationWrapper) que.remove();
       try {
         sendNotificationMsg(wrapr);
       } catch (IOException ioe) {
         if (isExiting()) break;
         // XXX: Log it; drop the notification
         if (!isDisconnected(ioe)) break;
         isIOException = true;
         synchronized (this) {
           this.notify();
         }
         break;
       }
     }
     lastNotifTime = System.currentTimeMillis();
     dispatching = false;
   }
 }
class DBPortPool extends SimplePool<DBPort> {

  static class Holder {

    Holder(MongoOptions options) {
      _options = options;
    }

    DBPortPool get(InetSocketAddress addr) {

      DBPortPool p = _pools.get(addr);

      if (p != null) return p;

      synchronized (_pools) {
        p = _pools.get(addr);
        if (p != null) {
          return p;
        }

        p = new DBPortPool(addr, _options);
        _pools.put(addr, p);
        String name = "com.mongodb:type=ConnectionPool,host=" + addr.toString().replace(':', '_');

        try {
          ObjectName on = new ObjectName(name);
          if (_server.isRegistered(on)) {
            _server.unregisterMBean(on);
            Bytes.LOGGER.log(
                Level.INFO, "multiple Mongo instances for same host, jmx numbers might be off");
          }
          _server.registerMBean(p, on);
        } catch (JMException e) {
          Bytes.LOGGER.log(Level.WARNING, "jmx registration error, continuing", e);
        } catch (java.security.AccessControlException e) {
          Bytes.LOGGER.log(Level.WARNING, "jmx registration error, continuing", e);
        }
      }

      return p;
    }

    void close() {
      synchronized (_pools) {
        for (DBPortPool p : _pools.values()) {
          p.close();
        }
      }
    }

    final MongoOptions _options;
    final Map<InetSocketAddress, DBPortPool> _pools =
        Collections.synchronizedMap(new HashMap<InetSocketAddress, DBPortPool>());
    final MBeanServer _server = ManagementFactory.getPlatformMBeanServer();
  }

  // ----

  public static class NoMoreConnection extends MongoInternalException {
    NoMoreConnection(String msg) {
      super(msg);
    }
  }

  public static class SemaphoresOut extends NoMoreConnection {
    SemaphoresOut() {
      super("Out of semaphores to get db connection");
    }
  }

  public static class ConnectionWaitTimeOut extends NoMoreConnection {
    ConnectionWaitTimeOut(int timeout) {
      super("Connection wait timeout after " + timeout + " ms");
    }
  }

  // ----

  DBPortPool(InetSocketAddress addr, MongoOptions options) {
    super("DBPortPool-" + addr.toString(), options.connectionsPerHost, options.connectionsPerHost);
    _options = options;
    _addr = addr;
    _waitingSem =
        new Semaphore(
            _options.connectionsPerHost * _options.threadsAllowedToBlockForConnectionMultiplier);
  }

  protected long memSize(DBPort p) {
    return 0;
  }

  protected int pick(int iThink, boolean couldCreate) {
    final int id = Thread.currentThread().hashCode();
    final int s = _availSafe.size();
    for (int i = 0; i < s; i++) {
      DBPort p = _availSafe.get(i);
      if (p._lastThread == id) return i;
    }

    if (couldCreate) return -1;
    return iThink;
  }

  public DBPort get() {
    DBPort port = null;
    if (!_waitingSem.tryAcquire()) throw new SemaphoresOut();

    try {
      port = get(_options.maxWaitTime);
    } finally {
      _waitingSem.release();
    }

    if (port == null) throw new ConnectionWaitTimeOut(_options.maxWaitTime);

    port._lastThread = Thread.currentThread().hashCode();
    return port;
  }

  void gotError(Exception e) {
    if (e instanceof java.nio.channels.ClosedByInterruptException
        || e instanceof InterruptedException) {
      // this is probably a request that is taking too long
      // so usually doesn't mean there is a real db problem
      return;
    }

    if (e instanceof java.net.SocketTimeoutException && _options.socketTimeout > 0) {
      // we don't want to clear the port pool for 1 connection timing out
      return;
    }

    // We don't want to clear the entire pool for the occasional error.
    if (e instanceof SocketException) {
      if (recentFailures < ALLOWED_ERRORS_BEFORE_CLEAR) {
        return;
      }
    }

    Bytes.LOGGER.log(Level.INFO, "emptying DBPortPool b/c of error", e);
    clear();
  }

  void close() {
    clear();
  }

  public void cleanup(DBPort p) {
    p.close();
  }

  public boolean ok(DBPort t) {
    return _addr.equals(t._addr);
  }

  protected DBPort createNew() throws MongoInternalException {
    try {
      return new DBPort(_addr, this, _options);
    } catch (IOException ioe) {
      throw new MongoInternalException("can't create port to:" + _addr, ioe);
    }
  }

  public int getRecentFailures() {
    return recentFailures;
  }

  public void incrementRecentFailures() {
    _logger.warning("Failure recorded:" + _addr.toString());
    this.recentFailures++;
  }

  public void resetRecentFailures() {
    if (this.recentFailures > 0) {
      _logger.warning("Successful Request. Reseting recent failures:" + _addr.toString());
    }

    this.recentFailures = 0;
  }

  final MongoOptions _options;
  private final Semaphore _waitingSem;
  final InetSocketAddress _addr;
  boolean _everWorked = false;
  public static final Integer ALLOWED_ERRORS_BEFORE_CLEAR =
      Integer.valueOf(System.getProperty("MONGO.ERRORS_BEFORE_CLEAR", "5"));
  private Logger _logger = Logger.getLogger(DBPortPool.class.toString());

  /** The number of failures that this port pool has recently experienced. */
  private int recentFailures = 0;
}
Example #27
0
  /**
   * Program Main.
   *
   * <p>Lookup all JMX agents in the LDAP Directory and list their MBeans and attributes.
   *
   * <p>You may wish to use the following properties on the Java command line:
   *
   * <ul>
   *   <li><code>-Dagent.name=&lt;AgentName&gt;</code>: specifies an AgentName to lookup (default is
   *       null, meaning any agent).
   *   <li><code>-Dprotocol=&lt;ProtocolType&gt;</code>: restrains the client to lookup for a
   *       specific protocol type (default is null, meaning any type).
   *   <li><code>-Djava.naming.factory.initial=&lt;initial-context-factory&gt;
   *     </code>: The initial context factory to use for accessing the LDAP directory (see {@link
   *       Context#INITIAL_CONTEXT_FACTORY Context.INITIAL_CONTEXT_FACTORY}) - default is <code>
   *       "com.sun.jndi.ldap.LdapCtxFactory"</code>.
   *   <li><code>-Djava.naming.provider.url=&lt;provider-url&gt;</code>: The LDAP Provider URL (see
   *       {@link Context#PROVIDER_URL Context.PROVIDER_URL}).
   *   <li><code>-Djava.naming.security.principal=&lt;ldap-principal&gt;
   *     </code>: The security principal (login) to use to connect with the LDAP directory (see
   *       {@link Context#SECURITY_PRINCIPAL Context.SECURITY_PRINCIPAL} - default is <code>
   *       "cn=Directory Manager"</code>.
   *   <li><code>-Djava.naming.security.credentials=&lt;ldap-credentials&gt;
   *     </code>: The security credentials (password) to use to connect with the LDAP directory (see
   *       {@link Context#SECURITY_CREDENTIALS Context.SECURITY_CREDENTIALS}).
   *   <li><code>-Ddebug="true|false"</code>: switch the Server debug flag on/off (default is
   *       "false")
   * </ul>
   */
  public static void main(String[] args) {
    try {
      // Get the value of the debug flag.
      //
      debug = (Boolean.valueOf(System.getProperty("debug", "false"))).booleanValue();

      // Get a pointer to the LDAP Directory.
      //
      final DirContext root = getRootContext();
      debug("root is: " + root.getNameInNamespace());

      final String protocolType = System.getProperty("protocol");
      final String agentName = System.getProperty("agent.name");

      // Lookup all matching agents in the LDAP Directory.
      //
      List l = lookup(root, protocolType, agentName);

      // Attempt to connect to retrieved agents
      //
      System.out.println("Number of agents found : " + l.size());
      int j = 1;
      for (Iterator i = l.iterator(); i.hasNext(); j++) {
        JMXConnector c1 = (JMXConnector) i.next();
        if (c1 != null) {

          // Connect
          //
          System.out.println("----------------------------------------------------");
          System.out.println("\tConnecting to agent number " + j);
          System.out.println("----------------------------------------------------");
          debug("JMXConnector is: " + c1);

          // Prepare the environment Map
          //
          final HashMap env = new HashMap();
          final String factory = System.getProperty(Context.INITIAL_CONTEXT_FACTORY);
          final String ldapServerUrl = System.getProperty(Context.PROVIDER_URL);
          final String ldapUser = System.getProperty(Context.SECURITY_PRINCIPAL);
          final String ldapPasswd = System.getProperty(Context.SECURITY_CREDENTIALS);

          // Transfer some system properties to the Map
          //
          if (factory != null) // this should not be needed
          env.put(Context.INITIAL_CONTEXT_FACTORY, factory);
          if (ldapServerUrl != null) // this should not be needed
          env.put(Context.PROVIDER_URL, ldapServerUrl);
          if (ldapUser != null) // this is needed when LDAP is used
          env.put(Context.SECURITY_PRINCIPAL, ldapUser);
          if (ldapPasswd != null) // this is needed when LDAP is used
          env.put(Context.SECURITY_CREDENTIALS, ldapPasswd);

          try {
            c1.connect(env);
          } catch (IOException x) {
            System.err.println("Connection failed: " + x);
            x.printStackTrace(System.err);
            continue;
          }

          // Get MBeanServerConnection
          //
          MBeanServerConnection conn = c1.getMBeanServerConnection();
          debug("Connection is:" + conn);
          System.out.println("Server domain is: " + conn.getDefaultDomain());

          // List all MBeans
          //
          try {
            listMBeans(conn);
          } catch (IOException x) {
            System.err.println("Failed to list MBeans: " + x);
            x.printStackTrace(System.err);
          }

          // Close connector
          //
          try {
            c1.close();
          } catch (IOException x) {
            System.err.println("Failed to close connection: " + x);
            x.printStackTrace(System.err);
          }
        }
      }
    } catch (Exception x) {
      System.err.println("Unexpected exception caught in main: " + x);
      x.printStackTrace(System.err);
    }
  }
 private static void setSystemPropertyIfNotDefined(String systemPropertyName, String value) {
   if (!System.getProperties().contains(systemPropertyName))
     System.setProperty(systemPropertyName, value);
 }
Example #29
0
  /**
   * Program Main
   *
   * <p>Lookup all JMX agents in the Jini Lookup Service and list their MBeans and attributes.
   *
   * <p>You may wish to use the following properties on the Java command line:
   *
   * <ul>
   *   <li><code>-Dagent.name=&lt;AgentName&gt;</code>: specifies an AgentName to lookup (default is
   *       null, meaning any agent).
   *   <li><code>-Djini.lookup.url=&lt;jini-url&gt;</code>: the Jini Lookup Service URL (default is
   *       "jini://localhost"), see {@link #getRegistrar()}.
   *   <li><code>-Ddebug="true|false"</code>: switch the Client debug flag on/off (default is
   *       "false").
   * </ul>
   */
  public static void main(String[] args) {
    try {
      // Jini requires a security manager.
      //
      if (System.getSecurityManager() == null) System.setSecurityManager(new RMISecurityManager());

      // Get the value of the debug flag.
      //
      debug = (Boolean.valueOf(System.getProperty("debug", "false"))).booleanValue();

      // Get AgentName to lookup. If not defined, all agents
      // are looked up.
      //
      final String agentName = System.getProperty("agent.name");

      // Get a pointer to the Jini Lookup Service.
      //
      final ServiceRegistrar registrar = getRegistrar();
      debug("registrar is: " + registrar);

      // Lookup all matching agents in the Jini Lookup Service.
      //
      List l = lookup(registrar, agentName);

      // Attempt to connect to retrieved agents
      //
      System.out.println("Number of agents found : " + l.size());
      int j = 1;
      for (Iterator i = l.iterator(); i.hasNext(); j++) {
        JMXConnector c1 = (JMXConnector) i.next();
        if (c1 != null) {

          // Connect
          //
          System.out.println("----------------------------------------------------");
          System.out.println("\tConnecting to agent number " + j);
          System.out.println("----------------------------------------------------");
          debug("JMXConnector is: " + c1);

          try {
            c1.connect(null);
          } catch (IOException x) {
            System.err.println("Connection failed: " + x);
            if (debug) x.printStackTrace(System.err);
            continue;
          }

          // Get MBeanServerConnection
          //
          MBeanServerConnection conn = c1.getMBeanServerConnection();
          debug("Connection is:" + conn);
          System.out.println("Server domain is: " + conn.getDefaultDomain());

          // List all MBeans
          //
          try {
            listMBeans(conn);
          } catch (IOException x) {
            System.err.println("Failed to list MBeans: " + x);
            if (debug) x.printStackTrace(System.err);
          }

          // Close connector
          //
          try {
            c1.close();
          } catch (IOException x) {
            System.err.println("Failed to close connection: " + x);
            if (debug) x.printStackTrace(System.err);
          }
        }
      }
    } catch (Exception x) {
      System.err.println("Unexpected exception caught in main: " + x);
      x.printStackTrace(System.err);
    }
  }
Example #30
0
 public long getUptime() {
   return System.currentTimeMillis() - startTime;
 }