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.project.layers;
043:
044: import java.awt.Toolkit;
045: import java.lang.reflect.InvocationTargetException;
046: import java.lang.reflect.Method;
047: import java.net.URL;
048: import java.util.Iterator;
049: import java.util.LinkedList;
050: import java.util.List;
051:
052: import javax.xml.parsers.SAXParser;
053: import javax.xml.parsers.SAXParserFactory; //import java.util.HashSet;
054: //import java.util.Set;
055: //import org.netbeans.api.project.FileOwnerQuery;
056: //import org.netbeans.api.project.Project;
057: //import org.netbeans.api.project.ProjectUtils;
058: //import org.netbeans.api.project.ui.OpenProjects;
059: //import org.openide.DialogDisplayer;
060: //import org.openide.DialogDisplayer;
061: //import org.openide.NotifyDescriptor;
062: import org.openide.cookies.EditorCookie;
063: import org.openide.cookies.LineCookie;
064: import org.openide.filesystems.FileObject;
065: import org.openide.filesystems.FileStateInvalidException;
066: import org.openide.filesystems.FileSystem;
067: import org.openide.filesystems.MultiFileSystem;
068: import org.openide.filesystems.URLMapper;
069: import org.openide.filesystems.XMLFileSystem;
070: import org.openide.loaders.DataObject;
071: import org.openide.loaders.DataObjectNotFoundException;
072: import org.openide.nodes.Node;
073: import org.openide.text.Line;
074: import org.openide.util.Exceptions;
075: import org.openide.util.HelpCtx;
076: import org.openide.util.NbBundle;
077: import org.openide.util.actions.CookieAction;
078: import org.xml.sax.Attributes;
079: import org.xml.sax.InputSource;
080: import org.xml.sax.Locator;
081: import org.xml.sax.SAXException;
082: import org.xml.sax.helpers.DefaultHandler;
083:
084: /**
085: * Open the layer file(s) declaring the SFS node.
086: *
087: * @author Sandip Chitale
088: */
089: public class OpenLayerFilesAction extends CookieAction {
090:
091: // HACK Tunnel through the MultiFileSystem to get to the delegates
092: private static Method getDelegatesMethod;
093: static {
094: try {
095: getDelegatesMethod = MultiFileSystem.class
096: .getDeclaredMethod("getDelegates");
097: getDelegatesMethod.setAccessible(true);
098: } catch (NoSuchMethodException ex) {
099: Exceptions.printStackTrace(ex);
100: } catch (SecurityException ex) {
101: Exceptions.printStackTrace(ex);
102: }
103: }
104:
105: protected void performAction(Node[] activatedNodes) {
106: if (getDelegatesMethod == null) {
107: Toolkit.getDefaultToolkit().beep();
108: return;
109: }
110: try {
111: // Set<Project> projectsSet = new HashSet<Project>();
112: FileObject f = activatedNodes[0]
113: .getCookie(DataObject.class).getPrimaryFile();
114: FileSystem fs = f.getFileSystem();
115: while (fs instanceof MultiFileSystem) {
116: try {
117: FileSystem[] delegates = (FileSystem[]) getDelegatesMethod
118: .invoke(fs);
119: if (delegates != null && delegates.length > 0) {
120: fs = delegates[0];
121: if (fs instanceof MultiFileSystem) {
122: // keep going
123: continue;
124: } else if (fs instanceof WritableXMLFileSystem) {
125: // Now, try other layer files visible to the module project
126: for (int i = 0; i < delegates.length; i++) {
127: fs = delegates[i];
128: FileObject originalF = fs
129: .findResource(f.getPath());
130: if (fs instanceof WritableXMLFileSystem) {
131: // Issue # 118839
132: // Avoid CCE
133: // try current module project's layer file.
134: if (originalF != null) {
135: URL url = (URL) f
136: .getAttribute("WritableXMLFileSystem.location"); // NOI18N
137: FileObject layerFileObject = URLMapper
138: .findFileObject(url);
139: if (layerFileObject != null) {
140: try {
141: DataObject layerDataObject = DataObject
142: .find(layerFileObject);
143: openLayerFileAndFind(
144: layerDataObject,
145: originalF);
146: // Project project = FileOwnerQuery.getOwner(layerFileObject);
147: // if (project != null) {
148: // projectsSet.add(project);
149: // }
150: } catch (DataObjectNotFoundException ex) {
151: Exceptions
152: .printStackTrace(ex);
153: }
154: }
155: }
156: } else if (delegates[i] instanceof XMLFileSystem) {
157: XMLFileSystem xMLFileSystem = (XMLFileSystem) delegates[i];
158:
159: // Have to use deprecated API to get all the Xml URLs
160: URL[] urls = xMLFileSystem
161: .getXmlUrls();
162: for (URL url : urls) {
163: try {
164: // Build an XML FS for the given URL
165: XMLFileSystem aXMLFileSystem = new XMLFileSystem(
166: url);
167:
168: // Find the resource using the file path
169: originalF = aXMLFileSystem
170: .findResource(f
171: .getPath());
172:
173: // Found?
174: if (originalF != null) {
175: // locate the layer's file object and open it
176: FileObject layerFileObject = URLMapper
177: .findFileObject(url);
178: if (layerFileObject != null) {
179: try {
180: DataObject layerDataObject = DataObject
181: .find(layerFileObject);
182: openLayerFileAndFind(
183: layerDataObject,
184: originalF);
185:
186: // Project project = FileOwnerQuery.getOwner(layerFileObject);
187: // if (project != null) {
188: // projectsSet.add(project);
189: // }
190: } catch (DataObjectNotFoundException ex) {
191: Exceptions
192: .printStackTrace(ex);
193: }
194: }
195: }
196: } catch (SAXException ex) {
197: Exceptions
198: .printStackTrace(ex);
199: }
200: }
201: }
202: }
203: }
204: }
205:
206: // projectsSet.removeAll(Arrays.asList(OpenProjects.getDefault().getOpenProjects()));
207: // if (projectsSet.size() > 0) {
208: // Set<String> projectNames = new HashSet<String>(projectsSet.size());
209: // for(Project project:projectsSet) {
210: // projectNames.add(ProjectUtils.getInformation(project).getDisplayName());
211: // }
212: // if (DialogDisplayer.getDefault().notify(
213: // new NotifyDescriptor.Confirmation(
214: // projectNames.toArray(new String[0]),
215: // NbBundle.getMessage(OpenLayerFilesAction.class, "MSG_open_layer_projects"),
216: // NotifyDescriptor.YES_NO_OPTION,
217: // NotifyDescriptor.QUESTION_MESSAGE)) == NotifyDescriptor.YES_OPTION) {
218: // OpenProjects.getDefault().open(projectsSet.toArray(new Project[0]), false);
219: // }
220: // }
221: } catch (IllegalAccessException ex) {
222: Exceptions.printStackTrace(ex);
223: } catch (IllegalArgumentException ex) {
224: Exceptions.printStackTrace(ex);
225: } catch (InvocationTargetException ex) {
226: Exceptions.printStackTrace(ex);
227: }
228: }
229: } catch (FileStateInvalidException ex) {
230: Exceptions.printStackTrace(ex);
231: }
232: }
233:
234: private static void openLayerFileAndFind(
235: DataObject layerDataObject, FileObject originalF) {
236: EditorCookie editorCookie = layerDataObject
237: .getCookie(EditorCookie.class);
238: if (editorCookie != null) {
239: editorCookie.open();
240: LineCookie lineCookie = layerDataObject
241: .getCookie(LineCookie.class);
242: if (lineCookie != null) {
243: List<FileObject> lineage = new LinkedList<FileObject>();
244: FileObject parent = originalF;
245: while (parent != null) {
246: if (parent.getParent() != null) {
247: lineage.add(0, parent);
248: }
249: parent = parent.getParent();
250: }
251: try {
252: InputSource in = new InputSource(layerDataObject
253: .getPrimaryFile().getURL().toExternalForm());
254: SAXParserFactory factory = SAXParserFactory
255: .newInstance();
256: SAXParser parser = factory.newSAXParser();
257: final int[] line = new int[1];
258: //final int[] col = new int[1];
259: final String name = originalF.getNameExt();
260: class Handler extends DefaultHandler {
261: private Locator locator;
262: private Iterator<FileObject> lineageIterator;
263: private FileObject lookingFor;
264:
265: Handler(List<FileObject> lineage) {
266: lineageIterator = lineage.iterator();
267: lookingFor = lineageIterator.next();
268: }
269:
270: @Override
271: public void setDocumentLocator(Locator l) {
272: locator = l;
273: }
274:
275: @Override
276: public void startElement(String uri,
277: String localname, String qname,
278: Attributes attr) throws SAXException {
279: if (line[0] == 0) {
280: if (((lookingFor.isFolder() ? "folder"
281: .equals(qname) : "file"
282: .equals(qname)) && lookingFor
283: .getNameExt().equals(
284: attr.getValue("name")))) { // NOI18N
285: if (lineageIterator.hasNext()) {
286: lookingFor = lineageIterator
287: .next();
288: } else {
289: line[0] = locator
290: .getLineNumber();
291: // col[0] = locator.getColumnNumber();
292: }
293: }
294: }
295: }
296: }
297: parser.parse(in, new Handler(lineage));
298: if (line[0] < 1) {
299: return;
300: }
301: lineCookie
302: .getLineSet()
303: .getCurrent(line[0] - 1)
304: .show(Line.SHOW_GOTO /*, Math.max(0, col[0])*/);
305: } catch (Exception e) {
306: return;
307: }
308: }
309: }
310: }
311:
312: public String getName() {
313: return NbBundle.getMessage(OpenLayerFilesAction.class,
314: "LBL_open_layer_files_action");
315: }
316:
317: protected Class[] cookieClasses() {
318: return new Class[] { DataObject.class };
319: }
320:
321: protected int mode() {
322: return MODE_EXACTLY_ONE;
323: }
324:
325: public HelpCtx getHelpCtx() {
326: return null;
327: }
328:
329: @Override
330: protected boolean asynchronous() {
331: return false;
332: }
333:
334: }
|