JmxPerspectiveAction.java
001 /*
002  *
003  * Licensed to the Apache Software Foundation (ASF) under one
004  * or more contributor license agreements.  See the NOTICE file
005  * distributed with this work for additional information
006  * regarding copyright ownership.  The ASF licenses this file
007  * to you under the Apache License, Version 2.0 (the
008  * "License"); you may not use this file except in compliance
009  * with the License.  You may obtain a copy of the License at
010  *
011  *   http://www.apache.org/licenses/LICENSE-2.0
012  *
013  * Unless required by applicable law or agreed to in writing,
014  * software distributed under the License is distributed on an
015  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
016  * KIND, either express or implied.  See the License for the
017  * specific language governing permissions and limitations
018  * under the License.
019  *
020  */
021 package org.apache.qpid.management.web.action;
022 
023 import java.io.IOException;
024 import java.lang.management.ManagementFactory;
025 import java.util.HashMap;
026 import java.util.Hashtable;
027 import java.util.Map;
028 import java.util.Properties;
029 import java.util.Map.Entry;
030 
031 import javax.management.MBeanAttributeInfo;
032 import javax.management.MBeanInfo;
033 import javax.management.MBeanServer;
034 import javax.management.MalformedObjectNameException;
035 import javax.management.ObjectName;
036 import javax.servlet.RequestDispatcher;
037 import javax.servlet.ServletException;
038 import javax.servlet.http.HttpServlet;
039 import javax.servlet.http.HttpServletRequest;
040 import javax.servlet.http.HttpServletResponse;
041 
042 /**
043  * This controller is responsible to provide a jmx perspective of a specific resource.
044  * That means that this controller is querying the Platform MBean server in order to 
045  * get metadata for the requested mbean.
046  
047  * After that metadata will be forwarded to the appropriate view page and therefore 
048  * will be shown on the Admin console.
049  
050  @author Andrea Gazzarini
051  */
052 public class JmxPerspectiveAction extends HttpServlet
053 {
054   private static final long serialVersionUID = -2411413147821629363L;
055 
056   /**
057    * Adapter interface for converting objects on html strings.
058    
059    @author Andrea Gazzarini.
060    */
061   interface JavaToHtmlAdapter 
062   {
063     /**
064      * Returns an HTML string representation of the given object.
065      
066      @param javaObject the object that needs to be converted.
067      @return an html string containing value of the given object.
068      */
069     String toHtml(Object javaObject);
070   }
071   
072   /**
073    * Adapter implementation for Map (and subclasses).
074    */
075   private JavaToHtmlAdapter mapAdapter = new JavaToHtmlAdapter()
076   {
077     @SuppressWarnings("unchecked")
078     public String toHtml(Object javaObject)
079     {
080       Map<String,Object> value = (Map<String, Object>javaObject;
081 
082       // Sanity check : if the map is empty or null there's no need to 
083       // do any convertion
084       if (value == null || value.isEmpty())
085       {
086         return "(empty)";
087       }
088 
089       StringBuilder builder = new StringBuilder("<ul>");
090       for (Entry<String, Object> entry : value.entrySet())
091       {
092         builder
093           .append("<li>")
094           .append(entry.getKey())
095           .append(" = ")
096           .append(entry.getValue());
097       }
098       builder.append("</ul>");
099       return builder.toString();
100     }
101   };
102 
103   private Map<String, JavaToHtmlAdapter> _adapters = new HashMap<String, JavaToHtmlAdapter>();
104   
105   @Override
106   public void init() throws ServletException
107   {
108     _adapters.put(Map.class.getName(), mapAdapter);
109     _adapters.put(HashMap.class.getName(),mapAdapter);
110     _adapters.put(Properties.class.getName(),mapAdapter);
111     _adapters.put(Hashtable.class.getName(),mapAdapter);
112   }
113   
114   @SuppressWarnings("unchecked")
115   @Override
116   protected void service(HttpServletRequest request, HttpServletResponse responsethrows ServletException, IOException
117   {
118     String resourceId = null;
119     try 
120     {
121       resourceId = request.getParameter("resourceId");
122       
123       ObjectName objectName = new ObjectName(resourceId);
124       String [] keyProperties = objectName.getKeyPropertyListString().split(",");
125       
126       MBeanServer server = ManagementFactory.getPlatformMBeanServer();
127       
128       MBeanInfo metadata = server.getMBeanInfo(objectName);
129       
130       Map<String, String> attributes = getAttributes(server, objectName,metadata.getAttributes());
131       
132       request.setAttribute("resourceId", objectName);
133       request.setAttribute("metadata",metadata);
134       request.setAttribute("nameAttributes",keyProperties);
135       request.setAttribute("attributes",attributes);
136       
137       RequestDispatcher dispatcher = request.getRequestDispatcher("/jmx_perspective.jsp");
138       dispatcher.forward(request,response);
139     catch(MalformedObjectNameException exception)
140     {
141       request.setAttribute("errorMessage","Malformed Resource ID : supplied value is "+resourceId);
142       request.setAttribute("exception",exception);
143       RequestDispatcher dispatcher = request.getRequestDispatcher("/error_page.jsp");
144       dispatcher.forward(request,response);      
145       
146     }
147     catch(Exception exception)
148     {
149       request.setAttribute("errorMessage","Unable to detect the exact cause Please look at the reported stack trace below.");
150       request.setAttribute("exception",exception);
151       RequestDispatcher dispatcher = request.getRequestDispatcher("/error_page.jsp");
152       dispatcher.forward(request,response);      
153     }
154   }
155 
156   /**
157    * Starting from an mbean metadata, this method retrieves all the attributes 
158    * from the corresponding MBean Server.
159    
160    @param server the mbean server where the target mbean is registered.
161    @param name the name of the target mbean.
162    @param metadata the metadata of mbean.
163    @return a map containing all attributes of the given mbean.
164    @throws Exception when it's not possible to retrieve attributes.
165    */
166   private Map<String, String> getAttributes(MBeanServer server, ObjectName name, MBeanAttributeInfo [] metadatathrows Exception
167   {
168     Map<String,String> result = new HashMap<String, String>(metadata.length);
169     for (MBeanAttributeInfo attribute : metadata)
170     {
171       Object value = server.getAttribute(name, attribute.getName());
172       result.put(attribute.getName(),getAdaptedValue(attribute.getType(), value));
173     }
174     return result;
175   }
176   
177   /**
178    * Converts the given attribute value in a html string format.
179    *  
180    @param type the java type of the given attribute value.
181    @param value the attribute value.
182    @return a html string format of the given value.
183    */
184   private String getAdaptedValue(String type, Object value
185   {
186     JavaToHtmlAdapter adapter = _adapters.get(type);
187     return (adapter != null? adapter.toHtml(value: String.valueOf(value);
188   }
189 }