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-2007 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: package org.netbeans.modules.xml.refactoring.spi;
042:
043: import java.awt.Image;
044: import java.beans.BeanInfo;
045: import java.io.File;
046: import java.io.IOException;
047: import java.net.URI;
048: import java.net.URISyntaxException;
049: import java.net.URL;
050: import java.util.ArrayList;
051: import java.util.Arrays;
052: import java.util.Collection;
053: import java.util.Collections;
054: import java.util.HashMap;
055: import java.util.HashSet;
056: import java.util.List;
057: import java.util.Map;
058: import java.util.Set;
059: import java.util.StringTokenizer;
060: import org.netbeans.api.project.FileOwnerQuery;
061: import org.netbeans.api.project.Project;
062: import org.netbeans.api.project.ProjectUtils;
063: import org.netbeans.spi.project.support.ant.PropertyUtils;
064: import org.netbeans.api.project.SourceGroup;
065: import org.netbeans.api.project.Sources;
066: import org.netbeans.modules.refactoring.api.AbstractRefactoring;
067: import org.netbeans.modules.refactoring.api.MoveRefactoring;
068: import org.netbeans.modules.refactoring.api.Problem;
069: import org.netbeans.modules.refactoring.api.RefactoringElement;
070: import org.netbeans.modules.refactoring.api.RefactoringSession;
071: import org.netbeans.modules.refactoring.api.RenameRefactoring;
072: import org.netbeans.modules.refactoring.api.SafeDeleteRefactoring;
073: import org.netbeans.modules.refactoring.api.WhereUsedQuery;
074: import org.netbeans.modules.refactoring.spi.RefactoringElementImplementation;
075: import org.netbeans.modules.refactoring.spi.ui.UI;
076: import org.netbeans.modules.xml.nbprefuse.AnalysisConstants;
077: import org.netbeans.modules.xml.refactoring.CannotRefactorException;
078: import org.netbeans.modules.xml.refactoring.ErrorItem;
079: import org.netbeans.modules.xml.refactoring.XMLRefactoringTransaction;
080: import org.netbeans.modules.xml.refactoring.spi.RefactoringUtil;
081: import org.netbeans.modules.xml.refactoring.ui.DeleteRefactoringUI;
082: import org.netbeans.modules.xml.refactoring.ui.FileRenameRefactoringUI;
083: import org.netbeans.modules.xml.refactoring.ui.ModelProvider;
084: import org.netbeans.modules.xml.refactoring.ui.ReferenceableProvider;
085: import org.netbeans.modules.xml.refactoring.ui.RenameRefactoringUI;
086: import org.netbeans.modules.xml.retriever.catalog.ProjectCatalogSupport;
087: import org.netbeans.modules.xml.xam.Component;
088: import org.netbeans.modules.xml.xam.EmbeddableRoot;
089: import org.netbeans.modules.xml.xam.Model;
090: import org.netbeans.modules.xml.xam.ModelSource;
091: import org.netbeans.modules.xml.xam.Nameable;
092: import org.netbeans.modules.xml.xam.Named;
093: import org.netbeans.modules.xml.xam.NamedReferenceable;
094: import org.netbeans.modules.xml.xam.Referenceable;
095: import org.netbeans.modules.xml.xam.dom.DocumentModel;
096: import org.netbeans.spi.project.SubprojectProvider;
097: import org.openide.DialogDisplayer;
098: import org.openide.ErrorManager;
099: import org.openide.NotifyDescriptor;
100: import org.openide.filesystems.FileLock;
101: import org.openide.filesystems.FileObject;
102: import org.openide.filesystems.FileUtil;
103: import org.openide.filesystems.URLMapper;
104: import org.openide.loaders.DataFolder;
105: import org.openide.loaders.DataObject;
106: import org.openide.loaders.DataObjectNotFoundException;
107: import org.openide.nodes.AbstractNode;
108: import org.openide.nodes.Children;
109: import org.openide.nodes.Node;
110: import org.openide.text.CloneableEditorSupport;
111: import org.openide.util.NbBundle;
112: import org.openide.util.lookup.Lookups;
113: import org.openide.windows.TopComponent;
114:
115: /**
116: * Shared utilities for service implementation code.
117: *
118: * @author Nam Nguyen
119: */
120: public class SharedUtils {
121:
122: public static final String WSDL_MIME_TYPE = "text/xml-wsdl"; // NOI18N
123: public static final String SOURCES_TYPE_XML = "xml";
124: public static final String SOURCES_TYPE_JAVA = "java";
125: public static final String TYPE_DOC_ROOT = "doc_root";
126: public static final String TYPE_WEB_INF = "web_inf";
127:
128: public static void renameTarget(Nameable target, String newName)
129: throws IOException {
130: if (target.getModel() == null)
131: return;
132: Model model = target.getModel();
133:
134: boolean startTransaction = !model.isIntransaction();
135: try {
136: if (startTransaction) {
137: model.startTransaction();
138: }
139: ((Nameable) target).setName(newName);
140: } finally {
141: if (startTransaction && model.isIntransaction()) {
142: model.endTransaction();
143: }
144: }
145:
146: // request.setRenamedTarget(request.getNameableTarget());
147: }
148:
149: public static void deleteTarget(NamedReferenceable target)
150: throws IOException {
151: if (target == null || getModel(target) == null)
152: return;
153: //System.out.println("DeleteTarget called");
154: Model model = getModel(target);
155: boolean startTransaction = !model.isIntransaction();
156: try {
157: if (startTransaction) {
158: model.startTransaction();
159: }
160: model.removeChildComponent(target);
161: } finally {
162: if (startTransaction && model.isIntransaction()) {
163: model.endTransaction();
164: }
165: }
166: //request.setDone(true);
167: }
168:
169: public static List<ErrorItem> addCascadeDeleteErrors(
170: List<Model> models,
171: Class<? extends Model> referencingModelType) {
172: List<ErrorItem> errors = new ArrayList<ErrorItem>();
173: for (Model model : models) {
174: if (!(referencingModelType.isAssignableFrom(model
175: .getClass()))) {
176: continue;
177: }
178: String msg = NbBundle.getMessage(RefactoringUtil.class,
179: "MSG_CascadeDeleteNotSupported");
180: errors.add(new ErrorItem(model, msg));
181: }
182: return errors;
183: }
184:
185: public static boolean isWritable(FileObject fo) {
186: boolean canLock = false;
187: FileLock lock = null;
188: try {
189: lock = fo.lock();
190: canLock = true;
191: } catch (IOException ioe) {
192: if (lock != null)
193: lock.releaseLock();
194: }
195: return fo != null && fo.canWrite() && canLock;
196: }
197:
198: public static String getURI(FileObject fo) {
199: return FileUtil.toFile(fo).toURI().toString();
200: }
201:
202: public static ProjectCatalogSupport getCatalogSupport(
203: FileObject file) {
204: Project p = FileOwnerQuery.getOwner(file);
205: if (p != null) {
206: return (ProjectCatalogSupport) p.getLookup().lookup(
207: ProjectCatalogSupport.class);
208: }
209: return null;
210: }
211:
212: public static FileObject renameFile(FileObject fo, String newName)
213: throws IOException {
214: String extension = fo.getExt();
215: FileLock lock = null;
216: try {
217: lock = fo.lock();
218: fo.rename(lock, newName, extension);
219: return fo;
220: } finally {
221: if (lock != null)
222: lock.releaseLock();
223: }
224: }
225:
226: public static FileObject moveFile(FileObject source,
227: FileObject target) throws IOException {
228: if (source != null) {
229: return FileUtil.moveFile(source, target, source.getName());
230: }
231: return null;
232:
233: }
234:
235: public static FileObject copyFile(FileObject source,
236: FileObject targetFolder, String newName) throws IOException {
237: if (source != null)
238: return FileUtil.copyFile(source, targetFolder, newName);
239:
240: return null;
241:
242: }
243:
244: protected static List<SourceGroup> getSourceGroups(Referenceable ref) {
245: List<SourceGroup> sourceGroups = new ArrayList<SourceGroup>();
246: Project project = RefactoringUtil.findCurrentProject(ref);
247: if (project != null) {
248: sourceGroups.addAll(RefactoringUtil
249: .findSourceRoots(project));
250: Set<Project> referencings = RefactoringUtil
251: .getReferencingProjects(project);
252: for (Project p : referencings) {
253: sourceGroups.addAll(RefactoringUtil.findSourceRoots(p));
254: }
255: }
256:
257: return sourceGroups;
258: }
259:
260: public static Set<FileObject> getSearchFiles(Referenceable ref) {
261: HashSet<FileObject> files = new HashSet<FileObject>();
262: for (SourceGroup sourceGroup : getSourceGroups(ref)) {
263: files.addAll(RefactoringUtil.findSourceFiles(sourceGroup
264: .getRootFolder()));
265: }
266: // make sure target source is also included in search in case outside projects
267: Model model = null;
268: if (ref instanceof Model) {
269: model = (Model) ref;
270: } else if (ref instanceof Component) {
271: model = ((Component) ref).getModel();
272: }
273:
274: DataObject dobj = RefactoringUtil.getDataObject(model);
275: if (dobj != null) {
276: files.add(dobj.getPrimaryFile());
277: }
278: return files;
279: }
280:
281: public static Model getModel(Referenceable ref) {
282: if (ref instanceof Model) {
283: return (Model) ref;
284: } else if (ref instanceof Component) {
285: return ((Component) ref).getModel();
286: } else {
287: return null;
288: }
289: }
290:
291: public static String calculateNewLocationString(
292: String currentLocationString, RenameRefactoring request) {
293: StringBuilder sb = new StringBuilder();
294: int i = currentLocationString.lastIndexOf('/');
295: if (i > -1) {
296: sb.append(currentLocationString.substring(0, i + 1));
297: }
298: sb.append(request.getNewName());
299: sb.append("."); //NOI18N
300: Referenceable ref = request.getRefactoringSource().lookup(
301: Referenceable.class);
302: Model model = SharedUtils.getModel(ref);
303: FileObject fo = model.getModelSource().getLookup().lookup(
304: FileObject.class);
305: sb.append(fo.getExt());
306: return sb.toString();
307: }
308:
309: public static String calculateNewLocationString(Model model,
310: MoveRefactoring request) throws IOException,
311: URISyntaxException {
312: StringBuilder sb = new StringBuilder();
313: URL url = ((MoveRefactoring) request).getTarget().lookup(
314: URL.class);
315: FileObject sfo = getOrCreateFolder(url);
316: FileObject tfo = model.getModelSource().getLookup().lookup(
317: FileObject.class);
318: URI uri = getReferenceURI(tfo, sfo);
319: sb.append(uri.toString());
320: Referenceable ref = request.getRefactoringSource().lookup(
321: Referenceable.class);
322: Model mod = SharedUtils.getModel(ref);
323: FileObject ofo = mod.getModelSource().getLookup().lookup(
324: FileObject.class);
325: if (!sb.toString().endsWith("/"))
326: sb.append("/");
327: sb.append(ofo.getNameExt());
328: return sb.toString();
329: }
330:
331: /* public static String calculateNewLocationString(ModelSource source, ModelSource target) throws Exception {
332: FileObject sourceFO = source.getLookup().lookup(FileObject.class);
333: FileObject referencedFO = target.getLookup().lookup(FileObject.class);
334: DefaultProjectCatalogSupport catalogSupport = DefaultProjectCatalogSupport.getInstance(sourceFO);
335: return (catalogSupport.getReferenceURI(sourceFO, referencedFO)).toString();
336: }*/
337:
338: public static Map<Model, Set<RefactoringElementImplementation>> getModelMap(
339: List<RefactoringElementImplementation> elements) {
340: Map<Model, Set<RefactoringElementImplementation>> results = new HashMap<Model, Set<RefactoringElementImplementation>>();
341: for (RefactoringElementImplementation element : elements) {
342: Model model = ((Component) element.getLookup().lookup(
343: Component.class)).getModel();
344: Set<RefactoringElementImplementation> elementsInModel = results
345: .get(model);
346: if (elementsInModel == null) {
347: elementsInModel = new HashSet<RefactoringElementImplementation>();
348: elementsInModel.add(element);
349: results.put(model, elementsInModel);
350: } else
351: elementsInModel.add(element);
352: }
353: return results;
354: }
355:
356: public static void silentDeleteRefactor(NamedReferenceable target,
357: boolean failsOnUsage) throws CannotRefactorException,
358: IOException {
359: SafeDeleteRefactoring refactoring = new SafeDeleteRefactoring(
360: Lookups.singleton(target));
361: XMLRefactoringTransaction transaction = new XMLRefactoringTransaction(
362: (Referenceable) target, refactoring);
363: transaction.setLocalScope();
364: refactoring.getContext().add(transaction);
365: refactor(refactoring, failsOnUsage);
366: }
367:
368: public static void silentRename(Nameable target, String newName,
369: boolean failsOnUsage) throws CannotRefactorException,
370: IOException {
371: RenameRefactoring refactoring = new RenameRefactoring(Lookups
372: .singleton(target));
373: refactoring.setNewName(newName);
374: XMLRefactoringTransaction transaction = new XMLRefactoringTransaction(
375: (Referenceable) target, refactoring);
376: transaction.setLocalScope();
377: refactoring.getContext().add(transaction);
378: refactoring.getContext().add(target.getName());
379: refactor(refactoring, failsOnUsage);
380: }
381:
382: public static void silentFileRefactor(Model model, String name,
383: boolean b) throws CannotRefactorException, IOException {
384: RenameRefactoring refactoring = new RenameRefactoring(Lookups
385: .singleton(model));
386: refactoring.setNewName(name);
387: String oldFileName = (model.getModelSource().getLookup()
388: .lookup(FileObject.class)).getName();
389: refactoring.getContext().add(oldFileName);
390: XMLRefactoringTransaction transaction = new XMLRefactoringTransaction(
391: (Referenceable) model, refactoring);
392: refactoring.getContext().add(transaction);
393: refactor(refactoring, b);
394: }
395:
396: public static void refactor(AbstractRefactoring refactoring,
397: boolean failsOnUsages) throws CannotRefactorException,
398: IOException {
399: RefactoringSession session = RefactoringSession.create(NbBundle
400: .getMessage(SharedUtils.class, "LBL_Silent_Refactor"));
401: Problem problem = refactoring.checkParameters();
402: while (problem != null) {
403: if (problem.isFatal())
404: throw new CannotRefactorException(problem.getMessage());
405: problem = problem.getNext();
406: }
407:
408: problem = refactoring.prepare(session);
409: if (failsOnUsages
410: && session.getRefactoringElements().size() > 0) {
411: throw new CannotRefactorException(NbBundle.getMessage(
412: RefactoringUtil.class, "MSG_HasUsages"));
413: }
414: while (problem != null) {
415: if (problem.isFatal())
416: throw new CannotRefactorException(problem.getMessage());
417: problem = problem.getNext();
418: }
419:
420: //save the file before refactoring..
421: Referenceable obj = refactoring.getRefactoringSource().lookup(
422: Referenceable.class);
423: if (obj == null)
424: return;
425: Set<Model> all = new HashSet<Model>();
426: if (obj instanceof Model)
427: RefactoringUtil.saveTargetFile((Model) obj, all);
428: else if (obj instanceof Nameable)
429: RefactoringUtil.saveTargetFile(((Nameable) obj).getModel(),
430: all);
431: session.doRefactoring(true);
432: }
433:
434: public static void showRefactoringUI(AbstractRefactoring request) {
435: Referenceable target = request.getRefactoringSource().lookup(
436: Referenceable.class);
437: org.netbeans.modules.refactoring.spi.ui.RefactoringUI ui = null;
438: if (target instanceof Model
439: && request instanceof RenameRefactoring)
440: ui = new FileRenameRefactoringUI((Model) target);
441: else if (target instanceof Nameable
442: && request instanceof RenameRefactoring)
443: ui = new RenameRefactoringUI((Nameable) target);
444:
445: TopComponent activetc = TopComponent.getRegistry()
446: .getActivated();
447: if (activetc instanceof CloneableEditorSupport.Pane) {
448: //new RefactoringPanel(ui, activetc);
449: UI.openRefactoringUI(ui, activetc);
450: } else {
451: // new RefactoringPanel(ui);
452: UI.openRefactoringUI(ui);
453: }
454: }
455:
456: public static void showDeleteRefactoringUI(NamedReferenceable target) {
457: org.netbeans.modules.refactoring.spi.ui.RefactoringUI ui = new DeleteRefactoringUI(
458: target);
459: TopComponent activetc = TopComponent.getRegistry()
460: .getActivated();
461: if (activetc instanceof CloneableEditorSupport.Pane) {
462: //new RefactoringPanel(ui, activetc);
463: UI.openRefactoringUI(ui, activetc);
464: } else {
465: // new RefactoringPanel(ui);
466: UI.openRefactoringUI(ui);
467: }
468: }
469:
470: public static void showRenameRefactoringUI(Nameable target) {
471: showRenameRefactoringUI(target, null);
472: }
473:
474: public static void showRenameRefactoringUI(Nameable target,
475: String newName) {
476: org.netbeans.modules.refactoring.spi.ui.RefactoringUI ui = new RenameRefactoringUI(
477: target, newName);
478: TopComponent activetc = TopComponent.getRegistry()
479: .getActivated();
480: if (activetc instanceof CloneableEditorSupport.Pane) {
481: //new RefactoringPanel(ui, activetc);
482: UI.openRefactoringUI(ui, activetc);
483: } else {
484: // new RefactoringPanel(ui);
485: UI.openRefactoringUI(ui);
486: }
487: }
488:
489: public static void showFileRenameRefactoringUI(Model target) {
490: org.netbeans.modules.refactoring.spi.ui.RefactoringUI ui = new FileRenameRefactoringUI(
491: target);
492: TopComponent activetc = TopComponent.getRegistry()
493: .getActivated();
494: if (activetc instanceof CloneableEditorSupport.Pane) {
495: //new RefactoringPanel(ui, activetc);
496: UI.openRefactoringUI(ui, activetc);
497: } else {
498: // new RefactoringPanel(ui);
499: UI.openRefactoringUI(ui);
500: }
501: }
502:
503: public static void showFileRenameRefactoringUI(Model target,
504: String newName) {
505: org.netbeans.modules.refactoring.spi.ui.RefactoringUI ui = new FileRenameRefactoringUI(
506: target, newName);
507: TopComponent activetc = TopComponent.getRegistry()
508: .getActivated();
509: if (activetc instanceof CloneableEditorSupport.Pane) {
510: //new RefactoringPanel(ui, activetc);
511: UI.openRefactoringUI(ui, activetc);
512: } else {
513: // new RefactoringPanel(ui);
514: UI.openRefactoringUI(ui);
515: }
516: }
517:
518: /**
519: * @param fobj a FileObject
520: * @returns Image java.awt.Image for the FileObject
521: *
522: */
523: public static Image getImage(FileObject fobj) {
524: try {
525: return DataObject.find(fobj).getNodeDelegate().getIcon(
526: BeanInfo.ICON_COLOR_16x16);
527: } catch (DataObjectNotFoundException ex) {
528: ErrorManager.getDefault().notify(ex);
529: }
530: return null;
531: }
532:
533: public static FileObject getFileObject(final Component xamComp) {
534: return (FileObject) xamComp.getModel().getModelSource()
535: .getLookup().lookup(FileObject.class);
536: }
537:
538: public static String getXmlFileType(FileObject fobj) {
539: if (fobj.getExt().equals(
540: AnalysisConstants.SCHEMA_FILE_EXTENSION)) {
541: return AnalysisConstants.SCHEMA_FILE_TYPE;
542: }
543: if (WSDL_MIME_TYPE.equals(FileUtil.getMIMEType(fobj))) {
544: return AnalysisConstants.WSDL_FILE_TYPE;
545: }
546: if (fobj.getExt().equals(AnalysisConstants.BPEL_FILE_EXTENSION)) {
547: return AnalysisConstants.BPEL_FILE_TYPE;
548: }
549: return ""; //NOI18N
550: }
551:
552: public static String getXmlFileTypeDisplayName(String fileType) {
553: if (fileType.equals(AnalysisConstants.SCHEMA_FILE_TYPE)) {
554: return NbBundle.getMessage(SharedUtils.class, "LBL_Schema");
555: }
556:
557: if (fileType.equals(AnalysisConstants.WSDL_FILE_TYPE)) {
558: return NbBundle.getMessage(SharedUtils.class, "LBL_WSDL");
559: }
560:
561: if (fileType.equals(AnalysisConstants.BPEL_FILE_TYPE)) {
562: return NbBundle.getMessage(SharedUtils.class, "LBL_BPEL");
563: }
564: return ""; //NOI18N
565:
566: }
567:
568: /**
569: * Check for the ReferenceableProvider Node.Cookie in node 0
570: *
571: * @returns NamedReferenceable instance of null if the node does
572: * not have the provider cookie
573: */
574: public static Referenceable getReferenceable(
575: final org.openide.nodes.Node[] nodes) {
576: Referenceable referenceable = null;
577: ReferenceableProvider provider = (ReferenceableProvider) nodes[0]
578: .getCookie(ReferenceableProvider.class);
579: if (provider != null) {
580: referenceable = provider.getReferenceable();
581: } else {
582: ModelProvider modelProvider = (ModelProvider) nodes[0]
583: .getCookie(ModelProvider.class);
584: if (modelProvider != null) {
585: referenceable = modelProvider.getModel();
586: }
587: }
588: return referenceable;
589: }
590:
591: /**
592: * Quiet and local rename refactoring.
593: */
594: public static void locallyRenameRefactor(Nameable target,
595: String newName) {
596: RenameRefactoring refactoring = new RenameRefactoring(Lookups
597: .singleton(target));
598: refactoring.setNewName(newName);
599: XMLRefactoringTransaction transaction = new XMLRefactoringTransaction(
600: (Referenceable) target, refactoring);
601: transaction.setLocalScope();
602: refactoring.getContext().add(transaction);
603: refactoring.getContext().add(target.getName());
604: doQuietRefactor(refactoring);
605: }
606:
607: /**
608: * Quietly execute the given refactoring request.
609: *
610: */
611: public static void doQuietRefactor(AbstractRefactoring request) {
612: try {
613: //RefactoringManager.getInstance().execute(request, false);
614: refactor(request, false);
615: } catch (IOException ex) {
616: String msg = ex.getMessage();
617: NotifyDescriptor nd = new NotifyDescriptor.Message(msg,
618: NotifyDescriptor.ERROR_MESSAGE);
619: DialogDisplayer.getDefault().notify(nd);
620: } catch (CannotRefactorException cre) {
621: Referenceable target = request.getRefactoringSource()
622: .lookup(Referenceable.class);
623:
624: if (request instanceof RenameRefactoring) {
625: String newName = ((RenameRefactoring) request)
626: .getNewName();
627: showRenameRefactoringUI((Nameable) target, newName);
628: }
629: }
630: }
631:
632: public static String getName(Referenceable target) {
633: if (target instanceof Model) {
634: FileObject fo = (FileObject) ((Model) target)
635: .getModelSource().getLookup().lookup(
636: FileObject.class);
637: assert fo != null : "Target model does not contain FileObject in lookkup";
638: return fo.getName();
639: } else {
640: return ((Named) target).getName();
641: }
642: }
643:
644: public static Set<Component> getLocalSearchRoots(
645: Referenceable target) {
646: Set<Component> scope = null;
647: if (target instanceof DocumentModel) {
648: scope = new HashSet<Component>();
649: scope.add(((DocumentModel) target).getRootComponent());
650: } else if (target instanceof Component) {
651: scope = Collections
652: .singleton(getRootOf((Component) target));
653: }
654: return scope;
655: }
656:
657: public static Component getRootOf(Component component) {
658: Component root = (Component) component;
659: while (root != null) {
660: Component parent = getEffectiveParent(root);
661: if (parent == null) {
662: break;
663: }
664: root = parent;
665: }
666: return root;
667: }
668:
669: public static Component getEffectiveParent(Component component) {
670: if (component instanceof EmbeddableRoot) {
671: return ((EmbeddableRoot) component).getForeignParent();
672: } else {
673: return component.getParent();
674: }
675: }
676:
677: public static Collection<RefactoringElement> findUsages(
678: Referenceable target, Component searchRoot) {
679: WhereUsedQuery query = new WhereUsedQuery(Lookups
680: .singleton(target));
681: query.getContext().add(searchRoot);
682: RefactoringSession session = RefactoringSession
683: .create("Inner Query");
684: query.prepare(session);
685: return session.getRefactoringElements();
686: }
687:
688: public Node getDisplayNode(Component component) {
689: AbstractNode n = new AbstractNode(Children.LEAF);
690: String name = component instanceof Named ? ((Named) component)
691: .getName() : component.getClass().getName();
692: n.setName(name);
693: return n;
694: }
695:
696: public Node getDisplayNode(Model model) {
697: AbstractNode n = new AbstractNode(Children.LEAF);
698: FileObject fo = (FileObject) model.getModelSource().getLookup()
699: .lookup(FileObject.class);
700: assert fo != null : "Model source does not provide FileObject lookup";
701: n.setName(fo.getName());
702: return n;
703: }
704:
705: /**
706: * creates or finds FileObject according to
707: * @param url
708: * @return FileObject
709: * @throws java.io.IOException
710: */
711: public static FileObject getOrCreateFolder(URL url)
712: throws IOException {
713: try {
714: FileObject result = URLMapper.findFileObject(url);
715: if (result != null)
716: return result;
717: File f = new File(url.toURI());
718:
719: result = FileUtil.createFolder(f);
720: return result;
721: } catch (URISyntaxException ex) {
722: throw (IOException) new IOException().initCause(ex);
723: }
724: }
725:
726: public static String getRelativePath(Model model1, Model model2)
727: throws IOException {
728: FileObject origFile = model1.getModelSource().getLookup()
729: .lookup(FileObject.class);
730: FileObject origRelativeTo = model2.getModelSource().getLookup()
731: .lookup(FileObject.class);
732: return getRelativePath(origFile, origRelativeTo);
733: }
734:
735: /*public static String getRelativePath(FileObject origFile, FileObject origRelativeTo) throws IOException {
736: File file = FileUtil.toFile(origFile);
737: File relativeTo = FileUtil.toFile(origRelativeTo);
738: List filePathStack = new ArrayList();
739: List relativeToPathStack = new ArrayList();
740: // build the path stack info to compare it afterwards
741: file = file.getCanonicalFile();
742: while (file!=null) {
743: filePathStack.add(0, file);
744: file = file.getParentFile();
745: }
746: relativeTo = relativeTo.getCanonicalFile();
747: while (relativeTo!=null) {
748: relativeToPathStack.add(0, relativeTo);
749: relativeTo = relativeTo.getParentFile();
750: }
751: // compare as long it goes
752: int count = 0;
753: file = (File)filePathStack.get(count);
754: relativeTo = (File)relativeToPathStack.get(count);
755: while ( (count < filePathStack.size()-1) && (count <relativeToPathStack.size()-1) && file.equals(relativeTo)) {
756: count++;
757: file = (File)filePathStack.get(count);
758: relativeTo = (File)relativeToPathStack.get(count);
759: }
760: if (file.equals(relativeTo)) count++;
761: // up as far as necessary
762:
763: StringBuffer relString = new StringBuffer();
764: for (int i = count; i < relativeToPathStack.size(); i++) {
765: relString.append(".."+File.separatorChar);
766: }
767: // now back down to the file
768: for (int i = count; i <filePathStack.size()-1; i++) {
769: relString.append(((File)filePathStack.get(i)).getName()+File.separatorChar);
770: }
771: relString.append(((File)filePathStack.get(filePathStack.size()-1)).getName());
772: return relString.toString();
773: }
774: */
775:
776: public static List<String> getSourceGroups() {
777: List<String> srcGroups = new ArrayList<String>();
778: srcGroups.add(SOURCES_TYPE_JAVA);
779: srcGroups.add(SOURCES_TYPE_XML);
780: return srcGroups;
781: }
782:
783: public static CloneableEditorSupport findCloneableEditorSupport(
784: DataObject dob) {
785: Object obj = dob
786: .getCookie(org.openide.cookies.OpenCookie.class);
787: if (obj instanceof CloneableEditorSupport) {
788: return (CloneableEditorSupport) obj;
789: }
790: obj = dob.getCookie(org.openide.cookies.EditorCookie.class);
791: if (obj instanceof CloneableEditorSupport) {
792: return (CloneableEditorSupport) obj;
793: }
794: return null;
795: }
796:
797: public static URI getReferenceURI(FileObject source,
798: FileObject target) throws URISyntaxException, IOException {
799: Project targetProject = FileOwnerQuery.getOwner(target);
800: Project project = FileOwnerQuery.getOwner(source);
801: FileObject sourceFolder = getSourceFolder(project, source);
802:
803: if (sourceFolder == null) {
804: sourceFolder = source;
805: // throw new IllegalArgumentException(source.getPath()+" is not in project source"); //NOI18N
806: }
807: if (!source.isFolder())
808: source = source.getParent();
809:
810: String relPathToSrcGroup = getRelativePath(source, sourceFolder);
811: String relPathToSrcGroupWithSlash = relPathToSrcGroup.trim()
812: .equals("") ? "" : relPathToSrcGroup.concat("/");
813: if (project != targetProject) {
814:
815: if (!getProjectReferences(project).contains(targetProject)) {
816: return target.getURL().toURI();
817: }
818:
819: FileObject folder = getSourceFolder(targetProject, target);
820: if (folder == null) {
821: folder = target;
822: //throw new IllegalArgumentException(target.getPath()+" is not in target project source"); //NOI18N
823: }
824: String relPathFromTgtGroup = getRelativePath(folder, target);
825: return new URI(relPathToSrcGroupWithSlash.concat(
826: getUsableProjectName(targetProject)).concat("/")
827: .concat(relPathFromTgtGroup));
828: } else {
829: FileObject targetSourceFolder = getSourceFolder(
830: targetProject, target);
831: if (targetSourceFolder == null) {
832: throw new IllegalArgumentException(target.getPath()
833: + " is not in project source"); //NOI18N
834: }
835: String relPathFromTgtGroup = getRelativePath(
836: targetSourceFolder, target);
837: return new URI(relPathToSrcGroupWithSlash
838: .concat(relPathFromTgtGroup));
839: }
840: }
841:
842: public static String getRelativePath(FileObject source,
843: FileObject target) {
844: File sourceLocationFile = FileUtil.toFile(source);
845: File targetLocationFile = FileUtil.toFile(target);
846: String sourceLocation = sourceLocationFile.toURI().toString();
847: String targetLocation = targetLocationFile.toURI().toString();
848: StringTokenizer st1 = new StringTokenizer(sourceLocation, "/");
849: StringTokenizer st2 = new StringTokenizer(targetLocation, "/");
850: String relativeLoc = "";
851: while (st1.hasMoreTokens() && st2.hasMoreTokens()) {
852: relativeLoc = st2.nextToken();
853: if (!st1.nextToken().equals(relativeLoc)) {
854: break;
855: }
856: if (!st1.hasMoreTokens() || !st2.hasMoreTokens()) {
857: // seems like one of the file is parent directory of other file
858: if (st1.hasMoreElements()) {
859: // seems like target is parent of source
860: relativeLoc = "..";
861: st1.nextToken();
862: } else if (st2.hasMoreTokens()) {
863: // seems like source is parent of target
864: relativeLoc = st2.nextToken();
865: } else {
866: // both represent same file
867: relativeLoc = "";
868: }
869: }
870: }
871: while (st1.hasMoreTokens()) {
872: relativeLoc = "../".concat(relativeLoc);
873: st1.nextToken();
874: }
875: while (st2.hasMoreTokens()) {
876: relativeLoc = relativeLoc.concat("/").concat(
877: st2.nextToken());
878: }
879: return relativeLoc;
880: }
881:
882: private static String[] sourceTypes = new String[] {
883: SOURCES_TYPE_XML, SOURCES_TYPE_JAVA, TYPE_DOC_ROOT,
884: TYPE_WEB_INF };
885:
886: public static FileObject getSourceFolder(Project project,
887: FileObject source) {
888: Sources sources = ProjectUtils.getSources(project);
889: assert sources != null;
890: ArrayList<SourceGroup> sourceGroups = new ArrayList<SourceGroup>();
891: for (String type : sourceTypes) {
892: SourceGroup[] groups = sources.getSourceGroups(type);
893: if (groups != null) {
894: sourceGroups.addAll(Arrays.asList(groups));
895: }
896: }
897:
898: assert sourceGroups.size() > 0;
899: for (SourceGroup sourceGroup : sourceGroups) {
900: if (FileUtil
901: .isParentOf(sourceGroup.getRootFolder(), source))
902: return sourceGroup.getRootFolder();
903: }
904:
905: FileObject metaInf = project.getProjectDirectory()
906: .getFileObject("src/conf"); //NOI18N
907: if (metaInf != null) {
908: if (FileUtil.isParentOf(metaInf, source)) {
909: return metaInf;
910: }
911: }
912: return null;
913: }
914:
915: private static String getUsableProjectName(Project project) {
916: return PropertyUtils.getUsablePropertyName(
917: ProjectUtils.getInformation(project).getName())
918: .replace('.', '_');
919: }
920:
921: public static FileObject getFileObject(Model model, URI uri) {
922: File result = null;
923: FileObject fobj = model.getModelSource().getLookup().lookup(
924: FileObject.class);
925: File sourceFile = FileUtil.toFile(fobj);
926: if (sourceFile != null) {
927: URI sourceFileObjectURI = sourceFile.toURI();
928: URI resultURI = sourceFileObjectURI.resolve(uri);
929: try {
930: result = new File(resultURI);
931: if (result.isFile()) {
932: return FileUtil.toFileObject(result);
933: }
934: } catch (Exception e) {
935: //do nothing
936: }
937: }
938: return null;
939: }
940:
941: public static boolean inSameProject(FileObject source,
942: FileObject target) {
943: Project targetProject = FileOwnerQuery.getOwner(target);
944: Project project = FileOwnerQuery.getOwner(source);
945: return (targetProject == project);
946: }
947:
948: public static Set getProjectReferences(Project project) {
949: SubprojectProvider provider = (SubprojectProvider) project
950: .getLookup().lookup(SubprojectProvider.class);
951: return provider.getSubprojects();
952: }
953:
954: }
|