1 package org.jmux.app.component;
2
3 import org.jmux.app.App;
4 import org.jmux.app.component.config.Config;
5
6 import javax.servlet.ServletException;
7 import javax.servlet.http.HttpServlet;
8 import javax.servlet.http.HttpServletRequest;
9 import javax.servlet.http.HttpServletResponse;
10 import java.io.IOException;
11 import java.io.PrintWriter;
12 import java.lang.reflect.Field;
13 import java.lang.reflect.Modifier;
14 import java.util.Date;
15 import java.util.HashMap;
16 import java.util.IdentityHashMap;
17 import java.util.Map;
18
19 /******************************************************************************
20 jmux - Java Modules Using XML
21 Copyright © 2006 jmux.org
22
23 This library is free software; you can redistribute it and/or
24 modify it under the terms of the GNU Lesser General Public
25 License as published by the Free Software Foundation; either
26 version 2.1 of the License, or (at your option) any later version.
27
28 This library is distributed in the hope that it will be useful,
29 but WITHOUT ANY WARRANTY; without even the implied warranty of
30 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
31 Lesser General Public License for more details.
32
33 You should have received a copy of the GNU Lesser General Public
34 License along with this library; if not, write to the Free Software
35 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
36 *****************************************************************************/
37
38 /***
39 * @author donaldw
40 */
41 public class Inspector extends AbstractComponent {
42
43 @Wire
44 private JettyControl jettyControl;
45
46 @Wire
47 private ControlManager controlManager;
48
49 private static App app;
50
51 public void configure(Config config, App app) {
52 super.configure(config, app);
53
54 jettyControl.addServlet(Servlet.class, "/Inspect");
55 Inspector.app = app;
56 }
57
58 public static class Servlet extends HttpServlet {
59 private Map<String, Object> stringToObject = new HashMap<String, Object>();
60 private Map<Object, String> objectToString = new IdentityHashMap<Object, String>();
61
62 private long nextObjectId;
63
64
65 protected void doGet(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse)
66 throws ServletException, IOException {
67
68 String objectId = httpServletRequest.getParameter("object");
69
70 PrintWriter writer = httpServletResponse.getWriter();
71 try {
72 Object object = getObject(objectId);
73 dumpObject(writer, object);
74 } catch (Exception e) {
75 throw new ServletException("Exception whilst dumping object: ", e);
76 }
77 }
78
79 private void dumpObject(PrintWriter writer, Object object) throws Exception {
80 writer.println("<html><head></head><body>");
81 Class clazz = object.getClass();
82 writer.printf("<h1>%s</h1>", clazz.getName());
83 writer.printf("<h2>Fields</h2>");
84
85 Class fieldLoopclazz = object.getClass();
86
87 while (fieldLoopclazz != null) {
88 writer.println("<h3>" + fieldLoopclazz.getName() + "</h3>");
89 for (Field field : fieldLoopclazz.getDeclaredFields()) {
90 field.setAccessible(true);
91 Object fieldValue = field.get(object);
92 if (field.getName().equals("objectToString")) {
93 continue;
94 }
95 writer.print("<font color='Grey'> "
96 + Modifier.toString(field.getModifiers())
97 + "</font><font color='DarkBlue'> "
98 + field.getType().getName()
99 + "</font> "
100 + field.getName() + ": ");
101 dumpLinkedObject(field.getType(), writer, fieldValue);
102 writer.println("<br/>");
103 }
104
105 fieldLoopclazz = fieldLoopclazz.getSuperclass();
106 }
107 writer.println("</body></html>");
108 }
109
110
111 private void dumpLinkedObject(Class clazz, PrintWriter writer, Object object) {
112 if (object == null) {
113 writer.print("null");
114 return;
115 }
116 if (clazz.isPrimitive() || clazz.equals(String.class) || clazz.equals(Date.class)) {
117 writer.println(object.toString());
118 } else if (clazz.isAssignableFrom(Map.class)) {
119 writer.println("<table border='1'>");
120 Map map = (Map) object;
121 for (Object o : map.entrySet()) {
122 Map.Entry entry = (Map.Entry) o;
123 Object key = entry.getKey();
124 Object value = entry.getValue();
125 writer.print("<tr><td>");
126 if (key != null) {
127 dumpLinkedObject(key.getClass(), writer, key);
128 } else {
129 writer.print("null");
130 }
131
132 writer.print("</td><td>");
133 if (value != null) {
134 dumpLinkedObject(value.getClass(), writer, value);
135 } else {
136 writer.print("null");
137 }
138 writer.println("</td>");
139 }
140 writer.println("</table>");
141 } else if (clazz.isArray()) {
142 writer.println("<table border='1'>");
143 Object[] objectArray = (Object[]) object;
144 for (Object o : objectArray) {
145 writer.print("<td>");
146 if (o == null) {
147 writer.print("null");
148 } else {
149 dumpLinkedObject(o.getClass(), writer, o);
150 }
151 writer.print("</td>");
152 }
153 writer.println("</table>");
154 } else {
155 String objectId = putObject(object);
156 writer.print("<a href='/Inspect?object=" + objectId + "'>" + object + "</a>");
157 }
158 }
159
160 public synchronized Object getObject(String objectId) {
161 if (objectId == null) {
162 return Inspector.app;
163 } else {
164 return stringToObject.get(objectId);
165 }
166 }
167
168 private synchronized String putObject(Object object) {
169 String key = objectToString.get(object);
170 if (key == null) {
171 key = "obj" + nextObjectId++;
172 stringToObject.put(key, object);
173 objectToString.put(object, key);
174 }
175
176 return key;
177 }
178 }
179
180
181 }