1 19 20 package org.apache.tools.ant.module.run; 21 22 import java.awt.Toolkit ; 23 import java.beans.PropertyChangeEvent ; 24 import java.beans.PropertyChangeListener ; 25 import java.io.IOException ; 26 import java.net.URL ; 27 import java.util.Iterator ; 28 import java.util.Set ; 29 import org.apache.tools.ant.module.AntModule; 30 import org.openide.ErrorManager; 31 import org.openide.awt.StatusDisplayer; 32 import org.openide.cookies.EditorCookie; 33 import org.openide.filesystems.FileObject; 34 import org.openide.filesystems.URLMapper; 35 import org.openide.loaders.DataObject; 36 import org.openide.loaders.DataObjectNotFoundException; 37 import org.openide.text.Annotatable; 38 import org.openide.text.Annotation; 39 import org.openide.text.Line; 40 import org.openide.util.WeakSet; 41 import org.openide.windows.OutputEvent; 42 import org.openide.windows.OutputListener; 43 44 50 public final class Hyperlink extends Annotation implements OutputListener, PropertyChangeListener { 51 52 private static final Set <Hyperlink> hyperlinks = new WeakSet<Hyperlink>(); 54 public static void detachAllAnnotations() { 55 synchronized (hyperlinks) { 56 Iterator <Hyperlink> it = hyperlinks.iterator(); 57 while (it.hasNext()) { 58 it.next().destroy(); 59 it.remove(); 60 } 61 } 62 } 63 64 private final URL url; 65 private final String message; 66 private final int line1; 67 private int col1; 68 private final int line2; 69 private final int col2; 70 private Line liveLine; 71 72 private boolean masked; 73 74 private boolean dead = false; 75 76 public Hyperlink(URL url, String message, int line1, int col1, int line2, int col2) { 77 this.url = url; 78 this.message = message; 79 this.line1 = line1; 80 this.col1 = col1; 81 this.line2 = line2; 82 this.col2 = col2; 83 synchronized (hyperlinks) { 84 hyperlinks.add(this); 85 } 86 } 87 88 92 public void setColumn1(int col1) { 93 if (this.col1 == -1) { 94 this.col1 = col1; 95 } 96 } 97 98 void destroy() { 99 doDetach(); 100 dead = true; 101 synchronized (hyperlinks) { 102 liveLine = null; 103 } 104 } 105 106 public void outputLineAction(OutputEvent ev) { 107 if (dead) return; 108 FileObject file = URLMapper.findFileObject(url); 109 if (file == null) { Toolkit.getDefaultToolkit().beep(); 111 return; 112 } 113 try { 114 DataObject dob = DataObject.find(file); 115 EditorCookie ed = dob.getCookie(EditorCookie.class); 116 if (ed != null && file == dob.getPrimaryFile()) { 117 if (line1 == -1) { 118 ed.open(); 120 } else { 121 ed.openDocument(); AntModule.err.log("opened document for " + file); 123 try { 124 Line line = updateLines(ed); 125 if (!line.isDeleted()) { 126 attachAsNeeded(line); 127 if (col1 == -1) { 128 line.show(Line.SHOW_GOTO); 129 } else { 130 line.show(Line.SHOW_GOTO, col1 - 1); 131 } 132 } 133 } catch (IndexOutOfBoundsException ioobe) { 134 ed.open(); 136 } 137 } 138 } else { 139 Toolkit.getDefaultToolkit().beep(); 140 } 141 } catch (DataObjectNotFoundException donfe) { 142 ErrorManager.getDefault().notify(ErrorManager.WARNING, donfe); 143 } catch (IOException ioe) { 144 ErrorManager.getDefault().notify(ErrorManager.WARNING, ioe); 146 } 147 if (message != null) { 148 StatusDisplayer.getDefault().setStatusText(message); 151 } 152 } 153 154 158 private Line updateLines(EditorCookie ed) { 159 Line.Set lineset = ed.getLineSet(); 160 synchronized (hyperlinks) { 161 assert line1 != -1; 162 boolean ran = false; 163 boolean encounteredThis = false; 164 boolean modifiedThis = false; 165 if (liveLine == null) { 166 ran = true; 167 for (Hyperlink h : hyperlinks) { 168 if (h == this) { 169 encounteredThis = true; 170 } 171 if (h.liveLine == null && h.url.equals(url) && h.line1 != -1) { 172 Line l = lineset.getOriginal(h.line1 - 1); 173 assert l != null : h; 174 h.liveLine = l; 175 if (h == this) { 176 modifiedThis = true; 177 } 178 } 179 } 180 } 181 assert liveLine != null : "this=" + this + " ran=" + ran + 182 " encounteredThis=" + encounteredThis + " modifiedThis=" + modifiedThis + 183 " hyperlinks=" + hyperlinks + " hyperlinks.contains(this)=" + hyperlinks.contains(this); 184 return liveLine; 185 } 186 } 187 188 public void outputLineSelected(OutputEvent ev) { 189 if (dead) return; 190 FileObject file = URLMapper.findFileObject(url); 191 if (file == null) { 192 return; 193 } 194 try { 195 DataObject dob = DataObject.find(file); 196 EditorCookie ed = dob.getCookie(EditorCookie.class); 197 if (ed != null) { 198 if (ed.getDocument() == null) { 199 AntModule.err.log("no document for " + file); 202 return; 203 } 204 AntModule.err.log("got document for " + file); 205 if (line1 != -1) { 206 Line line = updateLines(ed); 207 if (!line.isDeleted()) { 208 attachAsNeeded(line); 209 if (col1 == -1) { 210 line.show(Line.SHOW_TRY_SHOW); 211 } else { 212 line.show(Line.SHOW_TRY_SHOW, col1 - 1); 213 } 214 } 215 } 216 } 217 } catch (DataObjectNotFoundException donfe) { 218 ErrorManager.getDefault().notify(ErrorManager.WARNING, donfe); 219 } catch (IndexOutOfBoundsException iobe) { 220 } 222 } 223 224 private synchronized void attachAsNeeded(Line l) { 225 if (getAttachedAnnotatable() == null) { 226 boolean log = AntModule.err.isLoggable(ErrorManager.INFORMATIONAL); 227 masked |= l.getAnnotationCount() > 0; 229 if (masked) { 230 return; 231 } 232 Annotatable ann; 233 String text = l.getText(); 235 if (log) AntModule.err.log("Attaching to line " + l.getDisplayName() + " text=`" + text + "' line1=" + line1 + " line2=" + line2 + " col1=" + col1 + " col2=" + col2); 236 if (text != null && (line2 == -1 || line1 == line2) && col1 != -1) { 237 int new_col1 = convertTabColumnsToCharacterColumns(text, col1 - 1, 8); 238 int new_col2 = convertTabColumnsToCharacterColumns(text, col2 - 1, 8); 239 if (log) AntModule.err.log("\tfits on one line"); 240 if (new_col2 != -1 && new_col2 >= new_col1 && new_col2 < text.length()) { 241 if (log) AntModule.err.log("\tspecified section of the line"); 242 ann = l.createPart(new_col1, new_col2 - new_col1 + 1); 243 } else if (new_col1 < text.length()) { 244 if (log) AntModule.err.log("\tspecified column to end of line"); 245 ann = l.createPart(new_col1, text.length() - new_col1 - 1); 246 } else { 247 if (log) AntModule.err.log("\tcolumn numbers are bogus"); 248 ann = l; 249 } 250 } else { 251 if (log) AntModule.err.log("\tmultiple lines, something wrong with line, or no column given"); 252 ann = l; 253 } 254 attach(ann); 255 synchronized (hyperlinks) { 257 for (Hyperlink h : hyperlinks) { 258 if (h != this) { 259 h.doDetach(); 260 } 261 } 262 } 263 ann.addPropertyChangeListener(this); 264 } 265 } 266 267 private int convertTabColumnsToCharacterColumns(String text, int column, int tabSize) { 269 char[] textChars = text.toCharArray(); 274 int i; 275 int jikes_column = 0; 276 for (i=0; i<textChars.length && jikes_column<column; i++) { 277 if (textChars[i] == 9) { 278 jikes_column += (tabSize-(jikes_column%tabSize)); 279 } else { 280 jikes_column++; 281 } 282 } 283 return i; 284 } 285 286 private synchronized void doDetach() { 287 Annotatable ann = getAttachedAnnotatable(); 288 if (ann != null) { 289 if (AntModule.err.isLoggable(ErrorManager.INFORMATIONAL)) { 290 AntModule.err.log("Detaching from " + ann + " `" + ann.getText() + "'"); 291 } 292 ann.removePropertyChangeListener(this); 293 detach(); 294 } 295 } 296 297 public void outputLineCleared(OutputEvent ev) { 298 doDetach(); 299 synchronized (hyperlinks) { 300 liveLine = null; 301 } 302 } 303 304 public void propertyChange(PropertyChangeEvent ev) { 305 if (dead) return; 306 String prop = ev.getPropertyName(); 307 if (prop == null || 308 prop.equals(Annotatable.PROP_TEXT) || 309 prop.equals(Annotatable.PROP_DELETED)) { 310 if (AntModule.err.isLoggable(ErrorManager.INFORMATIONAL)) { 313 AntModule.err.log("Received Annotatable property change: " + prop); 314 } 315 doDetach(); 316 } 317 if (Annotatable.PROP_ANNOTATION_COUNT.equals(prop)) { 318 Annotatable ann = getAttachedAnnotatable(); 320 if (ann != null) { 321 int count = ann.getAnnotationCount(); 322 if (ann instanceof Line.Part) { 323 count += ((Line.Part) ann).getLine().getAnnotationCount(); 325 } 326 if (count > 1) { 327 masked = true; 328 doDetach(); 329 } 330 } 331 } 332 } 333 334 @Override 335 public String getAnnotationType() { 336 return "org-apache-tools-ant-module-error"; } 338 339 @Override 340 public String getShortDescription() { 341 return message; 342 } 343 344 @Override 345 public String toString() { 346 return "Hyperlink[" + url + ":" + line1 + ":" + col1 + ":" + line2 + ":" + col2 + "]"; } 348 349 } 350 | Popular Tags |