001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.modules.java;
043:
044: import com.sun.source.tree.ClassTree;
045: import com.sun.source.tree.CompilationUnitTree;
046: import com.sun.source.tree.Tree;
047: import java.io.IOException;
048: import org.netbeans.api.java.source.Task;
049: import org.netbeans.api.java.source.JavaSource;
050: import org.netbeans.api.java.source.JavaSource.Phase;
051: import org.netbeans.api.java.loaders.JavaDataSupport;
052: import org.netbeans.api.java.source.WorkingCopy;
053: import org.netbeans.api.java.source.TreeMaker;
054: import org.openide.cookies.EditCookie;
055: import org.openide.cookies.EditorCookie;
056: import org.openide.cookies.OpenCookie;
057: import org.openide.cookies.PrintCookie;
058: import org.openide.cookies.SaveCookie;
059: import org.openide.filesystems.FileLock;
060: import org.openide.filesystems.FileObject;
061: import org.openide.loaders.DataFolder;
062: import org.openide.loaders.DataObject;
063: import org.openide.loaders.DataObjectExistsException;
064: import org.openide.loaders.MultiDataObject;
065: import org.openide.loaders.MultiFileLoader;
066: import org.openide.loaders.SaveAsCapable;
067: import org.openide.nodes.CookieSet.Factory;
068: import org.openide.nodes.Node;
069: import org.openide.nodes.Node.Cookie;
070: import org.openide.text.CloneableEditor;
071: import org.openide.text.CloneableEditorSupport;
072: import org.openide.text.DataEditorSupport;
073: import org.openide.util.Lookup;
074: import org.openide.windows.CloneableOpenSupport;
075:
076: public final class JavaDataObject extends MultiDataObject {
077:
078: private JavaEditorSupport jes;
079:
080: public JavaDataObject(FileObject pf, MultiFileLoader loader)
081: throws DataObjectExistsException {
082: super (pf, loader);
083: getCookieSet().assign(SaveAsCapable.class, new SaveAsCapable() {
084: public void saveAs(FileObject folder, String fileName)
085: throws IOException {
086: createJavaEditorSupport().saveAs(folder, fileName);
087: }
088: });
089: getCookieSet().add(JavaEditorSupport.class, new Factory() {
090: public <T extends Cookie> T createCookie(Class<T> klass) {
091: return klass.cast(createJavaEditorSupport());
092: }
093: });
094: }
095:
096: public @Override
097: Node createNodeDelegate() {
098: return JavaDataSupport.createJavaNode(getPrimaryFile());
099: }
100:
101: @Override
102: public Lookup getLookup() {
103: return getCookieSet().getLookup();
104: }
105:
106: protected DataObject handleCopyRename(DataFolder df, String name,
107: String ext) throws IOException {
108: FileObject fo = getPrimaryEntry().copyRename(
109: df.getPrimaryFile(), name, ext);
110: DataObject dob = DataObject.find(fo);
111: //TODO invoke refactoring here (if needed)
112: return dob;
113: }
114:
115: private synchronized JavaEditorSupport createJavaEditorSupport() {
116: if (jes == null) {
117: jes = new JavaEditorSupport(this );
118: }
119: return jes;
120: }
121:
122: public static final class JavaEditorSupport extends
123: DataEditorSupport implements OpenCookie, EditCookie,
124: EditorCookie, PrintCookie, EditorCookie.Observable {
125:
126: private static final class Environment extends
127: DataEditorSupport.Env {
128:
129: private static final long serialVersionUID = -1;
130:
131: private transient SaveSupport saveCookie = null;
132:
133: private final class SaveSupport implements SaveCookie {
134: public void save() throws java.io.IOException {
135: ((JavaEditorSupport) findCloneableOpenSupport())
136: .saveDocument();
137: getDataObject().setModified(false);
138: }
139: }
140:
141: public Environment(JavaDataObject obj) {
142: super (obj);
143: }
144:
145: protected FileObject getFile() {
146: return this .getDataObject().getPrimaryFile();
147: }
148:
149: protected FileLock takeLock() throws java.io.IOException {
150: return ((MultiDataObject) this .getDataObject())
151: .getPrimaryEntry().takeLock();
152: }
153:
154: public @Override
155: CloneableOpenSupport findCloneableOpenSupport() {
156: return (CloneableEditorSupport) ((JavaDataObject) this
157: .getDataObject()).getCookie(EditorCookie.class);
158: }
159:
160: public void addSaveCookie() {
161: JavaDataObject javaData = (JavaDataObject) this
162: .getDataObject();
163: if (javaData.getCookie(SaveCookie.class) == null) {
164: if (this .saveCookie == null)
165: this .saveCookie = new SaveSupport();
166: javaData.getCookieSet().add(this .saveCookie);
167: javaData.setModified(true);
168: }
169: }
170:
171: public void removeSaveCookie() {
172: JavaDataObject javaData = (JavaDataObject) this
173: .getDataObject();
174: if (javaData.getCookie(SaveCookie.class) != null) {
175: javaData.getCookieSet().remove(this .saveCookie);
176: javaData.setModified(false);
177: }
178: }
179: }
180:
181: public JavaEditorSupport(JavaDataObject dataObject) {
182: super (dataObject, new Environment(dataObject));
183: setMIMEType("text/x-java"); // NOI18N
184: }
185:
186: protected boolean notifyModified() {
187: if (!super .notifyModified())
188: return false;
189: ((Environment) this .env).addSaveCookie();
190: return true;
191: }
192:
193: protected @Override
194: void notifyUnmodified() {
195: super .notifyUnmodified();
196: ((Environment) this .env).removeSaveCookie();
197: }
198:
199: protected @Override
200: CloneableEditor createCloneableEditor() {
201: return new JavaEditor(this );
202: }
203:
204: public @Override
205: boolean close(boolean ask) {
206: return super .close(ask);
207: }
208:
209: }
210:
211: private static final class JavaEditor extends CloneableEditor {
212:
213: private static final long serialVersionUID = -1;
214:
215: public JavaEditor() {
216: }
217:
218: public JavaEditor(JavaEditorSupport sup) {
219: super (sup);
220: }
221:
222: }
223:
224: /**
225: * XXX: Change this when there will be a write model.
226: * When there will be a refactoring it shoud be called only in case of handleCreateFromTemplate
227: */
228: static void renameFO(final FileObject fileToUpdate,
229: final String packageName, final String newName,
230: final String originalName) throws IOException {
231: JavaSource javaSource = JavaSource.forFileObject(fileToUpdate);
232:
233: Task<WorkingCopy> task = new Task<WorkingCopy>() {
234:
235: public void run(WorkingCopy workingCopy) throws IOException {
236: workingCopy.toPhase(Phase.RESOLVED);
237: TreeMaker make = workingCopy.getTreeMaker();
238: CompilationUnitTree compilationUnitTree = workingCopy
239: .getCompilationUnit();
240: // change the package when file was move to different dir.
241: CompilationUnitTree cutCopy = make.CompilationUnit(""
242: .equals(packageName) ? null : make
243: .Identifier(packageName), compilationUnitTree
244: .getImports(), compilationUnitTree
245: .getTypeDecls(), compilationUnitTree
246: .getSourceFile());
247: workingCopy.rewrite(compilationUnitTree, cutCopy);
248: // go to rename also the top level class too...
249: if (originalName != null
250: && !originalName.equals(newName)) {
251: for (Tree typeDecl : compilationUnitTree
252: .getTypeDecls()) {
253: if (Tree.Kind.CLASS == typeDecl.getKind()) {
254: ClassTree clazz = (ClassTree) typeDecl;
255: if (originalName.contentEquals(clazz
256: .getSimpleName())) {
257: Tree copy = make.setLabel(typeDecl,
258: newName);
259: workingCopy.rewrite(typeDecl, copy);
260: }
261: }
262: }
263: }
264: }
265: };
266: javaSource.runModificationTask(task).commit();
267: }
268: }
|