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

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