source: MDUTILS/src/eu/clarin/cmdi/mdservice/internal/MDTransformer.java @ 1649

Last change on this file since 1649 was 1649, checked in by vronk, 12 years ago

correcting config-loading / -usage

File size: 12.5 KB
Line 
1package eu.clarin.cmdi.mdservice.internal;
2
3import java.io.BufferedInputStream;
4import java.io.BufferedReader;
5import java.io.ByteArrayInputStream;
6import java.io.ByteArrayOutputStream;
7import java.io.File;
8import java.io.FileInputStream;
9import java.io.IOException;
10import java.io.InputStream;
11import java.io.InputStreamReader;
12import java.io.OutputStream;
13import java.io.Reader;
14import java.io.StringReader;
15import java.io.StringWriter;
16import java.net.URL;
17import java.util.HashMap;
18import java.util.Iterator;
19import java.util.Map;
20import java.util.Properties;
21import java.util.Set;
22import java.util.Map.Entry;
23
24import javax.xml.transform.Transformer;
25import javax.xml.transform.TransformerException;
26import javax.xml.transform.TransformerFactory;
27import javax.xml.transform.stream.StreamResult;
28import javax.xml.transform.stream.StreamSource;
29
30import org.apache.log4j.Logger;
31
32import net.sf.saxon.event.MessageEmitter;
33
34/**
35 * Helper class, encapsulating the xsl-transformations handling.
36 * The contract is, that the requester passes a key, which can be resolved to a xsl-script (momentary mapped in properties: Utils.getConfig())
37 *
38 * Bad things happen, if the key or the appropriate xsl-file do not exist - well the client gets a diagnostic message.
39 *   
40 *
41 * @author vronk
42 *
43 */
44
45public class MDTransformer {
46       
47        private static Logger log = Logger.getLogger("MDTransformer");
48
49        private String transkey;
50        private URL srcFile ;
51        private Map<String, String[]> params;
52       
53        private Properties config;
54        private ClassLoader loader = null;
55       
56               
57        // don't use singleton!! Bad things happen
58        // private MDTransformer singleton;
59        //TransformerFactory tfactory ;
60       
61        //public MDTransformer () {             
62        //      tfactory = TransformerFactory.newInstance();   
63        //}
64       
65        public ClassLoader getLoader(){
66                if (loader == null){
67                        return Utils.class.getClassLoader();
68                }
69                return loader;
70        }
71        public void configure(String configPath){
72                config = Utils.createConfig(configPath, null);
73        }
74        public void configure(Properties _config, ClassLoader _loader){
75                config = _config;
76                loader = _loader;
77        }
78       
79        public URL getSrcFile() {
80                return srcFile;
81        }
82
83        public void setSrcFile(URL srcFile) {
84                this.srcFile = srcFile;
85        }
86
87        /**
88         * This serves the caller (mainly GenericProxyAction.prepare())
89         * to provide/fill the request parameters.
90         * They then get translated to stylesheet-parameters (in SetTransformerParameters()).
91         * @return
92         */
93        public void setParams(Map<String, String[]> map){
94                this.params = map;
95        }
96       
97       
98        public Map<String,String[]> getParams(){
99                return this.params;
100        }
101
102        public Properties getConfig(){
103                if (config == null){ // shouldn't happen  - config should be set by the calling app.
104                                                        // if not - try to use the default config
105                         return Utils.getAppConfig("");
106                }
107                return config;
108        }
109        /**
110         * Get the path to the xsl file from properties, based on the key (aka format-parameter)
111         * @param key
112         * @return
113         * @throws NoStylesheetException - if no matching entry in properties could be found
114         */
115        private String getXSLPath (String key) throws NoStylesheetException {           
116                String xslpath = "";
117                String xslfilename= getConfig().getProperty("xsl." + key);
118               
119                if (xslfilename!=null) {                       
120                        xslpath =  getConfig().getProperty("scripts.path") + xslfilename;
121                } else {
122                        throw new NoStylesheetException("No Stylesheet found for format-key: " + key);
123                }
124                log.debug("xslfile:" + xslpath);
125                return xslpath;
126        }
127        /**
128         * Tries to load the stylesheet based on the key.
129         * This is done in two steps:
130         * 1. try to resolve the key to a path
131         * 2. get the xsl-file as a stream (and establish it as StreamSource)
132         *
133         * @param key The key identifying the stylesheet for the transformation as passed by GenericProxyAction.
134         * @return the stylesheet to be applied (as StreamSource)
135         * @throws NoStylesheetException If the stylesheet could not be located
136         */
137       
138        private StreamSource getXSLStreamSource (String key) throws NoStylesheetException{             
139               
140                InputStream xslstream;
141                       
142                //URL myURL = new URL (getXSLPath(key));
143                //xslstream = myURL.openStream();
144                String xslPath = getXSLPath(key);
145                xslstream = getLoader().getResourceAsStream(xslPath);
146                StreamSource streamSource = new StreamSource(xslstream);
147
148                streamSource.setSystemId(getLoader().getResource(xslPath).toString());
149                return streamSource ;   
150               
151        }
152
153        public void setTranskey(String key){
154                transkey = key;
155        }
156       
157        public String getTranskey(){
158                //return params.get("x-cmd-format")[0];
159                if (transkey == null & params.containsKey("fullformat")) {
160                        transkey = params.get("fullformat")[0] ;
161                }
162                if (transkey.equals("") & params.containsKey("fullformat")) {
163                        transkey = params.get("fullformat")[0] ;       
164                }
165                return transkey;
166        }
167
168        /**
169         * The main method for transforming, applies the appropriate (based on the transkey) stylesheet on the xml-stream
170         * and writes the result into the output stream.   
171         * @param in InpuStream with xml 
172         * @param transkey this defines the stylesheet to use and is also passed to the stylesheet as "format"-parameter
173         * @param out the stream to write the output to
174         * @throws TransformerException
175         * @throws IOException
176         * @throws NoStylesheetException
177         */
178        public void transformXML (InputStream in, OutputStream out ) throws TransformerException, IOException, NoStylesheetException {
179        //public void transformXML (InputStream in, String transkey, String cols, String startRecord, String maximumRecords, String lang, String q, String repositoryURI, OutputStream out ) throws TransformerException, IOException {
180       
181                        System.setProperty("javax.xml.transform.TransformerFactory", "net.sf.saxon.TransformerFactoryImpl");
182                // Create a transform factory instance.
183                TransformerFactory tfactory = TransformerFactory.newInstance();
184                //OutputStream os = new ByteArrayOutputStream();
185                StreamResult stream = new StreamResult(out);
186               
187                // Create a transformer for the stylesheet.
188                        //String xslpath = getXSLPath(transkey);               
189                Transformer transformer = tfactory.newTransformer(
190                                                                        getXSLStreamSource(getTranskey()));
191                SetTransformerParameters(transformer);
192               
193                //MessageWarner gg = new net.sf.saxon.event.MessageWarner();
194                MessageEmitter me = new net.sf.saxon.event.MessageEmitter();
195                StringWriter w = new StringWriter();
196                me.setWriter(w);
197               ((net.sf.saxon.Controller)transformer).setMessageEmitter(me);//new net.sf.saxon.event.MessageWarner());
198
199               
200                if (srcFile!=null) {
201                       
202                        File f = new File(srcFile.getPath());
203                           
204                        //log.debug("src:" + srcFile.getFile());
205                        //log.debug("fpath:" + f.getAbsolutePath());
206                        String root_uri =  srcFile.toString();
207                        String xsrcfile =  srcFile.getFile();
208                        if  (srcFile.getProtocol().equals("file")) {
209                                root_uri = "file:///" + f.getParent().replace('\\', '/');
210                                xsrcfile = "file:///" + f.getPath().replace('\\', '/');
211                        } 
212                        // TODO repository-path -removed, bad formating
213                        String[] xsrcfiles = xsrcfile.split("&repository=");
214                        String[] root_uris = root_uri.split("&repository=");
215                        xsrcfile = xsrcfiles[0];
216                        root_uri = root_uris[0];
217                        ///
218                       
219                        log.debug("root_uri:" +  root_uri );
220                        log.debug("xsrcfile:" +  xsrcfile );
221                       
222                        transformer.setParameter("root_uri", root_uri );
223                        transformer.setParameter("src_file", xsrcfile);
224                } else {
225                        log.error("transformXML(): srcFile not set!!");                         
226                }
227                //
228                StreamSource src =new StreamSource();                   
229                src.setInputStream(in);
230                // Transform the source XML to out-stream
231                transformer.transform(src, stream );
232               
233                // Write <xsl:message>
234                writeXslMessages(w);
235                ///log.debug(w.getBuffer().toString());         
236   }
237       
238
239        /**
240         * just a wrapper for the main method translating the output-stream into a input-stream (expected by the Controller-Actions to return as response)
241         * @param xmlStream the source xml stream
242         * @param transkey
243         * @return result-stream (converted to InputStream)
244         * @throws IOException
245         * @throws InterruptedException
246         * @throws TransformerException
247         * @throws NoStylesheetException
248         */
249        public InputStream transformXML ( InputStream xmlStream) throws IOException, InterruptedException, TransformerException, NoStylesheetException {
250        //public InputStream transformXML ( InputStream xmlStream, String transkey, String cols, String startRecord, String maximumRecords, String lang, String q, String repositoryURI) throws IOException, InterruptedException, TransformerException {
251               
252                ByteArrayOutputStream out = new ByteArrayOutputStream();
253                transformXML(xmlStream, out);           
254            InputStream transformedStream = new ByteArrayInputStream(out.toByteArray());
255            return transformedStream;
256        }
257       
258        /**
259         * another wrapper for the main method allowing to directly pass a URL to the source-xml   
260         * @param xmlFile URL of the source-file   
261         * @param transkey
262         * @return the result-stream (already converted to an InputStream)
263         * @throws TransformerException
264         * @throws IOException
265         * @throws NoStylesheetException
266         */
267        public InputStream transformXML (URL xmlFile ) throws IOException, InterruptedException, TransformerException, NoStylesheetException {
268        //public InputStream transformXML (URL xmlFile, String transkey ) throws IOException, InterruptedException, TransformerException {
269                srcFile= xmlFile;
270                InputStream  xmlStream =
271             new BufferedInputStream(new FileInputStream(xmlFile.getPath()));
272           
273                return transformXML ( xmlStream); 
274        }
275
276        /**
277         * this is for xml-data present as string (primarily the query string present as XCQL).
278         * if xml in a file or a stream, use the other methods
279         * @param xml xml-data as string
280         * @param transkey
281         * @return
282         * @throws NoStylesheetException
283         * @throws IOException
284         */
285        public String transformXML (String xml) throws NoStylesheetException {
286        //public String transformXML (String xml, String transkey ) {
287                String result="";
288                try {
289                // Create a transform factory instance.
290                        System.setProperty("javax.xml.transform.TransformerFactory", "net.sf.saxon.TransformerFactoryImpl");
291                        //System.setProperty("javax.xml.transform.TransformerFactory", "com.icl.saxon.TransformerFactoryImpl");
292                TransformerFactory tfactory = TransformerFactory.newInstance();
293                OutputStream os = new ByteArrayOutputStream();
294                StreamResult stream = new StreamResult(os);
295                // Create a transformer for the stylesheet.
296                Transformer transformer = tfactory.newTransformer(
297                                                getXSLStreamSource(getTranskey()));
298
299                MessageEmitter me = new net.sf.saxon.event.MessageEmitter();
300                StringWriter w = new StringWriter();
301                me.setWriter(w);
302                ((net.sf.saxon.Controller)transformer).setMessageEmitter(me);//new net.sf.saxon.event.MessageWarner());
303
304                // Transform the source XML to System.out.
305                StreamSource src =new StreamSource();       
306                Reader reader  = new StringReader(xml);
307                src.setReader(reader);
308               
309                transformer.transform(src, stream );
310                                    //  new StreamResult(new File("Simple2.out")));
311             // Write <xsl:message>
312                writeXslMessages(w);
313                 
314                result = os.toString(); 
315               
316                        } catch (TransformerException e) {
317                                e.printStackTrace();
318                        }
319                       
320                        return result;
321        }
322
323        private void writeXslMessages(StringWriter w){
324       
325        byte[] bytes = w.getBuffer().toString().getBytes();
326        InputStream is =  new ByteArrayInputStream(bytes);
327        BufferedReader br = new BufferedReader(new InputStreamReader(is));
328        String s;
329                try {
330                        while ((s = br.readLine()) != null){
331                        log.debug(s);
332                }
333                } catch (IOException e) {
334                        log.error(Utils.errorMessage(e));
335                }
336        }
337
338        /**
339         * Makes the request-parameters available in the stylesheets
340         * by translating them to stylesheet-parameters
341         * @param transformer
342         */
343        public void SetTransformerParameters(Transformer transformer){
344               
345                Set<Entry<String, String[]>> set = params.entrySet();
346                Iterator<Entry<String, String[]>> i = set.iterator();
347
348            while(i.hasNext()){
349              Map.Entry<String,String[]> e = (Map.Entry<String,String[]>)i.next();
350              transformer.setParameter((String)e.getKey(), (String)e.getValue()[0]);
351            }
352        }
353
354       
355        public static HashMap<String,String[]> createParamsMap(String key){
356                HashMap<String,String[]> hm = new HashMap<String,String[]>();
357               
358            if (key != null){
359                String[] arrkey = new String[1];
360                arrkey[0] = key;
361                        hm.put("fullformat", arrkey);                   
362            }
363            return hm;
364        }
365       
366}
Note: See TracBrowser for help on using the repository browser.