001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: *
023: * Free Software Foundation, Inc.
024: * 59 Temple Place, Suite 330
025: * Boston, MA 02111-1307 USA
026: *
027: * @author Sam
028: */
029:
030: package com.caucho.quercus.lib.dom;
031:
032: import com.caucho.quercus.UnimplementedException;
033: import com.caucho.quercus.annotation.Optional;
034: import com.caucho.quercus.annotation.ReturnNullAsFalse;
035: import com.caucho.quercus.env.*;
036: import com.caucho.util.L10N;
037: import com.caucho.vfs.Path;
038: import com.caucho.vfs.ReadStream;
039: import com.caucho.vfs.StringStream;
040: import com.caucho.vfs.TempStream;
041: import com.caucho.vfs.WriteStream;
042: import com.caucho.vfs.Vfs;
043: import com.caucho.xml.XmlPrinter;
044:
045: import org.w3c.dom.Document;
046: import org.xml.sax.SAXException;
047:
048: import java.io.IOException;
049: import java.io.InputStream;
050: import java.util.logging.Level;
051: import java.util.logging.Logger;
052:
053: public class DOMDocument extends DOMNode<Document> {
054: private final static L10N L = new L10N(DOMDocument.class);
055: private final static Logger log = Logger
056: .getLogger(DOMDocument.class.getName());
057:
058: private String _encoding;
059:
060: public static DOMDocument __construct(Env env, @Optional("'1.0'")
061: String version, @Optional
062: String encoding) {
063: DOMDocument document = getImpl(env).createDocument();
064:
065: if (version != null && version.length() > 0)
066: document.setVersion(version);
067:
068: if (encoding != null && encoding.length() > 0)
069: document.setEncoding(encoding);
070:
071: return document;
072: }
073:
074: public void setVersion(String version) {
075: _delegate.setXmlVersion(version);
076: }
077:
078: DOMDocument(DOMImplementation impl, Document document) {
079: super (impl, document);
080: }
081:
082: public String getEncoding() {
083: return _encoding;
084: }
085:
086: public void setEncoding(String encoding) {
087: _encoding = encoding;
088: }
089:
090: public DOMNode adoptNode(DOMNode source) throws DOMException {
091: return wrap(_delegate.adoptNode(source.getDelegate()));
092: }
093:
094: public DOMAttr createAttribute(String name) throws DOMException {
095: try {
096: return wrap(_delegate.createAttribute(name));
097: } catch (org.w3c.dom.DOMException ex) {
098: throw wrap(ex);
099: }
100: }
101:
102: public DOMAttr createAttributeNS(String namespaceURI,
103: String qualifiedName) throws DOMException {
104: try {
105: return wrap(_delegate.createAttributeNS(namespaceURI,
106: qualifiedName));
107: } catch (org.w3c.dom.DOMException ex) {
108: throw wrap(ex);
109: }
110: }
111:
112: public DOMCDATASection createCDATASection(String data) {
113: return wrap(_delegate.createCDATASection(data));
114: }
115:
116: public DOMComment createComment(String data) {
117: return wrap(_delegate.createComment(data));
118: }
119:
120: public DOMDocumentFragment createDocumentFragment() {
121: return wrap(_delegate.createDocumentFragment());
122: }
123:
124: public DOMElement createElement(String tagName) throws DOMException {
125: try {
126: return wrap(_delegate.createElement(tagName));
127: } catch (org.w3c.dom.DOMException ex) {
128: throw wrap(ex);
129: }
130: }
131:
132: public DOMElement createElement(String tagName, String textContent)
133: throws DOMException {
134: try {
135: DOMElement element = createElement(tagName);
136:
137: element.setTextContent(textContent);
138:
139: return element;
140: } catch (org.w3c.dom.DOMException ex) {
141: throw wrap(ex);
142: }
143: }
144:
145: public DOMElement createElementNS(String namespaceURI,
146: String tagName) throws DOMException {
147: try {
148: return wrap(_delegate
149: .createElementNS(namespaceURI, tagName));
150: } catch (org.w3c.dom.DOMException ex) {
151: throw wrap(ex);
152: }
153: }
154:
155: public DOMElement createElementNS(String namespaceURI,
156: String tagName, String textContent) throws DOMException {
157: try {
158: DOMElement element = createElementNS(namespaceURI, tagName);
159:
160: element.setTextContent(textContent);
161:
162: return element;
163: } catch (org.w3c.dom.DOMException ex) {
164: throw wrap(ex);
165: }
166: }
167:
168: public DOMEntityReference createEntityReference(String name)
169: throws DOMException {
170: try {
171: return wrap(_delegate.createEntityReference(name));
172: } catch (org.w3c.dom.DOMException ex) {
173: throw wrap(ex);
174: }
175: }
176:
177: public DOMProcessingInstruction createProcessingInstruction(
178: String target) throws DOMException {
179: try {
180: return createProcessingInstruction(target, null);
181: } catch (org.w3c.dom.DOMException ex) {
182: throw wrap(ex);
183: }
184: }
185:
186: public DOMProcessingInstruction createProcessingInstruction(
187: String target, String data) throws DOMException {
188: try {
189: return wrap(_delegate.createProcessingInstruction(target,
190: data));
191: } catch (org.w3c.dom.DOMException ex) {
192: throw wrap(ex);
193: }
194: }
195:
196: public DOMText createTextNode(String data) {
197: return wrap(_delegate.createTextNode(data));
198: }
199:
200: public DOMConfiguration getConfig() {
201: throw new UnimplementedException();
202: }
203:
204: public DOMDocumentType getDoctype() {
205: return wrap(_delegate.getDoctype());
206: }
207:
208: public DOMElement getDocumentElement() {
209: return wrap(_delegate.getDocumentElement());
210: }
211:
212: public String getDocumentURI() {
213: return _delegate.getDocumentURI();
214: }
215:
216: public DOMConfiguration getDomConfig() {
217: return wrap(_delegate.getDomConfig());
218: }
219:
220: public DOMElement getElementById(String elementId) {
221: return wrap(_delegate.getElementById(elementId));
222: }
223:
224: public DOMNodeList getElementsByTagName(String name) {
225: return wrap(_delegate.getElementsByTagName(name));
226: }
227:
228: public DOMNodeList getElementsByTagNameNS(String uri, String name) {
229: return wrap(_delegate.getElementsByTagNameNS(uri, name));
230: }
231:
232: public boolean getFormatOutput() {
233: throw new UnimplementedException();
234: }
235:
236: public DOMImplementation getImplementation() {
237: return getImpl();
238: }
239:
240: public String getInputEncoding() {
241: return _delegate.getInputEncoding();
242: }
243:
244: public boolean getPreserveWhiteSpace() {
245: throw new UnimplementedException();
246: }
247:
248: public boolean getRecover() {
249: throw new UnimplementedException();
250: }
251:
252: public boolean getResolveExternals() {
253: throw new UnimplementedException();
254: }
255:
256: public boolean getStrictErrorChecking() {
257: return _delegate.getStrictErrorChecking();
258: }
259:
260: public boolean getSubstituteEntities() {
261: throw new UnimplementedException();
262: }
263:
264: public boolean getValidateOnParse() {
265: throw new UnimplementedException();
266: }
267:
268: public String getVersion() {
269: return _delegate.getXmlVersion();
270: }
271:
272: public String getXmlEncoding() {
273: return _delegate.getXmlEncoding();
274: }
275:
276: public boolean getXmlStandalone() {
277: return _delegate.getXmlStandalone();
278: }
279:
280: public String getXmlVersion() {
281: return _delegate.getXmlVersion();
282: }
283:
284: public DOMNode importNode(DOMNode node) {
285: return importNode(node, false);
286: }
287:
288: public DOMNode importNode(DOMNode importedNode, boolean deep)
289: throws DOMException {
290: try {
291: return wrap(_delegate.importNode(
292: importedNode.getDelegate(), deep));
293: } catch (org.w3c.dom.DOMException ex) {
294: throw wrap(ex);
295: }
296: }
297:
298: // XXX: also can be called statically, returns a DOMDocument in that case
299: public boolean load(Env env, Path path, @Optional
300: Value options) throws IOException {
301: if (options != null)
302: env.stub(L.l("`{0}' is ignored", "options"));
303:
304: ReadStream is = null;
305:
306: try {
307: is = path.openRead();
308:
309: getImpl().parseXMLDocument(_delegate, is, path.getPath());
310: } catch (SAXException ex) {
311: env.warning(ex);
312:
313: return false;
314: } catch (IOException ex) {
315: env.warning(ex);
316: return false;
317: } finally {
318: if (is != null) {
319: is.close();
320: }
321: }
322:
323: return true;
324: }
325:
326: /**
327: * @param source A string containing the HTML
328: */
329: // XXX: also can be called statically, returns a DOMDocument in that case
330: public boolean loadHTML(Env env, String source) {
331: ReadStream is = StringStream.open(source);
332:
333: try {
334: getImpl().parseHTMLDocument(_delegate, is, null);
335:
336: _delegate.setXmlStandalone(true);
337:
338: /**
339: * XXX:
340: _delegate.setDoctype(new QDocumentType("html",
341: "-//W3C//DTD HTML 4.0 Transitional//EN",
342: "http://www.w3.org/TR/REC-html40/loose.dtd"));
343: */
344: } catch (SAXException ex) {
345: env.warning(ex);
346: return false;
347: } catch (IOException ex) {
348: env.warning(ex);
349: return false;
350: } finally {
351: if (is != null) {
352: is.close();
353: }
354: }
355:
356: return true;
357: }
358:
359: // XXX: also can be called statically, returns a DOMDocument in that case
360: public boolean loadHTMLFile(Env env, Path path) {
361: ReadStream is = null;
362:
363: try {
364: is = path.openRead();
365:
366: getImpl().parseHTMLDocument(_delegate, is, path.getPath());
367:
368: _delegate.setXmlStandalone(true);
369: /**
370: * XXX:
371: _delegate.setDoctype(new QDocumentType("html",
372: "-//W3C//DTD HTML 4.0 Transitional//EN",
373: "http://www.w3.org/TR/REC-html40/loose.dtd"));
374: */
375: } catch (SAXException ex) {
376: env.warning(ex);
377: return false;
378: } catch (IOException ex) {
379: env.warning(ex);
380: return false;
381: } finally {
382: if (is != null) {
383: is.close();
384: }
385: }
386:
387: return true;
388: }
389:
390: // XXX: also can be called statically, returns a DOMDocument in that case
391: public boolean loadXML(Env env, StringValue source, @Optional
392: Value options) {
393: if (options != null)
394: env.stub(L.l("`{0}' is ignored", "options"));
395:
396: InputStream is = source.toInputStream();
397:
398: try {
399: getImpl().parseXMLDocument(_delegate, Vfs.openRead(is),
400: null);
401: } catch (SAXException ex) {
402: env.warning(ex);
403:
404: return false;
405: } catch (IOException ex) {
406: env.warning(ex);
407: return false;
408: } finally {
409: if (is != null) {
410: try {
411: is.close();
412: } catch (IOException ex) {
413: env.warning(ex);
414: }
415: }
416: }
417:
418: return true;
419: }
420:
421: public void normalizeDocument() {
422: _delegate.normalizeDocument();
423: }
424:
425: public boolean relaxNGValidate(String rngFilename) {
426: throw new UnimplementedException();
427: }
428:
429: public boolean relaxNGValidateSource(String rngSource) {
430: throw new UnimplementedException();
431: }
432:
433: public DOMNode renameNode(DOMNode node, String namespaceURI,
434: String qualifiedName) throws DOMException {
435: try {
436: return wrap(_delegate.renameNode(node.getDelegate(),
437: namespaceURI, qualifiedName));
438: } catch (org.w3c.dom.DOMException ex) {
439: throw wrap(ex);
440: }
441: }
442:
443: /**
444: * @return the number of bytes written, or FALSE for an error
445: */
446: public Value save(Env env, Path path, @Optional
447: Value options) {
448: if (options != null)
449: env.stub(L.l("`{0}' is ignored", "options"));
450:
451: return saveToFile(env, path, false);
452: }
453:
454: private Value saveToFile(Env env, Path path, boolean isHTML) {
455: WriteStream os = null;
456:
457: try {
458: os = path.openWrite();
459: saveToStream(os, isHTML);
460: } catch (IOException ex) {
461: env.warning(ex);
462: return BooleanValue.FALSE;
463: } finally {
464: if (os != null) {
465: try {
466: os.close();
467: } catch (Exception ex) {
468: log.log(Level.FINE, ex.toString(), ex);
469: }
470: }
471: }
472:
473: return new LongValue(path.getLength());
474: }
475:
476: private void saveToStream(WriteStream os, boolean isHTML)
477: throws IOException {
478: XmlPrinter printer = new XmlPrinter(os);
479:
480: printer.setMethod(isHTML ? "html" : "xml");
481:
482: printer.setPrintDeclaration(true);
483:
484: printer.setVersion(_delegate.getXmlVersion());
485: printer.setEncoding(_encoding);
486:
487: if (_delegate.getXmlStandalone())
488: printer.setStandalone("yes");
489:
490: printer.printXml(_delegate);
491:
492: if (hasChildNodes())
493: os.println();
494: }
495:
496: @ReturnNullAsFalse
497: public StringValue saveHTML(Env env) {
498: return saveToString(env, true);
499: }
500:
501: private StringValue saveToString(Env env, boolean isHTML) {
502: TempStream tempStream = new TempStream();
503:
504: try {
505: tempStream.openWrite();
506: WriteStream os = new WriteStream(tempStream);
507:
508: saveToStream(os, isHTML);
509:
510: os.close();
511: } catch (IOException ex) {
512: tempStream.discard();
513: env.warning(ex);
514: return null;
515: }
516:
517: TempBufferBytesValue result = new TempBufferBytesValue(
518: tempStream.getHead());
519:
520: tempStream.discard();
521:
522: return result;
523: }
524:
525: /**
526: * @return the number of bytes written, or FALSE for an error
527: */
528:
529: public Value saveHTMLFile(Env env, Path path) {
530: return saveToFile(env, path, true);
531: }
532:
533: @ReturnNullAsFalse
534: public StringValue saveXML(Env env) {
535: return saveToString(env, false);
536: }
537:
538: public boolean schemaValidate(String schemaFilename) {
539: throw new UnimplementedException();
540: }
541:
542: public boolean schemaValidateSource(String schemaSource) {
543: throw new UnimplementedException();
544: }
545:
546: public void setDocumentURI(String documentURI) {
547: _delegate.setDocumentURI(documentURI);
548: }
549:
550: public void setFormatOutput(boolean formatOutput) {
551: throw new UnimplementedException();
552: }
553:
554: public void setPreserveWhiteSpace(boolean preserveWhiteSpace) {
555: throw new UnimplementedException();
556: }
557:
558: public void setRecover(boolean recover) {
559: throw new UnimplementedException();
560: }
561:
562: public void setResolveExternals(boolean resolveExternals) {
563: throw new UnimplementedException();
564: }
565:
566: public void setStrictErrorChecking(boolean strictErrorChecking) {
567: _delegate.setStrictErrorChecking(strictErrorChecking);
568: }
569:
570: public void setSubstituteEntities(boolean substituteEntities) {
571: throw new UnimplementedException();
572: }
573:
574: public void setValidateOnParse(boolean validateOnParse) {
575: throw new UnimplementedException();
576: }
577:
578: public void setXmlStandalone(boolean xmlStandalone)
579: throws DOMException {
580: _delegate.setXmlStandalone(xmlStandalone);
581: }
582:
583: public void setXmlVersion(String xmlVersion) throws DOMException {
584: _delegate.setXmlVersion(xmlVersion);
585: }
586:
587: public boolean validate() {
588: throw new UnimplementedException();
589: }
590:
591: public int xinclude(Env env, @Optional
592: Value options) {
593: if (options != null)
594: env.stub(L.l("`{0}' is ignored", "options"));
595:
596: throw new UnimplementedException();
597: }
598: }
|