Save This Page
Home » apache-tomcat-6.0.16-src » org.apache » catalina » ant » jmx » [javadoc | source]
    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    * 
    9    *      http://www.apache.org/licenses/LICENSE-2.0
   10    * 
   11    * Unless required by applicable law or agreed to in writing, software
   12    * distributed under the License is distributed on an "AS IS" BASIS,
   13    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   14    * See the License for the specific language governing permissions and
   15    * limitations under the License.
   16    */
   17   
   18   package org.apache.catalina.ant.jmx;
   19   
   20   import java.io.IOException;
   21   import java.lang.reflect.Array;
   22   import java.net.InetAddress;
   23   import java.net.MalformedURLException;
   24   import java.net.UnknownHostException;
   25   import java.util.HashMap;
   26   import java.util.Iterator;
   27   import java.util.List;
   28   import java.util.Map;
   29   import java.util.Properties;
   30   import java.util.Set;
   31   import java.util.StringTokenizer;
   32   
   33   import javax.management.MBeanServerConnection;
   34   import javax.management.MalformedObjectNameException;
   35   import javax.management.ObjectName;
   36   import javax.management.openmbean.CompositeData;
   37   import javax.management.openmbean.CompositeDataSupport;
   38   import javax.management.openmbean.CompositeType;
   39   import javax.management.openmbean.OpenType;
   40   import javax.management.openmbean.SimpleType;
   41   import javax.management.openmbean.TabularDataSupport;
   42   import javax.management.remote.JMXConnector;
   43   import javax.management.remote.JMXConnectorFactory;
   44   import javax.management.remote.JMXServiceURL;
   45   
   46   import org.apache.catalina.ant.BaseRedirectorHelperTask;
   47   import org.apache.tools.ant.BuildException;
   48   import org.apache.tools.ant.Project;
   49   
   50   /**
   51    * Access <em>JMX</em> JSR 160 MBeans Server.
   52    * <ul>
   53    * <li>open more then one JSR 160 rmi connection</li>
   54    * <li>Get/Set Mbeans attributes</li>
   55    * <li>Call Mbean Operation with arguments</li>
   56    * <li>Argument values can be converted from string to
   57    * int,long,float,double,boolean,ObjectName or InetAddress</li>
   58    * <li>Query Mbeans</li>
   59    * <li>Show Get, Call, Query result at Ant console log</li>
   60    * <li>Bind Get, Call, Query result at Ant properties</li>
   61    * </ul>
   62    * 
   63    * Examples: open server with reference and autorisation
   64    * 
   65    * <pre>
   66    * 
   67    *    &lt;jmxOpen
   68    *            host=&quot;127.0.0.1&quot;
   69    *            port=&quot;9014&quot;
   70    *            username=&quot;monitorRole&quot;
   71    *            password=&quot;mysecret&quot;
   72    *            ref=&quot;jmx.myserver&quot; 
   73    *        /&gt;
   74    *  
   75    * </pre>
   76    * 
   77    * All calls after opening with same refid reuse the connection.
   78    * <p>
   79    * First call to a remote MBeanserver save the JMXConnection a referenz
   80    * <em>jmx.server</em>
   81    * </p>
   82    * All JMXAccessorXXXTask support the attribute <em>if</em> and
   83    * <em>unless</em>. With <em>if</em> the task is only execute when property
   84    * exist and with <em>unless</em> when property not exists. <br/><b>NOTE
   85    * </b>: These tasks require Ant 1.6 or later interface.
   86    * 
   87    * @author Peter Rossbach
   88    * @version $Revision: 467222 $ $Date: 2006-10-24 05:17:11 +0200 (mar., 24 oct. 2006) $
   89    * @since 5.5.10
   90    */
   91   
   92   public class JMXAccessorTask extends BaseRedirectorHelperTask {
   93   
   94       // ----------------------------------------------------- Instance Variables
   95   
   96       public static String JMX_SERVICE_PREFIX = "service:jmx:rmi:///jndi/rmi://";
   97   
   98       public static String JMX_SERVICE_SUFFIX = "/jmxrmi";
   99   
  100       private String name = null;
  101   
  102       private String resultproperty;
  103   
  104       private String url = null;
  105   
  106       private String host = "localhost";
  107   
  108       private String port = "8050";
  109   
  110       private String password = null;
  111   
  112       private String username = null;
  113   
  114       private String ref = "jmx.server";
  115   
  116       private boolean echo = false;
  117   
  118       private boolean separatearrayresults = true;
  119   
  120       private String delimiter;
  121   
  122       private String unlessCondition;
  123   
  124       private String ifCondition;
  125   
  126       private Properties properties = new Properties();
  127   
  128       // ----------------------------------------------------- Instance Info
  129   
  130       /**
  131        * Descriptive information describing this implementation.
  132        */
  133       private static final String info = "org.apache.catalina.ant.JMXAccessorTask/1.1";
  134   
  135       /**
  136        * Return descriptive information about this implementation and the
  137        * corresponding version number, in the format
  138        * <code>&lt;description&gt;/&lt;version&gt;</code>.
  139        */
  140       public String getInfo() {
  141   
  142           return (info);
  143   
  144       }
  145   
  146       // ------------------------------------------------------------- Properties
  147   
  148       /**
  149        * The name used at remote MbeanServer
  150        */
  151   
  152       public String getName() {
  153           return (this.name);
  154       }
  155   
  156       public void setName(String objectName) {
  157           this.name = objectName;
  158       }
  159   
  160       /**
  161        * @return Returns the resultproperty.
  162        */
  163       public String getResultproperty() {
  164           return resultproperty;
  165       }
  166   
  167       /**
  168        * @param propertyName The resultproperty to set.
  169        */
  170       public void setResultproperty(String propertyName) {
  171           this.resultproperty = propertyName;
  172       }
  173   
  174       /**
  175        * @return Returns the delimiter.
  176        */
  177       public String getDelimiter() {
  178           return delimiter;
  179       }
  180   
  181       /**
  182        * @param separator The delimiter to set.
  183        */
  184       public void setDelimiter(String separator) {
  185           this.delimiter = separator;
  186       }
  187   
  188       /**
  189        * @return Returns the echo.
  190        */
  191       public boolean isEcho() {
  192           return echo;
  193       }
  194   
  195       /**
  196        * @param echo
  197        *            The echo to set.
  198        */
  199       public void setEcho(boolean echo) {
  200           this.echo = echo;
  201       }
  202   
  203       /**
  204        * @return Returns the separatearrayresults.
  205        */
  206       public boolean isSeparatearrayresults() {
  207           return separatearrayresults;
  208       }
  209   
  210       /**
  211        * @param separateArrayResults
  212        *            The separatearrayresults to set.
  213        */
  214       public void setSeparatearrayresults(boolean separateArrayResults) {
  215           this.separatearrayresults = separateArrayResults;
  216       }
  217   
  218       /**
  219        * The login password for the <code>Manager</code> application.
  220        */
  221       public String getPassword() {
  222           return (this.password);
  223       }
  224   
  225       public void setPassword(String password) {
  226           this.password = password;
  227       }
  228   
  229       /**
  230        * The login username for the <code>JMX</code> MBeanServer.
  231        */
  232       public String getUsername() {
  233           return (this.username);
  234       }
  235   
  236       public void setUsername(String username) {
  237           this.username = username;
  238       }
  239   
  240       /**
  241        * The URL of the <code>JMX JSR 160</code> MBeanServer to be used.
  242        */
  243   
  244       public String getUrl() {
  245           return (this.url);
  246       }
  247   
  248       public void setUrl(String url) {
  249           this.url = url;
  250       }
  251   
  252       /**
  253        * The Host of the <code>JMX JSR 160</code> MBeanServer to be used.
  254        */
  255   
  256       public String getHost() {
  257           return (this.host);
  258       }
  259   
  260       public void setHost(String host) {
  261           this.host = host;
  262       }
  263   
  264       /**
  265        * The Port of the <code>JMX JSR 160</code> MBeanServer to be used.
  266        */
  267   
  268       public String getPort() {
  269           return (this.port);
  270       }
  271   
  272       public void setPort(String port) {
  273           this.port = port;
  274       }
  275   
  276       /**
  277        * @return Returns the useRef.
  278        */
  279       public boolean isUseRef() {
  280           return ref != null && !"".equals(ref);
  281       }
  282   
  283       /**
  284        * @return Returns the ref.
  285        */
  286       public String getRef() {
  287           return ref;
  288       }
  289   
  290       /**
  291        * @param refId The ref to set.
  292        */
  293       public void setRef(String refId) {
  294           this.ref = refId;
  295       }
  296   
  297       /**
  298        * @return Returns the ifCondition.
  299        */
  300       public String getIf() {
  301           return ifCondition;
  302       }
  303   
  304       /**
  305        * Only execute if a property of the given name exists in the current
  306        * project.
  307        * 
  308        * @param c property name
  309        */
  310       public void setIf(String c) {
  311           ifCondition = c;
  312       }
  313   
  314       /**
  315        * @return Returns the unlessCondition.
  316        */
  317       public String getUnless() {
  318           return unlessCondition;
  319       }
  320   
  321       /**
  322        * Only execute if a property of the given name does not exist in the
  323        * current project.
  324        * 
  325        * @param c property name
  326        */
  327       public void setUnless(String c) {
  328           unlessCondition = c;
  329       }
  330   
  331       // --------------------------------------------------------- Public Methods
  332   
  333       /**
  334        * Execute the specified command. This logic only performs the common
  335        * attribute validation required by all subclasses; it does not perform any
  336        * functional logic directly.
  337        * 
  338        * @exception BuildException
  339        *                if a validation error occurs
  340        */
  341       public void execute() throws BuildException {
  342           if (testIfCondition() && testUnlessCondition()) {
  343               try {
  344                   String error = null;
  345   
  346                   MBeanServerConnection jmxServerConnection = getJMXConnection();
  347                   error = jmxExecute(jmxServerConnection);
  348                   if (error != null && isFailOnError()) {
  349                       // exception should be thrown only if failOnError == true
  350                       // or error line will be logged twice
  351                       throw new BuildException(error);
  352                   }
  353               } catch (Throwable t) {
  354                   if (isFailOnError()) {
  355                       throw new BuildException(t);
  356                   } else {
  357                       handleErrorOutput(t.getMessage());
  358                   }
  359               } finally {
  360                   closeRedirector();
  361               }
  362           }
  363       }
  364   
  365       /**
  366        * create a new JMX Connection with auth when username and password is set.
  367        */
  368       public static MBeanServerConnection createJMXConnection(String url,
  369               String host, String port, String username, String password)
  370               throws MalformedURLException, IOException {
  371           String urlForJMX;
  372           if (url != null)
  373               urlForJMX = url;
  374           else
  375               urlForJMX = JMX_SERVICE_PREFIX + host + ":" + port
  376                       + JMX_SERVICE_SUFFIX;
  377           Map environment = null;
  378           if (username != null && password != null) {
  379               String[] credentials = new String[2];
  380               credentials[0] = username;
  381               credentials[1] = password;
  382               environment = new HashMap();
  383               environment.put(JMXConnector.CREDENTIALS, credentials);
  384           }
  385           return JMXConnectorFactory.connect(new JMXServiceURL(urlForJMX),
  386                   environment).getMBeanServerConnection();
  387   
  388       }
  389   
  390       /**
  391        * test the if condition
  392        * 
  393        * @return true if there is no if condition, or the named property exists
  394        */
  395       protected boolean testIfCondition() {
  396           if (ifCondition == null || "".equals(ifCondition)) {
  397               return true;
  398           }
  399           return getProperty(ifCondition) != null;
  400       }
  401   
  402       /**
  403        * test the unless condition
  404        * 
  405        * @return true if there is no unless condition, or there is a named
  406        *         property but it doesn't exist
  407        */
  408       protected boolean testUnlessCondition() {
  409           if (unlessCondition == null || "".equals(unlessCondition)) {
  410               return true;
  411           }
  412           return getProperty(unlessCondition) == null;
  413       }
  414   
  415       /**
  416        * Get Current Connection from <em>ref</em> parameter or create a new one!
  417        * 
  418        * @return The server connection
  419        * @throws MalformedURLException
  420        * @throws IOException
  421        */
  422       public static MBeanServerConnection accessJMXConnection(Project project,
  423               String url, String host, String port, String username,
  424               String password, String refId) throws MalformedURLException,
  425               IOException {
  426           MBeanServerConnection jmxServerConnection = null;
  427           boolean isRef = project != null && refId != null && refId.length() > 0;
  428           if (isRef) {
  429               Object pref = project.getReference(refId);
  430               try {
  431                   jmxServerConnection = (MBeanServerConnection) pref;
  432               } catch (ClassCastException cce) {
  433                   if (project != null) {
  434                       project.log("wrong object reference " + refId + " - "
  435                               + pref.getClass());
  436                   }
  437                   return null;
  438               }
  439           }
  440           if (jmxServerConnection == null) {
  441               jmxServerConnection = createJMXConnection(url, host, port,
  442                       username, password);
  443           }
  444           if (isRef && jmxServerConnection != null) {
  445               project.addReference(refId, jmxServerConnection);
  446           }
  447           return jmxServerConnection;
  448       }
  449   
  450       // ------------------------------------------------------ protected Methods
  451   
  452       /**
  453        * get JMXConnection
  454        * 
  455        * @return The connection
  456        * @throws MalformedURLException
  457        * @throws IOException
  458        */
  459       protected MBeanServerConnection getJMXConnection()
  460               throws MalformedURLException, IOException {
  461   
  462           MBeanServerConnection jmxServerConnection = null;
  463           if (isUseRef()) {
  464               Object pref = null ;
  465               if(getProject() != null) {
  466                   pref = getProject().getReference(getRef());
  467                   if (pref != null) {
  468                       try {
  469                           jmxServerConnection = (MBeanServerConnection) pref;
  470                       } catch (ClassCastException cce) {
  471                           getProject().log(
  472                               "Wrong object reference " + getRef() + " - "
  473                                       + pref.getClass());
  474                           return null;
  475                       }
  476                   }
  477               }
  478               if (jmxServerConnection == null) {
  479                   jmxServerConnection = accessJMXConnection(getProject(),
  480                           getUrl(), getHost(), getPort(), getUsername(),
  481                           getPassword(), getRef());
  482               }
  483           } else {
  484               jmxServerConnection = accessJMXConnection(getProject(), getUrl(),
  485                       getHost(), getPort(), getUsername(), getPassword(), null);
  486           }
  487           return jmxServerConnection;
  488       }
  489   
  490       /**
  491        * Execute the specified command, based on the configured properties. The
  492        * input stream will be closed upon completion of this task, whether it was
  493        * executed successfully or not.
  494        * 
  495        * @exception Exception
  496        *                if an error occurs
  497        */
  498       public String jmxExecute(MBeanServerConnection jmxServerConnection)
  499               throws Exception {
  500   
  501           if ((jmxServerConnection == null)) {
  502               throw new BuildException("Must open a connection!");
  503           } else if (isEcho()) {
  504               handleOutput("JMX Connection ref=" + ref + " is open!");
  505           }
  506           return null;
  507       }
  508   
  509       /**
  510        * Convert string to datatype FIXME How we can transfer values from ant
  511        * project reference store (ref)?
  512        * 
  513        * @param value The value
  514        * @param valueType The type
  515        * @return The converted object
  516        */
  517       protected Object convertStringToType(String value, String valueType) {
  518           if ("java.lang.String".equals(valueType))
  519               return value;
  520   
  521           Object convertValue = value;
  522           if ("java.lang.Integer".equals(valueType) || "int".equals(valueType)) {
  523               try {
  524                   convertValue = new Integer(value);
  525               } catch (NumberFormatException ex) {
  526                   if (isEcho())
  527                       handleErrorOutput("Unable to convert to integer:" + value);
  528               }
  529           } else if ("java.lang.Long".equals(valueType)
  530                   || "long".equals(valueType)) {
  531               try {
  532                   convertValue = new Long(value);
  533               } catch (NumberFormatException ex) {
  534                   if (isEcho())
  535                       handleErrorOutput("Unable to convert to long:" + value);
  536               }
  537           } else if ("java.lang.Boolean".equals(valueType)
  538                   || "boolean".equals(valueType)) {
  539               convertValue = new Boolean(value);
  540           } else if ("java.lang.Float".equals(valueType)
  541                   || "float".equals(valueType)) {
  542               try {
  543                   convertValue = new Float(value);
  544               } catch (NumberFormatException ex) {
  545                   if (isEcho())
  546                       handleErrorOutput("Unable to convert to float:" + value);
  547               }
  548           } else if ("java.lang.Double".equals(valueType)
  549                   || "double".equals(valueType)) {
  550               try {
  551                   convertValue = new Double(value);
  552               } catch (NumberFormatException ex) {
  553                   if (isEcho())
  554                       handleErrorOutput("Unable to convert to double:" + value);
  555               }
  556           } else if ("javax.management.ObjectName".equals(valueType)
  557                   || "name".equals(valueType)) {
  558               try {
  559                   convertValue = new ObjectName(value);
  560               } catch (MalformedObjectNameException e) {
  561                   if (isEcho())
  562                       handleErrorOutput("Unable to convert to ObjectName:"
  563                               + value);
  564               }
  565           } else if ("java.net.InetAddress".equals(valueType)) {
  566               try {
  567                   convertValue = InetAddress.getByName(value);
  568               } catch (UnknownHostException exc) {
  569                   if (isEcho())
  570                       handleErrorOutput("Unable to resolve host name:" + value);
  571               }
  572           }
  573           return convertValue;
  574       }
  575   
  576       /**
  577        * @param name context of result
  578        * @param result
  579        */
  580       protected void echoResult(String name, Object result) {
  581           if (isEcho()) {
  582               if (result.getClass().isArray()) {
  583                   for (int i = 0; i < Array.getLength(result); i++) {
  584                       handleOutput(name + "." + i + "=" + Array.get(result, i));
  585                   }
  586               } else
  587                   handleOutput(name + "=" + result);
  588           }
  589       }
  590   
  591       /**
  592        * create result as property with name from attribute resultproperty
  593        * 
  594        * @param result The result
  595        * @see #createProperty(String, Object)
  596        */
  597       protected void createProperty(Object result) {
  598           if (resultproperty != null) {
  599               createProperty(resultproperty, result);
  600           }
  601       }
  602   
  603       /**
  604        * create result as property with name from property prefix When result is
  605        * an array and isSeparateArrayResults is true, resultproperty used as
  606        * prefix (<code>resultproperty.0-array.length</code> and store the
  607        * result array length at <code>resultproperty.length</code>. Other
  608        * option is that you delemit your result with a delimiter
  609        * (java.util.StringTokenizer is used).
  610        * 
  611        * @param propertyPrefix
  612        * @param result
  613        */
  614       protected void createProperty(String propertyPrefix, Object result) {
  615           if (propertyPrefix == null)
  616               propertyPrefix = "";
  617           if (result instanceof CompositeDataSupport) {
  618               CompositeDataSupport data = (CompositeDataSupport) result;
  619               CompositeType compositeType = data.getCompositeType();
  620               Set keys = compositeType.keySet();
  621               for (Iterator iter = keys.iterator(); iter.hasNext();) {
  622                   String key = (String) iter.next();
  623                   Object value = data.get(key);
  624                   OpenType type = compositeType.getType(key);
  625                   if (type instanceof SimpleType) {
  626                       setProperty(propertyPrefix + "." + key, value);
  627                   } else {
  628                       createProperty(propertyPrefix + "." + key, value);
  629                   }
  630               }
  631           } else if (result instanceof TabularDataSupport) {
  632               TabularDataSupport data = (TabularDataSupport) result;
  633               for (Iterator iter = data.keySet().iterator(); iter.hasNext();) {
  634                   Object key = iter.next();
  635                   for (Iterator iter1 = ((List) key).iterator(); iter1.hasNext();) {
  636                       Object key1 = iter1.next();
  637                       CompositeData valuedata = data.get(new Object[] { key1 });
  638                       Object value = valuedata.get("value");
  639                       OpenType type = valuedata.getCompositeType().getType(
  640                               "value");
  641                       if (type instanceof SimpleType) {
  642                           setProperty(propertyPrefix + "." + key1, value);
  643                       } else {
  644                           createProperty(propertyPrefix + "." + key1, value);
  645                       }
  646                   }
  647               }
  648           } else if (result.getClass().isArray()) {
  649               if (isSeparatearrayresults()) {
  650                   int size = 0;
  651                   for (int i = 0; i < Array.getLength(result); i++) {
  652                       if (setProperty(propertyPrefix + "." + size, Array.get(
  653                               result, i))) {
  654                           size++;
  655                       }
  656                   }
  657                   if (size > 0) {
  658                       setProperty(propertyPrefix + ".Length", Integer
  659                               .toString(size));
  660                   }
  661               }
  662           } else {
  663               String delim = getDelimiter();
  664               if (delim != null) {
  665                   StringTokenizer tokenizer = new StringTokenizer(result
  666                           .toString(), delim);
  667                   int size = 0;
  668                   for (; tokenizer.hasMoreTokens();) {
  669                       String token = tokenizer.nextToken();
  670                       if (setProperty(propertyPrefix + "." + size, token)) {
  671                           size++;
  672                       }
  673                   }
  674                   if (size > 0)
  675                       setProperty(propertyPrefix + ".Length", Integer
  676                               .toString(size));
  677               } else {
  678                   setProperty(propertyPrefix, result.toString());
  679               }
  680           }
  681       }
  682   
  683       /**
  684        * get all properties, when project is there got all project Properties
  685        * @return properties
  686        */
  687       public Map getProperties() {
  688           Project currentProject = getProject();
  689           if (currentProject != null) {
  690               return currentProject.getProperties();
  691           } else {
  692               return properties;
  693           }        
  694       }
  695       
  696       /**
  697        * get all Properties
  698        * @param property
  699        * @return The property
  700        */
  701       public String getProperty(String property) {
  702           Project currentProject = getProject();
  703           if (currentProject != null) {
  704               return currentProject.getProperty(property);
  705           } else {
  706               return properties.getProperty(property);
  707           }
  708       }
  709   
  710       /**
  711        * @param property The property
  712        * @param value The value
  713        * @return True if successful
  714        */
  715       public boolean setProperty(String property, Object value) {
  716           if (property != null) {
  717               if (value == null)
  718                   value = "";
  719               if (isEcho()) {
  720                   handleOutput(property + "=" + value.toString());
  721               }
  722               Project currentProject = getProject();
  723               if (currentProject != null) {
  724                   currentProject.setNewProperty(property, value.toString());
  725               } else {
  726                   properties.setProperty(property, value.toString());
  727               }
  728               return true;
  729           }
  730           return false;
  731       }
  732   }

Save This Page
Home » apache-tomcat-6.0.16-src » org.apache » catalina » ant » jmx » [javadoc | source]