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.apisupport.refactoring;
043:
044: import com.sun.source.tree.ClassTree;
045: import com.sun.source.tree.Tree;
046: import com.sun.source.util.TreePath;
047:
048: import java.io.IOException;
049: import java.io.InputStream;
050: import java.io.OutputStream;
051: import java.net.URL;
052: import java.util.ArrayList;
053: import java.util.Collection;
054: import java.util.Collections;
055: import java.util.HashMap;
056: import java.util.HashSet;
057: import java.util.Iterator;
058: import java.util.List;
059: import java.util.Map;
060: import java.util.Set;
061: import java.util.StringTokenizer;
062: import java.util.jar.Attributes;
063: import java.util.jar.Manifest;
064: import java.util.regex.Pattern;
065: import org.netbeans.api.fileinfo.NonRecursiveFolder;
066: import org.netbeans.api.java.classpath.ClassPath;
067: import org.netbeans.api.java.project.JavaProjectConstants;
068: import org.netbeans.api.java.source.CancellableTask;
069: import org.netbeans.api.java.source.ClassIndex;
070: import org.netbeans.api.java.source.ClasspathInfo;
071: import org.netbeans.api.java.source.CompilationController;
072: import org.netbeans.api.java.source.ElementHandle;
073: import org.netbeans.api.java.source.JavaSource;
074: import org.netbeans.api.java.source.ModificationResult;
075: import org.netbeans.api.java.source.TreePathHandle;
076: import org.netbeans.api.project.FileOwnerQuery;
077: import org.netbeans.api.project.Project;
078: import org.netbeans.api.project.ProjectUtils;
079: import org.netbeans.api.project.SourceGroup;
080: import org.netbeans.api.project.Sources;
081: import org.netbeans.api.queries.VisibilityQuery;
082: import org.netbeans.modules.apisupport.project.EditableManifest;
083: import org.netbeans.modules.apisupport.project.spi.NbModuleProvider;
084: import org.netbeans.modules.refactoring.api.AbstractRefactoring;
085: import org.netbeans.modules.refactoring.api.MoveRefactoring;
086: import org.netbeans.modules.refactoring.api.Problem;
087: import org.netbeans.modules.refactoring.api.RenameRefactoring;
088: import org.netbeans.modules.refactoring.spi.RefactoringElementImplementation;
089: import org.netbeans.modules.refactoring.spi.RefactoringElementsBag;
090: import org.netbeans.modules.refactoring.spi.RefactoringPlugin;
091: import org.openide.ErrorManager;
092: import org.openide.filesystems.FileLock;
093: import org.openide.filesystems.FileObject;
094: import org.openide.filesystems.FileUtil;
095: import org.openide.loaders.DataObject;
096: import org.openide.util.Exceptions;
097: import org.openide.util.Lookup;
098: import org.openide.util.NbBundle;
099:
100: /**
101: *
102: * @author Milos Kleint
103: */
104: public class NbMoveRefactoringPlugin extends AbstractRefactoringPlugin {
105: protected static ErrorManager err = ErrorManager.getDefault()
106: .getInstance("org.netbeans.modules.apisupport.refactoring"); // NOI18N
107:
108: /** This one is important creature - makes sure that cycles between plugins won't appear */
109: private static ThreadLocal semafor = new ThreadLocal();
110:
111: private Collection manifestRefactorings;
112: private boolean firstManifestRefactoring = true;
113:
114: private HashMap oldManifests;
115: /** <NBModuleProject, EditableManifest> */
116: private EditableManifest targetManifest;
117:
118: private Map packagePostfix = new HashMap();
119: ArrayList<FileObject> filesToMove = new ArrayList();
120: HashMap<FileObject, ElementHandle> classes;
121:
122: /**
123: * Creates a new instance of NbRenameRefactoringPlugin
124: */
125: public NbMoveRefactoringPlugin(MoveRefactoring move) {
126: super (move);
127:
128: manifestRefactorings = new ArrayList();
129: oldManifests = new HashMap();
130: setup(move.getRefactoringSource().lookupAll(FileObject.class),
131: "", true);
132: }
133:
134: public NbMoveRefactoringPlugin(RenameRefactoring rename) {
135: super (rename);
136: FileObject fo = rename.getRefactoringSource().lookup(
137: FileObject.class);
138: if (fo != null) {
139: setup(Collections.singletonList(fo), "", true);
140: } else {
141: setup(Collections
142: .singletonList(((NonRecursiveFolder) rename
143: .getRefactoringSource().lookup(
144: NonRecursiveFolder.class))
145: .getFolder()), "", false);
146: }
147: }
148:
149: /** Checks pre-conditions of the refactoring and returns problems.
150: * @return Problems found or null (if no problems were identified)
151: */
152: public Problem preCheck() {
153: return null;
154: }
155:
156: /** Checks parameters of the refactoring.
157: * @return Problems found or null (if no problems were identified)
158: */
159: public Problem checkParameters() {
160: return null;
161: }
162:
163: public void cancelRequest() {
164:
165: }
166:
167: public Problem fastCheckParameters() {
168: return null;
169: }
170:
171: /** Collects refactoring elements for a given refactoring.
172: * @param refactoringElements Collection of refactoring elements - the implementation of this method
173: * should add refactoring elements to this collections. It should make no assumptions about the collection
174: * content.
175: * @return Problems found or null (if no problems were identified)
176: */
177: public Problem prepare(RefactoringElementsBag refactoringElements) {
178: if (semafor.get() != null) {
179: return null;
180: }
181: semafor.set(new Object());
182: Problem problem = null;
183: try {
184: initClasses();
185: Project cachedProject = null;
186: String[] cachedServices = null;
187: FileObject[] cachedServicesFiles = null;
188: Manifest cachedManifest = null;
189:
190: Lookup lkp = refactoring.getRefactoringSource();
191: TreePathHandle handle = lkp.lookup(TreePathHandle.class);
192:
193: if (handle != null) {
194: InfoHolder infoholder = examineLookup(lkp);
195: Project project = FileOwnerQuery.getOwner(handle
196: .getFileObject());
197: if (project == null
198: || project.getLookup().lookup(
199: NbModuleProvider.class) == null) {
200: // take just netbeans module development into account..
201: return null;
202: }
203:
204: if (infoholder.isClass) {
205: checkManifest(project, infoholder.fullName,
206: refactoringElements);
207: checkMetaInfServices(project, infoholder.fullName,
208: refactoringElements);
209: checkLayer(project, infoholder.fullName,
210: refactoringElements);
211: }
212: if (infoholder.isMethod) {
213: checkMethodLayer(infoholder,
214: handle.getFileObject(), refactoringElements);
215: }
216: }
217: } catch (IOException e) {
218: Exceptions.printStackTrace(e);
219:
220: //TODO
221:
222: // Iterator it = col.iterator();
223: // while (it.hasNext()) {
224: // Resource res = (Resource)it.next();
225: // FileObject fo = JavaModel.getFileObject(res);
226: // Project project = FileOwnerQuery.getOwner(fo);
227: // if (project != null && project instanceof NbModuleProject) {
228: // if (cachedProject == null || cachedProject != project) {
229: // cachedProject = (NbModuleProject)project;
230: // cachedServices = loadMetaInfServices(cachedProject);
231: // cachedManifest = cachedProject.getManifest();
232: // FileObject services = Utility.findMetaInfServices(cachedProject);
233: // if (services == null) {
234: // cachedServicesFiles = new FileObject[0];
235: // } else {
236: // cachedServicesFiles = services.getChildren();
237: // }
238: // }
239: // String name = res.getName();
240: // String clazzName = name.replaceAll("\\.java$", ".class"); //NOI18N
241: // String serviceName = name.replaceAll("\\.java$", "").replace('/', '.'); //NOI18N
242: // JavaClass clazz = findClazz(res, serviceName);
243: // //check services for this one
244: // for (int i = 0; i < cachedServices.length; i++) {
245: // serviceName = serviceName.replaceAll("[.]", "\\."); //NOI18N
246: // // #65343 somehow the reading of individual services files can happen.
247: // if (cachedServices[i] != null) {
248: // if (cachedServices[i].matches("^" + serviceName + "[ \\\n]?")) { //NOI18N
249: // RefactoringElementImplementation elem =
250: // new ServicesMoveRefactoringElement(clazz, cachedServicesFiles[i], cachedProject);
251: // refactoringElements.add(refactoring, elem);
252: // }
253: // } else {
254: // //huh? reading the service file failed for some reason, report or silently ignore?
255: // ErrorManager.getDefault().log(ErrorManager.WARNING, "Error loading one of the files in folder " + cachedServices);
256: // }
257: // }
258: // // check main attributes..
259: // Attributes attrs = cachedManifest.getMainAttributes();
260: // Iterator itx = attrs.entrySet().iterator();
261: // while (itx.hasNext()) {
262: // Map.Entry entry = (Map.Entry)itx.next();
263: // String val = (String)entry.getValue();
264: // if (val.indexOf(clazzName) != -1 || val.indexOf(clazzName) != -1) {
265: // RefactoringElementImplementation elem =
266: // createManifestRefactoring(clazz, cachedProject.getManifestFile(),
267: // ((Attributes.Name)entry.getKey()).toString(), val, null, cachedProject);
268: // refactoringElements.add(refactoring, elem);
269: // manifestRefactorings.add(elem);
270: // }
271: // }
272: // // check section attributes
273: // Map entries = cachedManifest.getEntries();
274: // if (entries != null) {
275: // Iterator itf = entries.entrySet().iterator();
276: // while (itf.hasNext()) {
277: // Map.Entry secEnt = (Map.Entry)itf.next();
278: // attrs = (Attributes)secEnt.getValue();
279: // String val = (String)secEnt.getKey();
280: // if (val.indexOf(clazzName) != -1) {
281: // String section = attrs.getValue("OpenIDE-Module-Class"); //NOI18N
282: // RefactoringElementImplementation elem =
283: // createManifestRefactoring(clazz, cachedProject.getManifestFile(), null, val, section, cachedProject);
284: // refactoringElements.add(refactoring, elem);
285: // manifestRefactorings.add(elem);
286: // }
287: // }
288: // }
289: // }
290: // }
291: // // now check layer.xml and bundle file in manifest
292: //
293: // Iterator itd = refactoring.getOtherDataObjects().iterator();
294: // while (itd.hasNext()) {
295: // DataObject dobj = (DataObject)itd.next();
296: // Project project = FileOwnerQuery.getOwner(dobj.getPrimaryFile());
297: // if (project != null && project instanceof NbModuleProject) {
298: // if (cachedProject == null || cachedProject != project) {
299: // cachedProject = (NbModuleProject)project;
300: // cachedServices = loadMetaInfServices(cachedProject);
301: // cachedManifest = cachedProject.getManifest();
302: // }
303: // }
304: // String packageName = findPackageName(cachedProject, dobj.getPrimaryFile());
305: // if (packageName != null) {
306: // Iterator itf = cachedManifest.getMainAttributes().entrySet().iterator();
307: // while (itf.hasNext()) {
308: // Map.Entry ent = (Map.Entry)itf.next();
309: // String val = (String)ent.getValue();
310: // if (packageName.equals(val)) {
311: // RefactoringElementImplementation elem = new ManifestMoveRefactoringElement(cachedProject.getManifestFile(), val,
312: // ((Attributes.Name)ent.getKey()).toString(), cachedProject, dobj.getPrimaryFile());
313: // refactoringElements.add(refactoring, elem);
314: // manifestRefactorings.add(elem);
315: // }
316: // }
317: // }
318: // }
319:
320: } finally {
321: semafor.set(null);
322: }
323: return problem;
324: }
325:
326: protected RefactoringElementImplementation createMetaInfServicesRefactoring(
327: String fqclazz, FileObject serviceFile, int line) {
328: return null;
329: //TODO throw new UnsupportedOperationException("Not supported yet.");
330: }
331:
332: protected RefactoringElementImplementation createManifestRefactoring(
333: String fqname, FileObject manifestFile,
334: String attributeKey, String attributeValue, String section) {
335: return null;
336: //TODO return new ManifestMoveRefactoringElement(fqname, manifestFile, attributeValue,
337: // attributeKey, section);
338: }
339:
340: // private JavaClass findClazz(Resource res, String name) {
341: // Iterator itx = res.getClassifiers().iterator();
342: // while (itx.hasNext()) {
343: // JavaClass clzz = (JavaClass)itx.next();
344: // if (clzz.getName().equals(name)) {
345: // return clzz;
346: // }
347: // }
348: // //what to do now.. we should match always something, better to return wrong, than nothing?
349: // return (JavaClass)res.getClassifiers().iterator().next();
350: // }
351:
352: protected final String[] loadMetaInfServices(Project project) {
353: FileObject services = Utility.findMetaInfServices(project);
354: if (services == null) {
355: return new String[0];
356: }
357:
358: FileObject[] files = services.getChildren();
359: String[] ret = new String[files.length];
360: for (int i = 0; i < files.length; i++) {
361: ret[i] = Utility.readFileIntoString(files[i]);
362: }
363: return ret;
364: }
365:
366: private static String findPackageName(Project project, FileObject fo) {
367: Sources srcs = ProjectUtils.getSources(project);
368: SourceGroup[] grps = srcs
369: .getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA);
370: for (int i = 0; i < grps.length; i++) {
371: if (FileUtil.isParentOf(grps[i].getRootFolder(), fo)
372: && grps[i].contains(fo)) {
373: return FileUtil.getRelativePath(
374: grps[i].getRootFolder(), fo);
375: }
376: }
377: return null;
378: }
379:
380: public final class ManifestMoveRefactoringElement extends
381: AbstractRefactoringElement {
382:
383: private String clazz;
384: private String attrName;
385: private String sectionName = null;
386: private FileObject movedFile = null;
387:
388: public ManifestMoveRefactoringElement(String clazz,
389: FileObject parentFile, String attributeValue,
390: String attributeName) {
391: this .name = attributeValue;
392: this .clazz = clazz;
393: this .parentFile = parentFile;
394: attrName = attributeName;
395: }
396:
397: public ManifestMoveRefactoringElement(String clazz,
398: FileObject parentFile, String attributeValue,
399: String attributeName, String secName) {
400: this (clazz, parentFile, attributeValue, attributeName);
401: sectionName = secName;
402: }
403:
404: //for data objects that are not classes
405: public ManifestMoveRefactoringElement(FileObject parentFile,
406: String attributeValue, String attributeName,
407: FileObject movedFile) {
408: this .name = attributeValue;
409: this .parentFile = parentFile;
410: attrName = attributeName;
411: this .movedFile = movedFile;
412: }
413:
414: /** Returns text describing the refactoring formatted for display (using HTML tags).
415: * @return Formatted text.
416: */
417: public String getDisplayText() {
418: if (sectionName != null) {
419: return NbBundle.getMessage(
420: NbMoveRefactoringPlugin.class,
421: "TXT_ManifestSectionRename", this .name,
422: sectionName);
423: }
424: return NbBundle.getMessage(NbMoveRefactoringPlugin.class,
425: "TXT_ManifestRename", this .name, attrName);
426: }
427:
428: public void performChange() {
429: // NbModuleProject targetProject = (NbModuleProject)FileOwnerQuery.getOwner(refactoring.getTargetClassPathRoot());
430: // if (firstManifestRefactoring) {
431: // // if this is the first manifest refactoring, check the list for non-enable ones and remove them
432: // Iterator it = manifestRefactorings.iterator();
433: // while (it.hasNext()) {
434: // ManifestMoveRefactoringElement el = (ManifestMoveRefactoringElement)it.next();
435: // if (!el.isEnabled()) {
436: // it.remove();
437: // }
438: // }
439: // FileObject fo = targetProject.getManifestFile();
440: // targetManifest = readManifest(fo);
441: // firstManifestRefactoring = false;
442: // }
443: //
444: // NbModuleProject sourceProject = project;
445: // EditableManifest sourceManifest = null;
446: // if (sourceProject == targetProject) {
447: // sourceManifest = targetManifest;
448: // } else {
449: // sourceManifest = (EditableManifest)oldManifests.get(sourceProject);
450: // if (sourceManifest == null) {
451: // sourceManifest = readManifest(sourceProject.getManifestFile());
452: // oldManifests.put(sourceProject, sourceManifest);
453: // }
454: // }
455: // // update section info
456: // if (sectionName != null) {
457: // String newSectionName = clazz.getName().replace('.', '/') + ".class"; //NOI18N
458: // targetManifest.addSection(newSectionName);
459: // Iterator it = sourceManifest.getAttributeNames(name).iterator();
460: // while (it.hasNext()) {
461: // String secattrname = (String)it.next();
462: // targetManifest.setAttribute(secattrname, sourceManifest.getAttribute(secattrname, name), newSectionName);
463: // }
464: // sourceManifest.removeSection(name);
465: // } else {
466: // // update regular attributes
467: // if (sourceManifest != targetManifest) {
468: // sourceManifest.removeAttribute(attrName, null);
469: // }
470: // if (clazz != null) {
471: // String newClassname = clazz.getName().replace('.','/') + ".class"; //NOI18N
472: // targetManifest.setAttribute(attrName, newClassname, null);
473: // } else {
474: // // mkleint - afaik this will get called only on folder rename.
475: // String newPath = refactoring.getTargetPackageName(movedFile).replace('.','/') + "/" + movedFile.getNameExt(); //NOI18N
476: // targetManifest.setAttribute(attrName, newPath, null);
477: // }
478: // }
479: // manifestRefactorings.remove(this);
480: // if (manifestRefactorings.isEmpty()) {
481: // // now write all the manifests that were edited.
482: // writeManifest(targetProject.getManifestFile(), targetManifest);
483: // Iterator it = oldManifests.entrySet().iterator();
484: // while (it.hasNext()) {
485: // Map.Entry entry = (Map.Entry)it.next();
486: // EditableManifest man = (EditableManifest)entry.getValue();
487: // NbModuleProject proj = (NbModuleProject)entry.getKey();
488: // if (man == targetManifest) {
489: // continue;
490: // }
491: // writeManifest(proj.getManifestFile(), man);
492: // }
493: // }
494: }
495: }
496:
497: public final class ServicesMoveRefactoringElement extends
498: AbstractRefactoringElement {
499:
500: private String clazz;
501: private String oldName;
502: private Project project;
503:
504: /**
505: * Creates a new instance of ServicesRenameRefactoringElement
506: */
507: public ServicesMoveRefactoringElement(String clazz,
508: FileObject file, Project proj) {
509: // this.name = clazz.getSimpleName();
510: parentFile = file;
511: this .clazz = clazz;
512: oldName = clazz;
513: project = proj;
514: }
515:
516: /** Returns text describing the refactoring formatted for display (using HTML tags).
517: * @return Formatted text.
518: */
519: public String getDisplayText() {
520: return NbBundle.getMessage(NbMoveRefactoringPlugin.class,
521: "TXT_ServicesRename", this .name);
522: }
523:
524: public void performChange() {
525: // MoveClassRefactoring move = (MoveClassRefactoring)refactoring;
526: // NbModuleProject newproject = (NbModuleProject)FileOwnerQuery.getOwner(move.getTargetClassPathRoot());
527: // FileObject newFile = parentFile;
528: // if (newproject != project) {
529: // FileObject services = Utility.findMetaInfServices(newproject);
530: // try {
531: // if (services == null) {
532: // services = createMetaInf(newproject);
533: // }
534: // newFile = services.getFileObject(parentFile.getNameExt());
535: // if (newFile == null) {
536: // newFile = services.createData(parentFile.getNameExt());
537: // }
538: // } catch (IOException ex) {
539: // err.notify(ex);
540: // }
541: // }
542: // String oldcontent = Utility.readFileIntoString(parentFile);
543: // String longName = oldName;
544: // String newName = clazz.getName();
545: // if (oldcontent != null) {
546: // longName = longName.replaceAll("[.]", "\\."); //NOI18N
547: // if (newFile == parentFile) {
548: // // same file, just replace
549: // oldcontent = oldcontent.replaceAll("^" + longName, newName); //NOI18N
550: // Utility.writeFileFromString(parentFile, oldcontent);
551: // } else {
552: // // moving to a different file.
553: // oldcontent = oldcontent.replaceAll("^" + longName + "[ \\\n]?", ""); //NOI18N
554: // String newcontent = Utility.readFileIntoString(newFile);
555: // newcontent = newName + "\n" + newcontent; // NOI18N
556: // Utility.writeFileFromString(newFile, newcontent);
557: // //check if we want to delete the old file or just update it.
558: // StringTokenizer tok = new StringTokenizer(oldcontent, "\n"); //NOI18N
559: // boolean hasMoreThanComments = false;
560: // while (tok.hasMoreTokens()) {
561: // String token = tok.nextToken().trim();
562: // if (token.length() > 0 && (! Pattern.matches("^[#].*", token))) { //NOI18N
563: // hasMoreThanComments = true;
564: // break;
565: // }
566: // }
567: // if (hasMoreThanComments) {
568: // Utility.writeFileFromString(parentFile, oldcontent);
569: // } else {
570: // try {
571: // parentFile.delete();
572: // } catch (IOException exc) {
573: // err.notify(exc);
574: // }
575: // }
576: //
577: // }
578: // }
579: }
580: }
581:
582: private static FileObject createMetaInf(Project project)
583: throws IOException {
584: Sources srcs = ProjectUtils.getSources(project);
585: SourceGroup[] grps = srcs
586: .getSourceGroups(JavaProjectConstants.SOURCES_TYPE_RESOURCES);
587: if (grps == null) {
588: grps = srcs
589: .getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA);
590: }
591: for (int i = 0; i < grps.length; i++) {
592: FileObject fo = grps[i].getRootFolder().getFileObject(
593: "META-INF"); //NOI18N
594: if (fo != null) {
595: return fo.createFolder("services"); //NOI18N
596: }
597: }
598: return grps[0].getRootFolder().createFolder("META-INF")
599: .createFolder("services"); //NOI18N
600: }
601:
602: private static EditableManifest readManifest(FileObject fo) {
603: InputStream str = null;
604: try {
605: str = fo.getInputStream();
606: return new EditableManifest(str);
607: } catch (IOException exc) {
608: err.notify(exc);
609: } finally {
610: if (str != null) {
611: try {
612: str.close();
613: } catch (IOException exc) {
614: err.notify(exc);
615: }
616: }
617: }
618: return new EditableManifest();
619: }
620:
621: private static void writeManifest(FileObject fo,
622: EditableManifest manifest) {
623: OutputStream str = null;
624: FileLock lock = null;
625: try {
626: lock = fo.lock();
627: str = fo.getOutputStream(lock);
628: manifest.write(str);
629:
630: } catch (IOException exc) {
631: err.notify(exc);
632: } finally {
633: if (str != null) {
634: try {
635: str.close();
636: } catch (IOException exc) {
637: err.notify(exc);
638: }
639: }
640: if (lock != null) {
641: lock.releaseLock();
642: }
643: }
644: }
645:
646: ///------- copied from MoveRefactoringPlugin
647:
648: private void setup(Collection fileObjects, String postfix,
649: boolean recursively) {
650: for (Iterator i = fileObjects.iterator(); i.hasNext();) {
651: FileObject fo = (FileObject) i.next();
652: if (RetoucheUtils.isJavaFile(fo)) {
653: packagePostfix.put(fo, postfix.replace('/', '.'));
654: filesToMove.add(fo);
655: } else if (!(fo.isFolder())) {
656: packagePostfix.put(fo, postfix.replace('/', '.'));
657: } else if (VisibilityQuery.getDefault().isVisible(fo)) {
658: //o instanceof DataFolder
659: //CVS folders are ignored
660: boolean addDot = !"".equals(postfix);
661: Collection col = new ArrayList();
662: for (FileObject fo2 : fo.getChildren()) {
663: col.add(fo2);
664: }
665: if (recursively)
666: setup(col, postfix + (addDot ? "." : "")
667: + fo.getName(), true); // NOI18N
668: }
669: }
670: }
671:
672: String getNewPackageName() {
673: if (refactoring instanceof MoveRefactoring) {
674: return RetoucheUtils
675: .getPackageName(((MoveRefactoring) refactoring)
676: .getTarget().lookup(URL.class));
677: } else {
678: return ((RenameRefactoring) refactoring).getNewName();
679: }
680: }
681:
682: String getTargetPackageName(FileObject fo) {
683: if (refactoring instanceof RenameRefactoring) {
684: if (refactoring.getRefactoringSource().lookup(
685: NonRecursiveFolder.class) != null)
686: //package rename
687: return getNewPackageName();
688: else {
689: //folder rename
690: FileObject folder = refactoring.getRefactoringSource()
691: .lookup(FileObject.class);
692: ClassPath cp = ClassPath.getClassPath(folder,
693: ClassPath.SOURCE);
694: FileObject root = cp.findOwnerRoot(folder);
695: String prefix = FileUtil.getRelativePath(root,
696: folder.getParent()).replace('/', '.');
697: String postfix = FileUtil.getRelativePath(folder,
698: fo.getParent()).replace('/', '.');
699: String t = concat(prefix, getNewPackageName(), postfix);
700: return t;
701: }
702: } else if (packagePostfix != null) {
703: String postfix = (String) packagePostfix.get(fo);
704: String packageName = concat(null, getNewPackageName(),
705: postfix);
706: return packageName;
707: } else
708: return getNewPackageName();
709: }
710:
711: private String concat(String s1, String s2, String s3) {
712: String result = "";
713: if (s1 != null && !"".equals(s1)) {
714: result += s1 + "."; // NOI18N
715: }
716: result += s2;
717: if (s3 != null && !"".equals(s3)) {
718: result += ("".equals(result) ? "" : ".") + s3; // NOI18N
719: }
720: return result;
721: }
722:
723: private void initClasses() {
724: classes = new HashMap();
725: for (int i = 0; i < filesToMove.size(); i++) {
726: final int j = i;
727: try {
728: JavaSource source = JavaSource
729: .forFileObject(filesToMove.get(i));
730:
731: source.runUserActionTask(
732: new CancellableTask<CompilationController>() {
733:
734: public void cancel() {
735: throw new UnsupportedOperationException(
736: "Not supported yet.");
737: }
738:
739: public void run(
740: final CompilationController parameter)
741: throws Exception {
742: parameter
743: .toPhase(JavaSource.Phase.ELEMENTS_RESOLVED);
744: List<? extends Tree> trees = parameter
745: .getCompilationUnit()
746: .getTypeDecls();
747: for (Tree t : trees) {
748: if (t.getKind() == Tree.Kind.CLASS) {
749: if (((ClassTree) t)
750: .getSimpleName()
751: .toString()
752: .equals(
753: filesToMove
754: .get(j)
755: .getName())) {
756: classes
757: .put(
758: filesToMove
759: .get(j),
760: ElementHandle
761: .create(parameter
762: .getTrees()
763: .getElement(
764: TreePath
765: .getPath(
766: parameter
767: .getCompilationUnit(),
768: t))));
769: return;
770: }
771: }
772: }
773:
774: }
775: }, true);
776: } catch (IOException ex) {
777: java.util.logging.Logger.getLogger("global").log(
778: java.util.logging.Level.SEVERE,
779: ex.getMessage(), ex);
780: }
781: ;
782:
783: }
784: }
785:
786: }
|