source: MDService2/branches/MDService_simple2/src/eu/clarin/cmdi/mdservice/internal/MDTransformer.java @ 1511

Last change on this file since 1511 was 1511, checked in by vronk, 13 years ago

brutal refactoring,
added new packages: proxies, internal,
very much restructured Action hierarchy.
Introduced division Action/Proxy?.
This is a first compiling version.
it's total mess.

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