KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > api > java > source > WorkingCopy


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.api.java.source;
21
22 import com.sun.source.tree.CompilationUnitTree;
23 import com.sun.source.tree.Tree;
24 import com.sun.tools.javac.api.JavacTaskImpl;
25 import com.sun.tools.javac.code.Source;
26 import com.sun.tools.javac.util.Context;
27 import java.io.IOException JavaDoc;
28 import java.io.PrintWriter JavaDoc;
29 import java.io.Writer JavaDoc;
30 import java.util.ArrayList JavaDoc;
31 import java.util.Collections JavaDoc;
32 import java.util.List JavaDoc;
33 import java.util.Map JavaDoc;
34 import java.util.logging.Level JavaDoc;
35 import java.util.logging.Logger JavaDoc;
36 import javax.swing.text.BadLocationException JavaDoc;
37 import javax.swing.text.Position.Bias;
38 import javax.tools.JavaFileObject;
39 import org.netbeans.api.java.source.ModificationResult.Difference;
40 import org.netbeans.api.java.source.transform.ChangeSet;
41 import org.netbeans.api.java.source.query.QueryException;
42 import org.netbeans.api.java.source.transform.Transformer;
43 import org.netbeans.modules.java.source.engine.RootTree;
44 import org.netbeans.modules.java.source.builder.UndoListService;
45 import org.netbeans.modules.java.source.builder.ASTService;
46 import org.netbeans.modules.java.source.builder.DefaultEnvironment;
47 import org.netbeans.modules.java.source.builder.TreeFactory;
48 import org.netbeans.modules.java.source.engine.DefaultApplicationContext;
49 import org.netbeans.modules.java.source.engine.EngineEnvironment;
50 import org.netbeans.modules.java.source.engine.ReattributionException;
51 import org.netbeans.modules.java.source.engine.SourceReader;
52 import org.netbeans.modules.java.source.engine.SourceRewriter;
53 import org.netbeans.modules.java.source.save.Commit;
54 import org.openide.cookies.EditorCookie;
55 import org.openide.filesystems.FileObject;
56 import org.openide.filesystems.FileUtil;
57 import org.openide.loaders.DataObject;
58 import org.openide.text.CloneableEditorSupport;
59
60 /**XXX: extends CompilationController now, finish method delegation
61  *
62  * @author Dusan Balek, Petr Hrebejk
63  */

64 public class WorkingCopy extends CompilationController {
65     
66     private EngineEnvironment ce;
67     private ChangeSet changes;
68     private boolean afterCommit = false;
69     private WorkingCopyContext wcc;
70     private TreeMaker treeMaker;
71     
72     WorkingCopy(final CompilationInfo delegate) throws IOException JavaDoc {
73         super(delegate);
74         wcc = new WorkingCopyContext();
75     }
76
77     private synchronized void init() throws ReattributionException {
78         final CompilationUnitTree tree = getCompilationUnit();
79         if (tree != null) {
80             Context context = getContext();
81             ASTService model = ASTService.instance(context);
82             List JavaDoc<CompilationUnitTree> units = new ArrayList JavaDoc<CompilationUnitTree>();
83             units.add(tree);
84             model.setRoot(TreeFactory.instance(context).Root(units));
85             UndoListService.instance(context).reset();
86         }
87         
88         JavacTaskImpl task = this.delegate.getJavacTask();
89         ce = new DefaultEnvironment(
90                 task, getCompilationUnit(), Source.instance(task.getContext()).name, wcc);
91         treeMaker = new TreeMaker(this, ce.getTreeMaker());
92         changes = new ChangeSet("<no-description>");
93         changes.attach(ce);
94     }
95     
96     private Context getContext() {
97         return getJavacTask().getContext();
98     }
99     
100     // API of the class --------------------------------------------------------
101

102     EngineEnvironment getCommandEnvironment() {
103         return ce;
104     }
105
106     @Override JavaDoc
107     public JavaSource.Phase toPhase(JavaSource.Phase phase) throws IOException JavaDoc {
108         JavaSource.Phase result = super.toPhase(phase);
109         
110         if (result.compareTo(JavaSource.Phase.PARSED) >= 0) {
111             try {
112                 init();
113             } catch (ReattributionException ex) {
114                 IOException JavaDoc ioe = new IOException JavaDoc();
115                 ioe.initCause(ex);
116                 throw ioe;
117             }
118         }
119         
120         return result;
121     }
122     
123     public synchronized TreeMaker getTreeMaker() {
124         if (treeMaker == null)
125             throw new IllegalStateException JavaDoc("Cannot call getTreeMaker before toPhase.");
126         return treeMaker;
127     }
128     
129     void run(Transformer t) {
130         if (afterCommit)
131             throw new IllegalStateException JavaDoc ("The run method can't be called on a WorkingCopy instance after the commit"); //NOI18N
132
t.init();
133         t.attach(ce);
134         t.apply();
135         t.release();
136         t.destroy();;
137     }
138     
139     void run(Transformer t, Tree tree) {
140         if (afterCommit)
141             throw new IllegalStateException JavaDoc ("The run method can't be called on a WorkingCopy instance after the commit"); //NOI18N
142
t.init();
143         t.attach(ce);
144         t.apply(tree);
145         t.release();
146         t.destroy();;
147     }
148     
149     ChangeSet getChangeSet() {
150         return changes;
151     }
152     
153     /**
154      * Replaces the original tree <code>oldTree</code> with the new one -
155      * <code>newTree</code>. <code>null</code> values are not allowed.
156      * Use methods in {@link TreeMaker} for tree element removal.
157      *
158      * @param oldTree tree to be replaced, use tree already represented in
159      * source code.
160      * @param newTree new tree, either created by <code>TreeMaker</code>
161      * or obtained from different place.
162      * @throws IllegalStateException if <code>toPhase()</code> method was not
163      * called before.
164      * @throws IllegalArgumentException when <code>null</code> was passed to the
165      * method.
166      * @see TreeMaker
167      */

168     public synchronized void rewrite(Tree oldTree, Tree newTree) {
169         if (changes == null)
170             throw new IllegalStateException JavaDoc("Cannot call rewrite before toPhase.");
171         if (oldTree == null || newTree == null)
172             throw new IllegalArgumentException JavaDoc("Null values are not allowed.");
173         
174         changes.rewrite(oldTree, newTree);
175     }
176               
177     // Package private methods -------------------------------------------------
178

179     List JavaDoc<Difference> getChanges() throws IOException JavaDoc {
180         if (afterCommit)
181             throw new IllegalStateException JavaDoc("The commit method can be called only once on a WorkingCopy instance"); //NOI18N
182
afterCommit = true;
183         
184         if (changes == null) {
185             //may happen when the modification task does not call toPhase at all.
186
return null;
187         }
188         
189         try {
190             RootTree newRoot = changes.commit((RootTree)ce.getRootNode());
191             
192             if (changes.hasChanges()) {
193                 getCommandEnvironment().getModel().setRoot(newRoot);
194             }
195             
196             Commit save = new Commit(this);
197             save.init();
198             save.attach(ce);
199             save.commit();
200             save.release();
201             save.destroy();
202             return wcc.diffs;
203         } catch (QueryException qe) {
204             Logger.getLogger("global").log(Level.WARNING, qe.getMessage(), qe);
205             return null;
206         } catch (ReattributionException qe) {
207             Logger.getLogger("global").log(Level.WARNING, qe.getMessage(), qe);
208             return null;
209         }
210     }
211     
212     // Innerclasses ------------------------------------------------------------
213

214     private class WorkingCopyContext extends DefaultApplicationContext {
215         
216         private ArrayList JavaDoc<Difference> diffs = new ArrayList JavaDoc<Difference>();
217
218         public PrintWriter JavaDoc getOutputWriter(String JavaDoc title) {
219             // Sink any log output so it isn't displayed.
220
return new PrintWriter JavaDoc(new Writer JavaDoc() {
221                 public void write(char[] cbuf, int off, int len) throws IOException JavaDoc {}
222                 public void flush() throws IOException JavaDoc {}
223                 public void close() throws IOException JavaDoc {}
224             }, true);
225         }
226
227         private Map JavaDoc<Integer JavaDoc, String JavaDoc> userInfo = Collections.<Integer JavaDoc, String JavaDoc>emptyMap();
228         
229         @Override JavaDoc
230         public void setResult(Object JavaDoc result, String JavaDoc title) {
231             if ("user-info".equals(title)) {
232                 userInfo = Map JavaDoc.class.cast(result);
233             }
234         }
235
236         public SourceRewriter getSourceRewriter(JavaFileObject sourcefile) throws IOException JavaDoc {
237             return new Rewriter();
238         }
239         
240         private class Rewriter implements SourceRewriter {
241             
242             private int offset = 0;
243             private CloneableEditorSupport ces;
244             
245             private Rewriter() throws IOException JavaDoc {
246                 FileObject fo = getFileObject();
247                 if (fo != null) {
248                     DataObject dObj = DataObject.find(fo);
249                     ces = dObj != null ? (CloneableEditorSupport)dObj.getCookie(EditorCookie.class) : null;
250                 }
251                 if (ces == null)
252                     throw new IOException JavaDoc("Could not find CloneableEditorSupport for " + FileUtil.getFileDisplayName (fo)); //NOI18N
253
}
254             
255             public void writeTo(String JavaDoc s) throws IOException JavaDoc, BadLocationException JavaDoc {
256                 Difference diff = diffs.size() > 0 ? diffs.get(diffs.size() - 1) : null;
257                 if (diff != null && diff.getKind() == Difference.Kind.REMOVE && diff.getEndPosition().getOffset() == offset) {
258                     diff.kind = Difference.Kind.CHANGE;
259                     diff.newText = s;
260                 } else {
261                     diffs.add(new Difference(Difference.Kind.INSERT, ces.createPositionRef(offset, Bias.Forward), ces.createPositionRef(offset, Bias.Forward), null, s, userInfo.get(offset)));
262                 }
263             }
264             
265             public void skipThrough(SourceReader in, int pos) throws IOException JavaDoc, BadLocationException JavaDoc {
266                 char[] buf = in.getCharsTo(pos);
267                 Difference diff = diffs.size() > 0 ? diffs.get(diffs.size() - 1) : null;
268                 if (diff != null && diff.getKind() == Difference.Kind.INSERT && diff.getStartPosition().getOffset() == offset) {
269                     diff.kind = Difference.Kind.CHANGE;
270                     diff.oldText = new String JavaDoc(buf);
271                 } else {
272                     diffs.add(new Difference(Difference.Kind.REMOVE, ces.createPositionRef(offset, Bias.Forward), ces.createPositionRef(offset + buf.length, Bias.Forward), new String JavaDoc(buf), null, userInfo.get(offset)));
273                 }
274                 offset += buf.length;
275             }
276             
277             public void copyTo(SourceReader in, int pos) throws IOException JavaDoc {
278                 char[] buf = in.getCharsTo(pos);
279                 offset += buf.length;
280             }
281             
282             public void copyRest(SourceReader in) throws IOException JavaDoc {
283             }
284             
285             public void close(boolean save) {
286             }
287         }
288     }
289 }
290
Popular Tags