View Javadoc

    1   /**
    2    * Copyright (c) 2002-2011 "Neo Technology,"
    3    * Network Engine for Objects in Lund AB [http://neotechnology.com]
    4    *
    5    * This file is part of Neo4j.
    6    *
    7    * Neo4j is free software: you can redistribute it and/or modify
    8    * it under the terms of the GNU General Public License as published by
    9    * the Free Software Foundation, either version 3 of the License, or
    10   * (at your option) any later version.
    11   *
    12   * This program is distributed in the hope that it will be useful,
    13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    15   * GNU General Public License for more details.
    16   *
    17   * You should have received a copy of the GNU General Public License
    18   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    19   */
    20  package org.neo4j.server.webadmin.rest;
    21
    22  import java.io.UnsupportedEncodingException;
    23  import java.lang.management.ManagementFactory;
    24  import java.net.URLDecoder;
    25  import java.util.ArrayList;
    26  import java.util.Collection;
    27
    28  import javax.management.MBeanServer;
    29  import javax.management.MalformedObjectNameException;
    30  import javax.management.ObjectName;
    31  import javax.ws.rs.Consumes;
    32  import javax.ws.rs.FormParam;
    33  import javax.ws.rs.GET;
    34  import javax.ws.rs.POST;
    35  import javax.ws.rs.Path;
    36  import javax.ws.rs.PathParam;
    37  import javax.ws.rs.Produces;
    38  import javax.ws.rs.WebApplicationException;
    39  import javax.ws.rs.core.Context;
    40  import javax.ws.rs.core.MediaType;
    41  import javax.ws.rs.core.Response;
    42
    43  import org.neo4j.jmx.Kernel;
    44  import org.neo4j.server.database.Database;
    45  import org.neo4j.server.database.DatabaseBlockedException;
    46  import org.neo4j.server.rest.domain.JsonHelper;
    47  import org.neo4j.server.rest.repr.BadInputException;
    48  import org.neo4j.server.rest.repr.InputFormat;
    49  import org.neo4j.server.rest.repr.ListRepresentation;
    50  import org.neo4j.server.rest.repr.OutputFormat;
    51  import org.neo4j.server.webadmin.rest.representations.JmxDomainRepresentation;
    52  import org.neo4j.server.webadmin.rest.representations.JmxMBeanRepresentation;
    53  import org.neo4j.server.webadmin.rest.representations.ServiceDefinitionRepresentation;
    54
    55  @Path( JmxService.ROOT_PATH )
    56  public class JmxService implements AdvertisableService
    57  {
    58      public static final String ROOT_PATH = "server/jmx";
    59
    60      public static final String DOMAINS_PATH = "/domain";
    61      public static final String DOMAIN_TEMPLATE = DOMAINS_PATH + "/{domain}";
    62      public static final String BEAN_TEMPLATE = DOMAIN_TEMPLATE + "/{objectName}";
    63      public static final String QUERY_PATH = "/query";
    64      public static final String KERNEL_NAME_PATH = "/kernelquery";
    65      private final OutputFormat output;
    66
    67      public JmxService( @Context OutputFormat output, @Context InputFormat input )
    68      {
    69          this.output = output;
    70      }
    71
    72      @GET
    73      public Response getServiceDefinition()
    74      {
    75          ServiceDefinitionRepresentation serviceDef = new ServiceDefinitionRepresentation( ROOT_PATH );
    76          serviceDef.resourceUri( "domains", JmxService.DOMAINS_PATH );
    77          serviceDef.resourceTemplate( "domain", JmxService.DOMAIN_TEMPLATE );
    78          serviceDef.resourceTemplate( "bean", JmxService.BEAN_TEMPLATE );
    79          serviceDef.resourceUri( "query", JmxService.QUERY_PATH );
    80          serviceDef.resourceUri( "kernelquery", JmxService.KERNEL_NAME_PATH );
    81
    82          return output.ok( serviceDef );
    83      }
    84
    85      @GET
    86      @Path( DOMAINS_PATH )
    87      public Response listDomains() throws NullPointerException
    88      {
    89          MBeanServer server = ManagementFactory.getPlatformMBeanServer();
    90          ListRepresentation domains = ListRepresentation.strings( server.getDomains() );
    91          return output.ok( domains );
    92      }
    93
    94      @GET
    95      @Path( DOMAIN_TEMPLATE )
    96      public Response getDomain( @PathParam( "domain" ) String domainName )
    97      {
    98          MBeanServer server = ManagementFactory.getPlatformMBeanServer();
    99
    100         JmxDomainRepresentation domain = new JmxDomainRepresentation( domainName );
    101
    102         for ( Object objName : server.queryNames( null, null ) )
    103         {
    104             if ( objName.toString().startsWith( domainName ) )
    105             {
    106                 domain.addBean( (ObjectName)objName );
    107             }
    108         }
    109
    110         return output.ok( domain );
    111     }
    112
    113     @GET
    114     @Path( BEAN_TEMPLATE )
    115     public Response getBean( @PathParam( "domain" ) String domainName, @PathParam( "objectName" ) String objectName )
    116     {
    117         MBeanServer server = ManagementFactory.getPlatformMBeanServer();
    118
    119         ArrayList<JmxMBeanRepresentation> beans = new ArrayList<JmxMBeanRepresentation>();
    120         for ( Object objName : server.queryNames( createObjectName( domainName, objectName ), null ) )
    121         {
    122             beans.add( new JmxMBeanRepresentation( (ObjectName)objName ) );
    123         }
    124
    125         return output.ok( new ListRepresentation( "bean", beans ) );
    126     }
    127
    128     private ObjectName createObjectName( final String domainName, final String objectName )
    129     {
    130         try
    131         {
    132             return new ObjectName( domainName + ":" + URLDecoder.decode( objectName, "UTF-8" ) );
    133         } catch ( MalformedObjectNameException e )
    134         {
    135             throw new WebApplicationException( e, 400 );
    136         } catch ( UnsupportedEncodingException e )
    137         {
    138             throw new WebApplicationException( e, 400 );
    139         }
    140     }
    141
    142
    143     @POST
    144     @Consumes( MediaType.APPLICATION_JSON )
    145     @Path( QUERY_PATH )
    146     @SuppressWarnings( "unchecked" )
    147     public Response queryBeans( String query )
    148     {
    149         try
    150         {
    151             MBeanServer server = ManagementFactory.getPlatformMBeanServer();
    152
    153
    154             String json = dodgeStartingUnicodeMarker( query );
    155             Collection<Object> queries = (Collection<Object>)JsonHelper.jsonToSingleValue( json );
    156
    157             ArrayList<JmxMBeanRepresentation> beans = new ArrayList<JmxMBeanRepresentation>();
    158             for ( Object queryObj : queries )
    159             {
    160                 assert queryObj instanceof String;
    161                 for ( Object objName : server.queryNames( new ObjectName( (String)queryObj ), null ) )
    162                 {
    163                     beans.add( new JmxMBeanRepresentation( (ObjectName)objName ) );
    164                 }
    165             }
    166
    167             return output.ok( new ListRepresentation( "jmxBean", beans ) );
    168         } catch ( MalformedObjectNameException e )
    169         {
    170             return output.badRequest( e );
    171         } catch ( BadInputException e )
    172         {
    173             return output.badRequest( e );
    174         }
    175
    176     }
    177
    178     @POST
    179     @Produces( MediaType.APPLICATION_JSON )
    180     @Consumes( MediaType.APPLICATION_FORM_URLENCODED )
    181     @Path( QUERY_PATH )
    182     public Response formQueryBeans( @FormParam( "value" ) String data )
    183     {
    184         return queryBeans( data );
    185     }
    186
    187     @GET
    188     @Produces( MediaType.APPLICATION_JSON )
    189     @Path( KERNEL_NAME_PATH )
    190     public Response currentKernelInstance( @Context Database database ) throws DatabaseBlockedException
    191     {
    192         Kernel kernelBean = database.graph.getManagementBean( Kernel.class );
    193         return Response.ok( "\"" + kernelBean.getMBeanQuery().toString() + "\"" ).type( MediaType.APPLICATION_JSON ).build();
    194     }
    195
    196     public String getName()
    197     {
    198         return "jmx";
    199     }
    200
    201     public String getServerPath()
    202     {
    203         return ROOT_PATH;
    204     }
    205
    206     private static String dodgeStartingUnicodeMarker( String string )
    207     {
    208         if ( string != null && string.length() > 0 )
    209         {
    210             if ( string.charAt( 0 ) == 0xfeff )
    211             {
    212                 return string.substring( 1 );
    213             }
    214         }
    215         return string;
    216     }
    217 }