View Javadoc
1   /*
2    * Licensed under the GPL License. You may not use this file except in compliance with the License.
3    * You may obtain a copy of the License at
4    *
5    *   https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
6    *
7    * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
8    * WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
9    * PURPOSE.
10   */
11  package psiprobe.controllers.threads;
12  
13  import java.lang.management.ManagementFactory;
14  import java.util.ArrayList;
15  import java.util.List;
16  
17  import javax.management.MBeanServer;
18  import javax.management.MalformedObjectNameException;
19  import javax.management.ObjectName;
20  import javax.management.openmbean.CompositeData;
21  import javax.servlet.http.HttpServletRequest;
22  import javax.servlet.http.HttpServletResponse;
23  
24  import org.springframework.beans.factory.annotation.Value;
25  import org.springframework.stereotype.Controller;
26  import org.springframework.web.bind.ServletRequestBindingException;
27  import org.springframework.web.bind.ServletRequestUtils;
28  import org.springframework.web.bind.annotation.RequestMapping;
29  import org.springframework.web.servlet.ModelAndView;
30  import org.springframework.web.servlet.mvc.ParameterizableViewController;
31  
32  import psiprobe.model.ThreadStackElement;
33  import psiprobe.tools.JmxTools;
34  
35  /**
36   * The Class ThreadStackController.
37   */
38  @Controller
39  public class ThreadStackController extends ParameterizableViewController {
40  
41    /** The stack element count. */
42    private int stackElementCount = 20;
43  
44    /**
45     * Gets the stack element count.
46     *
47     * @return the stack element count
48     */
49    public int getStackElementCount() {
50      return stackElementCount;
51    }
52  
53    /**
54     * Sets the stack element count.
55     *
56     * @param stackElementCount the new stack element count
57     */
58    @Value("100")
59    public void setStackElementCount(int stackElementCount) {
60      this.stackElementCount = stackElementCount;
61    }
62  
63    @RequestMapping(path = "/app/threadstack.ajax")
64    @Override
65    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
66        throws Exception {
67      return super.handleRequest(request, response);
68    }
69  
70    @Override
71    protected ModelAndView handleRequestInternal(HttpServletRequest request,
72        HttpServletResponse response)
73        throws ServletRequestBindingException, MalformedObjectNameException {
74  
75      long threadId = ServletRequestUtils.getLongParameter(request, "id", -1);
76      String threadName = ServletRequestUtils.getStringParameter(request, "name");
77  
78      MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();
79      ObjectName objectNameThreading = new ObjectName("java.lang:type=Threading");
80  
81      if (threadId == -1 && threadName != null) {
82        // find thread by name
83        for (long id : (long[]) JmxTools.getAttribute(mbeanServer, objectNameThreading,
84            "AllThreadIds")) {
85          CompositeData cd = (CompositeData) JmxTools.invoke(mbeanServer, objectNameThreading,
86              "getThreadInfo", new Object[] {id}, new String[] {"long"});
87          String name = JmxTools.getStringAttr(cd, "threadName");
88          if (threadName.equals(name)) {
89            threadId = id;
90            break;
91          }
92        }
93      }
94  
95      List<ThreadStackElement> stack = null;
96      if (mbeanServer.queryMBeans(objectNameThreading, null) != null && threadId != -1) {
97  
98        CompositeData cd =
99            (CompositeData) JmxTools.invoke(mbeanServer, objectNameThreading, "getThreadInfo",
100               new Object[] {threadId, stackElementCount}, new String[] {"long", "int"});
101       if (cd != null) {
102         CompositeData[] elements = (CompositeData[]) cd.get("stackTrace");
103         threadName = JmxTools.getStringAttr(cd, "threadName");
104 
105         stack = new ArrayList<>(elements.length);
106 
107         for (CompositeData cd2 : elements) {
108           ThreadStackElement tse = new ThreadStackElement();
109           tse.setClassName(JmxTools.getStringAttr(cd2, "className"));
110           tse.setFileName(JmxTools.getStringAttr(cd2, "fileName"));
111           tse.setMethodName(JmxTools.getStringAttr(cd2, "methodName"));
112           tse.setLineNumber(JmxTools.getIntAttr(cd2, "lineNumber", -1));
113           tse.setNativeMethod(JmxTools.getBooleanAttr(cd2, "nativeMethod"));
114           stack.add(tse);
115         }
116       }
117     }
118 
119     return new ModelAndView(getViewName(), "stack", stack).addObject("threadName", threadName);
120   }
121 
122   @Value("ajax/ThreadStack")
123   @Override
124   public void setViewName(String viewName) {
125     super.setViewName(viewName);
126   }
127 
128 }