001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: package org.netbeans.modules.collab.core;
042:
043: import com.sun.collablet.*;
044:
045: import org.openide.*;
046: import org.openide.filesystems.*;
047: import org.openide.loaders.*;
048: import org.openide.windows.*;
049:
050: import java.beans.*;
051:
052: import java.io.*;
053:
054: import java.lang.reflect.*;
055:
056: import java.util.*;
057:
058: /**
059: *
060: * @author Todd Fast, todd.fast@sun.com
061: * @author Matt Stevens, matthew.stevens@sun.com
062: * @author Mike Frisino, michael.frisino@sun.com
063: */
064: public class Debug extends Object {
065: ////////////////////////////////////////////////////////////////////////////
066: // Class variables
067: ////////////////////////////////////////////////////////////////////////////
068: public static final String OUTPUT_TAB_NAME = "Collaboration Module Debug";
069: public static final String DISCRIMINATOR_TODO = "TODO";
070: public static PrintWriter out;// = InputOutput.NULL.getOut();
071: public static ErrorManager errorManager;
072: private static InputOutput inputOutput;
073: private static Set allowed = new HashSet();
074:
075: ////////////////////////////////////////////////////////////////////////////
076: // Initializers
077: ////////////////////////////////////////////////////////////////////////////
078: static {
079: initializeOut();
080:
081: String filename = System
082: .getProperty("com.sun.collablet.debug.file"); // NOI18N
083:
084: try {
085: if ((filename != null) && (filename.trim().length() != 0)) {
086: Properties props = new Properties();
087: props.load(new BufferedInputStream(new FileInputStream(
088: filename)));
089:
090: Enumeration keys = props.keys();
091:
092: while (keys.hasMoreElements()) {
093: Object key = keys.nextElement();
094: allow(key);
095: System.out.println("Enabling debug messages for \""
096: + key + "\""); // NOI18N
097: }
098: } else {
099: allow(DISCRIMINATOR_TODO);
100: }
101: } catch (IOException e) {
102: System.out.println("Failed to load debug file \""
103: + filename + "\""); // NOI18N
104: e.printStackTrace(System.out);
105: }
106: }
107:
108: /**
109: *
110: *
111: */
112: private Debug() {
113: super ();
114: }
115:
116: /**
117: *
118: *
119: */
120: public static boolean isEnabled() {
121: return Boolean.getBoolean("com.sun.collablet.debug");
122: }
123:
124: /**
125: *
126: *
127: */
128: public synchronized static void initializeOut() {
129: if (out != null) {
130: return;
131: }
132:
133: //
134: // MJS 8/7/2003
135: // We found code changes in NetBeans 3.5 OutputTabTerm caused severe
136: // latencies of 500-2000 milleseconds between writes to 'out'
137: // Temporary workaround is to use OS console with command line argument
138: // TAF: Changed Matt's workaround to populate the Debug.out member
139: // properly
140: if (errorManager != null) {
141: return;
142: }
143:
144: if (isEnabled()) {
145: if (Boolean
146: .getBoolean("com.sun.collablet.debug.usesystemout")) {
147: out = new PrintWriter(System.out, true);
148: out.println("Module debug enabled on System.out");
149: } else if (Boolean
150: .getBoolean("com.sun.collablet.debug.usesystemerr")) {
151: out = new PrintWriter(System.err, true);
152: out.println("Module debug enabled on System.err");
153: } else {
154: inputOutput = IOProvider.getDefault().getIO(
155: OUTPUT_TAB_NAME, true);
156:
157: // inputOutput.setFocusTaken(true);
158: out = inputOutput.getOut();
159: }
160: } else {
161: out = InputOutput.NULL.getOut();
162: }
163:
164: errorManager = ErrorManager.getDefault().getInstance(
165: "com.sun.collablet"); // NOI18N
166: }
167:
168: /**
169: *
170: *
171: */
172: public static InputOutput getInputOutput() {
173: return inputOutput;
174: }
175:
176: ////////////////////////////////////////////////////////////////////////////
177: // Logging methods
178: ////////////////////////////////////////////////////////////////////////////
179:
180: /**
181: *
182: *
183: */
184: public static void debugNotify(Throwable e) {
185: if (isEnabled()) {
186: errorManager.notify(errorManager.annotate(e,
187: "[DEBUG-only exception]")); // NOI18N
188: }
189: }
190:
191: /**
192: *
193: *
194: */
195: public static void debugNotify(Throwable e, String message) {
196: if (isEnabled()) {
197: errorManager.notify(errorManager.annotate(e, message));
198: }
199: }
200:
201: /**
202: *
203: *
204: */
205: public static void dumpObject(Object object) {
206: out.println("--- BEGIN OBJECT DUMP ---");
207: out.println(" Object: " + object);
208:
209: try {
210: if (object == null) {
211: return;
212: }
213:
214: Class clazz = object.getClass();
215: Field[] fields = clazz.getDeclaredFields();
216:
217: Map fieldMap = new TreeMap();
218:
219: for (int i = 0; i < fields.length; i++) {
220: fields[i].setAccessible(true);
221:
222: try {
223: fieldMap.put(fields[i].getName(), fields[i]
224: .get(object));
225: } catch (Exception e) {
226: fieldMap.put(fields[i].getName(), e);
227: }
228: }
229:
230: out.println("OBJECT FIELDS:");
231:
232: for (Iterator i = fieldMap.entrySet().iterator(); i
233: .hasNext();) {
234: Map.Entry entry = (Map.Entry) i.next();
235: out.println(" " + entry.getKey() + " = "
236: + entry.getValue());
237: }
238: } catch (Throwable e) {
239: out.println("Exception dumping object");
240: e.printStackTrace(out);
241: } finally {
242: out.println("--- END OBJECT DUMP ---");
243: }
244: }
245:
246: /**
247: *
248: *
249: */
250: public static void dumpMessage(CollabMessage message) {
251: try {
252: out.println("Message:\t" + message.getID());
253: out
254: .println("\tOriginator:\n\t\t"
255: + message.getOriginator());
256:
257: // out.println("\tRecipients:\t");
258: // for (int i=0; i<message.getRecipients().length; i++)
259: // out.println("\t\t"+message.getRecipients()[i]);
260: out.println("\tParts:");
261:
262: CollabMessagePart[] parts = message.getParts();
263:
264: for (int i = 0; i < parts.length; i++)
265: dumpMessagePart(parts[i]);
266: } catch (Throwable e) {
267: out.println("Exception dumping message:");
268: e.printStackTrace(out);
269: }
270: }
271:
272: /**
273: *
274: *
275: */
276: public static void dumpMessagePart(CollabMessagePart part)
277: throws CollabException {
278: out.println("\t\tPart");
279: out.println("\t\t\tContent name:\t" + part.getContentName());
280: out.println("\t\t\tContent type:\t" + part.getContentType());
281: out.println("\t\t\tEncoding:\t\t" + part.getContentEncoding());
282: out.println("\t\t\tSize:\t\t\t" + part.getSize());
283: out.println("\t\t\tContent:\t\t" + part.getContent());
284: }
285:
286: /**
287: *
288: * @return flag indicating that discriminator is not enabled for logging
289: */
290: public static boolean isAllowed(Object discriminator) {
291: if (!isEnabled()) {
292: return false;
293: }
294:
295: // shame shame shame
296: if (discriminator == null) {
297: return true;
298: }
299:
300: if (allowed.size() == 0) {
301: return false;
302: }
303:
304: if (discriminator.getClass().isAssignableFrom(String.class)) {
305: return allowed.contains(discriminator);
306: }
307:
308: Class temp = discriminator.getClass();
309:
310: if (temp == Class.class) {
311: temp = (Class) discriminator;
312: }
313:
314: // Test to see if the discriminator matches an explicit class
315: if (allowed.contains(getShortName(temp))) {
316: return true;
317: }
318:
319: // Test to see if the disciminator matches allowed package
320: return allowed.contains(getShortPackageName(temp));
321: }
322:
323: /**
324: *
325: *
326: */
327: public static void allow(Object discriminator) {
328: allowed.add(discriminator);
329: }
330:
331: /**
332: *
333: *
334: */
335: public static void disallow(Object discriminator) {
336: allowed.remove(discriminator);
337: }
338:
339: /**
340: *
341: *
342: */
343: private static String getShortName(Class clazz) {
344: return clazz.getName().substring(
345: clazz.getPackage().getName().length() + 1);
346: }
347:
348: /**
349: *
350: *
351: */
352: private static String getShortPackageName(Class clazz) {
353: if (clazz.getPackage().getName().startsWith(
354: "com.sun.tools.ide.collab")) // NOI18N
355: {
356: String packageName = clazz.getPackage().getName();
357:
358: if (packageName.length() < 26) {
359: return ".";
360: } else {
361: return packageName.substring(26);
362: }
363: } else {
364: return clazz.getPackage().getName();
365: }
366: }
367:
368: /**
369: *
370: *
371: */
372: public static void log(Object discriminator, String msg) {
373: if (isAllowed(discriminator)) {
374: out.println(msg);
375: }
376: }
377:
378: /**
379: *
380: *
381: */
382: public static void log(Object discriminator, Object value) {
383: if (isAllowed(discriminator)) {
384: out.println((value == null) ? "null" : value.toString());
385: }
386: }
387:
388: /**
389: *
390: *
391: */
392: public static void logPropertyChange(Object receiver,
393: PropertyChangeEvent event) {
394: logPropertyChange(null, receiver, event);
395: }
396:
397: /**
398: *
399: *
400: */
401: public static void logPropertyChange(Object discriminator,
402: Object receiver, PropertyChangeEvent event) {
403: if (!isAllowed(discriminator)) {
404: return;
405: }
406:
407: StringBuffer temp = new StringBuffer();
408:
409: try {
410: temp.append("\nProperty change:");
411: temp.append("\n\tTName: "
412: + Thread.currentThread().getName() + "\n\tTPrio: "
413: + Thread.currentThread().getPriority()
414: + "\n\tTHash: "
415: + Thread.currentThread().hashCode());
416: temp.append("\n\tProperty: " + event.getPropertyName());
417:
418: if ((event.getOldValue() != null)
419: && event.getOldValue().getClass().isArray()) {
420: temp.append("\n\tOld Value: "
421: + delimitedString((Object[]) event
422: .getOldValue(), ","));
423: } else {
424: temp.append("\n\tOld Value: " + event.getOldValue());
425: }
426:
427: if ((event.getNewValue() != null)
428: && event.getNewValue().getClass().isArray()) {
429: temp.append("\n\tNew Value: "
430: + delimitedString((Object[]) event
431: .getNewValue(), ","));
432: } else {
433: temp.append("\n\tNew Value: " + event.getNewValue());
434: }
435:
436: if ((event.getOldValue() != null)
437: && event.getOldValue().getClass().isArray()) {
438: temp.append("\n\tValue Type: ARRAY of "
439: + event.getOldValue().getClass()
440: .getComponentType());
441: } else if (event.getOldValue() != null) {
442: temp.append("\n\tValue Type: "
443: + event.getOldValue().getClass());
444: }
445:
446: try {
447: temp.append("\n\tReceiver: " + receiver);
448: } catch (Exception e) {
449: temp.append("\n\tReceiver: SEE EXCEPTION");
450: temp.append("\n\tException: " + e.toString());
451:
452: OutputStream byteOutputStream = new ByteArrayOutputStream();
453: PrintWriter pw = new PrintWriter(byteOutputStream);
454: e.printStackTrace(pw);
455: pw.flush();
456: pw.close();
457: temp.append(byteOutputStream.toString());
458: }
459:
460: try {
461: temp.append("\n\tSource: " + event.getSource());
462: } catch (Exception e) {
463: temp.append("\n\ttSource: SEE EXCEPTION");
464: temp.append("\n\tException: " + e.toString());
465:
466: OutputStream byteOutputStream = new ByteArrayOutputStream();
467: PrintWriter pw = new PrintWriter(byteOutputStream);
468: e.printStackTrace(pw);
469: pw.flush();
470: pw.close();
471: temp.append(byteOutputStream.toString());
472: }
473: } catch (Exception e) {
474: logDebugException("logPropertyChange caught exception", e,
475: true);
476: }
477:
478: log(discriminator, temp.toString());
479: }
480:
481: /**
482: * Converts an array of Objects into a delimited string of values
483: *
484: */
485: private static String delimitedString(Object[] vals,
486: String delimiter) {
487: // Make sure we have a valid array
488: if (vals == null) {
489: return null;
490: }
491:
492: // Get one less than the size, so we can add on the last seperately.
493: int lastIndex = vals.length - 1;
494:
495: if (lastIndex < 0) {
496: // Handle empty array as special case
497: return ""; // NOI18N
498: }
499:
500: // Iterate over the elements
501: StringBuffer buf = new StringBuffer();
502:
503: for (int count = 0; count < lastIndex; count++) {
504: // Add element + delimiter
505: buf.append(vals[count]);
506: buf.append(delimiter);
507: }
508:
509: // Add on last element
510: buf.append(vals[lastIndex]);
511:
512: return buf.toString();
513: }
514:
515: /**
516: *
517: *
518: * @param fo The FileObject
519: */
520: public static void logFileDetails(FileObject fo) {
521: logFileDetails(null, fo);
522: }
523:
524: /**
525: *
526: * @param discriminator optional filter where String.toString() or name of
527: * Object.getClass().{ShortName}
528: * @param fo The FileObject
529: */
530: public static void logFileDetails(Object discriminator,
531: FileObject fo) {
532: if (!isAllowed(discriminator)) {
533: return;
534: }
535:
536: StringBuffer temp = new StringBuffer();
537: temp.append("\nFile Object details:");
538: temp.append("\n\tgetName: " + fo.getName());
539: temp.append("\n\tgetNameExt: " + fo.getNameExt());
540: temp.append("\n\tgetPackageName(/): "
541: + fo.getPackageName('/'));
542: temp.append("\n\tgetPackageNameExt(/): "
543: + fo.getPackageNameExt('/', '.'));
544:
545: log(discriminator, temp.toString());
546: }
547:
548: /**
549: *
550: *
551: * @param note A note describing situation where exception occurred
552: * @param e The exception
553: * @param stackTrace boolean to indicate whether you want stack trace
554: */
555: public static void logDebugException(String note, Throwable e,
556: boolean stackTrace) {
557: StringBuffer temp = new StringBuffer();
558: temp.append("\nException:");
559: temp.append("\n\tNote: " + note);
560: temp.append("\n\tException: " + e.toString());
561:
562: out.println(temp.toString());
563:
564: if (stackTrace) {
565: e.printStackTrace(out);
566: }
567: }
568:
569: /**
570: *
571: *
572: */
573: public static void todo(String msg) {
574: log(DISCRIMINATOR_TODO, "TODO: " + msg + " --> "
575: + new Exception().getStackTrace()[1]);
576: }
577:
578: /**
579: *
580: *
581: */
582: public static void notImplemented() {
583: // Note, we can't call todo() here because that would throw off the
584: // the stack trace index
585: log(DISCRIMINATOR_TODO, "TODO: Not implemented --> "
586: + new Exception().getStackTrace()[1]);
587: }
588: }
|