1 package net.sf.tomp.xtcl;
2
3 import java.io.ByteArrayInputStream;
4 import java.io.File;
5 import java.io.IOException;
6 import java.io.OutputStream;
7 import java.io.PrintStream;
8 import java.util.HashMap;
9 import java.util.Iterator;
10 import java.util.LinkedList;
11 import java.util.List;
12 import java.util.Map;
13 import java.util.Properties;
14 import java.util.Map.Entry;
15
16 import javax.xml.parsers.DocumentBuilder;
17 import javax.xml.parsers.DocumentBuilderFactory;
18 import javax.xml.parsers.ParserConfigurationException;
19 import javax.xml.parsers.SAXParserFactory;
20 import javax.xml.transform.Result;
21 import javax.xml.transform.Source;
22 import javax.xml.transform.Templates;
23 import javax.xml.transform.Transformer;
24 import javax.xml.transform.TransformerConfigurationException;
25 import javax.xml.transform.URIResolver;
26 import javax.xml.transform.dom.DOMResult;
27 import javax.xml.transform.dom.DOMSource;
28 import javax.xml.transform.sax.SAXTransformerFactory;
29 import javax.xml.transform.stream.StreamResult;
30 import javax.xml.transform.stream.StreamSource;
31
32 import net.sf.joost.trax.TransformerFactoryImpl;
33 import net.sf.tomp.xtcl.command.Template;
34 import net.sf.tomp.xtcl.filter.XTFilterFactory;
35 import net.sf.tomp.xtcl.filter.XTFilterFactoryImpl;
36 import net.sf.tomp.xtcl.resolver.XTResolver;
37 import net.sf.tomp.xtcl.resolver.XTResolvingReader;
38 import net.sf.tomp.xtcl.result.HasResult;
39 import net.sf.tomp.xtcl.source.XTSourceFactory;
40 import net.sf.tomp.xtcl.source.XTSourceFactoryImpl;
41
42 import org.w3c.dom.Document;
43 import org.xml.sax.InputSource;
44 import org.xml.sax.XMLFilter;
45
46 /***
47 * Context for compilation, execution, creating XMLReaders, XMLFilters
48 * Resolvers, Transformations etc
49 *
50 * @author tomp
51 */
52 public class Context {
53
54 protected static Class uriResolverClass = XTResolver.class;
55
56 protected static Class resolvingXMLReaderClass = XTResolvingReader.class;
57
58 private Map c;
59
60 private List compilers;
61
62 private DocumentBuilder db;
63
64 private int depth;
65
66 private Transformer empty;
67
68 private TransformerFactoryImpl jtf;
69
70 private PrintStream out;
71
72 private Context previous;
73
74 private File realPath;
75
76 private SAXParserFactory spf;
77
78 private boolean strictPassing;
79
80 private SAXTransformerFactory tf;
81
82 /*** DOCUMENT ME! */
83 private boolean verbose, extraVerbose;
84
85 private XTFilterFactory xff;
86
87 private XTSourceFactory xrf;
88
89 private URIResolver uriResolver;
90
91 /***
92 * Creates a new instance of Context from scratch
93 *
94 * @throws ParserConfigurationException DOCUMENT ME!
95 * @throws TransformerConfigurationException DOCUMENT ME!
96 * @throws IOException DOCUMENT ME!
97 * @throws ClassNotFoundException
98 * @throws IllegalAccessException
99 * @throws InstantiationException
100 */
101 public Context() throws ParserConfigurationException,
102 TransformerConfigurationException, IOException,
103 InstantiationException, IllegalAccessException,
104 ClassNotFoundException {
105 verbose = true;
106 depth = 0;
107 c = new HashMap();
108 db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
109 tf = (SAXTransformerFactory) SAXTransformerFactory.newInstance();
110 spf = SAXParserFactory.newInstance();
111 jtf = new TransformerFactoryImpl();
112 empty = tf.newTransformer();
113 realPath = new File(".");
114 strictPassing = true;
115 xff = new XTFilterFactoryImpl(this, tf, jtf);
116 xrf = new XTSourceFactoryImpl();
117 compilers = new LinkedList();
118 CompilerFactory.createDefaultCompilers(this);
119
120 setResolverToFactories();
121 }
122
123 /***
124 * Creates a new instance of Context, copying all data from the given parent
125 * Context.
126 *
127 * @param p parent Context
128 * @throws ParserConfigurationException DOCUMENT ME!
129 * @throws TransformerConfigurationException DOCUMENT ME!
130 * @throws ClassNotFoundException
131 * @throws IllegalAccessException
132 * @throws InstantiationException
133 */
134 public Context(Context p) throws ParserConfigurationException,
135 TransformerConfigurationException, InstantiationException,
136 IllegalAccessException, ClassNotFoundException {
137 verbose = p.isVerbose();
138 previous = p;
139 c = new HashMap();
140 db = p.getDocumentBuilder();
141 tf = p.getTransformerFactory();
142 jtf = p.getJoostTransformerFactory();
143 empty = p.getEmptyTransformer();
144 out = p.getOut();
145 depth = p.depth + 1;
146 realPath = p.getRealPath();
147 strictPassing = p.isStrictPassing();
148 xff = p.getXTFilterFactory();
149 xff.setContext(this);
150 xrf = p.getXTSourceFactory();
151 compilers = new LinkedList();
152 CompilerFactory.cloneCompilers(p, this);
153 setResolverToFactories();
154 }
155
156 /***
157 * Sets all registered Resolvers All to all known factories.
158 */
159 private void setResolverToFactories() {
160 try {
161 uriResolver = (URIResolver) uriResolverClass.newInstance();
162
163 if (uriResolver instanceof XTResolver) {
164 ((XTResolver) uriResolver).setContext(this);
165 }
166
167 tf.setURIResolver(uriResolver);
168 jtf.setURIResolver(uriResolver);
169 } catch (Exception e) {
170 e.printStackTrace();
171 }
172 }
173
174 /***
175 * Adds a Compiler to the compilers' list at the position 0 {start}
176 * @param comp Compiler to be added
177 */
178 public void addCompiler(Compiler comp) {
179 addCompiler(0, comp);
180 }
181
182 protected void addCompiler(int index, Compiler comp) {
183 compilers.add(index, comp);
184 comp.setContext(this);
185 }
186
187 /***
188 * Removes the first Compiler from the list
189 */
190 public void removeCompiler() {
191 removeCompiler(0);
192 }
193
194 protected void removeCompiler(int index) {
195 if (index < compilers.size()) {
196 compilers.remove(index);
197 } else {
198 return;
199 }
200 }
201
202 /***
203 * Dumps the Context content, i.e. variables
204 *
205 * @param deep dump deeply, i.e. also variables context
206 *
207 * @throws Exception if dump of any variable fails
208 */
209 public void dump(boolean deep) throws Exception {
210 out.println("--- context " + depth + " ---");
211
212 for (Iterator i = c.entrySet().iterator(); i.hasNext();) {
213 Entry me = (Entry) i.next();
214
215 out.println("\nVAR " + me.getKey() + "->" + me.getValue());
216
217 if (deep) {
218 dumpVariable(me.getKey());
219 }
220 }
221
222 out.println("---------------");
223 }
224
225 /***
226 * Dumps not just this Context and also all its ancestors.
227 *
228 * @param deep dump deeply, i.e. also variables context
229 * @throws Exception if dump of any variable fails
230 */
231 public void dumpAll(boolean deep) throws Exception {
232 out.println("=== all contexts ===");
233
234 Context context = this;
235
236 while (context != null) {
237 context.dump(deep);
238 context = context.getPrevious();
239 }
240
241 out.println("====================");
242 }
243
244 /***
245 * Dumps one variable identified by the key.
246 *
247 * @param k the variable key (usually a String name)
248 * @throws Exception if dump of this variable fails,
249 * for example if XML output fails
250 */
251 public void dumpVariable(Object k) throws Exception {
252 Object v = c.get(k);
253
254 if (v instanceof Document) {
255 empty.transform(new DOMSource((Document) v), new StreamResult(out));
256
257
258
259 } else {
260 out.println(v);
261 }
262 }
263
264 /***
265 * Executes a command in the current context
266 *
267 * @param command to be executed
268 * @return return code from execution
269 * @throws Exception if the command fails, an unspecified Exception is
270 * thrown
271 */
272 public int execute(Command command) throws Exception {
273 if (command == null) {
274 return 0;
275 } else {
276 return command.execute(this);
277 }
278 }
279
280 /***
281 * Gets an object from Context - if not found here, recursively recursively
282 * calls get on previous Context
283 *
284 * @param ref the key
285 * @return the object found or null
286 */
287 public Object get(Object ref) {
288 Object o = c.get(ref);
289
290 if ((o == null) && (previous != null)) {
291 return previous.get(ref);
292 } else {
293 return o;
294 }
295 }
296
297 /***
298 * Removes an object from Context
299 *
300 * @param ref the key
301 * @return the object found or null
302 */
303 public Object remove(Object ref) {
304 return c.remove(ref);
305 }
306
307 /***
308 * Returns count of all compilers in this Context
309 * @return count of all compilers in this Context
310 */
311 public int getCompilerCount() {
312 return compilers.size();
313 }
314
315 public Compiler getCompiler() {
316 if (compilers.isEmpty()) {
317 return null;
318 } else {
319 return getCompiler(0);
320 }
321 }
322
323 protected Compiler getCompiler(int index) {
324 return (Compiler) compilers.get(index);
325 }
326
327 /***
328 * returns the context's depth
329 *
330 * @return the context's depth
331 */
332 public int getDepth() {
333 return depth;
334 }
335
336 /***
337 * Returns the DocumentBuilder registered with this Context
338 *
339 * @return DocumentBuilder registered with this Context
340 */
341 public DocumentBuilder getDocumentBuilder() {
342 return db;
343 }
344
345 /***
346 * Returns a do-nothing Transformer.
347 *
348 * @return a do-nothing Transformer
349 */
350 public Transformer getEmptyTransformer() {
351 return empty;
352 }
353
354 /***
355 * Get a File relative to the realPath (current directory)
356 * of this Context. If an absolute filename n is given,
357 * returns directly a File(n).
358 *
359 * @param f the (relative or absolute) file name
360 * @return the File
361 */
362 public File getFile(String n) {
363 File f = new File(n);
364
365
366 if (f.isAbsolute() || f.getPath().startsWith("//")
367 || f.getPath().startsWith("/")) {
368 return f;
369 } else {
370 return new File(getRealPath(), n);
371 }
372 }
373
374 /***
375 * DOCUMENT ME!
376 *
377 * @return DOCUMENT ME!
378 */
379 public TransformerFactoryImpl getJoostTransformerFactory() {
380 return jtf;
381 }
382
383 public Compiler getNextCompiler(Compiler c) {
384 int compilerIndex = compilers.indexOf(c);
385
386 if ((compilerIndex >= 0) && (compilerIndex < (compilers.size() - 1))) {
387 return getCompiler(compilerIndex + 1);
388 } else {
389 return null;
390 }
391 }
392
393 /***
394 * Gets the Context's standard out PrintStream
395 *
396 * @return the Context's standard out PrintStream
397 */
398 public PrintStream getOut() {
399 return out;
400 }
401
402 /***
403 * Returns the previous (parent) Context
404 *
405 * @return the previous (parent) Context
406 */
407 public Context getPrevious() {
408 return previous;
409 }
410
411 /***
412 * Returns the Context's real path (root directory)
413 * used to resolve relative filenames
414 *
415 * @return the Context's real path
416 */
417 public File getRealPath() {
418 return realPath;
419 }
420
421 /***
422 * Returns the registered SAXParserFactory
423 *
424 * @return the registered SAXParserFactory
425 */
426 public SAXParserFactory getSAXParserFactory() {
427 return spf;
428 }
429
430 /***
431 * Returns the registered SAXTransformerFactory
432 *
433 * @return the registered SAXTransformerFactory
434 */
435 public SAXTransformerFactory getTransformerFactory() {
436 return tf;
437 }
438
439 /***
440 * DOCUMENT ME!
441 *
442 * @return DOCUMENT ME!
443 */
444 public XTFilterFactory getXTFilterFactory() {
445 return xff;
446 }
447
448 /***
449 * DOCUMENT ME!
450 *
451 * @return DOCUMENT ME!
452 */
453 public XTSourceFactory getXTSourceFactory() {
454 return xrf;
455 }
456
457 /***
458 * Is the parameter passing strict?
459 *
460 * @return true iff parameter passing is strict
461 */
462 public boolean isStrictPassing() {
463 return strictPassing;
464 }
465
466 /***
467 * @return Returns the verbose.
468 */
469 public boolean isVerbose() {
470 return verbose;
471 }
472
473 /***
474 * DOCUMENT ME!
475 *
476 * @param ref DOCUMENT ME!
477 * @param value DOCUMENT ME!
478 */
479 public void put(Object ref, Object value) {
480 c.put(ref, value);
481 }
482
483 /***
484 * DOCUMENT ME!
485 *
486 * @param o DOCUMENT ME!
487 */
488 public void setOut(PrintStream o) {
489 out = o;
490 }
491
492 /***
493 * DOCUMENT ME!
494 *
495 * @param f DOCUMENT ME!
496 */
497 public void setRealPath(File f) {
498 realPath = f;
499 }
500
501 /***
502 * Sets the parameter passing to be strict
503 *
504 * @param b DOCUMENT ME!
505 */
506 public void setStrictPassing(boolean b) {
507 strictPassing = b;
508 }
509
510 /***
511 * @param verbose The verbose to set.
512 */
513 public void setVerbose(boolean verbose) {
514 this.verbose = verbose;
515 }
516
517 /***
518 * DOCUMENT ME!
519 *
520 * @param f DOCUMENT ME!
521 */
522 public void setXTFilterFactory(XTFilterFactory f) {
523 xff = f;
524 }
525
526 /***
527 * DOCUMENT ME!
528 *
529 * @param ref DOCUMENT ME!
530 * @param context DOCUMENT ME!
531 * @return DOCUMENT ME!
532 * @throws IllegalArgumentException DOCUMENT ME!
533 */
534 public File refToFile(Object ref) {
535 Object o = get(ref);
536
537 if (o instanceof File) {
538 return (File) o;
539 } else if (o instanceof String) {
540 return new File(getRealPath(), (String) o);
541 } else {
542 throw new IllegalArgumentException("refToFile=" + ref
543 + " has not pointed to File/String but to " + o
544 + " in Context=" + this);
545 }
546 }
547
548 public Properties refToProperties(Object ref) {
549 Object o = get(ref);
550
551 if (o instanceof Properties) {
552 return (Properties) o;
553 } else {
554 throw new IllegalArgumentException("refToProperties=" + ref
555 + " has not pointed to Properties but to " + o
556 + " in Context=" + this);
557 }
558 }
559
560 public Template refToTemplate(Object ref) {
561 Object o = get(ref);
562
563 if (o instanceof Template) {
564 return (Template) o;
565 } else {
566 throw new IllegalArgumentException("refToTemplate=" + ref
567 + " has not pointed to Template but to " + o
568 + " in Context=" + this);
569 }
570 }
571
572 /***
573 * DOCUMENT ME!
574 *
575 * @param ref DOCUMENT ME!
576 * @param context DOCUMENT ME!
577 * @return DOCUMENT ME!
578 * @throws IllegalArgumentException DOCUMENT ME!
579 */
580 public XMLFilter refToXMLFilter(Object ref) {
581 Object o = get(ref);
582
583 if (o instanceof XMLFilter) {
584 return (XMLFilter) o;
585 } else {
586 throw new IllegalArgumentException("refToXMLFilter=" + ref
587 + " has not pointed to XMLFilter but to " + o
588 + " in Context=" + this);
589 }
590 }
591
592 /***
593 * DOCUMENT ME!
594 *
595 * @param ref DOCUMENT ME!
596 * @param context DOCUMENT ME!
597 * @return DOCUMENT ME!
598 * @throws IllegalArgumentException DOCUMENT ME!
599 */
600 public Source refToSource(Object ref) {
601 Object o = get(ref);
602
603
604 if (o instanceof Source) {
605 return (Source) o;
606 } else if (o instanceof Document) {
607 return new DOMSource((Document) o);
608 } else if (o instanceof File) {
609 return new StreamSource((File) o);
610 } else if (o instanceof String) {
611 return new StreamSource(new ByteArrayInputStream(((String) o)
612 .getBytes()));
613 } else {
614 throw new IllegalArgumentException("refToSource=" + ref
615 + " has not pointed to Source/Document/String/File but to "
616 + o + " in Context=" + this);
617 }
618 }
619
620 /***
621 * DOCUMENT ME!
622 *
623 * @param ref DOCUMENT ME!
624 * @param context DOCUMENT ME!
625 * @return DOCUMENT ME!
626 * @throws IOException DOCUMENT ME!
627 * @throws IllegalArgumentException DOCUMENT ME!
628 */
629 public InputSource refToInputSource(Object ref) throws IOException {
630 Object o = get(ref);
631
632
633 if (o instanceof InputSource) {
634 return (InputSource) o;
635 } else if (o instanceof File) {
636 return new InputSource(((File) o).getCanonicalPath());
637
638
639 } else if (o instanceof String) {
640 return new InputSource(new ByteArrayInputStream(((String) o)
641 .getBytes()));
642 } else {
643 throw new IllegalArgumentException("refToInputSource=" + ref
644 + " has not pointed to InputSource/String/File but to " + o
645 + " in Context=" + this);
646 }
647 }
648
649 /***
650 * DOCUMENT ME!
651 *
652 * @param ref DOCUMENT ME!
653 * @param context DOCUMENT ME!
654 * @return DOCUMENT ME!
655 * @throws TransformerConfigurationException DOCUMENT ME!
656 */
657 public Templates refToStyle(Object ref)
658 throws TransformerConfigurationException {
659 Object o = get(ref);
660
661
662 if (o instanceof Templates) {
663 return (Templates) o;
664 }
665
666 Source templatesSource = refToSource(ref);
667
668 return getTransformerFactory().newTemplates(templatesSource);
669 }
670
671 /***
672 * DOCUMENT ME!
673 *
674 * @param ref DOCUMENT ME!
675 * @param context DOCUMENT ME!
676 * @return DOCUMENT ME!
677 * @throws TransformerConfigurationException DOCUMENT ME!
678 */
679 public Templates refToJoostStyle(Object ref)
680 throws TransformerConfigurationException {
681 Object o = get(ref);
682
683
684 if (o instanceof net.sf.joost.trax.TemplatesImpl) {
685 return (net.sf.joost.trax.TemplatesImpl) o;
686 }
687
688 Source templatesSource = refToSource(ref);
689
690 return getJoostTransformerFactory().newTemplates(templatesSource);
691 }
692
693 /***
694 * public Object refToTransformParam(Object ref, Context context) { Object o =
695 * context.get(ref); //System.out.println("refToTransformParam="+o); if (o
696 * instanceof Document) { return new DOMSource((Document)o); } else if (o
697 * instanceof File) { return new StreamSource((File)o); } return o; }
698 *
699 * @param ref DOCUMENT ME!
700 * @param context DOCUMENT ME!
701 * @return DOCUMENT ME!
702 * @throws IllegalArgumentException DOCUMENT ME!
703 */
704 public Result refToResult(Object ref) {
705 Object o = get(ref);
706
707 if (o == null) {
708 DocumentBuilder db = getDocumentBuilder();
709 Document doc = db.newDocument();
710
711 put(ref, doc);
712
713 return new DOMResult(doc);
714 } else if (o instanceof Document) {
715 return new DOMResult((Document) o);
716 } else if (o instanceof File) {
717
718
719 return new StreamResult((File) o);
720 } else if (o instanceof OutputStream) {
721 return new StreamResult((OutputStream) o);
722 } else if (o instanceof HasResult) {
723
724
725 return ((HasResult) o).getResult();
726
727
728
729
730
731
732
733
734
735
736 } else if (o instanceof Result) {
737 return (Result) o;
738 } else {
739 throw new IllegalArgumentException(
740 "refToResult="
741 + ref
742 + " has not pointed to null/Document/File/OutputStream/DerivationFilter/Result but to "
743 + o + " in Context=" + this);
744 }
745 }
746
747 /***
748 * @return Returns the resolvingXMLReaderClass.
749 */
750 public static Class getResolvingXMLReaderClass() {
751 return resolvingXMLReaderClass;
752 }
753
754 /***
755 * @param resolvingXMLReaderClass The resolvingXMLReaderClass to set.
756 */
757 public static void setResolvingXMLReaderClass(Class resolvingXMLReaderClass) {
758 Context.resolvingXMLReaderClass = resolvingXMLReaderClass;
759 }
760
761 /***
762 * @return Returns the uriResolverClass.
763 */
764 public static Class getUriResolverClass() {
765 return uriResolverClass;
766 }
767
768 /***
769 * @param uriResolverClass The uriResolverClass to set.
770 */
771 public static void setUriResolverClass(Class uriResolverClass) {
772 Context.uriResolverClass = uriResolverClass;
773 }
774 /***
775 * @return Returns the extraVerbose.
776 */
777 public boolean isExtraVerbose() {
778 return extraVerbose;
779 }
780 /***
781 * @param extraVerbose The extraVerbose to set.
782 */
783 public void setExtraVerbose(boolean extraVerbose) {
784 this.extraVerbose = extraVerbose;
785 }
786 /***
787 * @return Returns the uriResolver.
788 */
789 public URIResolver getUriResolver() {
790 return uriResolver;
791 }
792 /***
793 * @param uriResolver The uriResolver to set.
794 */
795 public void setUriResolver(URIResolver uriResolver) {
796 this.uriResolver = uriResolver;
797 }
798 }
799
800
801
802
803
804
805
806
807
808
809