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 }