KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > j2ee > sun > ide > j2ee > LogHyperLinkSupport


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.j2ee.sun.ide.j2ee;
21
22 import java.io.File JavaDoc;
23 import java.util.HashMap JavaDoc;
24 import java.util.Map JavaDoc;
25 import java.util.Collections JavaDoc;
26
27 import org.openide.ErrorManager;
28 import org.openide.cookies.EditorCookie;
29 import org.openide.filesystems.FileObject;
30 import org.openide.filesystems.FileUtil;
31 import org.openide.loaders.DataObject;
32 import org.openide.loaders.DataObjectNotFoundException;
33 import org.openide.text.Annotation;
34 import org.openide.text.Line;
35 import org.openide.util.NbBundle;
36 import org.openide.windows.OutputEvent;
37 import org.openide.windows.OutputListener;
38
39 import org.netbeans.api.java.classpath.GlobalPathRegistry;
40
41 /**
42  * <code>LogSupport</code> class for creating links in the output window.
43  *
44  * @author Stepan Herold
45  */

46 public class LogHyperLinkSupport {
47     private Map JavaDoc/*<Link, Link>*/ links = Collections.synchronizedMap(new HashMap JavaDoc());
48     private Annotation errAnnot;
49     
50     /**
51      * Return a link which implements <code>OutputListener</code> interface. Link
52      * is then used to represent a link in the output window. This class also
53      * handles error annotations which are shown after a line is clicked.
54      *
55      * @return link which implements <code>OutputListener</code> interface. Link
56      * is then used to represent a link in the output window.
57      */

58     public Link getLink(String JavaDoc errorMsg, String JavaDoc path, int line) {
59         Link newLink = new Link(errorMsg, path, line);
60         Link cachedLink = (Link)links.get(newLink);
61         if (cachedLink != null) {
62             return cachedLink;
63         }
64         links.put(newLink, newLink);
65         return newLink;
66     }
67
68     /**
69      * Detach error annotation.
70      */

71     public void detachAnnotation() {
72         if (errAnnot != null) {
73             errAnnot.detach();
74         }
75     }
76     
77     /**
78      * <code>LineInfo</code> is used to store info about the parsed line.
79      */

80     public static class LineInfo {
81         private String JavaDoc path;
82         private int line;
83         private String JavaDoc message;
84         private boolean error;
85         private boolean accessible;
86         
87         /**
88          * <code>LineInfo</code> is used to store info about the parsed line.
89          *
90          * @param path path to file
91          * @param line line number where the error occurred
92          * @param message error message
93          * @param error represents the line an error?
94          * @param accessible is the file accessible?
95          */

96         public LineInfo(String JavaDoc path, int line, String JavaDoc message, boolean error, boolean accessible) {
97             this.path = path;
98             this.line = line;
99             this.message = message;
100             this.error = error;
101             this.accessible = accessible;
102         }
103         
104         public String JavaDoc path() {
105             return path;
106         }
107         
108         public int line() {
109             return line;
110         }
111         
112         public String JavaDoc message() {
113             return message;
114         }
115         
116         public boolean isError() {
117             return error;
118         }
119         
120         public boolean isAccessible() {
121             return accessible;
122         }
123         
124         public String JavaDoc toString() {
125             return "path=" + path + " line=" + line + " message=" + message
126                     + " isError=" + error + " isAccessible=" + accessible;
127         }
128     }
129     
130     /**
131      * Error annotation.
132      */

133     static class ErrorAnnotation extends Annotation {
134         private String JavaDoc shortDesc = null;
135         
136         public ErrorAnnotation(String JavaDoc desc) {
137             shortDesc = desc;
138         }
139         
140         public String JavaDoc getAnnotationType() {
141             return "org-netbeans-modules-j2ee-sunserver"; // NOI18N
142
}
143         
144         public String JavaDoc getShortDescription() {
145             return shortDesc;
146         }
147         
148     }
149     
150     /**
151      * <code>Link</code> is used to create a link in the output window. To create
152      * a link use the <code>getLink</code> method of the <code>LogSupport</code>
153      * class. This prevents from memory vast by returning already existing instance,
154      * if one with such values exists.
155      */

156     public class Link implements OutputListener {
157         private String JavaDoc msg;
158         private String JavaDoc path;
159         private int line;
160         
161         private int hashCode = 0;
162         
163         Link(String JavaDoc msg, String JavaDoc path, int line) {
164             this.msg = msg;
165             this.path = path;
166             this.line = line;
167         }
168         
169         public int hashCode() {
170             if (hashCode == 0) {
171                 int result = 17;
172                 result = 37 * result + line;
173                 result = 37 * result + (path != null ? path.hashCode() : 0);
174                 result = 37 * result + (msg != null ? msg.hashCode() : 0);
175                 hashCode = result;
176             }
177             return hashCode;
178         }
179         
180         public boolean equals(Object JavaDoc obj) {
181             if (this == obj) {
182                 return true;
183             }
184             if (obj instanceof Link) {
185                 Link anotherLink = (Link)obj;
186                 if ((((msg != null) && msg.equals(anotherLink.msg)) || (msg == anotherLink.msg))
187                     && (((path != null) && path.equals(anotherLink.path)) || (path == anotherLink.path))
188                     && line == anotherLink.line) {
189                         return true;
190                 }
191             }
192             return false;
193         }
194         
195         /**
196          * If the link is clicked, required file is opened in the editor and an
197          * <code>ErrorAnnotation</code> is attached.
198          */

199         public void outputLineAction(OutputEvent ev) {
200             FileObject sourceFile = GlobalPathRegistry.getDefault().findResource(path);
201             if (sourceFile == null) {
202                 sourceFile = FileUtil.toFileObject(new File JavaDoc(path));
203             }
204             DataObject dataObject = null;
205             if (sourceFile != null) {
206                 try {
207                     dataObject = DataObject.find(sourceFile);
208                 } catch(DataObjectNotFoundException ex) {
209                     ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex);
210                 }
211             }
212             if (dataObject != null) {
213                 EditorCookie editorCookie = (EditorCookie)dataObject.getCookie(EditorCookie.class);
214                 if (editorCookie == null) {
215                     return;
216                 }
217                 editorCookie.open();
218                 Line errorLine = null;
219                 try {
220                     errorLine = editorCookie.getLineSet().getCurrent(line - 1);
221                 } catch (IndexOutOfBoundsException JavaDoc iobe) {
222                     return;
223                 }
224                 if (errAnnot != null) {
225                     errAnnot.detach();
226                 }
227                 String JavaDoc errorMsg = msg;
228                 if (errorMsg == null || errorMsg.equals("")) { //NOI18N
229
errorMsg = NbBundle.getMessage(Link.class, "MSG_ExceptionOccurred");
230                 }
231                 errAnnot = new ErrorAnnotation(errorMsg);
232                 errAnnot.attach(errorLine);
233                 errAnnot.moveToFront();
234                 errorLine.show(Line.SHOW_TRY_SHOW);
235             }
236         }
237         
238         /**
239          * If a link is cleared, error annotation is detached and link cache is
240          * clared.
241          */

242         public void outputLineCleared(OutputEvent ev) {
243             if (errAnnot != null) {
244                 errAnnot.detach();
245             }
246             if (!links.isEmpty()) {
247                 links.clear();
248             }
249         }
250         
251         public void outputLineSelected(OutputEvent ev) {
252         }
253     }
254     /**
255      * Support class for context log line analyzation and for creating links in
256      * the output window.
257      */

258     public static class AppServerLogSupport extends LogHyperLinkSupport {
259         private final String JavaDoc appServerInstallDir;
260         private String JavaDoc context = null;
261         private String JavaDoc prevMessage = null;
262         private static final String JavaDoc STANDARD_CONTEXT = "StandardContext["; // NOI18N
263
private static final int STANDARD_CONTEXT_LENGTH = STANDARD_CONTEXT.length();
264         private GlobalPathRegistry globalPathReg = GlobalPathRegistry.getDefault();
265         
266
267         public AppServerLogSupport(String JavaDoc catalinaWork, String JavaDoc webAppContext) {
268             appServerInstallDir = catalinaWork;
269             context = webAppContext;
270         }
271         
272         public LineInfo analyzeLine(String JavaDoc logLine) {
273             String JavaDoc path = null;
274             int line = -1;
275             String JavaDoc message = null;
276             boolean error = false;
277             boolean accessible = false;
278
279             logLine = logLine.trim();
280             int lineLenght = logLine.length();
281
282             // look for unix file links (e.g. /foo/bar.java:51: 'error msg')
283
if (logLine.startsWith("/")) {
284                 error = true;
285                 int colonIdx = logLine.indexOf(':');
286                 if (colonIdx > -1) {
287                     path = logLine.substring(0, colonIdx);
288                     accessible = true;
289                     if (lineLenght > colonIdx) {
290                         int nextColonIdx = logLine.indexOf(':', colonIdx + 1);
291                         if (nextColonIdx > -1) {
292                             String JavaDoc lineNum = logLine.substring(colonIdx + 1, nextColonIdx);
293                             try {
294                                 line = Integer.valueOf(lineNum).intValue();
295                             } catch(NumberFormatException JavaDoc nfe) {
296                                 accessible = true;
297                                 // ignore it
298
//ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, nfe);
299
}
300                             if (lineLenght > nextColonIdx) {
301                                 message = logLine.substring(nextColonIdx + 1, lineLenght);
302                             }
303                         }
304                     }
305                 }
306             }
307             // look for windows file links (e.g. c:\foo\bar.java:51: 'error msg')
308
else if (lineLenght > 3 && Character.isLetter(logLine.charAt(0))
309                         && (logLine.charAt(1) == ':') && (logLine.charAt(2) == '\\')) {
310                 error = true;
311                 int secondColonIdx = logLine.indexOf(':', 2);
312                 if (secondColonIdx > -1) {
313                     path = logLine.substring(0, secondColonIdx);
314                     accessible = true;
315                     if (lineLenght > secondColonIdx) {
316                         int thirdColonIdx = logLine.indexOf(':', secondColonIdx + 1);
317                         if (thirdColonIdx > -1) {
318                             String JavaDoc lineNum = logLine.substring(secondColonIdx + 1, thirdColonIdx);
319                             try {
320                                 line = Integer.valueOf(lineNum).intValue();
321                             } catch(NumberFormatException JavaDoc nfe) { // ignore it
322
accessible = true;
323                                  //ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, nfe);
324
}
325                             if (lineLenght > thirdColonIdx) {
326                                 message = logLine.substring(thirdColonIdx + 1, lineLenght);
327                             }
328                         }
329                     }
330                 }
331             }
332             // look for stacktrace links (e.g. at java.lang.Thread.run(Thread.java:595)
333
// at t.HyperlinkTest$1.run(HyperlinkTest.java:24))
334
else if (logLine.startsWith("at ") && lineLenght > 3) { // NOI18N
335
error = true;
336                 int parenthIdx = logLine.indexOf('(');
337                 if (parenthIdx > -1) {
338                     String JavaDoc classWithMethod = logLine.substring(3, parenthIdx);
339                     int lastDotIdx = classWithMethod.lastIndexOf('.');
340                     if (lastDotIdx > -1) {
341                         int lastParenthIdx = logLine.lastIndexOf(')');
342                         int lastColonIdx = logLine.lastIndexOf(':');
343                         if (lastParenthIdx > -1 && lastColonIdx > -1) {
344                             String JavaDoc lineNum = logLine.substring(lastColonIdx + 1, lastParenthIdx);
345                             try {
346                                 line = Integer.valueOf(lineNum).intValue();
347                             } catch(NumberFormatException JavaDoc nfe) { // ignore it
348
//ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, nfe);
349
error = true;
350                             }
351                             message = prevMessage;
352                         }
353                         int firstDolarIdx = classWithMethod.indexOf('$'); // > -1 for inner classes
354
String JavaDoc className = classWithMethod.substring(0, firstDolarIdx > -1 ? firstDolarIdx : lastDotIdx);
355                         path = className.replace('.','/') + ".java"; // NOI18N
356
accessible = globalPathReg.findResource(path) != null;
357                         if (className.startsWith("org.apache.jsp.") && context != null) { // NOI18N
358
if (context != null) {
359                                 String JavaDoc contextPath = context.equals("/")
360                                                         ? "/_" // hande ROOT context
361
: context;
362                                 path = appServerInstallDir + contextPath + "/" + path;
363                                 accessible = new File JavaDoc(path).exists();
364                             }
365                         }
366                     }
367                 }
368             }
369             // every other message treat as normal info message
370
else {
371                 prevMessage = logLine;
372                 // try to get context, if stored
373
int stdContextIdx = logLine.indexOf(STANDARD_CONTEXT);
374                 int lBracketIdx = -1;
375                 if (stdContextIdx > -1) {
376                     lBracketIdx = stdContextIdx + STANDARD_CONTEXT_LENGTH;
377                 }
378                 int rBracketIdx = logLine.indexOf(']');
379                 if (lBracketIdx > -1 && rBracketIdx > -1 && rBracketIdx > lBracketIdx) {
380                     context = logLine.substring(lBracketIdx, rBracketIdx);
381                 }
382             }
383             return new LineInfo(path, line, message, error, accessible);
384         }
385     }
386 }
387
Popular Tags