Source Code Cross Referenced for Controller.java in  » Profiler » JIP » com » mentorgen » tools » profile » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Profiler » JIP » com.mentorgen.tools.profile 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:        Copyright (c) 2005-2006, MentorGen, LLC
003:        All rights reserved.
004:
005:        Redistribution and use in source and binary forms, with or without 
006:        modification, are permitted provided that the following conditions are met:
007:
008:        + Redistributions of source code must retain the above copyright notice, 
009:          this list of conditions and the following disclaimer.
010:        + Redistributions in binary form must reproduce the above copyright notice, 
011:          this list of conditions and the following disclaimer in the documentation 
012:          and/or other materials provided with the distribution.
013:        + Neither the name of MentorGen LLC nor the names of its contributors may be 
014:          used to endorse or promote products derived from this software without 
015:          specific prior written permission.
016:
017:          THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
018:          AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
019:          IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
020:          ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
021:          LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
022:          CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
023:          SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
024:          INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
025:          CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
026:          ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
027:          POSSIBILITY OF SUCH DAMAGE.
028:         */
029:        package com.mentorgen.tools.profile;
030:
031:        import java.io.BufferedInputStream;
032:        import java.io.FileInputStream;
033:        import java.io.IOException;
034:        import java.io.InputStream;
035:        import java.lang.reflect.Method;
036:        import java.net.ServerSocket;
037:        import java.net.Socket;
038:        import java.net.SocketException;
039:        import java.util.ArrayList;
040:        import java.util.Properties;
041:        import java.util.StringTokenizer;
042:
043:        import net.sourceforge.jiprof.instrument.clfilter.GenericClassLoaderFilter;
044:
045:        import com.mentorgen.tools.profile.instrument.clfilter.ClassLoaderFilter;
046:        import com.mentorgen.tools.profile.instrument.clfilter.StandardClassLoaderFilter;
047:        import com.mentorgen.tools.profile.output.ProfileDump;
048:        import com.mentorgen.tools.profile.runtime.Profile;
049:
050:        /**
051:         * <code>Controller</code> reads the properties file that controls
052:         * how the profiler operates, both when the byte code is instrumented
053:         * as well as at runtime. It also opens a server socket to receive 
054:         * remote commands to modify the profiler's behavior, like turning 
055:         * the profiler on and off, but only if <code>remote=on</code> 
056:         * has been specified in the profile properties. Here's a short
057:         * description of all of the properties that are supported:
058:         <ul>
059:         <li><a href="#profiler">profiler</a></li>
060:         <li><a href="#remote">remote</a></li>
061:         <li><a href="#port">port</a></li>
062:         <li><a href="#classloader">ClassLoaderFilter.x</a></li>
063:         <li><a href="#thread-depth">thread-depth</a></li>
064:         <li><a href="#thread-threshold">thread.compact.threshold.ms</a></li>
065:         <li><a href="#max-method-count">max-method-count</a></li>
066:         <li><a href="#method-threshold">method.compact.threshold.ms</a></li>
067:         <li><a href="#file">file</a></li>
068:         <li><a href="#exlcude">exclude</a></li>
069:         <li><a href="#include">include</a></li>
070:         <li><a href="#alloc">track.object.alloc</a></li>
071:         <li><a href="#output">output</a></li>
072:         <li><a href="#debug">debug</a></li>
073:         <li><a href="#profiler-class">profiler-class</a></li>
074:         <li><a href="#output-method-signatures">output-method-signatures</a></li>
075:         <li><a href="#clock-resolution">clock-resolution</a></li>
076:         <li><a href="#output-summary-only">output-summary-only</li>
077:         <li><a href="#accept-class-loaders">accept-class-loaders</li>
078:         </ul>
079:        
080:         <A NAME="profiler"/>
081:         <h3>profiler</h3>
082:         <blockquote>
083:         <b>Values</b>: on, off<br/>
084:         <b>Default</b>: on<br/>
085:         <b>Description</b>: controls whether or not profiling information
086:         is gathered when the VM starts. Usually you'll want this to 
087:         be on for command-line apps but off if you're profiling a web
088:         app.
089:         </blockquote>
090:        
091:         <a name="remote"/>
092:         <h3>remote</h3>
093:         <blockquote>
094:         <b>Values</b>: on, off<br/>
095:         <b>Default</b>: off<br/>
096:         <b>Description</b>: controls whether of not the remote interface
097:         is enabled or not. The remote interface allows you to turn the
098:         profiler on and off at runtime. This lets you take multiple 
099:         measurements without having to stop and start the application. 
100:         Usually you'll want this to be <code>on</code> for webapps
101:         but <code>off</code> for command-line apps.
102:         </blockquote>
103:        
104:         <a name="port"/>
105:         <h3>port</h3>
106:         <blockquote>
107:         <b>Values</b>: any valid TCP port number<br/>
108:         <b>Default</b>: 15599<br/>
109:         <b>Description</b>: this controls which port the remote interface 
110:         listens on.
111:         </blockquote>
112:        
113:         <a name="classloader"/>
114:         <h3>ClassLoaderFilter.x</h3>
115:         <blockquote>
116:         <b>Values</b>: any valid implemtation of 
117:         <code>com.mentorgen.tools.profile.ClassLoaderFilter</code><br/>
118:         <b>Default</b>: If no class loader filters a specificed then
119:         <code>net.sourceforge.jiprof.instrument.clfilter.GenericClassLoaderFilter</code>
120:         is used (see also: <a href="#accept-class-loaders">accept-class-loaders</a>).<br/>
121:         <b>Description</b>: JIP has to know which classloader will be 
122:         loading the classes to be profiled. With command-line
123:         apps we know what this is. However webapps and other
124:         kinds of apps that run in a container use different classloaders.
125:         The solution to this was to defined an interface: 
126:         <code>ClassLoaderFilter</code> to use in a chain of responsilbility
127:         pattern to determine which classloader should be "hooked"
128:         for profiling. The way this works is that you can define a number
129:         of realizations of this interface, one of each different env.
130:         You specify the search order by appending a number to the end
131:         of the property. For exmaple, the standard setup is:<pre><code>
132:         ClassLoaderFilter.1=com.mentorgen.tools.profile.instrument.clfilter.WebAppClassLoaderFilter
133:         ClassLoaderFilter.2=com.mentorgen.tools.profile.instrument.clfilter.StandardClassLoaderFilter		
134:         </code></pre>
135:         This indicates that the <code>WebAppClassLoaderFilter</code>
136:         should be called to determine if we're running in Tomcat. If that
137:         fails, call the <code>StandardClassLoaderFilter</code>. Note
138:         that currently only the Java 5(tm) and Tomcat 5.5 environments
139:         are supported. People who would like to add support for other
140:         environments are encouraged to do so.
141:         </blockquote>
142:        
143:         <a name="thread-depth"/>
144:         <h3>thread-depth</h3>
145:         <blockquote>
146:         <b>Values</b>: any positive integer, -1 or <i>compact</i><br/>
147:         <b>Default</b>: -1<br/>
148:         <b>Description</b>: Call stacks can get really deep and sometimes
149:         you only want to see a certain number of levels. This parameter
150:         controls the number of levels you will see. The default is -1 
151:         which means that there is no limit. Another option that can
152:         be used is <i>compact</i>. This will limit the call stacks
153:         to items that have a gross time that is at least 10 ms (this 
154:         can be <a href="#hread-threshold">changed</a>). Using
155:         <i>compact</i> is nice way to limit what you see while not
156:         imposing an arbitrary limit on the thread-depth.
157:         </blockquote>
158:        
159:         <a name="thread-threshold"/>
160:         <h3>thread.compact.threshold.ms</h3>
161:         <blockquote>
162:         <b>Values</b>: any positive integer<br/>
163:         <b>Default</b>: 10<br/>
164:         <b>Description</b>: Modifies the call stack output to 
165:         only show nodes with the given gross time. Only works when
166:         <code>thread-depth</code> is set to <i>compact</i>
167:         </blockquote>
168:        
169:         <a name="max-method-count"/>
170:         <h3>max-method-count</h3>
171:         <blockquote>
172:         <b>Values</b>: any positive integer, -1 or <i>compact</i><br/>
173:         <b>Default</b>: -1<br/>
174:         <b>Description</b>: This property modifieds the section 
175:         of the profiler output that shows the most expensive method. 
176:         Giving a number greater than -1 will limit the number of methods
177:         that are shown. -1 means no limit. <i>compact</i> can be usd to 
178:         show only methods with a creatin minimum gross time (the
179:         default is 10ms but can be changed by using 
180:         <a href="#method-threshold">method.compact.threshold.ms</a>
181:         </blockquote>
182:        
183:         <a name="method-threshold"/>
184:         <h3>method.compact.threshold.ms</h3>
185:         <blockquote>
186:         <b>Values</b>: any positive integer<br/>
187:         <b>Default</b>: 10<br/>
188:         <b>Description</b>: Modifies the method output to 
189:         only show methods with the given gross time. Only works when
190:         <code>max-method-count</code> is set to <i>compact</i>.
191:         </blockquote>
192:        
193:         <a name="file"/>
194:         <h3>file</h3>
195:         <blockquote>
196:         <b>Values</b>: the name of any valid file or directory.<br/>
197:         <b>Default</b>: ./profile.txt<br/>
198:         <b>Description</b>: Names the file that the profile is
199:         sent to. If this is a directory, JIP will auto-generate 
200:         file names and
201:         put the files in that directory. The format for the
202:         generated file name is <code>yyyyMMdd-HHmmss</code>.
203:         </blockquote>
204:
205:         <a name="exlcude"/>
206:         <h3>exclude</h3>
207:         <blockquote>
208:         <b>Values</b>: a comman spearated list of package or class
209:         names (class names must be fully qualified).<br/>
210:         <b>Default</b>: <i>no default</i><br/>
211:         <b>Description</b>: the values for this property name
212:         packages or classes to be excluded from the profile. This
213:         is handy when you have a chatty package or class that you
214:         just don't want to see all over the place. Note that only
215:         classes that are loaded by the &quot;app&quot; class loader
216:         are profiled to start with.
217:         </blockquote>
218:
219:         <a name="include"/>
220:         <h3>include</h3>
221:         <blockquote>
222:         <b>Values</b>: a comman spearated list of package or class
223:         names (class names must be fully qualified).<br/>
224:         <b>Default</b>: <i>no default</i><br/>
225:         <b>Description</b>: the values for this property name
226:         packages or classes to be explicitly included in the profile.
227:         Normally, you wouldn't use this, you'd let the <code><a href="#classloader">ClassLoaderFilter</a></code>
228:         determine which classes to include. If you don't want to see something,
229:         use <code><a href="#exlcude">exclude</a></code>. However, there
230:         are situations where you want to exclude so much stuff, that it's easier
231:         just to say what you want to be included. When using both exclude and include,
232:         the include list is applied, then the exclude list is applied.
233:         </blockquote>
234:        
235:         <a name="alloc"/>
236:         <h3>track.object.alloc</h3>
237:         <blockquote>
238:         <b>Values</b>: <code>on</code> or <code>off</code><br/>
239:         <b>Default</b>: <code>off</code><br/>
240:         <b>Description</b>: control whether or not JIP tracks 
241:         object allocation. 
242:         </blockquote>
243:        
244:         <a name="output"/>
245:         <h3>output</h3>
246:         <blockquote>
247:         <b>Values</b>: <code>text</code>, <code>xml</code> or <code>both</code><br/>
248:         <b>Default</b>: <code>text</code><br/>
249:         <b>Description</b>: in addition to the standard human readable
250:         profiles, this option allows you to output the profile information
251:         in a raw XML format.
252:         </blockquote>
253:        
254:         <a name="debug"/>
255:         <h3>debug</h3>
256:         <blockquote>
257:         <b>Values</b>: <code>on</code> or <code>off</code><br/>
258:         <b>Default</b>: <code>off</code><br/>
259:         <b>Description</b>: when debug is turned on, text will be sent to 
260:         standard out each time a class is classloaded and inspected by
261:         the profiler for possbile instrumentation (see <code>
262:         com.mentorgen.tools.profile.instrument.Transformer</code>). If the 
263:         class is instrumented, <code>INST</code>, plus the class name
264:         plus the classloader name will be sent to stddout. If the class
265:         is not instrumented, <code>skip</code>, plus the class name
266:         plus the classloader name will be sent to stddout. This is a 
267:         helpful tool when the profile you're getting (or not getting)
268:         doesn't match what you're expecting.<p/>
269:         In addition, text will be sent to standard error when an exception is
270:         detected and when the profile for a method has not been completed 
271:         when the profiler terminates. <br/>
272:         Exceptions are usually handled gracefully.
273:         However, there are some cases where they skew the timings and therefore
274:         the output is incorrect. Knowing that an exception is being thrown is a great
275:         help in diagnosing problems like this.<br/>
276:         Needing to &quot;fixup&quot; the profile
277:         for one or two methods is also not that unusual. However, if the timing
278:         for a method seems to be incorrect, knowing if the profiler needed to
279:         fixup that method can be useful from a diagnosics perspective.			
280:         </blockquote>
281:        
282:         <a name="profiler-class"/>
283:         <h3>profiler-class</h3>
284:         <blockquote>
285:         <b>Values</b>: any class name<br/>
286:         <b>Default</b>: <code>com.mentorgen.tools.profile.runtime.Profile</code><br/>
287:         <b>Description</b>: allows the another profiling backend to be used. 
288:         </blockquote>		
289:        
290:         <a name="output-method-signatures"/>
291:         <h3>output-method-signatures</h3>
292:         <blockquote>
293:         <b>Values:</b> <code>yes</code> or <code>no</code></br>
294:         <b>Default:</b> <code>no</code></br>
295:         <b>Description:</b> When set to <code>yes</code>, outputs the signature
296:         of methods. By default, the method signature is omitted from the output
297:         to save space. However, if you're dealing with methods that have been overloaded
298:         you need to be able to see the method signature.</br>
299:         </blockquote>
300:        
301:         <a name="clock-resolution"/>
302:         <h3>clock-resolution</h3>
303:         <blockquote>
304:         <b>Values:</b> <code>ms</code> or <code>ns</code></br>
305:         <b>Default:</b> <code>ns</code></br>
306:         <b>Description:</b> Sets the resolution of the TimeLineProfiler's clock to either milliseconds
307:         (<code>ms</code>) or nanoseconds (<code>ns</code>). Only valid when using the <code>
308:         TimeLineProfiler</code>.</br>
309:         </blockquote>
310:        
311:         <a name="output-summary-only"/>
312:         <h3>output-summary-only</h3>
313:         <blockquote>
314:         <b>Values:</b> <code>yes</code> or <code>no</code></br>
315:         <b>Default:</b> <code>no</code></br>
316:         <b>Description:</b> When set to <code>yes</code> the top most section of the profiler output
317:         (the section that contains thread + call stack information) is omitted. The section can be 
318:         quite large so it is sometime desirable to not have to page through it to get to the 
319:         summary information. </br>
320:         </blockquote>
321:        
322:         <a name="accept-class-loaders"/>
323:         <h3>accept-class-loaders</h3>
324:         <blockquote>
325:         <b>Values:</b> A comma separated list of classloader names (you can also specify
326:         interface names)</br>
327:         <b>Default:</b> If no values are given, <code>java.lang.ClassLoader.getSystemClassLoader()</code> 
328:         is used.</br>
329:         <b>Description:</b> A list of <code>Class Loaders</code> whose classes will be instrumented 
330:         when using <code>net.sourceforge.jiprof.instrument.clfilter.GenericClassLoaderFilter</code>
331:         as the classloader filter. Note that when looking to determine if profiling should be applied 
332:         to a classloader, <code>instanceof</code> is used as the mode of comparison. This means, for 
333:         example, that when profiling Tomcat, you can specify <code>org.apache.catalina.loader.Reloader</code>
334:         which is an interface rather than a subclass of <code>java.lang.ClassLoader</code>.
335:         </br>
336:         </blockquote>
337:         * 
338:         * 
339:         * 
340:         * @author Andrew Wilcox
341:         *
342:         */
343:        public class Controller implements  Runnable {
344:            private static final String DEFAULT_PROFILE = "on";
345:            private static final String DEFAULT_REMOVE = "off";
346:            private static final String DEFAULT_PORT = "15599";
347:            private static final String DEFAULT_MAX_THREAD_DEPTH = "-1";
348:            private static final String DEFAULT_THREAD_COMPACT_THRESHOLD = "10";
349:            private static final String DEFAULT_MAX_METHOD_COUNT = "-1";
350:            private static final String DEFAULT_METHOD_COMPACT_THRESHOLD = "10";
351:            private static final String DEFAULT_FILE = "profile.txt";
352:            private static final String DEFAULT_OBJECT_ALLOC = "off";
353:            private static final String DEFAULT_PROFILER_CLASS = "com.mentorgen.tools.profile.runtime.Profile";
354:
355:            private static final String ON = "on";
356:
357:            public static final int UNLIMITED = -1;
358:
359:            private static final String START = "start";
360:            private static final String STOP = "stop";
361:            private static final String DUMP = "dump";
362:            private static final String FILE = "file";
363:            private static final String CLEAR = "clear";
364:            private static final String FINISH = "finish";
365:
366:            public static enum OutputType {
367:                Text, XML, Both
368:            };
369:
370:            public static enum TimeResolution {
371:                ms, ns
372:            };
373:
374:            public static boolean _profile;
375:            public static boolean _remote;
376:            public static int _port;
377:            public static int _threadDepth;
378:            public static int _methodCount;
379:            public static String _fileName;
380:            public static String[] _excludeList;
381:            public static String[] _includeList;
382:            public static boolean _compactThreadDepth = false;
383:            public static boolean _compactMethodCount = false;
384:            public static int _compactThreadThreshold;
385:            public static int _compactMethodThreshold;
386:            public static boolean _trackObjectAlloc = false;
387:            public static ClassLoaderFilter _filter;
388:            public static OutputType _outputType = OutputType.Text;
389:            public static boolean _debug = false;
390:            public static String _profiler;
391:            public static boolean _outputMethodSignatures = false;
392:            public static TimeResolution _timeResoltion;
393:            public static boolean _outputSummaryOnly = false;
394:            public static Class[] _acceptClassLoaders;
395:
396:            public static int _instrumentCount = 0;
397:
398:            private ServerSocket _socket;
399:
400:            static {
401:                Properties props = new Properties();
402:                String propsFile = System.getProperty("profile.properties");
403:
404:                if (propsFile != null) {
405:                    try {
406:                        props.load(new FileInputStream(propsFile));
407:                    } catch (IOException e) {
408:                        System.err.print("Unable to open ");
409:                        System.err.print(propsFile);
410:                        System.err.println(". Using the defaults.");
411:                    }
412:                }
413:
414:                String profile = getProperty(props, "profiler", DEFAULT_PROFILE);
415:                String remote = getProperty(props, "remote", DEFAULT_REMOVE);
416:                String port = getProperty(props, "port", DEFAULT_PORT);
417:                String threadDepth = getProperty(props, "thread-depth",
418:                        DEFAULT_MAX_THREAD_DEPTH);
419:                String threadCompactThreshold = getProperty(props,
420:                        "thread.compact.threshold.ms",
421:                        DEFAULT_THREAD_COMPACT_THRESHOLD);
422:                String maxMethodCount = getProperty(props, "max-method-count",
423:                        DEFAULT_MAX_METHOD_COUNT);
424:                String methodCompactThreshold = getProperty(props,
425:                        "method.compact.threshold.ms",
426:                        DEFAULT_METHOD_COMPACT_THRESHOLD);
427:                String file = getProperty(props, "file", DEFAULT_FILE);
428:                String objectAlloc = getProperty(props, "track.object.alloc",
429:                        DEFAULT_OBJECT_ALLOC);
430:                String outputType = getProperty(props, "output", "text");
431:                String debug = getProperty(props, "debug", "off");
432:                String profiler = getProperty(props, "profiler-class",
433:                        DEFAULT_PROFILER_CLASS);
434:                String methodSigs = getProperty(props,
435:                        "output-method-signatures", "no");
436:                String clockResolution = getProperty(props, "clock-resolution",
437:                        "ms");
438:                String outputSummaryOnly = getProperty(props,
439:                        "output-summary-only", "no");
440:
441:                Controller._profile = profile.equals(ON);
442:                Controller._remote = remote.equals(ON);
443:                Controller._port = Integer.parseInt(port);
444:                Controller._compactThreadThreshold = Integer
445:                        .parseInt(threadCompactThreshold);
446:                Controller._compactMethodThreshold = Integer
447:                        .parseInt(methodCompactThreshold);
448:
449:                if ("compact".equals(threadDepth.trim())) {
450:                    Controller._compactThreadDepth = true;
451:                } else {
452:                    Controller._threadDepth = Integer.parseInt(threadDepth);
453:                }
454:
455:                if ("compact".equals(maxMethodCount.trim())) {
456:                    Controller._compactMethodCount = true;
457:                } else {
458:                    Controller._methodCount = Integer.parseInt(maxMethodCount);
459:                }
460:
461:                if ("on".equalsIgnoreCase(objectAlloc.trim())) {
462:                    _trackObjectAlloc = true;
463:                }
464:
465:                if ("on".equalsIgnoreCase(debug.trim())) {
466:                    _debug = true;
467:                }
468:
469:                if ("yes".equalsIgnoreCase(methodSigs)) {
470:                    _outputMethodSignatures = true;
471:                }
472:
473:                if ("text".equalsIgnoreCase(outputType.trim())) {
474:                    _outputType = OutputType.Text;
475:                } else if ("xml".equalsIgnoreCase(outputType.trim())) {
476:                    _outputType = OutputType.XML;
477:                } else if ("both".equalsIgnoreCase(outputType.trim())) {
478:                    _outputType = OutputType.Both;
479:                }
480:
481:                if ("ms".equalsIgnoreCase(clockResolution)) {
482:                    _timeResoltion = TimeResolution.ms;
483:                } else {
484:                    _timeResoltion = TimeResolution.ns;
485:                }
486:
487:                if ("yes".equalsIgnoreCase(outputSummaryOnly)) {
488:                    _outputSummaryOnly = true;
489:                }
490:
491:                Controller._fileName = file;
492:
493:                String excludeList = props.getProperty("exclude");
494:                String includeList = props.getProperty("include");
495:
496:                System.out.print("exclude:");
497:                System.out.println(excludeList);
498:
499:                if (includeList != null && includeList.length() > 0) {
500:                    System.out.print("include:");
501:                    System.out.println(includeList);
502:                }
503:
504:                Controller._excludeList = parseList(excludeList, true);
505:                Controller._includeList = parseList(includeList, true);
506:
507:                String[] classLoaderNames = parseList(props.getProperty(
508:                        "accept-class-loaders", ClassLoader
509:                                .getSystemClassLoader().getClass().getName()),
510:                        false);
511:
512:                Controller._acceptClassLoaders = new Class[classLoaderNames.length];
513:
514:                for (int i = 0; i < classLoaderNames.length; i++) {
515:                    try {
516:                        Controller._acceptClassLoaders[i] = Class
517:                                .forName(classLoaderNames[i]);
518:                        System.out.println("Accept ClassLoader: "
519:                                + Controller._acceptClassLoaders[i].getName());
520:                    } catch (ClassNotFoundException e) {
521:                        System.err.println("UNKNOWN CLASSLOADER: "
522:                                + classLoaderNames[i]);
523:                        System.err
524:                                .println("Using the system classloader instead");
525:                        Controller._acceptClassLoaders[i] = ClassLoader
526:                                .getSystemClassLoader().getClass();
527:                    }
528:                }
529:
530:                // get the class loader filter;
531:
532:                for (int i = 1;; i++) {
533:                    StringBuffer b = new StringBuffer("ClassLoaderFilter.");
534:                    b.append(i);
535:                    String filter = getProperty(props, b.toString(), null);
536:
537:                    if (filter == null) {
538:                        break;
539:                    }
540:
541:                    try {
542:                        ClassLoaderFilter clf = (ClassLoaderFilter) Class
543:                                .forName(filter).newInstance();
544:
545:                        if (clf.canFilter()) {
546:                            _filter = clf;
547:                            break;
548:                        }
549:                    } catch (Exception e) {
550:                        System.err
551:                                .print("Could not instantiate ClassLoaderFilter ");
552:                        System.err.println(filter);
553:                    }
554:                }
555:
556:                if (_filter == null) {
557:                    System.err
558:                            .println("Using the generic class loader filter.");
559:                    _filter = new GenericClassLoaderFilter();
560:                }
561:
562:                Controller._profiler = profiler.replace('.', '/');
563:
564:                try {
565:                    Class c = Class.forName(profiler);
566:                    Method m = c.getMethod("initProfiler", new Class[0]);
567:                    m.invoke(null, new Object[0]);
568:                } catch (Exception e) {
569:                    System.err
570:                            .println("Unable to invoke init on Profiler class.");
571:                }
572:
573:                System.out.println("------------------");
574:            }
575:
576:            private static String[] parseList(String list, boolean doReplacement) {
577:                if (list == null || list.length() == 0 || list.equals("null")) {
578:                    return new String[0];
579:                }
580:
581:                ArrayList<String> al = new ArrayList<String>();
582:                StringTokenizer t = new StringTokenizer(list, ", ");
583:
584:                while (t.hasMoreTokens()) {
585:                    String token = t.nextToken();
586:
587:                    if (doReplacement) {
588:                        al.add(token.replace('.', '/'));
589:                    } else {
590:                        al.add(token);
591:                    }
592:                }
593:
594:                String[] sl = new String[al.size()];
595:                al.toArray(sl);
596:                return sl;
597:            }
598:
599:            private static String getProperty(Properties props, String key,
600:                    String defaultValue) {
601:
602:                String value = props.getProperty(key, defaultValue);
603:                System.out.print(key);
604:                System.out.print(": ");
605:                System.out.println(value);
606:                return value;
607:            }
608:
609:            public void setFileName(String fileName) {
610:                _fileName = fileName;
611:            }
612:
613:            //
614:            // Thread to open a server socket and listen for commands
615:            //
616:
617:            public void run() {
618:                try {
619:                    _socket = new ServerSocket(_port);
620:
621:                    top: while (true) {
622:                        Socket child = _socket.accept();
623:
624:                        // so that someone cannot tie-up this socket for too long
625:                        //
626:                        child.setSoTimeout(5000);
627:                        InputStream in = child.getInputStream();
628:                        BufferedInputStream bin = new BufferedInputStream(in);
629:                        StringBuffer b = new StringBuffer();
630:
631:                        while (true) {
632:                            char c = (char) bin.read();
633:
634:                            if (c == '\r') {
635:                                break;
636:                            } else {
637:                                b.append(c);
638:                            }
639:                        }
640:
641:                        String command = b.toString();
642:                        System.out.println(command);
643:
644:                        if (command.startsWith(START)) {
645:                            start();
646:                        } else if (command.startsWith(STOP)) {
647:                            stop();
648:                        } else if (command.startsWith(DUMP)) {
649:                            ProfileDump.dump();
650:                        } else if (command.startsWith(CLEAR)) {
651:                            Profile.init();
652:                        } else if (command.startsWith(FILE)) {
653:                            String name = command.substring(command
654:                                    .indexOf(' ') + 1);
655:                            _fileName = name;
656:                        } else if (command.startsWith(FINISH)) {
657:                            stop(); // stop
658:                            ProfileDump.dump(); // dump
659:                            Profile.init(); // clear
660:                        }
661:
662:                        child.close();
663:                    }
664:                } catch (SocketException e) {
665:                    // eat this type of exception ...
666:                } catch (IOException e) {
667:                    e.printStackTrace();
668:                    throw new RuntimeException(e);
669:                }
670:
671:            }
672:
673:            public void close() throws IOException {
674:                System.err.println("Controller -- shuttingdown");
675:
676:                if (_remote && _socket != null && !_socket.isClosed()) {
677:                    _socket.close();
678:                }
679:            }
680:
681:            public void start() {
682:
683:                // Nice little hack to explain to the user why they aren't getting
684:                // a profile.
685:                //
686:                if (_instrumentCount == 0) {
687:                    System.err
688:                            .println("Warning: a request has been made to start the "
689:                                    + "profiler but no classes have been instrumented. "
690:                                    + "Possible reasons: ");
691:                    System.err
692:                            .println("1. All the classes that have been classloaded "
693:                                    + "have been \"excluded\". Check the exclude property in "
694:                                    + "the current profile properties file.");
695:                    System.err
696:                            .println("2. No appropriate class loader filter has been "
697:                                    + "provided (see \"ClassLoaderFilter.x\" in the current "
698:                                    + "profile properties file.) If no appropriate "
699:                                    + "filter can be found, the standard filter is used. This"
700:                                    + "filter is really only useful for stand-alone "
701:                                    + "applications. Make sure your environment has a "
702:                                    + "ClassLoaderFilter and that your profile properties "
703:                                    + "file is configured correctly.");
704:                    System.err
705:                            .println("3. Sometimes when Tomcat is launched from "
706:                                    + "within "
707:                                    + "Eclipse, Tomcat, for some reason, will start using the "
708:                                    + "appication classloader (the one that stand-alone "
709:                                    + "apps use) to classload the webapp rather than the "
710:                                    + "web app classloader that it should use. One thing that "
711:                                    + "you can try to get around this odd behavior is to not "
712:                                    + "run Tomcat in debug mode (Window > Perferences > Tomcat > "
713:                                    + "JVM settings : Don't run Tomcat in debug mode.) If this "
714:                                    + "doesn't work, you could try removing the webapp "
715:                                    + "classlaoder filter from your profile properties file.");
716:                }
717:
718:                Profile.clear();
719:                _profile = true;
720:            }
721:
722:            public void stop() {
723:
724:                // Explain to the user why they aren't going to be seeing a profile.
725:                //
726:                if (_instrumentCount == 0) {
727:                    System.err
728:                            .println("No classes have been instrumented for "
729:                                    + "profiling. There should be a previous message to this "
730:                                    + "effect which outlines why this is happening.");
731:                }
732:
733:                Profile.shutdown();
734:            }
735:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.