1 19 package org.netbeans.modules.retouche.source.parsing; 20 21 import java.io.ByteArrayInputStream ; 22 import java.io.ByteArrayOutputStream ; 23 import java.io.IOException ; 24 import java.io.InputStream ; 25 import java.io.InputStreamReader ; 26 import java.io.OutputStream ; 27 import java.io.OutputStreamWriter ; 28 import java.io.Reader ; 29 import java.io.UnsupportedEncodingException ; 30 import java.net.URI ; 31 import java.nio.CharBuffer ; 32 import java.util.Set ; 33 import javax.swing.text.BadLocationException ; 34 import javax.swing.text.Document ; 35 import javax.swing.text.StyledDocument ; 36 import org.netbeans.api.lexer.TokenHierarchy; 37 import org.netbeans.modules.gsf.Language; 38 import org.netbeans.modules.gsf.LanguageRegistry; 39 import org.openide.ErrorManager; 41 import org.openide.cookies.EditorCookie; 42 import org.openide.filesystems.FileLock; 43 import org.openide.filesystems.FileObject; 44 import org.openide.filesystems.FileStateInvalidException; 45 import org.openide.loaders.DataObject; 46 import org.openide.loaders.DataObjectNotFoundException; 47 import org.openide.text.NbDocument; 48 49 58 public class SourceFileObject { 59 60 final FileObject file; 61 private URI uri; private String text; 64 private TokenHierarchy tokens; 65 66 public static SourceFileObject create (final FileObject file) { 67 try { 68 return new SourceFileObject (file, false); 69 } catch (IOException ioe) { 70 ErrorManager.getDefault().notify(ioe); 71 return null; 72 } 73 } 74 75 76 public SourceFileObject (final FileObject file, final boolean renderNow) throws IOException { 77 assert file != null; 78 this.file = file; 79 if (renderNow) { 93 text = getCharContentImpl().toString(); 94 } 95 } 96 97 98 99 104 public CharBuffer getCharContent(boolean ignoreEncodingErrors) throws IOException { 105 String _text; 106 synchronized (this) { 107 _text = this.text; 108 } 109 if (_text != null) { 110 return CharBuffer.wrap(_text); 111 } 112 else { 113 return getCharContentImpl(); 114 } 115 } 116 117 public TokenHierarchy getTokenHiearchy() throws IOException { 118 if (tokens == null) 119 getCharContentImpl(); 120 121 return tokens; 122 } 123 124 125 public java.io.Writer openWriter() throws IOException { 126 return new OutputStreamWriter (this.openOutputStream(),encodingName); 127 } 128 129 public Reader openReader(boolean ignoreEncodingErrors) throws IOException { 130 return new InputStreamReader (this.openInputStream(),encodingName); 131 } 132 133 static final String encodingName = new OutputStreamWriter (new ByteArrayOutputStream ()).getEncoding(); 134 135 public java.io.OutputStream openOutputStream() throws IOException { 136 final StyledDocument doc = getDocument(isOpened()); 137 if (doc == null) { 138 return new LckStream (this.file); 139 } 140 else { 141 return new DocumentStream (doc); 142 } 143 } 144 145 public InputStream openInputStream() throws IOException { 146 String _text; 147 synchronized (this) { 148 _text = text; 149 } 150 if (_text != null) { 151 return new ByteArrayInputStream (_text.getBytes()); 152 } 153 else { 154 final Document doc = getDocument(isOpened()); 155 if (doc == null) { 156 return this.file.getInputStream(); 157 } 158 else { 159 final StringBuilder builder = new StringBuilder (); 160 doc.render(new Runnable () { 161 public void run () { 162 try { 163 builder.append(doc.getText(0, doc.getLength())); 164 } catch (BadLocationException e) { 165 ErrorManager.getDefault().notify(e); 166 } 167 } 168 }); 169 return new ByteArrayInputStream (builder.toString().getBytes()); 170 } 171 } 172 } 173 174 public boolean delete() { 175 if (isModified()!=null) { 176 return false; 178 } 179 else { 180 try { 181 FileLock lock = this.file.lock(); 182 try { 183 this.file.delete (lock); 184 return true; 185 } 186 finally { 187 lock.releaseLock(); 188 } 189 } catch (IOException e) { 190 return false; 191 } 192 } 193 } 194 195 196 public String getName() { 201 return this.file.getNameExt(); 202 } 203 204 public String getNameWithoutExtension() { 205 return this.file.getName(); 206 } 207 208 public synchronized URI toUri () { 209 if (this.uri == null) { 210 try { 211 this.uri = URI.create(this.file.getURL().toExternalForm()); 212 } catch (FileStateInvalidException e) { 213 ErrorManager.getDefault().notify(e); 214 } 215 } 216 return this.uri; 217 } 218 219 224 public long getLastModified() { 225 if (isModified()==null) { 226 return this.file.lastModified().getTime(); 227 } 228 else { 229 return System.currentTimeMillis(); 230 } 231 } 232 233 245 public @Override boolean equals (Object other) { 246 if (other instanceof SourceFileObject) { 247 SourceFileObject otherSource = (SourceFileObject) other; 248 return this.file.equals (otherSource.file); 249 } 250 else { 251 return false; 252 } 253 } 254 255 public @Override int hashCode () { 256 return this.file.hashCode(); 257 } 258 259 public StyledDocument getDocument() { 260 EditorCookie ec = isOpened(); 261 return ec != null ? getDocument(ec) : null; 262 } 263 264 public void runAtomic(final Runnable r) { 265 assert r != null; 266 final StyledDocument doc = getDocument(); 267 if (doc == null) { 268 throw new IllegalStateException (); 269 } 270 else { 271 NbDocument.runAtomic(doc,r); 272 } 273 } 274 275 @SuppressWarnings ("unchecked") private EditorCookie isModified () { 277 DataObject.Registry regs = DataObject.getRegistry(); 278 Set <DataObject> modified = (Set <DataObject>) regs.getModifiedSet(); 279 for (DataObject dobj : modified) { 280 if (this.file.equals(dobj.getPrimaryFile())) { 281 EditorCookie ec = (EditorCookie) dobj.getCookie(EditorCookie.class); 282 return ec; 283 } 284 } 285 return null; 286 } 287 288 public EditorCookie isOpened () { 289 try { 293 DataObject dobj = DataObject.find(this.file); 294 return (EditorCookie) dobj.getCookie(EditorCookie.class); 295 } catch (DataObjectNotFoundException dnf) { 296 return null; 297 } 298 } 299 300 private CharBuffer getCharContentImpl () throws IOException { 301 final Document doc = getDocument(isOpened()); 302 final char[][] result = new char[1][]; 303 final int[] length = new int[1]; 304 if (doc == null) { 305 Reader in = this.openReader (true); 306 int red = 0, rv; 307 try { 308 int len = (int)this.file.getSize(); 309 result[0] = new char [len+1]; 310 while ((rv=in.read(result[0],red,len-red))>0 && (red=red+rv)<len); 311 } finally { 312 in.close(); 313 } 314 int j=0; 315 for (int i=0; i<red;i++) { 316 if (result[0][i] =='\r') { if (i+1>=red || result[0][i+1]!='\n') { result[0][j++] = '\n'; } 320 } 321 else { 322 result[0][j++] = result[0][i]; 323 } 324 } 325 length[0] = j; 326 } 327 else { 328 doc.render(new Runnable () { 329 public void run () { 330 try { 331 int len = doc.getLength(); 332 result[0] = new char[len+1]; 333 doc.getText(0,len).getChars(0,len,result[0],0); 334 length[0] = len; 335 } catch (BadLocationException e) { 336 ErrorManager.getDefault().notify(e); 337 } 338 } 339 }); 340 } 341 result[0][length[0]]='\n'; CharBuffer charBuffer = CharBuffer.wrap (result[0],0,length[0]); 343 Language language = LanguageRegistry.getInstance().getLanguageByMimeType(this.file.getMIMEType()); 344 if (language != null && language.getGsfLanguage() != null) { 345 org.netbeans.api.lexer.Language lexerLanguage = (org.netbeans.api.lexer.Language)language.getGsfLanguage().getLexerLanguage(); 346 tokens = doc == null ? TokenHierarchy.create(charBuffer, true, lexerLanguage, null, null) : TokenHierarchy.get(doc); } 348 return charBuffer; 349 } 350 351 private static StyledDocument getDocument (EditorCookie ec) { 352 return ec == null ? null : ec.getDocument(); 353 } 354 355 356 private class LckStream extends OutputStream { 357 358 private final OutputStream delegate; 359 private final FileLock lock; 360 361 public LckStream (final FileObject fo) throws IOException { 362 assert fo != null; 363 this.lock = fo.lock(); 364 try { 365 this.delegate = fo.getOutputStream (this.lock); 366 } finally { 367 if (this.delegate == null) { 368 this.lock.releaseLock(); 369 } 370 } 371 } 372 373 public @Override void write(byte[] b, int off, int len) throws IOException { 374 this.delegate.write(b, off, len); 375 } 376 377 public @Override void write(byte[] b) throws IOException { 378 this.delegate.write(b); 379 } 380 381 public void write(int b) throws IOException { 382 this.delegate.write (b); 383 } 384 385 public @Override void close() throws IOException { 386 try { 387 this.delegate.close(); 388 } finally { 389 this.lock.releaseLock(); 390 synchronized (SourceFileObject.this) { 391 text = null; 392 } 393 } 394 } 395 } 396 397 private class DocumentStream extends OutputStream { 398 399 private static final int BUF_SIZ=2048; 400 401 private final StyledDocument doc; 402 private byte[] data; 403 private int pos; 404 405 public DocumentStream (final StyledDocument doc) { 406 assert doc != null; 407 this.doc = doc; 408 this.data = new byte[BUF_SIZ]; 409 this.pos = 0; 410 } 411 412 public synchronized @Override void write(byte[] b, int off, int len) throws IOException { 413 ensureSize (len); 414 System.arraycopy(b,off,this.data,this.pos,len); 415 this.pos+=len; 416 } 417 418 public synchronized @Override void write(byte[] b) throws IOException { 419 ensureSize (b.length); 420 System.arraycopy(b,0,this.data,this.pos,b.length); 421 this.pos+=b.length; 422 } 423 424 public synchronized void write(int b) throws IOException { 425 ensureSize (1); 426 this.data[this.pos++]=(byte)(b&0xff); 427 } 428 429 private void ensureSize (int delta) { 430 int requiredLength = this.pos + delta; 431 if (this.data.length<requiredLength) { 432 int newSize = this.data.length + BUF_SIZ; 433 while (newSize<requiredLength) { 434 newSize+=BUF_SIZ; 435 } 436 byte[] newData = new byte[newSize]; 437 System.arraycopy(this.data,0,newData,0,this.pos); 438 this.data = newData; 439 } 440 } 441 442 public synchronized @Override void close() throws IOException { 443 try { 444 NbDocument.runAtomic(this.doc, 445 new Runnable () { 446 public void run () { 447 try { 448 doc.remove(0,doc.getLength()); 449 doc.insertString(0,new String (data,0,pos,encodingName),null); 450 } catch (BadLocationException e) { 451 ErrorManager.getDefault().notify(e); 452 } 453 catch (UnsupportedEncodingException ee) { 454 ErrorManager.getDefault().notify (ee); 455 } 456 } 457 }); 458 } finally { 459 synchronized (SourceFileObject.this) { 460 text = null; 461 } 462 } 463 } 464 } 465 } 466 | Popular Tags |