KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > java > source > parsing > SourceFileObject


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.java.source.parsing;
21
22 import java.io.ByteArrayInputStream JavaDoc;
23 import java.io.IOException JavaDoc;
24 import java.io.InputStream JavaDoc;
25 import java.io.InputStreamReader JavaDoc;
26 import java.io.OutputStream JavaDoc;
27 import java.io.OutputStreamWriter JavaDoc;
28 import java.io.Reader JavaDoc;
29 import java.io.StringReader JavaDoc;
30 import java.io.UnsupportedEncodingException JavaDoc;
31 import java.net.URI JavaDoc;
32 import java.nio.CharBuffer JavaDoc;
33 import java.util.Set JavaDoc;
34 import javax.lang.model.element.Modifier;
35 import javax.lang.model.element.NestingKind;
36 import javax.swing.text.BadLocationException JavaDoc;
37 import javax.swing.text.Document JavaDoc;
38 import javax.swing.text.StyledDocument JavaDoc;
39 import javax.tools.JavaFileObject;
40 import org.netbeans.api.java.lexer.JavaTokenId;
41 import org.netbeans.modules.java.source.parsing.DocumentProvider;
42 import org.netbeans.api.lexer.TokenHierarchy;
43 import org.netbeans.modules.java.preprocessorbridge.spi.JavaFileFilterImplementation;
44 import org.openide.ErrorManager;
45 import org.openide.cookies.EditorCookie;
46 import org.openide.filesystems.FileLock;
47 import org.openide.filesystems.FileObject;
48 import org.openide.filesystems.FileStateInvalidException;
49 import org.openide.loaders.DataObject;
50 import org.openide.loaders.DataObjectNotFoundException;
51 import org.openide.text.NbDocument;
52
53 /**
54  *
55  * @author Tomas Zezula
56  */

57 public class SourceFileObject implements JavaFileObject, DocumentProvider {
58     
59     final FileObject file;
60     private final Kind kind;
61     private URI JavaDoc uri; //Cache for URI
62
private String JavaDoc text;
63     private TokenHierarchy tokens;
64     private final JavaFileFilterImplementation filter;
65     
66     public static SourceFileObject create (final FileObject file) {
67         try {
68             return new SourceFileObject (file, null, false);
69         } catch (IOException JavaDoc ioe) {
70             ErrorManager.getDefault().notify(ioe);
71             return null;
72         }
73     }
74     
75     /** Creates a new instance of SourceFileObject */
76     public SourceFileObject (final FileObject file, final JavaFileFilterImplementation filter, final boolean renderNow) throws IOException JavaDoc {
77         assert file != null;
78         this.file = file;
79         this.filter = filter;
80         String JavaDoc ext = this.file.getExt();
81         if (FileObjects.JAVA.equalsIgnoreCase(ext)) { //NOI18N
82
this.kind = Kind.SOURCE;
83         }
84         else if (FileObjects.CLASS.equalsIgnoreCase(ext)) { //NOI18N
85
this.kind = Kind.CLASS;
86         }
87         else if (FileObjects.HTML.equalsIgnoreCase(ext)) { //NOI18N
88
this.kind = Kind.HTML;
89         }
90         else {
91             this.kind = Kind.OTHER;
92         }
93         if (renderNow) {
94             text = getCharContentImpl().toString();
95         }
96     }
97
98     
99
100     public boolean isNameCompatible (String JavaDoc simplename, JavaFileObject.Kind kind) {
101         assert simplename != null;
102         return this.kind == kind && this.getNameWithoutExtension().equals(simplename);
103     }
104
105     public CharBuffer JavaDoc getCharContent(boolean ignoreEncodingErrors) throws IOException JavaDoc {
106         String JavaDoc _text;
107         synchronized (this) {
108             _text = this.text;
109         }
110         if (_text != null) {
111             return CharBuffer.wrap(_text);
112         }
113         else {
114             return getCharContentImpl();
115         }
116     }
117     
118     public TokenHierarchy getTokenHierarchy() throws IOException JavaDoc {
119         if (tokens == null)
120             getCharContentImpl();
121         
122         return tokens;
123     }
124    
125
126     public java.io.Writer JavaDoc openWriter() throws IOException JavaDoc {
127         return new OutputStreamWriter JavaDoc (this.openOutputStream(),FileObjects.encodingName);
128     }
129
130     public Reader JavaDoc openReader(boolean ignoreEncodingErrors) throws IOException JavaDoc {
131         String JavaDoc _text;
132         synchronized (this) {
133             _text = text;
134         }
135         if (_text != null) {
136             return new StringReader JavaDoc (_text);
137         }
138         else {
139             final Document JavaDoc doc = getDocument(isOpened());
140             if (doc == null) {
141                 Reader JavaDoc r = new InputStreamReader JavaDoc (this.file.getInputStream(),FileObjects.encodingName);
142                 if (filter != null) {
143                     r = filter.filterReader(r);
144                 }
145                 return r;
146             }
147             else {
148                 final StringBuilder JavaDoc builder = new StringBuilder JavaDoc ();
149                 doc.render(new Runnable JavaDoc() {
150                     public void run () {
151                       try {
152                             builder.append(doc.getText(0, doc.getLength()));
153                         } catch (BadLocationException JavaDoc e) {
154                             ErrorManager.getDefault().notify(e);
155                         }
156                     }
157                 });
158                 return new StringReader JavaDoc (builder.toString());
159             }
160         }
161     }
162
163     public java.io.OutputStream JavaDoc openOutputStream() throws IOException JavaDoc {
164         final StyledDocument JavaDoc doc = getDocument(isOpened());
165         if (doc == null) {
166             return new LckStream (this.file);
167         }
168         else {
169             return new DocumentStream (doc);
170         }
171     }
172
173     public InputStream JavaDoc openInputStream() throws IOException JavaDoc {
174         String JavaDoc _text;
175         synchronized (this) {
176             _text = text;
177         }
178         if (_text != null) {
179             return new ByteArrayInputStream JavaDoc (_text.getBytes());
180         }
181         else {
182             final Document JavaDoc doc = getDocument(isOpened());
183             if (doc == null) {
184                 return this.file.getInputStream();
185             }
186             else {
187                 final StringBuilder JavaDoc builder = new StringBuilder JavaDoc ();
188                 doc.render(new Runnable JavaDoc() {
189                     public void run () {
190                       try {
191                             builder.append(doc.getText(0, doc.getLength()));
192                         } catch (BadLocationException JavaDoc e) {
193                             ErrorManager.getDefault().notify(e);
194                         }
195                     }
196                 });
197                 return new ByteArrayInputStream JavaDoc (builder.toString().getBytes());
198             }
199         }
200     }
201
202     public boolean delete() {
203         if (isModified()!=null) {
204             //If the file is modified in editor do not delete it
205
return false;
206         }
207         else {
208             try {
209                 FileLock lock = this.file.lock();
210                 try {
211                     this.file.delete (lock);
212                     return true;
213                 }
214                 finally {
215                     lock.releaseLock();
216                 }
217             } catch (IOException JavaDoc e) {
218                 return false;
219             }
220         }
221     }
222
223
224     public JavaFileObject.Kind getKind() {
225         return this.kind;
226     }
227
228     public String JavaDoc getName() {
229        return this.file.getNameExt();
230     }
231
232     public String JavaDoc getNameWithoutExtension() {
233         return this.file.getName();
234     }
235     
236     public synchronized URI JavaDoc toUri () {
237         if (this.uri == null) {
238             try {
239                 this.uri = URI.create(this.file.getURL().toExternalForm());
240             } catch (FileStateInvalidException e) {
241                 ErrorManager.getDefault().notify(e);
242             }
243         }
244         return this.uri;
245     }
246
247     /**
248      * Returns the mtime of the file, in the case of opened
249      * modified file, the mtime is not known, this method returns
250      * the current time.
251      */

252     public long getLastModified() {
253         if (isModified()==null) {
254             return this.file.lastModified().getTime();
255         }
256         else {
257             return System.currentTimeMillis();
258         }
259     }
260     
261     public NestingKind getNestingKind() {
262         return null;
263     }
264
265     public Modifier getAccessLevel() {
266         return null;
267     }
268     
269     public @Override JavaDoc String JavaDoc toString () {
270         return this.file.getPath();
271     }
272     
273     public @Override JavaDoc boolean equals (Object JavaDoc other) {
274         if (other instanceof SourceFileObject) {
275             SourceFileObject otherSource = (SourceFileObject) other;
276             return this.file.equals (otherSource.file);
277         }
278         else {
279             return false;
280         }
281     }
282     
283     public @Override JavaDoc int hashCode () {
284         return this.file.hashCode();
285     }
286     
287     public StyledDocument JavaDoc getDocument() {
288         EditorCookie ec = isOpened();
289         return ec != null ? getDocument(ec) : null;
290     }
291     
292     public void runAtomic(final Runnable JavaDoc r) {
293         assert r != null;
294         final StyledDocument JavaDoc doc = getDocument();
295         if (doc == null) {
296             throw new IllegalStateException JavaDoc ();
297         }
298         else {
299             NbDocument.runAtomic(doc,r);
300         }
301     }
302     
303     @SuppressWarnings JavaDoc ("unchecked") // NOI18N
304
private EditorCookie isModified () {
305         DataObject.Registry regs = DataObject.getRegistry();
306         Set JavaDoc<DataObject> modified = (Set JavaDoc<DataObject>) regs.getModifiedSet();
307         for (DataObject dobj : modified) {
308             if (this.file.equals(dobj.getPrimaryFile())) {
309                 EditorCookie ec = (EditorCookie) dobj.getCookie(EditorCookie.class);
310                 return ec;
311             }
312         }
313         return null;
314     }
315     
316     public EditorCookie isOpened () {
317         try {
318             if (this.kind == JavaFileObject.Kind.CLASS) {
319                 return null;
320             }
321             DataObject dobj = DataObject.find(this.file);
322             return (EditorCookie) dobj.getCookie(EditorCookie.class);
323         } catch (DataObjectNotFoundException dnf) {
324             return null;
325         }
326     }
327     
328     private CharBuffer JavaDoc getCharContentImpl () throws IOException JavaDoc {
329         final Document JavaDoc doc = getDocument(isOpened());
330     final char[][] result = new char[1][];
331         final int[] length = new int[1];
332         if (doc == null) {
333         Reader JavaDoc in = this.openReader (true);
334             int red = 0, rv;
335             try {
336                 int len = (int)this.file.getSize();
337                 result[0] = new char [len+1];
338                 while ((rv=in.read(result[0],red,len-red))>0 && (red=red+rv)<len);
339             } finally {
340                 in.close();
341             }
342             int j=0;
343             for (int i=0; i<red;i++) {
344                 if (result[0][i] =='\r') { //NOI18N
345
if (i+1>=red || result[0][i+1]!='\n') { //NOI18N
346
result[0][j++] = '\n'; //NOI18N
347
}
348                 }
349                 else {
350                     result[0][j++] = result[0][i];
351                 }
352             }
353             length[0] = j;
354         }
355         else {
356             doc.render(new Runnable JavaDoc() {
357                 public void run () {
358                   try {
359             int len = doc.getLength();
360             result[0] = new char[len+1];
361             doc.getText(0,len).getChars(0,len,result[0],0);
362                         length[0] = len;
363                     } catch (BadLocationException JavaDoc e) {
364                         ErrorManager.getDefault().notify(e);
365                     }
366                 }
367             });
368         }
369     result[0][length[0]]='\n'; //NOI18N
370
CharBuffer JavaDoc charBuffer = CharBuffer.wrap (result[0],0,length[0]);
371         tokens = doc == null ? TokenHierarchy.create(charBuffer, true, JavaTokenId.language(), null, null) : TokenHierarchy.get(doc);//TODO: .createSnapshot();
372
return charBuffer;
373     }
374             
375     private static StyledDocument JavaDoc getDocument (EditorCookie ec) {
376         return ec == null ? null : ec.getDocument();
377     }
378     
379     
380     private class LckStream extends OutputStream JavaDoc {
381         
382         private final OutputStream JavaDoc delegate;
383         private final FileLock lock;
384         
385         public LckStream (final FileObject fo) throws IOException JavaDoc {
386             assert fo != null;
387             this.lock = fo.lock();
388             try {
389                 this.delegate = fo.getOutputStream (this.lock);
390             } finally {
391                 if (this.delegate == null) {
392                     this.lock.releaseLock();
393                 }
394             }
395         }
396
397         public @Override JavaDoc void write(byte[] b, int off, int len) throws IOException JavaDoc {
398             this.delegate.write(b, off, len);
399         }
400
401         public @Override JavaDoc void write(byte[] b) throws IOException JavaDoc {
402             this.delegate.write(b);
403         }
404
405         public void write(int b) throws IOException JavaDoc {
406             this.delegate.write (b);
407         }
408
409         public @Override JavaDoc void close() throws IOException JavaDoc {
410             try {
411                 this.delegate.close();
412             } finally {
413                 this.lock.releaseLock();
414                 synchronized (SourceFileObject.this) {
415                     text = null;
416                 }
417             }
418         }
419     }
420     
421     private class DocumentStream extends OutputStream JavaDoc {
422         
423         private static final int BUF_SIZ=2048;
424         
425         private final StyledDocument JavaDoc doc;
426         private byte[] data;
427         private int pos;
428             
429         public DocumentStream (final StyledDocument JavaDoc doc) {
430             assert doc != null;
431             this.doc = doc;
432             this.data = new byte[BUF_SIZ];
433             this.pos = 0;
434         }
435         
436         public synchronized @Override JavaDoc void write(byte[] b, int off, int len) throws IOException JavaDoc {
437             ensureSize (len);
438             System.arraycopy(b,off,this.data,this.pos,len);
439             this.pos+=len;
440         }
441
442         public synchronized @Override JavaDoc void write(byte[] b) throws IOException JavaDoc {
443             ensureSize (b.length);
444             System.arraycopy(b,0,this.data,this.pos,b.length);
445             this.pos+=b.length;
446         }
447
448         public synchronized void write(int b) throws IOException JavaDoc {
449             ensureSize (1);
450             this.data[this.pos++]=(byte)(b&0xff);
451         }
452         
453         private void ensureSize (int delta) {
454             int requiredLength = this.pos + delta;
455             if (this.data.length<requiredLength) {
456                 int newSize = this.data.length + BUF_SIZ;
457                 while (newSize<requiredLength) {
458                     newSize+=BUF_SIZ;
459                 }
460                 byte[] newData = new byte[newSize];
461                 System.arraycopy(this.data,0,newData,0,this.pos);
462                 this.data = newData;
463             }
464         }
465         
466         public synchronized @Override JavaDoc void close() throws IOException JavaDoc {
467             try {
468                 NbDocument.runAtomic(this.doc,
469                     new Runnable JavaDoc () {
470                         public void run () {
471                             try {
472                                 doc.remove(0,doc.getLength());
473                                 doc.insertString(0,new String JavaDoc(data,0,pos,FileObjects.encodingName),null);
474                             } catch (BadLocationException JavaDoc e) {
475                                 ErrorManager.getDefault().notify(e);
476                             }
477                             catch (UnsupportedEncodingException JavaDoc ee) {
478                                 ErrorManager.getDefault().notify (ee);
479                             }
480                         }
481                     });
482             } finally {
483                 synchronized (SourceFileObject.this) {
484                     text = null;
485                 }
486             }
487         }
488     }
489 }
490
Popular Tags