Store received events in local fs (debug mode) even if they do not parse
[aquarium] / src / main / scala / gr / grnet / aquarium / store / LocalFSEventStore.scala
1 /*
2  * Copyright 2011-2012 GRNET S.A. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or
5  * without modification, are permitted provided that the following
6  * conditions are met:
7  *
8  *   1. Redistributions of source code must retain the above
9  *      copyright notice, this list of conditions and the following
10  *      disclaimer.
11  *
12  *   2. Redistributions in binary form must reproduce the above
13  *      copyright notice, this list of conditions and the following
14  *      disclaimer in the documentation and/or other materials
15  *      provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
18  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
21  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
24  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
25  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGE.
29  *
30  * The views and conclusions contained in the software and
31  * documentation are those of the authors and should not be
32  * interpreted as representing official policies, either expressed
33  * or implied, of GRNET S.A.
34  */
35
36 package gr.grnet.aquarium.store
37
38 import gr.grnet.aquarium.Configurator
39 import com.ckkloverdos.maybe.Maybe
40 import gr.grnet.aquarium.util.date.MutableDateCalc
41 import java.io.{FileOutputStream, File}
42 import gr.grnet.aquarium.logic.events.{UserEvent, ResourceEvent}
43
44 /**
45  * This is used whenever the property `events.store.folder` is setup in aquarium configuration.
46  *
47  * The public methods guarantee they will not propagate any failure.
48  *
49  * @author Christos KK Loverdos <loverdos@gmail.com>
50  */
51
52 object LocalFSEventStore {
53   private[this] def writeToFile(file: File, data: Array[Byte]): Unit = {
54     val out = new FileOutputStream(file)
55     out.write(data)
56     out.flush()
57     out.close()
58   }
59
60   private[this] def writeToFile(file: File, data: String): Unit = {
61     writeToFile(file, data.getBytes("UTF-8"))
62   }
63
64   private[this] def storeThem(parsedJson: String,
65                               parsedJsonTarget: File,
66                               initialPayload: Array[Byte],
67                               initialPayloadTarget: File): Unit = {
68
69     Maybe { writeToFile(parsedJsonTarget, parsedJson.getBytes("UTF-8")) }
70     Maybe { writeToFile(initialPayloadTarget, initialPayload) }
71   }
72
73   def storeResourceEvent(mc: Configurator, event: ResourceEvent, initialPayload: Array[Byte]): Maybe[Unit] = Maybe {
74     if(mc.hasEventsStoreFolder) {
75       val occurredString = new MutableDateCalc(event.occurredMillis).toYYYYMMDDHHMMSS
76       val root = mc.eventsStoreFolder
77       val rcEvents = new File(root, "rcevents")
78       val parsed = event ne null
79
80       // We save two files. One containing the initial payload and one containing the transformed object.
81       val initialPayloadFile = new File(rcEvents, "rc-%s.raw%s".format(occurredString, if(!parsed) "x" else ""))
82       Maybe { writeToFile(initialPayloadFile, initialPayload) }
83
84       if(parsed) {
85         val parsedJsonFile = new File(
86           rcEvents,
87           "rc-%s-[%s]-[%s]-[%s]-[%s].json".format(
88             occurredString,
89             event.id,
90             event.userId,
91             event.resource,
92             event.instanceId))
93
94         Maybe { writeToFile(parsedJsonFile, event.toJson) }
95       }
96     }
97   }
98
99   def storeUserEvent(mc: Configurator, event: UserEvent, initialPayload: Array[Byte]): Maybe[Unit] = Maybe {
100     if(mc.hasEventsStoreFolder) {
101       val occurredString = new MutableDateCalc(event.occurredMillis).toYYYYMMDDHHMMSS
102       val root = mc.eventsStoreFolder
103       val imEvents = new File(root, "imevents")
104       val parsed = event ne null
105
106      // We save two files. One containing the initial payload and one containing the transformed object.
107       val initialPayloadFile = new File(imEvents, "im-%s.raw%s".format(occurredString, if(!parsed) "x" else ""))
108       Maybe { writeToFile(initialPayloadFile, initialPayload) }
109
110       if(parsed) {
111         val parsedJsonFile = new File(imEvents, "im-%s-[%s]-[%s].json".format(occurredString, event.id, event.userID))
112         Maybe { writeToFile(parsedJsonFile, event.toJson) }
113       }
114     }
115   }
116 }