KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > ant > freeform > spi > support > Util


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.modules.ant.freeform.spi.support;
21
22 import java.io.File JavaDoc;
23 import java.io.IOException JavaDoc;
24 import java.util.ArrayList JavaDoc;
25 import java.util.Arrays JavaDoc;
26 import java.util.Iterator JavaDoc;
27 import java.util.List JavaDoc;
28 import javax.xml.XMLConstants JavaDoc;
29 import javax.xml.transform.dom.DOMSource JavaDoc;
30 import javax.xml.validation.Schema JavaDoc;
31 import javax.xml.validation.SchemaFactory JavaDoc;
32 import javax.xml.validation.Validator JavaDoc;
33 import org.netbeans.api.project.Project;
34 import org.netbeans.api.project.ProjectManager;
35 import org.netbeans.api.queries.CollocationQuery;
36 import org.netbeans.modules.ant.freeform.FreeformProject;
37 import org.netbeans.modules.ant.freeform.FreeformProjectGenerator;
38 import org.netbeans.modules.ant.freeform.FreeformProjectType;
39 import org.netbeans.modules.ant.freeform.spi.ProjectAccessor;
40 import org.netbeans.modules.ant.freeform.spi.ProjectConstants;
41 import org.netbeans.spi.project.AuxiliaryConfiguration;
42 import org.netbeans.spi.project.support.ant.AntProjectHelper;
43 import org.netbeans.spi.project.support.ant.PropertyEvaluator;
44 import org.netbeans.spi.project.support.ant.PropertyUtils;
45 import org.openide.ErrorManager;
46 import org.openide.filesystems.FileObject;
47 import org.openide.filesystems.FileUtil;
48 import org.openide.util.Mutex;
49 import org.w3c.dom.DOMException JavaDoc;
50 import org.w3c.dom.Document JavaDoc;
51 import org.w3c.dom.Element JavaDoc;
52 import org.w3c.dom.NamedNodeMap JavaDoc;
53 import org.w3c.dom.Node JavaDoc;
54 import org.w3c.dom.NodeList JavaDoc;
55 import org.w3c.dom.Text JavaDoc;
56 import org.w3c.dom.ls.DOMImplementationLS JavaDoc;
57 import org.w3c.dom.ls.LSSerializer JavaDoc;
58 import org.xml.sax.ErrorHandler JavaDoc;
59 import org.xml.sax.SAXException JavaDoc;
60 import org.xml.sax.SAXParseException JavaDoc;
61
62 /**
63  * Miscellaneous helper methods.
64  * @author Jesse Glick, David Konecny
65  */

66 public class Util {
67     
68     private Util() {}
69     
70     // XXX XML methods copied from ant/project... make a general API of these instead?
71

72     /**
73      * Search for an XML element in the direct children of a parent.
74      * DOM provides a similar method but it does a recursive search
75      * which we do not want. It also gives a node list and we want
76      * only one result.
77      * @param parent a parent element
78      * @param name the intended local name
79      * @param namespace the intended namespace
80      * @return the one child element with that name, or null if none or more than one
81      */

82     public static Element JavaDoc findElement(Element JavaDoc parent, String JavaDoc name, String JavaDoc namespace) {
83         Element JavaDoc result = null;
84         NodeList JavaDoc l = parent.getChildNodes();
85         for (int i = 0; i < l.getLength(); i++) {
86             if (l.item(i).getNodeType() == Node.ELEMENT_NODE) {
87                 Element JavaDoc el = (Element JavaDoc)l.item(i);
88                 if (name.equals(el.getLocalName()) && namespace.equals(el.getNamespaceURI())) {
89                     if (result == null) {
90                         result = el;
91                     } else {
92                         return null;
93                     }
94                 }
95             }
96         }
97         return result;
98     }
99     
100     /**
101      * Extract nested text from an element.
102      * Currently does not handle coalescing text nodes, CDATA sections, etc.
103      * @param parent a parent element
104      * @return the nested text, or null if none was found
105      */

106     public static String JavaDoc findText(Element JavaDoc parent) {
107         NodeList JavaDoc l = parent.getChildNodes();
108         for (int i = 0; i < l.getLength(); i++) {
109             if (l.item(i).getNodeType() == Node.TEXT_NODE) {
110                 Text JavaDoc text = (Text JavaDoc)l.item(i);
111                 return text.getNodeValue();
112             }
113         }
114         return null;
115     }
116     
117     /**
118      * Find all direct child elements of an element.
119      * More useful than {@link Element#getElementsByTagNameNS} because it does
120      * not recurse into recursive child elements.
121      * Children which are all-whitespace text nodes are ignored; others cause
122      * an exception to be thrown.
123      * @param parent a parent element in a DOM tree
124      * @return a list of direct child elements (may be empty)
125      * @throws IllegalArgumentException if there are non-element children besides whitespace
126      */

127     public static List JavaDoc<Element JavaDoc> findSubElements(Element JavaDoc parent) throws IllegalArgumentException JavaDoc {
128         NodeList JavaDoc l = parent.getChildNodes();
129         List JavaDoc<Element JavaDoc> elements = new ArrayList JavaDoc<Element JavaDoc>(l.getLength());
130         for (int i = 0; i < l.getLength(); i++) {
131             Node JavaDoc n = l.item(i);
132             if (n.getNodeType() == Node.ELEMENT_NODE) {
133                 elements.add((Element JavaDoc)n);
134             } else if (n.getNodeType() == Node.TEXT_NODE) {
135                 String JavaDoc text = ((Text JavaDoc)n).getNodeValue();
136                 if (text.trim().length() > 0) {
137                     throw new IllegalArgumentException JavaDoc("non-ws text encountered in " + parent + ": " + text); // NOI18N
138
}
139             } else if (n.getNodeType() == Node.COMMENT_NODE) {
140                 // skip
141
} else {
142                 throw new IllegalArgumentException JavaDoc("unexpected non-element child of " + parent + ": " + n); // NOI18N
143
}
144         }
145         return elements;
146     }
147
148     /**
149      * Finds AuxiliaryConfiguration for the given project helper. The method
150      * finds project associated with the helper and searches
151      * AuxiliaryConfiguration in project's lookup.
152      *
153      * @param helper instance of project's AntProjectHelper
154      * @return project's AuxiliaryConfiguration
155      */

156     public static AuxiliaryConfiguration getAuxiliaryConfiguration(AntProjectHelper helper) {
157         try {
158             Project p = ProjectManager.getDefault().findProject(helper.getProjectDirectory());
159             AuxiliaryConfiguration aux = p.getLookup().lookup(AuxiliaryConfiguration.class);
160             assert aux != null;
161             return aux;
162         } catch (IOException JavaDoc e) {
163             ErrorManager.getDefault().notify(e);
164             return null;
165         }
166     }
167
168     /**
169      * Relativize given file against the original project and if needed use
170      * ${project.dir} property as base. If file cannot be relativized
171      * the absolute filepath is returned.
172      * @param projectBase original project base folder
173      * @param freeformBase Freeform project base folder
174      * @param location location to relativize
175      * @return text suitable for storage in project.xml representing given location
176      */

177     public static String JavaDoc relativizeLocation(File JavaDoc projectBase, File JavaDoc freeformBase, File JavaDoc location) {
178         if (CollocationQuery.areCollocated(projectBase, location)) {
179             if (projectBase.equals(freeformBase)) {
180                 return PropertyUtils.relativizeFile(projectBase, location);
181             } else if (projectBase.equals(location) && ProjectConstants.PROJECT_LOCATION_PREFIX.endsWith("/")) { // NOI18N
182
return ProjectConstants.PROJECT_LOCATION_PREFIX.substring(0, ProjectConstants.PROJECT_LOCATION_PREFIX.length() - 1);
183             } else {
184                 return ProjectConstants.PROJECT_LOCATION_PREFIX + PropertyUtils.relativizeFile(projectBase, location);
185             }
186         } else {
187             return location.getAbsolutePath();
188         }
189     }
190
191     /**
192      * Resolve given string value (e.g. "${project.dir}/lib/lib1.jar")
193      * to a File.
194      * @param evaluator evaluator to use for properties resolving
195      * @param freeformProjectBase freeform project base folder
196      * @param val string to be resolved as file
197      * @return resolved File or null if file could not be resolved
198      */

199     public static File JavaDoc resolveFile(PropertyEvaluator evaluator, File JavaDoc freeformProjectBase, String JavaDoc val) {
200         String JavaDoc location = evaluator.evaluate(val);
201         if (location == null) {
202             return null;
203         }
204         return PropertyUtils.resolveFile(freeformProjectBase, location);
205     }
206
207     /**
208      * Returns location of original project base folder. The location can be dirrerent
209      * from NetBeans metadata project folder.
210      * @param helper AntProjectHelper associated with the project
211      * @param evaluator PropertyEvaluator associated with the project
212      * @return location of original project base folder
213      */

214     public static File JavaDoc getProjectLocation(AntProjectHelper helper, PropertyEvaluator evaluator) {
215         //assert ProjectManager.mutex().isReadAccess() || ProjectManager.mutex().isWriteAccess();
216
String JavaDoc loc = evaluator.getProperty(ProjectConstants.PROP_PROJECT_LOCATION);
217         if (loc != null) {
218             return helper.resolveFile(loc);
219         } else {
220             return FileUtil.toFile(helper.getProjectDirectory());
221         }
222     }
223
224     /**
225      * Append child element to the correct position according to given
226      * order.
227      * @param parent parent to which the child will be added
228      * @param el element to be added
229      * @param order order of the elements which must be followed
230      */

231     public static void appendChildElement(Element JavaDoc parent, Element JavaDoc el, String JavaDoc[] order) {
232         Element JavaDoc insertBefore = null;
233         List JavaDoc l = Arrays.asList(order);
234         int index = l.indexOf(el.getLocalName());
235         assert index != -1 : el.getLocalName()+" was not found in "+l; // NOI18N
236
Iterator JavaDoc it = Util.findSubElements(parent).iterator();
237         while (it.hasNext()) {
238             Element JavaDoc e = (Element JavaDoc)it.next();
239             int index2 = l.indexOf(e.getLocalName());
240             assert index2 != -1 : e.getLocalName()+" was not found in "+l; // NOI18N
241
if (index2 > index) {
242                 insertBefore = e;
243                 break;
244             }
245         }
246         parent.insertBefore(el, insertBefore);
247     }
248     
249     /**Get the "default" (user-specified) ant script for the given freeform project.
250      * Please note that this method may return <code>null</code> if there is no such script.
251      *
252      * WARNING: This method is there only for a limited set of usecases like the profiler plugin.
253      * It should not be used by the freeform project natures.
254      *
255      * @param prj the freeform project
256      * @return the "default" ant script or <code>null</code> if there is no such a script
257      * @throws IllegalArgumentException if the passed project is not a freeform project.
258      */

259     public static FileObject getDefaultAntScript(Project prj) throws IllegalArgumentException JavaDoc {
260         ProjectAccessor accessor = prj.getLookup().lookup(ProjectAccessor.class);
261         
262         if (accessor == null) {
263             throw new IllegalArgumentException JavaDoc("Only FreeformProjects are supported.");
264         }
265         
266         return FreeformProjectGenerator.getAntScript(accessor.getHelper(), accessor.getEvaluator());
267     }
268     
269     /**
270      * Convert an XML fragment from one namespace to another.
271      */

272     private static Element JavaDoc translateXML(Element JavaDoc from, String JavaDoc namespace) {
273         Element JavaDoc to = from.getOwnerDocument().createElementNS(namespace, from.getLocalName());
274         NodeList JavaDoc nl = from.getChildNodes();
275         int length = nl.getLength();
276         for (int i = 0; i < length; i++) {
277             Node JavaDoc node = nl.item(i);
278             Node JavaDoc newNode;
279             if (node.getNodeType() == Node.ELEMENT_NODE) {
280                 newNode = translateXML((Element JavaDoc) node, namespace);
281             } else {
282                 newNode = node.cloneNode(true);
283             }
284             to.appendChild(newNode);
285         }
286         NamedNodeMap JavaDoc m = from.getAttributes();
287         for (int i = 0; i < m.getLength(); i++) {
288             Node JavaDoc attr = m.item(i);
289             to.setAttribute(attr.getNodeName(), attr.getNodeValue());
290         }
291         return to;
292     }
293
294     /**
295      * Namespace of data used in {@link #getPrimaryConfigurationData} and {@link #putPrimaryConfigurationData}.
296      * @since org.netbeans.modules.ant.freeform/1 1.15
297      */

298     public static final String JavaDoc NAMESPACE = "http://www.netbeans.org/ns/freeform-project/2"; // NOI18N
299

300     /**
301      * Replacement for {@link AntProjectHelper#getPrimaryConfigurationData}
302      * taking into account the /1 -> /2 upgrade.
303      * @param helper a project helper
304      * @return data in {@link #NAMESPACE}, converting /1 data if needed
305      * @since org.netbeans.modules.ant.freeform/1 1.15
306      */

307     public static Element JavaDoc getPrimaryConfigurationData(final AntProjectHelper helper) {
308         return ProjectManager.mutex().readAccess(new Mutex.Action<Element JavaDoc>() {
309             public Element JavaDoc run() {
310                 AuxiliaryConfiguration ac = helper.createAuxiliaryConfiguration();
311                 Element JavaDoc data = ac.getConfigurationFragment(FreeformProjectType.NAME_SHARED, NAMESPACE, true);
312                 if (data != null) {
313                     return data;
314                 } else {
315                     return translateXML(helper.getPrimaryConfigurationData(true), NAMESPACE);
316                 }
317             }
318         });
319     }
320
321     /**
322      * Replacement for {@link AntProjectHelper#putPrimaryConfigurationData}
323      * taking into account the /1 -> /2 upgrade.
324      * Always pass the /2 data, which will be converted to /1 where legal.
325      * @param helper a project helper
326      * @param data data in {@link #NAMESPACE}
327      * @throws IllegalArgumentException if the incoming data is not in {@link #NAMESPACE}
328      * @since org.netbeans.modules.ant.freeform/1 1.15
329      */

330     public static void putPrimaryConfigurationData(final AntProjectHelper helper, final Element JavaDoc data) {
331         if (!data.getNamespaceURI().equals(FreeformProjectType.NS_GENERAL)) {
332             throw new IllegalArgumentException JavaDoc("Bad namespace"); // NOI18N
333
}
334         ProjectManager.mutex().writeAccess(new Mutex.Action<Void JavaDoc>() {
335             public Void JavaDoc run() {
336                 /* XXX schema validation is apparently broken in JDK 6! (#6529766)
337                 Element dataAs1 = translateXML(data, FreeformProjectType.NS_GENERAL_1);
338                 try {
339                     validate(dataAs1, SCHEMA_1);
340                     putPrimaryConfigurationDataAs1(helper, dataAs1);
341                 } catch (SAXException x1) {
342                     try {
343                         validate(data, SCHEMA_2);
344                         putPrimaryConfigurationDataAs2(helper, data);
345                     } catch (SAXException x2) {
346                         assert false : x2.getMessage() + "; rejected content: " + format(data);
347                         putPrimaryConfigurationDataAs1(helper, dataAs1);
348                     }
349                 }
350                  */

351                 // For now, just hardcode the differences between /1 and /2.
352
if (data.getElementsByTagName("includes").getLength() > 0 || data.getElementsByTagName("excludes").getLength() > 0) {
353                     putPrimaryConfigurationDataAs2(helper, data);
354                 } else {
355                     Element JavaDoc dataAs1 = translateXML(data, FreeformProjectType.NS_GENERAL_1);
356                     putPrimaryConfigurationDataAs1(helper, dataAs1);
357                 }
358                 return null;
359             }
360         });
361     }
362     private static void putPrimaryConfigurationDataAs1(AntProjectHelper helper, Element JavaDoc data) {
363         helper.createAuxiliaryConfiguration().removeConfigurationFragment(FreeformProjectType.NAME_SHARED, NAMESPACE, true);
364         helper.putPrimaryConfigurationData(data, true);
365     }
366     private static void putPrimaryConfigurationDataAs2(AntProjectHelper helper, Element JavaDoc data) {
367         Document JavaDoc doc = data.getOwnerDocument();
368         Element JavaDoc dummy1 = doc.createElementNS(FreeformProjectType.NS_GENERAL_1, FreeformProjectType.NAME_SHARED);
369         // Make sure it is not invalid.
370
dummy1.appendChild(doc.createElementNS(FreeformProjectType.NS_GENERAL_1, "name")). // NOI18N
371
appendChild(doc.createTextNode(findText(findElement(data, "name", NAMESPACE)))); // NOI18N
372
helper.putPrimaryConfigurationData(dummy1, true);
373         helper.createAuxiliaryConfiguration().putConfigurationFragment(data, true);
374     }
375     private static final Schema JavaDoc SCHEMA_1, SCHEMA_2;
376     static {
377         try {
378             SchemaFactory JavaDoc f = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
379             SCHEMA_1 = f.newSchema(FreeformProject.class.getResource("resources/freeform-project-general.xsd")); // NOI18N
380
SCHEMA_2 = f.newSchema(FreeformProject.class.getResource("resources/freeform-project-general-2.xsd")); // NOI18N
381
} catch (SAXException JavaDoc e) {
382             throw new ExceptionInInitializerError JavaDoc(e);
383         }
384     }
385     private static void validate(Element JavaDoc data, Schema JavaDoc schema) throws SAXException JavaDoc {
386         Validator JavaDoc v = schema.newValidator();
387         final SAXException JavaDoc[] error = {null};
388         v.setErrorHandler(new ErrorHandler JavaDoc() {
389             public void warning(SAXParseException JavaDoc x) throws SAXException JavaDoc {}
390             public void error(SAXParseException JavaDoc x) throws SAXException JavaDoc {
391                 // Just rethrowing it is bad because it will also print it to stderr.
392
error[0] = x;
393             }
394             public void fatalError(SAXParseException JavaDoc x) throws SAXException JavaDoc {
395                 error[0] = x;
396             }
397         });
398         try {
399             v.validate(new DOMSource JavaDoc(data));
400         } catch (IOException JavaDoc x) {
401             assert false : x;
402         }
403         if (error[0] != null) {
404             throw error[0];
405         }
406     }
407     private static String JavaDoc format(Element JavaDoc data) {
408         LSSerializer JavaDoc ser = ((DOMImplementationLS JavaDoc) data.getOwnerDocument().getImplementation().getFeature("LS", "3.0")).createLSSerializer();
409         try {
410             ser.getDomConfig().setParameter("format-pretty-print", true);
411             ser.getDomConfig().setParameter("xml-declaration", false);
412         } catch (DOMException JavaDoc ignore) {}
413         return ser.writeToString(data);
414     }
415
416 }
417
Popular Tags