1/*
2 * Copyright (c) 2001-2003 World Wide Web Consortium, (Massachusetts Institute
3 * of Technology, Institut National de Recherche en Informatique et en
4 * Automatique, Keio University). All Rights Reserved. This program is
5 * distributed under the W3C's Software Intellectual Property License. This
6 * program is distributed in the hope that it will be useful, but WITHOUT ANY
7 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
8 * FOR A PARTICULAR PURPOSE. See W3C License
9 * http://www.w3.org/Consortium/Legal/ for more details.
10 */
11
12
13package org.w3c.domts;
14
15import java.io.File;
16import java.io.IOException;
17import java.io.InputStream;
18import java.lang.reflect.Method;
19import java.net.MalformedURLException;
20import java.net.URL;
21
22import org.w3c.dom.DOMImplementation;
23import org.w3c.dom.Document;
24
25/**
26 * This is an abstract base class for generated DOM tests
27 *
28 */
29public abstract class DOMTest /* wBM: implements EventListener */ {
30  private DOMTestDocumentBuilderFactory factory;
31  private int mutationCount = 0;
32
33  /**
34   * This is the appropriate constructor for tests that make no requirements
35   * on the parser configuration.
36   *
37   * @param factory
38   *            must not be null
39   */
40  public DOMTest(DOMTestDocumentBuilderFactory factory) {
41    if (factory == null) {
42      throw new NullPointerException("factory");
43    }
44    this.factory = factory;
45  }
46
47  /**
48   * This constructor is used by tests that must create a modified document
49   * factory to meet requirements on the parser configuration. setFactory
50   * should be called within the test's constructor.
51   */
52  public DOMTest() {
53    factory = null;
54  }
55
56  /**
57   * Should only be called in the constructor of a derived type.
58   */
59  protected void setFactory(DOMTestDocumentBuilderFactory factory) {
60    this.factory = factory;
61  }
62
63  public boolean hasFeature(String feature, String version) {
64    return factory.hasFeature(feature, version);
65  }
66
67  public boolean hasSetting(DocumentBuilderSetting setting) {
68    return setting.hasSetting(factory);
69  }
70
71  protected DOMTestDocumentBuilderFactory getFactory() {
72    return factory;
73  }
74
75  public DOMImplementation getImplementation() {
76    return factory.getDOMImplementation();
77  }
78
79  private URL resolveURI(String baseURI) throws DOMTestLoadException {
80    String docURI = factory.addExtension(baseURI);
81
82    URL resolvedURI = null;
83    try {
84      resolvedURI = new URL(docURI);
85      if (resolvedURI.getProtocol() != null) {
86        return resolvedURI;
87      }
88    }
89    catch (MalformedURLException ex) {
90      //        throw new DOMTestLoadException(ex);
91    }
92    //
93    //   build a URL for a test file in the JAR
94    //
95    resolvedURI = getClass().getResource("/" + docURI);
96    if (resolvedURI == null) {
97      //
98      //   see if it is an absolute URI
99      //
100      int firstSlash = docURI.indexOf('/');
101      try {
102        if (firstSlash == 0
103            || (firstSlash >= 1
104                && docURI.charAt(firstSlash - 1) == ':')) {
105          resolvedURI = new URL(docURI);
106        }
107        else {
108          //
109          //  try the files/level?/spec directory
110          //
111          String filename = getClass().getPackage().getName();
112          filename =
113              "tests/"
114              + filename.substring(14).replace('.', '/')
115              + "/files/"
116              + docURI;
117          resolvedURI = new java.io.File(filename).toURL();
118        }
119      }
120      catch (MalformedURLException ex) {
121        throw new DOMTestLoadException(ex);
122      }
123    }
124
125    if (resolvedURI == null) {
126      throw new DOMTestLoadException(
127          new java.io.FileNotFoundException(docURI));
128    }
129    return resolvedURI;
130  }
131
132  public String getResourceURI(String href, String scheme, String contentType) throws
133      DOMTestLoadException {
134    if (scheme == null) {
135      throw new NullPointerException("scheme");
136    }
137    if ("file".equals(scheme)) {
138      return resolveURI(href).toString();
139    }
140    if ("http".equals(scheme)) {
141      StringBuffer httpURL = new StringBuffer(
142          System.getProperty("org.w3c.domts.httpbase",
143                             "http://localhost:8080/webdav/"));
144      httpURL.append(href);
145      if ("application/pdf".equals(contentType)) {
146        httpURL.append(".pdf");
147      }
148      else {
149        httpURL.append(".xml");
150      }
151      return httpURL.toString();
152    }
153    throw new DOMTestLoadException(new Exception("Unrecognized URI scheme " +
154                                                 scheme));
155  }
156
157  public String createTempURI(String scheme) throws DOMTestLoadException {
158    if (scheme == null) {
159      throw new NullPointerException("scheme");
160    }
161    if ("file".equals(scheme)) {
162      try {
163        File tempFile = File.createTempFile("domts", ".xml");
164        try {
165          //
166          //   if available use JDK 1.4's File.toURI().toString()
167          //
168          Method method = File.class.getMethod("toURI", (Class<?>) null);
169          Object uri = method.invoke(tempFile, (Class<?>) null);
170          return uri.toString();
171        }
172        catch (NoSuchMethodException ex) {
173          //
174          //   File.toURL is not as robust
175          //
176          URL url = tempFile.toURL();
177          return url.toString();
178        }
179      }
180      catch (Exception ex) {
181        throw new DOMTestLoadException(ex);
182      }
183    }
184    if ("http".equals(scheme)) {
185      String httpBase = System.getProperty("org.w3c.domts.httpbase",
186                                           "http://localhost:8080/webdav/");
187      java.lang.StringBuffer buf = new StringBuffer(httpBase);
188      if (!httpBase.endsWith("/")) {
189          buf.append("/");
190      }
191      buf.append("tmp");
192      buf.append( (new java.util.Random()).nextInt(Integer.MAX_VALUE));
193      buf.append(".xml");
194      return buf.toString();
195    }
196    throw new DOMTestLoadException(new Exception("Unrecognized URI scheme " +
197                                                 scheme));
198  }
199
200  public Document load(String docURI, boolean willBeModified) throws
201      DOMTestLoadException {
202    Document doc = factory.load(resolveURI(docURI));
203    //
204    //   if will be modified is false and doc is an EventTarget
205    //
206    /*
207     * wBM: if (!willBeModified && doc instanceof EventTarget) {
208     * ((EventTarget) doc).addEventListener("DOMSubtreeModified", this,
209     * false); }
210     */
211    return doc;
212  }
213
214  public void preload(String contentType, String docURI, boolean willBeModified) throws
215      DOMTestIncompatibleException {
216    if ("text/html".equals(contentType) ||
217        "application/xhtml+xml".equals(contentType)) {
218      if (docURI.startsWith("staff") || docURI.equals("datatype_normalization")) {
219        throw DOMTestIncompatibleException.incompatibleLoad(docURI, contentType);
220      }
221    }
222  }
223
224  public Object createXPathEvaluator(Document doc) {
225    return factory.createXPathEvaluator(doc);
226  }
227
228  public InputStream createStream(String bytes) throws DOMTestLoadException,
229      IOException {
230    int byteCount = bytes.length() / 2;
231    byte[] array = new byte[byteCount];
232    for (int i = 0; i < byteCount; i++) {
233      array[i] = Byte.parseByte(bytes.substring(i * 2, i * 2 + 2), 16);
234    }
235    return new java.io.ByteArrayInputStream(array);
236  }
237
238  abstract public String getTargetURI();
239
240  public final boolean isCoalescing() {
241    return factory.isCoalescing();
242  }
243
244  public final boolean isExpandEntityReferences() {
245    return factory.isExpandEntityReferences();
246  }
247
248  public final boolean isIgnoringElementContentWhitespace() {
249    return factory.isIgnoringElementContentWhitespace();
250  }
251
252  public final boolean isNamespaceAware() {
253    return factory.isNamespaceAware();
254  }
255
256  public final boolean isValidating() {
257    return factory.isValidating();
258  }
259
260  public final boolean isSigned() {
261    return true;
262  }
263
264  public final boolean isHasNullString() {
265    return true;
266  }
267
268  public final String getContentType() {
269    return factory.getContentType();
270  }
271
272  /**
273   * Implementation of EventListener.handleEvent
274   *
275   * This method is called when a mutation is reported for a document that
276   * was declared to not be modified during testing
277   *
278   * @param evt
279   *            mutation event
280   */
281  /*
282   * wBM: public final void handleEvent(Event evt) { mutationCount++; }
283   */
284
285  public final int getMutationCount() {
286    return mutationCount;
287  }
288
289}
290