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.core.xml;
043:
044: import java.io.*;
045: import java.net.*;
046: import java.util.*;
047: import javax.xml.parsers.*;
048: import javax.xml.parsers.SAXParserFactory;
049: import junit.framework.*;
050: import org.netbeans.core.startup.DOMFactoryImpl;
051: import org.netbeans.core.startup.SAXFactoryImpl;
052: import org.netbeans.junit.*;
053: import org.openide.util.*;
054: import org.xml.sax.*;
055:
056: /**
057: * A test verifying that by default, cheap JDK-default crimson parser is used,
058: * but if you ask for some fancy features, possible better parser is provided.
059: *
060: * @author Nenik
061: */
062: public class FactoriesTest extends NbTestCase {
063: static SAXParserFactory origSAX;
064: static DocumentBuilderFactory origDOM;
065: static {
066: origSAX = SAXParserFactory.newInstance();
067: origDOM = DocumentBuilderFactory.newInstance();
068: SAXFactoryImpl.install();
069: DOMFactoryImpl.install();
070: System
071: .setSecurityManager(new org.netbeans.TopSecurityManager());
072: }
073:
074: /** Creates a new instance of FactoriesTest */
075: public FactoriesTest(String testName) {
076: super (testName);
077: }
078:
079: public static void main(java.lang.String[] args) {
080: junit.textui.TestRunner.run(suite());
081: }
082:
083: public static Test suite() {
084: NbTestSuite suite = new NbTestSuite(FactoriesTest.class);
085: return suite;
086: }
087:
088: protected void setUp() throws Exception {
089: System.setProperty("org.openide.util.Lookup",
090: "org.netbeans.core.xml.FactoriesTest$Lkp");
091: assertNotNull("ErrManager has to be in lookup",
092: org.openide.util.Lookup.getDefault().lookup(
093: ErrManager.class));
094:
095: SAXParserFactory sax = SAXParserFactory.newInstance();
096: if (!(sax instanceof SAXFactoryImpl)) {
097: fail("We expect to see our factory, but was: " + sax);
098: }
099:
100: DocumentBuilderFactory dom = DocumentBuilderFactory
101: .newInstance();
102: if (!(dom instanceof DOMFactoryImpl)) {
103: fail("We expect to see our factory, but was: " + dom);
104: }
105:
106: }
107:
108: /** Check whether factory provides cheap parser by default */
109: public void testCreateCheapSAXParser() throws Exception {
110: SAXParser parser = SAXParserFactory.newInstance()
111: .newSAXParser();
112: assertFalse("JDK-provided parser", testMap.containsKey(parser));
113: }
114:
115: /** Check whether factory provides cheap parser by default */
116: public void testCreateFeaturedSAXParser() throws Exception {
117: String[] features = new String[] { SaxFactory1.class.getName(),
118: SaxFactory2.class.getName(),
119: SaxFactory3.class.getName(),
120: SaxFactory4.class.getName(), };
121:
122: for (int i = 0; i < features.length; i++) {
123: String feature = features[i];
124: SAXParserFactory fact = SAXParserFactory.newInstance();
125: fact.setFeature(feature, true);
126:
127: SAXParser parser = fact.newSAXParser();
128: assertEquals("Parser with feature " + feature, feature,
129: testMap.get(parser));
130: }
131: }
132:
133: /** Check whether factory fails for unsupported feature */
134: public void testCreateNonexistingSAXParser() throws Exception {
135: SAXParserFactory fact = SAXParserFactory.newInstance();
136: try {
137: fact.setFeature("NoNeXiStInGfEaTuRe", true);
138: } catch (Exception e) {
139: return; // OK
140: }
141:
142: fail("Created parser with unsupported feature");
143: }
144:
145: /** Check whether factory provides cheap parser by default */
146: public void testCreateCheapDOMBuilder() throws Exception {
147: DocumentBuilder builder = DocumentBuilderFactory.newInstance()
148: .newDocumentBuilder();
149: assertFalse("JDK-provided builder", testMap
150: .containsKey(builder));
151: }
152:
153: /** Check whether factory provides cheap parser by default */
154: public void testCreateFeaturedDOMBuilder() throws Exception {
155: String[] features = new String[] { DOMFactory1.class.getName(),
156: DOMFactory2.class.getName(),
157: DOMFactory3.class.getName(),
158: DOMFactory4.class.getName(), };
159:
160: for (int i = 0; i < features.length; i++) {
161: String feature = features[i];
162: DocumentBuilderFactory fact = DocumentBuilderFactory
163: .newInstance();
164: fact.setAttribute(feature, "YES");
165:
166: DocumentBuilder builder = fact.newDocumentBuilder();
167: assertEquals("Builder with feature " + feature, feature,
168: testMap.get(builder));
169: }
170: }
171:
172: /** Check whether factory fails for unsupported feature */
173: public void testCreateNonexistingDOMBuilder() throws Exception {
174: DocumentBuilderFactory fact = DocumentBuilderFactory
175: .newInstance();
176: try {
177: fact.setAttribute("NoNeXiStInGfEaTuRe", "YES");
178: } catch (Exception e) {
179: return; // OK
180: }
181:
182: fail("Created builder with unsupported feature");
183: }
184:
185: /** For cases the factories are not on classpath we fallback to
186: * some implementation.
187: */
188: public void testFactoriesAreNotOnClassPath() throws Exception {
189: ClassLoader parent = SAXFactoryImpl.class.getClassLoader();
190: assertNotNull("We have a classloader", parent);
191: parent = parent.getParent();
192: assertNotNull("Still not null", parent);
193:
194: try {
195: Class l = parent.loadClass(SAXFactoryImpl.class.getName());
196: fail("The classloader " + parent
197: + " should not be able to load: " + l);
198: } catch (ClassNotFoundException ex) {
199: // ok, satisfied
200: }
201:
202: CL loader = new CL(parent,
203: FactoriesRunnableHid.class.getName(), getClass()
204: .getResource("FactoriesRunnableHid.class"));
205: Class runnableClass = loader
206: .loadClass(FactoriesRunnableHid.class.getName());
207: assertNotNull(runnableClass);
208: assertFalse("Different class than our",
209: FactoriesRunnableHid.class == runnableClass);
210:
211: Thread.currentThread().setContextClassLoader(loader);
212: Runnable run = (Runnable) runnableClass.newInstance();
213: run.run();
214:
215: /** the runnable also implements map so we can get some values from it ;-) */
216: Map map = (Map) run;
217:
218: Object dom = map.get("dom");
219: Object sax = map.get("sax");
220:
221: assertNotNull("Wants dom", dom);
222: assertNotNull("Wants sax", sax);
223:
224: assertEquals("We should use orignal sax", origSAX.getClass(),
225: sax.getClass());
226: assertEquals("We should use orignal dom", origDOM.getClass(),
227: dom.getClass());
228:
229: }
230:
231: static Map testMap = new WeakHashMap();
232:
233: static class GenericSAXFactory extends SAXParserFactory {
234: String supported;
235: boolean value;
236:
237: GenericSAXFactory() {
238: this .supported = getClass().getName();
239: }
240:
241: public SAXParser newSAXParser()
242: throws ParserConfigurationException, SAXException {
243: SAXParser parser = origSAX.newSAXParser();
244: testMap.put(parser, supported);
245: return parser;
246: }
247:
248: public boolean getFeature(String name)
249: throws ParserConfigurationException,
250: SAXNotRecognizedException, SAXNotSupportedException {
251: if (supported.equals(name))
252: return value;
253: return false;
254: }
255:
256: public void setFeature(String name, boolean value)
257: throws ParserConfigurationException,
258: SAXNotRecognizedException, SAXNotSupportedException {
259: if (supported.equals(name)) {
260: this .value = value;
261: } else {
262: throw new ParserConfigurationException(name
263: + " not supported");
264: }
265: }
266:
267: }
268:
269: public static class SaxFactory1 extends GenericSAXFactory {
270: }
271:
272: public static class SaxFactory2 extends GenericSAXFactory {
273: }
274:
275: public static class SaxFactory3 extends GenericSAXFactory {
276: }
277:
278: public static class SaxFactory4 extends GenericSAXFactory {
279: }
280:
281: static class GenericDOMFactory extends DocumentBuilderFactory {
282: String supported;
283: Object value;
284:
285: GenericDOMFactory() {
286: this .supported = getClass().getName();
287: }
288:
289: public DocumentBuilder newDocumentBuilder()
290: throws ParserConfigurationException {
291: DocumentBuilder builder = origDOM.newDocumentBuilder();
292: testMap.put(builder, supported);
293: return builder;
294: }
295:
296: public java.lang.Object getAttribute(java.lang.String name)
297: throws java.lang.IllegalArgumentException {
298: if (supported.equals(name))
299: return value;
300: return null;
301: }
302:
303: public void setAttribute(java.lang.String name,
304: java.lang.Object value)
305: throws java.lang.IllegalArgumentException {
306: if (supported.equals(name)) {
307: this .value = value;
308: } else {
309: throw new IllegalArgumentException(name
310: + " not supported");
311: }
312: }
313:
314: public boolean getFeature(java.lang.String name)
315: throws javax.xml.parsers.ParserConfigurationException {
316: return false;
317: }
318:
319: public void setFeature(java.lang.String name, boolean value)
320: throws javax.xml.parsers.ParserConfigurationException {
321: }
322: }
323:
324: public static class DOMFactory1 extends GenericDOMFactory {
325: }
326:
327: public static class DOMFactory2 extends GenericDOMFactory {
328: }
329:
330: public static class DOMFactory3 extends GenericDOMFactory {
331: }
332:
333: public static class DOMFactory4 extends GenericDOMFactory {
334: }
335:
336: //
337: // Our fake lookup
338: //
339: public static final class Lkp extends
340: org.openide.util.lookup.AbstractLookup {
341: public Lkp() {
342: this (new org.openide.util.lookup.InstanceContent());
343: }
344:
345: private Lkp(org.openide.util.lookup.InstanceContent ic) {
346: super (ic);
347: ic.add(new ErrManager());
348: ic.add(new SaxFactory1());
349: ic.add(new SaxFactory2());
350: ic.add(new SaxFactory3());
351: ic.add(new SaxFactory4());
352: ic.add(new DOMFactory1());
353: ic.add(new DOMFactory2());
354: ic.add(new DOMFactory3());
355: ic.add(new DOMFactory4());
356: }
357: }
358:
359: //
360: // Logging support
361: //
362: public static final class ErrManager extends
363: org.openide.ErrorManager {
364: public static final StringBuffer messages = new StringBuffer();
365:
366: private String prefix;
367:
368: public ErrManager() {
369: this (null);
370: }
371:
372: public ErrManager(String prefix) {
373: this .prefix = prefix;
374: }
375:
376: public Throwable annotate(Throwable t, int severity,
377: String message, String localizedMessage,
378: Throwable stackTrace, java.util.Date date) {
379: return t;
380: }
381:
382: public Throwable attachAnnotations(Throwable t,
383: org.openide.ErrorManager.Annotation[] arr) {
384: return t;
385: }
386:
387: public org.openide.ErrorManager.Annotation[] findAnnotations(
388: Throwable t) {
389: return null;
390: }
391:
392: public org.openide.ErrorManager getInstance(String name) {
393: return new ErrManager();
394: }
395:
396: public void log(int severity, String s) {
397: if (prefix != null) {
398: messages.append(prefix);
399: messages.append(s);
400: messages.append('\n');
401: }
402: }
403:
404: public void notify(int severity, Throwable t) {
405: log(severity, t.getMessage());
406: }
407:
408: public boolean isNotifiable(int severity) {
409: return prefix != null;
410: }
411:
412: public boolean isLoggable(int severity) {
413: return prefix != null;
414: }
415:
416: } // end of ErrManager
417:
418: /** Our own classloader that loads FactoriesRunnableHid
419: */
420: public static final class CL extends ClassLoader {
421: private String name;
422: private URL url;
423:
424: public CL(ClassLoader parent, String className, URL url) {
425: super (parent);
426: this .name = className;
427: this .url = url;
428: }
429:
430: protected Class findClass(String str)
431: throws ClassNotFoundException {
432: if (str.equals(name)) {
433: try {
434: InputStream is = url.openStream();
435: byte[] arr = new byte[4096];
436: int len = is.read(arr);
437: return defineClass(name, arr, 0, len);
438: } catch (java.io.IOException ex) {
439: throw new ClassNotFoundException(ex.getMessage());
440: }
441: }
442: throw new ClassNotFoundException();
443: }
444:
445: } // end of CL
446: }
|