View Javadoc

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             //        } if (v instanceof Source) {
258             //              empty.transform((Source)v, new StreamResult(out));
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         //System.out.println("!!!"+f+"is abs="+f.isAbsolute());
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         //System.out.println("refToSource="+o);
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         //System.out.println("refToSource="+o);
633         if (o instanceof InputSource) {
634             return (InputSource) o;
635         } else if (o instanceof File) {
636             return new InputSource(((File) o).getCanonicalPath());
637 
638             // from a string: string will be parsed
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         //System.out.println("refToStyle="+ref+" => "+o);
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         //System.out.println("refToStyle="+ref+" => "+o);
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             //System.err.println("reffering to result, ref="+ref+" within
718             // Context="+context+", got="+o);
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             //System.err.println("reffering to result, ref="+ref+" within
724             // Context="+context+", got="+o);
725             return ((HasResult) o).getResult();
726 
727             /*
728              * } else if (o instanceof ContentHandler) {
729              * //System.err.println("reffering to result, ref="+ref+" within
730              * Context="+context+", got="+o); return new
731              * SAXResult((ContentHandler)o); } else if (o instanceof
732              * DerivationFilter) { //System.err.println("reffering to result,
733              * ref="+ref+" within Context="+context+", got="+o); return new
734              * SAXResult(((DerivationFilter)o).getLXPTreeBuilder());
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  * The contents of this file are subject to the Mozilla Public License Version
802  * 1.1 (the "License"); you may not use this file except in compliance with the
803  * License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
804  * Software distributed under the License is distributed on an "AS IS" basis,
805  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
806  * the specific language governing rights and limitations under the License. The
807  * Original Code is: all this file. The Initial Developer of the Original Code
808  * is: Tomas Pitner, Masaryk University in Brno, Czech Republic. Contributor(s):
809  */