001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2004-2006, Geotools Project Managment Committee (PMC)
005: * (C) 2004, TOPP - www.openplans.org
006: *
007: * This library is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU Lesser General Public
009: * License as published by the Free Software Foundation; either
010: * version 2.1 of the License, or (at your option) any later version.
011: *
012: * This library is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: */
017: package org.geotools.validation.xml;
018:
019: import java.io.File;
020: import java.io.IOException;
021: import java.io.Reader;
022: import java.util.ArrayList;
023: import java.util.List;
024: import java.util.logging.Logger;
025:
026: import javax.xml.parsers.DocumentBuilderFactory;
027: import javax.xml.parsers.ParserConfigurationException;
028:
029: import org.w3c.dom.Attr;
030: import org.w3c.dom.Document;
031: import org.w3c.dom.Element;
032: import org.w3c.dom.Node;
033: import org.w3c.dom.NodeList;
034: import org.xml.sax.InputSource;
035: import org.xml.sax.SAXException;
036:
037: /**
038: * ReaderUtils purpose.
039: *
040: * <p>
041: * This class is intended to be used as a library of XML relevant operation for
042: * the XMLConfigReader class.
043: * </p>
044: *
045: * <p></p>
046: *
047: * @author dzwiers, Refractions Research, Inc.
048: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/extension/validation/src/main/java/org/geotools/validation/xml/ReaderUtils.java $
049: * @version $Id: ReaderUtils.java 27862 2007-11-12 19:51:19Z desruisseaux $
050: *
051: * @see XMLConfigReader
052: */
053: class ReaderUtils {
054: /** Used internally to create log information to detect errors. */
055: private static final Logger LOGGER = org.geotools.util.logging.Logging
056: .getLogger("org.vfny.geoserver.global");
057:
058: /**
059: * ReaderUtils constructor.
060: *
061: * <p>
062: * Static class, this should never be called.
063: * </p>
064: */
065: private ReaderUtils() {
066: }
067:
068: /**
069: * loadConfig purpose.
070: *
071: * <p>
072: * Parses the specified file into a DOM tree.
073: * </p>
074: *
075: * @param configFile The file to parse int a DOM tree.
076: *
077: * @return the resulting DOM tree
078: *
079: * @throws ParserConfigurationException DOCUMENT ME!
080: * @throws ParserConfigurationException
081: * @throws SAXException DOCUMENT ME!
082: */
083: public static Element loadConfig(Reader configFile)
084: throws IOException, ParserConfigurationException,
085: SAXException {
086: LOGGER.finest("loading configuration file " + configFile);
087:
088: InputSource in = new InputSource(configFile);
089: DocumentBuilderFactory dfactory = DocumentBuilderFactory
090: .newInstance();
091: dfactory.setNamespaceAware(true);
092:
093: // TODO turn on validation
094: dfactory.setValidating(false);
095: dfactory.setIgnoringComments(true);
096: dfactory.setCoalescing(true);
097: dfactory.setIgnoringElementContentWhitespace(true);
098:
099: Document serviceDoc = dfactory.newDocumentBuilder().parse(in);
100: Element configElem = serviceDoc.getDocumentElement();
101:
102: return configElem;
103: }
104:
105: /**
106: * initFile purpose.
107: *
108: * <p>
109: * Checks to ensure the file is valid. Returns the file passed in to allow
110: * this to wrap file creations.
111: * </p>
112: *
113: * @param f A file Handle to test.
114: * @param isDir true when the File passed in is expected to be a directory,
115: * false when the handle is expected to be a file.
116: *
117: * @return the File handle passed in
118: *
119: * @throws IOException When the file does not exist or is not the type
120: * specified.
121: */
122: public static File initFile(File f, boolean isDir)
123: throws IOException {
124: if (!f.exists()) {
125: throw new IOException(
126: "Path specified does not have a valid file.\n" + f
127: + "\n\n");
128: }
129:
130: if (isDir && !f.isDirectory()) {
131: throw new IOException(
132: "Path specified does not have a valid file.\n" + f
133: + "\n\n");
134: }
135:
136: if (!isDir && !f.isFile()) {
137: throw new IOException(
138: "Path specified does not have a valid file.\n" + f
139: + "\n\n");
140: }
141:
142: LOGGER.fine("File is valid: " + f);
143:
144: return f;
145: }
146:
147: /**
148: * getChildElement purpose.
149: *
150: * <p>
151: * Used to help with XML manipulations. Returns the first child element of
152: * the specified name. An exception occurs when the node is required and
153: * not found.
154: * </p>
155: *
156: * @param root The root element to look for children in.
157: * @param name The name of the child element to look for.
158: * @param mandatory true when an exception should be thrown if the child
159: * element does not exist.
160: *
161: * @return The child element found, null if not found.
162: *
163: * @throws SAXException When a child element is required and not found.
164: */
165: public static Element getChildElement(Element root, String name,
166: boolean mandatory) throws SAXException {
167: Node child = root.getFirstChild();
168:
169: while (child != null) {
170: if (child.getNodeType() == Node.ELEMENT_NODE) {
171: if (name.equals(child.getNodeName())) {
172: return (Element) child;
173: }
174: }
175:
176: child = child.getNextSibling();
177: }
178:
179: if (mandatory && (child == null)) {
180: throw new SAXException(root.getNodeName()
181: + " does not contains a child element named "
182: + name);
183: }
184:
185: return null;
186: }
187:
188: /**
189: * getChildElement purpose.
190: *
191: * <p>
192: * Used to help with XML manipulations. Returns the first child element of
193: * the specified name.
194: * </p>
195: *
196: * @param root The root element to look for children in.
197: * @param name The name of the child element to look for.
198: *
199: * @return The child element found, null if not found.
200: *
201: * @see getChildElement(Element,String,boolean)
202: */
203: public static Element getChildElement(Element root, String name) {
204: try {
205: return getChildElement(root, name, false);
206: } catch (SAXException e) {
207: //will never be here.
208: return null;
209: }
210: }
211:
212: /**
213: * getIntAttribute purpose.
214: *
215: * <p>
216: * Used to help with XML manipulations. Returns the first child integer
217: * attribute of the specified name. An exception occurs when the node is
218: * required and not found.
219: * </p>
220: *
221: * @param elem The root element to look for children in.
222: * @param attName The name of the attribute to look for.
223: * @param mandatory true when an exception should be thrown if the
224: * attribute element does not exist.
225: * @param defaultValue a default value to return incase the attribute was
226: * not found. mutually exclusive with the ConfigurationException
227: * thrown.
228: *
229: * @return The int value if the attribute was found, the default otherwise.
230: *
231: * @throws SAXException When a attribute element is required and not found.
232: */
233: public static int getIntAttribute(Element elem, String attName,
234: boolean mandatory, int defaultValue) throws SAXException {
235: String attValue = getAttribute(elem, attName, mandatory);
236:
237: if (!mandatory && (attValue == null)) {
238: return defaultValue;
239: }
240:
241: try {
242: return Integer.parseInt(attValue);
243: } catch (Exception ex) {
244: if (mandatory) {
245: throw new SAXException(attName
246: + " attribute of element " + elem.getNodeName()
247: + " must be an integer, but it's '" + attValue
248: + "'");
249: } else {
250: return defaultValue;
251: }
252: }
253: }
254:
255: /**
256: * getIntAttribute purpose.
257: *
258: * <p>
259: * Used to help with XML manipulations. Returns the first child integer
260: * attribute of the specified name. An exception occurs when the node is
261: * required and not found.
262: * </p>
263: *
264: * @param elem The root element to look for children in.
265: * @param attName The name of the attribute to look for.
266: * @param mandatory true when an exception should be thrown if the
267: * attribute element does not exist.
268: *
269: * @return The value if the attribute was found, the null otherwise.
270: *
271: * @throws SAXException When a child attribute is required and not found.
272: */
273: public static String getAttribute(Element elem, String attName,
274: boolean mandatory) throws SAXException {
275: Attr att = elem.getAttributeNode(attName);
276:
277: String value = null;
278:
279: if (att != null) {
280: value = att.getValue();
281: }
282:
283: if (mandatory) {
284: if (att == null) {
285: throw new SAXException("element " + elem.getNodeName()
286: + " does not contains an attribute named "
287: + attName);
288: } else if ("".equals(value)) {
289: throw new SAXException("attribute " + attName
290: + "in element " + elem.getNodeName()
291: + " is empty");
292: }
293: }
294:
295: return value;
296: }
297:
298: /**
299: * getBooleanAttribute purpose.
300: *
301: * <p>
302: * Used to help with XML manipulations. Returns the first child integer
303: * attribute of the specified name. An exception occurs when the node is
304: * required and not found.
305: * </p>
306: *
307: * @param elem The root element to look for children in.
308: * @param attName The name of the attribute to look for.
309: * @param mandatory true when an exception should be thrown if the
310: * attribute element does not exist.
311: *
312: * @return The value if the attribute was found, the false otherwise.
313: *
314: * @throws SAXException When a child attribute is required and not found.
315: */
316: public static boolean getBooleanAttribute(Element elem,
317: String attName, boolean mandatory) throws SAXException {
318: String value = getAttribute(elem, attName, mandatory);
319:
320: return Boolean.valueOf(value).booleanValue();
321: }
322:
323: /**
324: * getChildText purpose.
325: *
326: * <p>
327: * Used to help with XML manipulations. Returns the first child text value
328: * of the specified element name.
329: * </p>
330: *
331: * @param root The root element to look for children in.
332: * @param childName The name of the attribute to look for.
333: *
334: * @return The value if the child was found, the null otherwise.
335: */
336: public static String getChildText(Element root, String childName) {
337: try {
338: return getChildText(root, childName, false);
339: } catch (SAXException ex) {
340: return null;
341: }
342: }
343:
344: /**
345: * getChildText purpose.
346: *
347: * <p>
348: * Used to help with XML manipulations. Returns the first child text value
349: * of the specified element name. An exception occurs when the node is
350: * required and not found.
351: * </p>
352: *
353: * @param root The root element to look for children in.
354: * @param childName The name of the attribute to look for.
355: * @param mandatory true when an exception should be thrown if the text
356: * does not exist.
357: *
358: * @return The value if the child was found, the null otherwise.
359: *
360: * @throws SAXException When a child attribute is required and not found.
361: */
362: public static String getChildText(Element root, String childName,
363: boolean mandatory) throws SAXException {
364: Element elem = getChildElement(root, childName, mandatory);
365:
366: if (elem != null) {
367: return getElementText(elem, mandatory);
368: } else {
369: if (mandatory) {
370: String msg = "Mandatory child " + childName
371: + "not found in " + " element: " + root;
372:
373: throw new SAXException(msg);
374: }
375:
376: return null;
377: }
378: }
379:
380: /**
381: * getChildText purpose.
382: *
383: * <p>
384: * Used to help with XML manipulations. Returns the text value of the
385: * specified element name.
386: * </p>
387: *
388: * @param elem The root element to look for children in.
389: *
390: * @return The value if the text was found, the null otherwise.
391: */
392: public static String getElementText(Element elem) {
393: try {
394: return getElementText(elem, false);
395: } catch (SAXException ex) {
396: return null;
397: }
398: }
399:
400: /**
401: * getChildText purpose.
402: *
403: * <p>
404: * Used to help with XML manipulations. Returns the text value of the
405: * specified element name. An exception occurs when the node is required
406: * and not found.
407: * </p>
408: *
409: * @param elem The root element to look for children in.
410: * @param mandatory true when an exception should be thrown if the text
411: * does not exist.
412: *
413: * @return The value if the text was found, the null otherwise.
414: *
415: * @throws SAXException When text is required and not found.
416: */
417: public static String getElementText(Element elem, boolean mandatory)
418: throws SAXException {
419: String value = null;
420:
421: LOGGER.finest("getting element text for " + elem);
422:
423: if (elem != null) {
424: Node child;
425:
426: NodeList childs = elem.getChildNodes();
427:
428: int nChilds = childs.getLength();
429:
430: for (int i = 0; i < nChilds; i++) {
431: child = childs.item(i);
432:
433: if (child.getNodeType() == Node.TEXT_NODE) {
434: value = child.getNodeValue();
435:
436: if (mandatory && "".equals(value.trim())) {
437: throw new SAXException(elem.getNodeName()
438: + " text is empty");
439: }
440:
441: break;
442: }
443: }
444:
445: if (mandatory && (value == null)) {
446: throw new SAXException(elem.getNodeName()
447: + " element does not contains text");
448: }
449: } else {
450: throw new SAXException("Argument element can't be null");
451: }
452:
453: return value;
454: }
455:
456: /**
457: * getKeyWords purpose.
458: *
459: * <p>
460: * Used to help with XML manipulations. Returns a list of keywords that
461: * were found.
462: * </p>
463: *
464: * @param keywordsElem The root element to look for children in.
465: *
466: * @return The list of keywords that were found.
467: */
468: public static String[] getKeyWords(Element keywordsElem) {
469: NodeList klist = keywordsElem.getElementsByTagName("keyword");
470: int kCount = klist.getLength();
471: List keywords = new ArrayList(kCount);
472: String kword;
473: Element kelem;
474:
475: for (int i = 0; i < kCount; i++) {
476: kelem = (Element) klist.item(i);
477: kword = getElementText(kelem);
478:
479: if (kword != null) {
480: keywords.add(kword);
481: }
482: }
483:
484: Object[] s = (Object[]) keywords.toArray();
485:
486: if (s == null) {
487: return new String[0];
488: }
489:
490: String[] ss = new String[s.length];
491:
492: for (int i = 0; i < ss.length; i++)
493: ss[i] = s[i].toString();
494:
495: return ss;
496: }
497:
498: /**
499: * getFirstChildElement purpose.
500: *
501: * <p>
502: * Used to help with XML manipulations. Returns the element which
503: * represents the first child.
504: * </p>
505: *
506: * @param root The root element to look for children in.
507: *
508: * @return The element if a child was found, the null otherwise.
509: */
510: public static Element getFirstChildElement(Element root) {
511: Node child = root.getFirstChild();
512:
513: while (child != null) {
514: if (child.getNodeType() == Node.ELEMENT_NODE) {
515: return (Element) child;
516: }
517:
518: child = child.getNextSibling();
519: }
520:
521: return null;
522: }
523:
524: /**
525: * getDoubleAttribute purpose.
526: *
527: * <p>
528: * Used to help with XML manipulations. Returns the first child integer
529: * attribute of the specified name. An exception occurs when the node is
530: * required and not found.
531: * </p>
532: *
533: * @param elem The root element to look for children in.
534: * @param attName The name of the attribute to look for.
535: * @param mandatory true when an exception should be thrown if the
536: * attribute element does not exist.
537: *
538: * @return The double value if the attribute was found, the NaN otherwise.
539: *
540: * @throws SAXException When a attribute element is required and not found.
541: */
542: public static double getDoubleAttribute(Element elem,
543: String attName, boolean mandatory) throws SAXException {
544: String value = getAttribute(elem, attName, mandatory);
545:
546: double d = Double.NaN;
547:
548: if (value != null) {
549: try {
550: d = Double.parseDouble(value);
551: } catch (NumberFormatException ex) {
552: throw new SAXException("Illegal attribute value for "
553: + attName + " in element " + elem.getNodeName()
554: + ". Expected double, but was " + value);
555: }
556: }
557:
558: return d;
559: }
560: }
|