source: MDService2/trunk/MDService2/src/eu/clarin/cmdi/mdservice/action/Cache.java @ 870

Last change on this file since 870 was 870, checked in by gaba, 14 years ago
File size: 14.3 KB
Line 
1package eu.clarin.cmdi.mdservice.action;
2
3import java.io.*;
4import java.net.MalformedURLException;
5import java.net.URL;
6/*import java.io.BufferedWriter;
7import java.io.File;
8import java.io.FileInputStream;
9import java.io.FileNotFoundException;
10import java.io.FileReader;
11import java.io.FileWriter;
12import java.io.IOException;
13import java.io.InputStream;
14import java.io.Writer;
15*/
16import java.util.Date;
17import java.text.DateFormat;
18import java.text.SimpleDateFormat;
19import java.util.Calendar;
20 
21import javax.xml.*;
22import javax.xml.parsers.*;
23import javax.xml.transform.*;
24import javax.xml.transform.sax.*;
25import javax.xml.transform.stream.*;import javax.xml.transform.dom.*;
26import javax.xml.xpath.*;
27
28import org.w3c.dom.*;
29import org.xml.sax.SAXException;
30import org.xml.sax.InputSource;
31import org.apache.commons.lang.StringEscapeUtils; 
32
33
34import eu.clarin.cmdi.mdservice.action.Admin;
35import eu.clarin.cmdi.mdservice.model.Query;
36
37/**
38 * This is a rudimentary caching mechanism.
39 * serializes the inputstream to a file (identifier => filename)
40 * and returns the inpustream based on the identifier
41 * @author master
42 *
43 */
44/* TODO: necessary to maintain own index
45 * for resolution of IDs to filenames
46 */
47
48
49public class Cache {
50        public static String PREFIX = "xc_";
51       
52        public static String USE = "use";
53        public static String REFRESH = "refresh";
54        public static String SKIP= "skip";     
55       
56        private static Cache singleton;
57        private String cachepath; 
58        private String cacheindex_path;
59        private static Integer cachecounter;
60        private static final Integer start_cache = 1;
61       
62        private static Document cacheindex_doc;
63       
64       
65        public Cache () {               
66                cachepath = Admin.getConfig().getProperty("cache.path");
67                cacheindex_path = cachepath + Admin.getConfig().getProperty("cacheindex.file");
68                cachecounter = initCachecounter();
69        }
70       
71        public static Cache getCache() {
72                if (singleton == null) {
73                        singleton = new Cache();
74                } 
75                return singleton;
76        }
77
78        protected void finalize() throws Throwable {       
79            try {               
80                updateCachecounter();
81            } catch(Exception e) {
82            }       
83            finally {           
84                super.finalize();
85                //more code can be written here as per need of application             
86            }
87        }
88       
89        /**
90         * here the external key for the data gets cache-internal counter-id assigned
91         * which is also returned back
92         * can be used (as shorthand instead of the (long) external key) from outside to retrieve the data.
93         * This is primarily meant to be able to reuse the recordset-data, when reading one record. 
94         * @param id
95         * @param instream
96         * @return
97         */
98        public String putInCache(String key_info, InputStream instream) {
99
100                Admin.notifyUser("CACHE.putInCache:"+key_info);
101                Integer c = getCounter();
102                String xc;
103               
104               
105                //update xml_structure
106                Element e = cacheindex_doc.createElement("f");
107                //Attr attr = cacheindex_doc.createAttribute("id");
108                //attr.setValue(c.toString());
109                //e.setNamedItem(attr);
110                e.setAttribute("id", c.toString());
111                String[] key_array = key_info.split("//-");
112               
113                e.setAttribute("type", key_array[0]);
114                if (key_array.length > 1){
115                        String query_str;
116                        if (key_array[0].equals("recordset")){
117                                query_str = transformQuery(key_array[1]);
118                        } else {
119                                query_str = key_array[1];
120                        }
121                        e.setAttribute("query", query_str);
122                }else{
123                        e.setAttribute("query", "");
124                }
125                if (key_array.length > 2){
126                        e.setAttribute("collection", key_array[2]);
127                }else{
128                        e.setAttribute("collection", "");
129                }
130                if (key_array.length > 3){
131                        e.setAttribute("squery", key_array[3]);
132                }else{
133                        e.setAttribute("squery", "");
134                }
135                if (key_array.length > 4){
136                        e.setAttribute("startRecord", key_array[4]);
137                }else{
138                        e.setAttribute("startRecord", "");
139                }
140                if (key_array.length > 5){
141                        e.setAttribute("maximumRecords", key_array[5]);
142                }else{
143                        e.setAttribute("maximumRecords", "");
144                }
145               
146                if (key_array.length > 6){
147                        e.setAttribute("repository", key_array[6]);
148                }else{
149                        e.setAttribute("repository", "");
150                }
151                if (key_array.length > 7){
152                        e.setAttribute("maxDepth", key_array[7]);
153                }else{
154                        e.setAttribute("maxDepth", "");
155                }
156                if (key_array.length > 8){
157                        e.setAttribute("lang", key_array[8]);
158                }else{
159                        e.setAttribute("lang", "");
160                }
161                if (key_array.length > 9){
162                        e.setAttribute("duration", key_array[9]);
163                }else{
164                        e.setAttribute("duration", "");
165                }
166               
167                DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd:hh-mm-ss");
168                e.setAttribute("date", dateFormat.format(new Date()).toString());
169                cacheindex_doc.getFirstChild().appendChild(e);
170               
171                // update XML-counter
172            //Admin.writeToFile(formPath(id + xc),instream);
173               
174                updateCachecounter();
175               
176                xc = PREFIX + key_array[0] + "_" + c.toString();
177                Admin.notifyUser("CACHE.putInCache.filename:" + xc + ".xml");
178                Admin.writeToFile(cachepath + xc + ".xml",instream);
179               
180            return xc;
181        }
182       
183       
184        public InputStream getFromCache(String key_info) {
185                   
186               
187                   File f = new File (formPath(key_info));
188                   Admin.notifyUser("CACHE.getFromCache:"+key_info);
189                   
190                   
191                    if (f.exists()) { // read from file to InputStream;
192                        Admin.notifyUser("CACHE.getFromCache.fromfile:"+f.getName());
193                        InputStream instream;
194                                try {
195                                        instream = new FileInputStream(f); 
196
197                                        return instream;
198                                } catch (FileNotFoundException e) {
199                                        // TODO Auto-generated catch block
200                                        e.printStackTrace();
201                                        return null;
202                                }
203                       
204                    } else { //not cached, my dear
205                        Admin.notifyUser("CACHE.getFromCache: NOT CACHED");
206                        return null;
207                    }       
208        }
209 
210        private String transformQuery (String str) {
211                String transformed;
212                Query query;
213               
214                if (str == null) return "";
215                if (str.trim().length() == 0) return "";
216               
217                // provisional hack, setting simple string to ""
218                query = new Query("", str,"recordset","");
219                if (query.isStatus(Query.PARSEERROR)) {
220                        Admin.notifyUser("Cache.transformQuery.PARSEERROR:" + query.getMsg());
221                        // pass this bad news to the client
222                        //setUserMsg(query.getMsg());
223                        transformed = "";
224                } else {
225                        transformed =  Query.getSimpleQueryString(str);
226                        transformed = StringEscapeUtils.escapeXml(transformed);
227                        //Admin.notifyUser("CACHE.transformQuery:"+transformed);
228                }
229                return transformed;
230        }
231       
232         //TODO: sanitize-key
233        public String formPath (String key_info) {
234                String id="";
235                String path="";
236                String xpath_expr="";
237               
238                String[] key_array = key_info.split("//-");
239                String query_str;               
240               
241                if(key_array.length > 1){
242                        Admin.notifyUser("formPATH- querystring:" + key_array[1]);
243                        if (key_array[0].equals("recordset")){
244                                query_str = this.transformQuery(key_array[1]); 
245                                Admin.notifyUser("formPATH- querystring-transformed:" + query_str);
246                        }
247                        else {
248                                query_str = key_array[1];
249                        }
250                } else {
251                        query_str = "";
252                }
253                xpath_expr = "//index/f[@type='" + key_array[0] + "'";
254                xpath_expr = xpath_expr + " and @query='"+query_str+"'";
255               
256                if (key_array.length > 2){
257                        xpath_expr = xpath_expr + "and @collection='"+key_array[2]+"'";
258                }else{
259                        xpath_expr = xpath_expr + " and @collection=''";
260                }
261                if (key_array.length > 3){
262                        xpath_expr = xpath_expr + "and @squery='"+key_array[3]+"'";
263                }else{
264                        xpath_expr = xpath_expr + " and @squery=''";
265                }
266                if (key_array.length > 4){
267                        xpath_expr = xpath_expr + "and @startRecord='"+key_array[4]+"'";
268                }else{
269                        xpath_expr = xpath_expr + " and @startRecord=''";
270                }
271                if (key_array.length > 5){
272                        xpath_expr = xpath_expr + "and @maximumRecords='"+key_array[5]+"'";
273                }else{
274                        xpath_expr = xpath_expr + " and @maximumRecords=''";
275                }
276               
277                if (key_array.length > 6){
278                        xpath_expr = xpath_expr + "and @repository='"+key_array[6]+"'";
279                }else{
280                        xpath_expr = xpath_expr + " and @repository=''";
281                }
282                if (key_array.length > 7){
283                        xpath_expr = xpath_expr + "and @maxDepth='"+key_array[7]+"'";
284                }else{
285                        xpath_expr = xpath_expr + " and @maxDepth=''";
286                }
287                if (key_array.length > 8){
288                        xpath_expr = xpath_expr + "and @lang='"+key_array[8]+"']";
289                }else{
290                        xpath_expr = xpath_expr + " and @lang='']";
291                }
292               
293                //Admin.notifyUser("formPath:xpath:"+xpath_expr);
294                //creating an XPathFactory:
295        XPathFactory factory = XPathFactory.newInstance();
296        //using this factory to create an XPath object:
297        XPath xpath = factory.newXPath();
298        //XPath object created compiles the XPath expression:
299        XPathExpression expr;
300                try {
301                        expr = xpath.compile(xpath_expr);
302                        //expression is evaluated with respect to a certain context node which is doc.
303                Object result = expr.evaluate(cacheindex_doc, XPathConstants.NODESET);
304                NodeList list = (NodeList) result;
305                if (list.getLength() > 0) {
306                        id = list.item(0).getAttributes().getNamedItem("id").getNodeValue();
307                        path = cachepath + PREFIX + key_array[0] + "_"+id + ".xml";
308                }  else if (list.getLength() > 1){
309                        Admin.notifyUser("formPath ERROR:!!!:multiple paths:"+key_info);
310                       
311                }
312               
313                } catch (XPathExpressionException e) {
314                        // TODO Auto-generated catch block
315                        e.printStackTrace();
316                }
317               
318            return path;
319        }
320       
321        public Integer getCounter () {
322                cachecounter = cachecounter +1 ;
323                return cachecounter;
324        }
325       
326        /**
327         * read counter-integer from file in cache
328         * or start that file
329         * @return
330         */
331        public Integer initCachecounter() {
332               
333                Integer counter = start_cache;
334                boolean init=false;
335                String fname = cacheindex_path;
336                File f = new File (fname);
337               
338                //Admin.notifyUser("initCacheCounter");
339                if (!f.exists()) {
340                                // create new  counter document
341                                DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
342                        DocumentBuilder docBuilder;
343                                try {
344                                        docBuilder = docFactory.newDocumentBuilder();
345                                        cacheindex_doc = docBuilder.newDocument();
346                                        // append root tag <index >
347                                        Element root = (Element) cacheindex_doc.createElement("index");
348                                        root.setAttribute("idcounter", "1");
349                                        cacheindex_doc.appendChild(root);
350                                        writeCachecounter(counter);
351                                       
352                                        //Admin.notifyUser("new document");
353                                } catch (ParserConfigurationException e) {
354                                        // TODO Auto-generated catch block
355                                        e.printStackTrace();
356                                }
357                               
358                        //} catch (IOException e2) {
359                        //      Admin.notifyUser("ERROR creating cache counter");
360                        //      e2.printStackTrace();
361                        //}
362            }
363                else {
364                        try {
365                               
366                        DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
367                        DocumentBuilder docBuilder;
368                                try {
369                                        docBuilder = docFactory.newDocumentBuilder();               
370                                        try {
371                                                        cacheindex_doc = docBuilder.parse(fname);
372                                        } catch (SAXException e) {
373                                                        // TODO Auto-generated catch block
374                                                       
375                                                        e.printStackTrace();
376                                        }
377                                } catch (ParserConfigurationException e) {
378                                                // TODO Auto-generated catch block
379                                                e.printStackTrace();
380                                }
381                               
382                         //read counter
383                         counter = new Integer(cacheindex_doc.getFirstChild().getAttributes().getNamedItem("idcounter").getNodeValue());
384                         init = true;
385                    }  catch (IOException ex){
386                        //Admin.notifyUser("initCacheCounter:" + ex.toString());
387                        ex.printStackTrace();
388                    }
389                }
390               
391            return counter;
392            /*
393              //use buffering, reading one line at a time
394              //FileReader always assumes default encoding is OK!
395                BufferedReader input =  new BufferedReader(new FileReader(f));
396                        try {
397                                String line = null; //not declared within while loop
398                        /*
399                        * readLine is a bit quirky :
400                        * it returns the content of a line MINUS the newline.
401                        * it returns null only for the END of the stream.
402                        * it returns an empty String if two newlines appear in a row.
403                        *
404                        try {
405                                        if (( line = input.readLine()) != null){
406                                                try {
407                                                        counter = new Integer(line);
408                                                } catch (NumberFormatException e) {
409                                                // if not a number, write a number
410                                                        init=true;     
411                                                } 
412                                        } else {
413                                                init=true;
414                                        }
415                                } catch (IOException e) {
416                                        init=true;
417                                }
418                       
419                        if (init) {                                                     
420                            writeCachecounter( start_cache);                                   
421                        }
422                       
423                } finally {
424                input.close();
425             }   
426             */         
427        }
428
429        public void updateCachecounter () {
430                //Admin.notifyUser("CACHEcounter:" + cachecounter);
431            writeCachecounter( cachecounter);
432        }
433        public void writeCachecounter (Integer i) {             
434               
435                // first update <index idcounter>
436                cacheindex_doc.getFirstChild().getAttributes().getNamedItem("idcounter").setNodeValue(i.toString());
437               
438                //Admin.notifyUser("writeCacheCounter:" + i.toString());
439                // write xml
440                Transformer transformer;
441                try {
442                        transformer = TransformerFactory.newInstance().newTransformer();
443                        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
444
445                        //initialize StreamResult with File object to save to file
446                        StreamResult result = new StreamResult(new StringWriter());
447                        DOMSource source = new DOMSource(cacheindex_doc);
448                        try {
449                                transformer.transform(source, result);
450                        } catch (TransformerException e1) {
451                                // TODO Auto-generated catch block
452                                e1.printStackTrace();
453                        }
454
455                        String xmlString = result.getWriter().toString();
456                        //Admin.notifyUser("writeCacheCounter:" + xmlString);
457                        //Admin.writeToFile("", result);
458
459
460                        File f = new File (cacheindex_path);
461                        FileWriter fw;
462                        try {
463                                fw = new FileWriter(f);
464                                try {
465                                        fw.write(xmlString);
466                                        fw.close();
467                                } catch (IOException e) {
468                                        // TODO Auto-generated catch block
469                                        e.printStackTrace();
470                                }       
471                        } catch (IOException e) {
472                                // TODO Auto-generated catch block
473                                e.printStackTrace();
474                        }
475                } catch (TransformerConfigurationException e2) {
476                        // TODO Auto-generated catch block
477                        e2.printStackTrace();
478                } catch (TransformerFactoryConfigurationError e2) {
479                        // TODO Auto-generated catch block
480                        e2.printStackTrace();
481                }
482               
483                       
484
485                /*
486                File f = new File (Admin.getConfig().getProperty("cache.path") + "counter.txt");
487           
488                try {
489                        Writer output = new BufferedWriter(new FileWriter(f));         
490              //FileWriter always assumes default encoding is OK!
491                        try {
492                                output.write( i);
493                        } finally {
494                                output.close();
495                        }       
496                } catch (IOException e) {
497                        // TODO Auto-generated catch block
498                        e.printStackTrace();
499                }
500                */
501        }
502}
Note: See TracBrowser for help on using the repository browser.