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

Last change on this file since 832 was 832, checked in by gaba, 14 years ago

QUERY(xml,htmlpage,link) - created; cache properties added - repository,lang,maxDepth

File size: 14.2 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               
162                DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd:hh-mm-ss");
163                e.setAttribute("date", dateFormat.format(new Date()).toString());
164                cacheindex_doc.getFirstChild().appendChild(e);
165               
166                // update XML-counter
167            //Admin.writeToFile(formPath(id + xc),instream);
168               
169                updateCachecounter();
170               
171                xc = PREFIX + key_array[0] + "_" + c.toString();
172                Admin.notifyUser("CACHE.putInCache.filename:" + xc + ".xml");
173                Admin.writeToFile(cachepath + xc + ".xml",instream);
174               
175            return xc;
176        }
177       
178       
179        public InputStream getFromCache(String key_info) {
180                   
181               
182                   File f = new File (formPath(key_info));
183                   Admin.notifyUser("CACHE.getFromCache:"+key_info);
184                   
185                   
186                    if (f.exists()) { // read from file to InputStream;
187                        Admin.notifyUser("CACHE.getFromCache.fromfile:"+f.getName());
188                        InputStream instream;
189                                try {
190                                        instream = new FileInputStream(f); 
191
192                                        return instream;
193                                } catch (FileNotFoundException e) {
194                                        // TODO Auto-generated catch block
195                                        e.printStackTrace();
196                                        return null;
197                                }
198                       
199                    } else { //not cached, my dear
200                        Admin.notifyUser("CACHE.getFromCache: NOT CACHED");
201                        return null;
202                    }       
203        }
204 
205        private String transformQuery (String str) {
206                String transformed;
207                Query query;
208               
209                if (str == null) return "";
210                if (str.trim().length() == 0) return "";
211               
212                // provisional hack, setting simple string to ""
213                query = new Query("", str,"recordset","");
214                if (query.isStatus(Query.PARSEERROR)) {
215                        Admin.notifyUser("Cache.transformQuery.PARSEERROR:" + query.getMsg());
216                        // pass this bad news to the client
217                        //setUserMsg(query.getMsg());
218                        transformed = "";
219                } else {
220                        transformed =  Query.getSimpleQueryString(str);
221                        transformed = StringEscapeUtils.escapeXml(transformed);
222                        //Admin.notifyUser("CACHE.transformQuery:"+transformed);
223                }
224                return transformed;
225        }
226       
227         //TODO: sanitize-key
228        public String formPath (String key_info) {
229                String id="";
230                String path="";
231                String xpath_expr="";
232               
233                String[] key_array = key_info.split("//-");
234                String query_str;               
235               
236                if(key_array.length > 1){
237                        Admin.notifyUser("formPATH- querystring:" + key_array[1]);
238                        if (key_array[0].equals("recordset")){
239                                query_str = this.transformQuery(key_array[1]); 
240                                Admin.notifyUser("formPATH- querystring-transformed:" + query_str);
241                        }
242                        else {
243                                query_str = key_array[1];
244                        }
245                } else {
246                        query_str = "";
247                }
248                xpath_expr = "//index/f[@type='" + key_array[0] + "'";
249                xpath_expr = xpath_expr + " and @query='"+query_str+"'";
250               
251                if (key_array.length > 2){
252                        xpath_expr = xpath_expr + "and @collection='"+key_array[2]+"'";
253                }else{
254                        xpath_expr = xpath_expr + " and @collection=''";
255                }
256                if (key_array.length > 3){
257                        xpath_expr = xpath_expr + "and @squery='"+key_array[3]+"'";
258                }else{
259                        xpath_expr = xpath_expr + " and @squery=''";
260                }
261                if (key_array.length > 4){
262                        xpath_expr = xpath_expr + "and @startRecord='"+key_array[4]+"'";
263                }else{
264                        xpath_expr = xpath_expr + " and @startRecord=''";
265                }
266                if (key_array.length > 5){
267                        xpath_expr = xpath_expr + "and @maximumRecords='"+key_array[5]+"'";
268                }else{
269                        xpath_expr = xpath_expr + " and @maximumRecords=''";
270                }
271               
272                if (key_array.length > 6){
273                        xpath_expr = xpath_expr + "and @repository='"+key_array[6]+"'";
274                }else{
275                        xpath_expr = xpath_expr + " and @repository=''";
276                }
277                if (key_array.length > 7){
278                        xpath_expr = xpath_expr + "and @maxDepth='"+key_array[7]+"'";
279                }else{
280                        xpath_expr = xpath_expr + " and @maxDepth=''";
281                }
282                if (key_array.length > 8){
283                        xpath_expr = xpath_expr + "and @lang='"+key_array[8]+"']";
284                }else{
285                        xpath_expr = xpath_expr + " and @lang='']";
286                }
287               
288                //Admin.notifyUser("formPath:xpath:"+xpath_expr);
289                //creating an XPathFactory:
290        XPathFactory factory = XPathFactory.newInstance();
291        //using this factory to create an XPath object:
292        XPath xpath = factory.newXPath();
293        //XPath object created compiles the XPath expression:
294        XPathExpression expr;
295                try {
296                        expr = xpath.compile(xpath_expr);
297                        //expression is evaluated with respect to a certain context node which is doc.
298                Object result = expr.evaluate(cacheindex_doc, XPathConstants.NODESET);
299                NodeList list = (NodeList) result;
300                if (list.getLength() > 0) {
301                        id = list.item(0).getAttributes().getNamedItem("id").getNodeValue();
302                        path = cachepath + PREFIX + key_array[0] + "_"+id + ".xml";
303                }  else if (list.getLength() > 1){
304                        Admin.notifyUser("formPath ERROR:!!!:multiple paths:"+key_info);
305                       
306                }
307               
308                } catch (XPathExpressionException e) {
309                        // TODO Auto-generated catch block
310                        e.printStackTrace();
311                }
312               
313            return path;
314        }
315       
316        public Integer getCounter () {
317                cachecounter = cachecounter +1 ;
318                return cachecounter;
319        }
320       
321        /**
322         * read counter-integer from file in cache
323         * or start that file
324         * @return
325         */
326        public Integer initCachecounter() {
327               
328                Integer counter = start_cache;
329                boolean init=false;
330                String fname = cacheindex_path;
331                File f = new File (fname);
332               
333                //Admin.notifyUser("initCacheCounter");
334                if (!f.exists()) {
335                                // create new  counter document
336                                DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
337                        DocumentBuilder docBuilder;
338                                try {
339                                        docBuilder = docFactory.newDocumentBuilder();
340                                        cacheindex_doc = docBuilder.newDocument();
341                                        // append root tag <index >
342                                        Element root = (Element) cacheindex_doc.createElement("index");
343                                        root.setAttribute("idcounter", "1");
344                                        cacheindex_doc.appendChild(root);
345                                        writeCachecounter(counter);
346                                       
347                                        //Admin.notifyUser("new document");
348                                } catch (ParserConfigurationException e) {
349                                        // TODO Auto-generated catch block
350                                        e.printStackTrace();
351                                }
352                               
353                        //} catch (IOException e2) {
354                        //      Admin.notifyUser("ERROR creating cache counter");
355                        //      e2.printStackTrace();
356                        //}
357            }
358                else {
359                        try {
360                               
361                        DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
362                        DocumentBuilder docBuilder;
363                                try {
364                                        docBuilder = docFactory.newDocumentBuilder();               
365                                        try {
366                                                        cacheindex_doc = docBuilder.parse(fname);
367                                        } catch (SAXException e) {
368                                                        // TODO Auto-generated catch block
369                                                       
370                                                        e.printStackTrace();
371                                        }
372                                } catch (ParserConfigurationException e) {
373                                                // TODO Auto-generated catch block
374                                                e.printStackTrace();
375                                }
376                               
377                         //read counter
378                         counter = new Integer(cacheindex_doc.getFirstChild().getAttributes().getNamedItem("idcounter").getNodeValue());
379                         init = true;
380                    }  catch (IOException ex){
381                        //Admin.notifyUser("initCacheCounter:" + ex.toString());
382                        ex.printStackTrace();
383                    }
384                }
385               
386            return counter;
387            /*
388              //use buffering, reading one line at a time
389              //FileReader always assumes default encoding is OK!
390                BufferedReader input =  new BufferedReader(new FileReader(f));
391                        try {
392                                String line = null; //not declared within while loop
393                        /*
394                        * readLine is a bit quirky :
395                        * it returns the content of a line MINUS the newline.
396                        * it returns null only for the END of the stream.
397                        * it returns an empty String if two newlines appear in a row.
398                        *
399                        try {
400                                        if (( line = input.readLine()) != null){
401                                                try {
402                                                        counter = new Integer(line);
403                                                } catch (NumberFormatException e) {
404                                                // if not a number, write a number
405                                                        init=true;     
406                                                } 
407                                        } else {
408                                                init=true;
409                                        }
410                                } catch (IOException e) {
411                                        init=true;
412                                }
413                       
414                        if (init) {                                                     
415                            writeCachecounter( start_cache);                                   
416                        }
417                       
418                } finally {
419                input.close();
420             }   
421             */         
422        }
423
424        public void updateCachecounter () {
425                //Admin.notifyUser("CACHEcounter:" + cachecounter);
426            writeCachecounter( cachecounter);
427        }
428        public void writeCachecounter (Integer i) {             
429               
430                // first update <index idcounter>
431                cacheindex_doc.getFirstChild().getAttributes().getNamedItem("idcounter").setNodeValue(i.toString());
432               
433                //Admin.notifyUser("writeCacheCounter:" + i.toString());
434                // write xml
435                Transformer transformer;
436                try {
437                        transformer = TransformerFactory.newInstance().newTransformer();
438                        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
439
440                        //initialize StreamResult with File object to save to file
441                        StreamResult result = new StreamResult(new StringWriter());
442                        DOMSource source = new DOMSource(cacheindex_doc);
443                        try {
444                                transformer.transform(source, result);
445                        } catch (TransformerException e1) {
446                                // TODO Auto-generated catch block
447                                e1.printStackTrace();
448                        }
449
450                        String xmlString = result.getWriter().toString();
451                        //Admin.notifyUser("writeCacheCounter:" + xmlString);
452                        //Admin.writeToFile("", result);
453
454
455                        File f = new File (cacheindex_path);
456                        FileWriter fw;
457                        try {
458                                fw = new FileWriter(f);
459                                try {
460                                        fw.write(xmlString);
461                                        fw.close();
462                                } catch (IOException e) {
463                                        // TODO Auto-generated catch block
464                                        e.printStackTrace();
465                                }       
466                        } catch (IOException e) {
467                                // TODO Auto-generated catch block
468                                e.printStackTrace();
469                        }
470                } catch (TransformerConfigurationException e2) {
471                        // TODO Auto-generated catch block
472                        e2.printStackTrace();
473                } catch (TransformerFactoryConfigurationError e2) {
474                        // TODO Auto-generated catch block
475                        e2.printStackTrace();
476                }
477               
478                       
479
480                /*
481                File f = new File (Admin.getConfig().getProperty("cache.path") + "counter.txt");
482           
483                try {
484                        Writer output = new BufferedWriter(new FileWriter(f));         
485              //FileWriter always assumes default encoding is OK!
486                        try {
487                                output.write( i);
488                        } finally {
489                                output.close();
490                        }       
491                } catch (IOException e) {
492                        // TODO Auto-generated catch block
493                        e.printStackTrace();
494                }
495                */
496        }
497}
Note: See TracBrowser for help on using the repository browser.