Added source for asterix installer and event execution framework as modules under the asterix source tree

git-svn-id: https://asterixdb.googlecode.com/svn/branches/asterix_stabilization_installer@1202 eaa15691-b419-025a-1212-ee371bd00084
diff --git a/asterix-events/pom.xml b/asterix-events/pom.xml
new file mode 100644
index 0000000..a9aeaa5
--- /dev/null
+++ b/asterix-events/pom.xml
@@ -0,0 +1,156 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+          <artifactId>asterix</artifactId>
+          <groupId>edu.uci.ics.asterix</groupId>
+          <version>0.0.4-SNAPSHOT</version>
+  </parent>
+  <groupId>edu.uci.ics.asterix</groupId>
+  <artifactId>asterix-events</artifactId>
+  <version>0.0.4-SNAPSHOT</version>
+
+  <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+  </properties>
+
+  <build>
+    <plugins>
+       <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-compiler-plugin</artifactId>
+          <version>2.0.2</version>
+          <configuration>
+             <source>1.6</source>
+             <target>1.6</target>
+          </configuration>
+       </plugin>
+       <plugin>
+          <groupId>org.jvnet.jaxb2.maven2</groupId>
+          <artifactId>maven-jaxb2-plugin</artifactId>
+          <executions>
+            <execution>
+              <id>event</id>
+              <goals>
+                <goal>generate</goal>
+              </goals>
+              <configuration>
+                <args>
+                  <arg>-Xsetters</arg>
+                  <arg>-Xvalue-constructor</arg>
+                </args>
+                <plugins>
+                  <plugin>
+                    <groupId>org.jvnet.jaxb2_commons</groupId>
+                    <artifactId>jaxb2-basics</artifactId>
+                    <version>0.6.2</version>
+                  </plugin>
+                  <plugin>
+                    <groupId>org.jvnet.jaxb2_commons</groupId>
+                    <artifactId>jaxb2-value-constructor</artifactId>
+                    <version>3.0</version>
+                  </plugin>
+                </plugins>
+                <schemaDirectory>src/main/resources/schema</schemaDirectory>
+                <schemaIncludes>
+	          <include>event.xsd</include>
+	        </schemaIncludes>
+                <generatePackage>edu.uci.ics.asterix.event.schema.event</generatePackage>
+                <generateDirectory>${project.build.directory}/generated-sources/event</generateDirectory>
+              </configuration>
+            </execution>
+            <execution>
+              <id>pattern</id>
+              <goals>
+                <goal>generate</goal>
+              </goals>
+              <configuration>
+                <args>
+                  <arg>-Xsetters</arg>
+                  <arg>-Xvalue-constructor</arg>
+                </args>
+                <plugins>
+                  <plugin>
+                    <groupId>org.jvnet.jaxb2_commons</groupId>
+                    <artifactId>jaxb2-basics</artifactId>
+                    <version>0.6.2</version>
+                  </plugin>
+                  <plugin>
+                    <groupId>org.jvnet.jaxb2_commons</groupId>
+                    <artifactId>jaxb2-value-constructor</artifactId>
+                    <version>3.0</version>
+                  </plugin>
+                </plugins>
+                <schemaDirectory>src/main/resources/schema</schemaDirectory>
+                <schemaIncludes>
+	          <include>pattern.xsd</include>
+	        </schemaIncludes>
+                <generatePackage>edu.uci.ics.asterix.event.schema.pattern</generatePackage>
+                <generateDirectory>${project.build.directory}/generated-sources/pattern</generateDirectory>
+              </configuration>
+            </execution>
+            <execution>
+              <id>cluster</id>
+              <goals>
+                <goal>generate</goal>
+              </goals>
+              <configuration>
+                <args>
+                  <arg>-Xsetters</arg>
+                  <arg>-Xvalue-constructor</arg>
+                </args>
+                <plugins>
+                  <plugin>
+                    <groupId>org.jvnet.jaxb2_commons</groupId>
+                    <artifactId>jaxb2-basics</artifactId>
+                    <version>0.6.2</version>
+                  </plugin>
+                  <plugin>
+                    <groupId>org.jvnet.jaxb2_commons</groupId>
+                    <artifactId>jaxb2-value-constructor</artifactId>
+                    <version>3.0</version>
+                  </plugin>
+                </plugins>
+                <schemaDirectory>src/main/resources/schema</schemaDirectory>
+                <schemaIncludes>
+	          <include>cluster.xsd</include>
+	        </schemaIncludes>
+                <generatePackage>edu.uci.ics.asterix.event.schema.cluster</generatePackage>
+                <generateDirectory>${project.build.directory}/generated-sources/cluster</generateDirectory>
+                <bindingDirectory>src/main/resources/schema</bindingDirectory>
+                <bindingIncludes>
+                  <bindingInclude>jaxb-bindings.xjb</bindingInclude>
+                </bindingIncludes>
+              </configuration>
+            </execution>
+          </executions>
+       </plugin>
+    </plugins>
+  </build>
+
+  <dependencies>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>4.8.1</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>args4j</groupId>
+      <artifactId>args4j</artifactId>
+      <version>2.0.12</version>
+      <type>jar</type>
+      <scope>compile</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.jvnet.jaxb2_commons</groupId>
+      <artifactId>jaxb2-value-constructor</artifactId>
+      <version>3.0</version>
+    </dependency>
+    <dependency>
+      <groupId>commons-io</groupId>
+      <artifactId>commons-io</artifactId>
+      <version>1.4</version>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/asterix-events/src/main/java/edu/uci/ics/asterix/event/api/ClusterInfo.java b/asterix-events/src/main/java/edu/uci/ics/asterix/event/api/ClusterInfo.java
new file mode 100644
index 0000000..630f9b3
--- /dev/null
+++ b/asterix-events/src/main/java/edu/uci/ics/asterix/event/api/ClusterInfo.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2009-2012 by The Regents of the University of California
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * you may obtain a copy of the License from
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package edu.uci.ics.asterix.event.api;
+
+import java.util.List;
+
+public class ClusterInfo {
+
+	List<NodeInfo> nodes;
+
+	public ClusterInfo(List<NodeInfo> nodes) {
+		this.nodes = nodes;
+	}
+}
diff --git a/asterix-events/src/main/java/edu/uci/ics/asterix/event/api/NodeInfo.java b/asterix-events/src/main/java/edu/uci/ics/asterix/event/api/NodeInfo.java
new file mode 100644
index 0000000..835e0dc
--- /dev/null
+++ b/asterix-events/src/main/java/edu/uci/ics/asterix/event/api/NodeInfo.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2009-2012 by The Regents of the University of California
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * you may obtain a copy of the License from
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package edu.uci.ics.asterix.event.api;
+
+public class NodeInfo {
+
+	private final String id;
+	private final String ip;
+
+	public NodeInfo(String id, String ip) {
+		this.id = id;
+		this.ip = ip;
+	}
+
+	public String getId() {
+		return id;
+	}
+
+	public String getIp() {
+		return ip;
+	}
+}
diff --git a/asterix-events/src/main/java/edu/uci/ics/asterix/event/driver/EventConfig.java b/asterix-events/src/main/java/edu/uci/ics/asterix/event/driver/EventConfig.java
new file mode 100644
index 0000000..9d0138b
--- /dev/null
+++ b/asterix-events/src/main/java/edu/uci/ics/asterix/event/driver/EventConfig.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2009-2012 by The Regents of the University of California
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * you may obtain a copy of the License from
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package edu.uci.ics.asterix.event.driver;
+
+import org.kohsuke.args4j.Option;
+
+public class EventConfig {
+
+	@Option(name = "-h", required = false, usage = "Help")
+	public boolean help = false;
+
+	@Option(name = "-d", required = false, usage = "Show the execution on a timeline")
+	public boolean dryRun = false;
+
+	@Option(name = "-s", required = false, usage = "Seed for randomization")
+	public int seed = -1;
+
+	@Option(name = "-c", required = true, usage = "Path to cluster configuration (REQUIRED)")
+	public String clusterPath;
+
+	@Option(name = "-p", required = true, usage = "Path to pattern configuration (REQUIRED)")
+	public String patternPath;
+
+}
diff --git a/asterix-events/src/main/java/edu/uci/ics/asterix/event/driver/EventDriver.java b/asterix-events/src/main/java/edu/uci/ics/asterix/event/driver/EventDriver.java
new file mode 100644
index 0000000..379d811
--- /dev/null
+++ b/asterix-events/src/main/java/edu/uci/ics/asterix/event/driver/EventDriver.java
@@ -0,0 +1,183 @@
+/*
+ * Copyright 2009-2012 by The Regents of the University of California
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * you may obtain a copy of the License from
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package edu.uci.ics.asterix.event.driver;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Logger;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Unmarshaller;
+
+import org.kohsuke.args4j.CmdLineParser;
+
+import edu.uci.ics.asterix.event.management.DefaultOutputHandler;
+import edu.uci.ics.asterix.event.management.EventUtil;
+import edu.uci.ics.asterix.event.management.EventrixClient;
+import edu.uci.ics.asterix.event.management.IOutputHandler;
+import edu.uci.ics.asterix.event.management.Randomizer;
+import edu.uci.ics.asterix.event.schema.cluster.Cluster;
+import edu.uci.ics.asterix.event.schema.cluster.Node;
+import edu.uci.ics.asterix.event.schema.cluster.Property;
+import edu.uci.ics.asterix.event.schema.event.Events;
+import edu.uci.ics.asterix.event.schema.pattern.Patterns;
+
+public class EventDriver {
+
+    public static final String CLIENT_NODE_ID = "client_node";
+    public static final Node CLIENT_NODE = new Node(CLIENT_NODE_ID, "127.0.0.1", null, null, null);
+
+    private static final Logger LOGGER = Logger.getLogger(EventDriver.class.getName());
+
+    private static String homeDir;
+    private static Events events;
+    private static Map<String, String> env = new HashMap<String, String>();
+    private static String scriptDirSuffix;
+
+    public static String getHomeDir() {
+        return homeDir;
+    }
+
+    public static void setHomeDir(String homeDir) {
+        EventDriver.homeDir = homeDir;
+    }
+
+    public static Events getEvents() {
+        return events;
+    }
+
+    public static void setEvents(Events events) {
+        EventDriver.events = events;
+    }
+
+    public static Map<String, String> getEnvironment() {
+        return env;
+    }
+
+    public static String getStringifiedEnv(Cluster cluster) {
+        StringBuffer buffer = new StringBuffer();
+        for (Property p : cluster.getEnv().getProperty()) {
+            buffer.append(p.getKey() + "=" + p.getValue() + " ");
+        }
+        return buffer.toString();
+    }
+
+    public static void initializeEvents(String path) throws IOException {
+        try {
+            File eventsFile = new File(path);
+            JAXBContext ctx = JAXBContext.newInstance(Events.class);
+            Unmarshaller unmarshaller = ctx.createUnmarshaller();
+            events = (Events) unmarshaller.unmarshal(eventsFile);
+        } catch (JAXBException e) {
+            e.printStackTrace();
+        }
+    }
+
+    public static Cluster initializeCluster(String path) throws JAXBException, IOException {
+        File file = new File(path);
+        JAXBContext ctx = JAXBContext.newInstance(Cluster.class);
+        Unmarshaller unmarshaller = ctx.createUnmarshaller();
+        Cluster cluster = (Cluster) unmarshaller.unmarshal(file);
+        for (Property p : cluster.getEnv().getProperty()) {
+            env.put(p.getKey(), p.getValue());
+        }
+        return cluster;
+    }
+
+    public static Patterns initializePatterns(String path) throws JAXBException, IOException {
+        File file = new File(path);
+        JAXBContext ctx = JAXBContext.newInstance(Patterns.class);
+        Unmarshaller unmarshaller = ctx.createUnmarshaller();
+        return (Patterns) unmarshaller.unmarshal(file);
+    }
+
+    private static void initialize(EventConfig eventConfig) throws IOException, JAXBException {
+        homeDir = System.getenv("EVENT_HOME");
+        if (homeDir == null) {
+            throw new IllegalStateException("EVENT_HOME is not set");
+        }
+        initializeEvents(homeDir + "/" + EventUtil.EVENTS_DIR + "/" + "events.xml");
+    }
+
+    public static EventrixClient getClient(Cluster cluster, boolean dryRun) throws Exception {
+        return new EventrixClient(cluster, dryRun, new DefaultOutputHandler());
+    }
+
+    public static EventrixClient getClient(Cluster cluster, boolean dryRun, IOutputHandler outputHandler)
+            throws Exception {
+        return new EventrixClient(cluster, dryRun, outputHandler);
+    }
+
+    public static void main(String[] args) throws Exception {
+        EventConfig eventConfig = new EventConfig();
+        CmdLineParser parser = new CmdLineParser(eventConfig);
+        try {
+            parser.parseArgument(args);
+            if (eventConfig.help) {
+                parser.printUsage(System.out);
+            }
+            if (eventConfig.seed > 0) {
+                Randomizer.getInstance(eventConfig.seed);
+            }
+            Cluster cluster = initializeCluster(eventConfig.clusterPath);
+            Patterns patterns = initializePatterns(eventConfig.patternPath);
+
+            initialize(eventConfig);
+            if (!eventConfig.dryRun) {
+                prepare(cluster);
+            }
+            EventrixClient client = new EventrixClient(cluster, eventConfig.dryRun, new DefaultOutputHandler());
+            client.submit(patterns);
+            if (!eventConfig.dryRun) {
+                cleanup(cluster);
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            parser.printUsage(System.err);
+        }
+    }
+
+    private static void prepare(Cluster cluster) throws IOException, InterruptedException {
+
+        scriptDirSuffix = "" + System.nanoTime();
+        List<String> args = new ArrayList<String>();
+        args.add(scriptDirSuffix);
+        Node clientNode = new Node();
+        clientNode.setId("client");
+        clientNode.setIp("127.0.0.1");
+        for (Node node : cluster.getNode()) {
+            args.add(node.getIp());
+        }
+        EventUtil.executeLocalScript(clientNode, homeDir + "/" + "events" + "/" + "prepare.sh", args);
+    }
+
+    private static void cleanup(Cluster cluster) throws IOException, InterruptedException {
+        List<String> args = new ArrayList<String>();
+        args.add(scriptDirSuffix);
+        Node clientNode = new Node();
+        clientNode.setId("client");
+        clientNode.setIp("127.0.0.1");
+        for (Node node : cluster.getNode()) {
+            args.add(node.getIp());
+        }
+        EventUtil.executeLocalScript(clientNode, homeDir + "/" + "events" + "/" + "cleanup.sh", args);
+    }
+
+}
diff --git a/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/DefaultOutputHandler.java b/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/DefaultOutputHandler.java
new file mode 100644
index 0000000..e8f06a0
--- /dev/null
+++ b/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/DefaultOutputHandler.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2009-2012 by The Regents of the University of California
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * you may obtain a copy of the License from
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package edu.uci.ics.asterix.event.management;
+
+import edu.uci.ics.asterix.event.schema.pattern.Event;
+
+public class DefaultOutputHandler implements IOutputHandler {
+
+    @Override
+    public OutputAnalysis reportEventOutput(Event event, String output) {
+        return new OutputAnalysis(true, null);
+    }
+
+}
diff --git a/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/ErrorHandler.java b/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/ErrorHandler.java
new file mode 100644
index 0000000..a6c038b
--- /dev/null
+++ b/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/ErrorHandler.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2009-2012 by The Regents of the University of California
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * you may obtain a copy of the License from
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package edu.uci.ics.asterix.event.management;
+
+public class ErrorHandler {
+
+}
diff --git a/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/EventExecutor.java b/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/EventExecutor.java
new file mode 100644
index 0000000..869edd7
--- /dev/null
+++ b/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/EventExecutor.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2009-2012 by The Regents of the University of California
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * you may obtain a copy of the License from
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package edu.uci.ics.asterix.event.management;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.io.IOUtils;
+
+import edu.uci.ics.asterix.event.driver.EventDriver;
+import edu.uci.ics.asterix.event.schema.cluster.Cluster;
+import edu.uci.ics.asterix.event.schema.cluster.Node;
+import edu.uci.ics.asterix.event.schema.pattern.Pattern;
+
+public class EventExecutor {
+
+    public static final String EVENTS_DIR = "events";
+    private static final String EXECUTE_SCRIPT = "execute.sh";
+    private static final String IP_LOCATION = "IP_LOCATION";
+    private static final String CLUSTER_ENV = "ENV";
+    private static final String SCRIPT = "SCRIPT";
+    private static final String ARGS = "ARGS";
+    private static final String DAEMON = "DAEMON";
+
+    public void executeEvent(Node node, String script, List<String> args, boolean isDaemon, Cluster cluster,
+            Pattern pattern, IOutputHandler outputHandler) throws IOException {
+        List<String> pargs = new ArrayList<String>();
+        pargs.add("/bin/bash");
+        pargs.add(EventDriver.getHomeDir() + File.separator + "events.pkg" + File.separator + EXECUTE_SCRIPT);
+        StringBuffer argBuffer = new StringBuffer();
+        StringBuffer envBuffer = new StringBuffer(IP_LOCATION + "=" + node.getIp());
+        if (!node.getId().equals(EventDriver.CLIENT_NODE_ID)) {
+            envBuffer.append(" " + EventDriver.getStringifiedEnv(cluster));
+            pargs.add(cluster.getUsername() == null ? System.getProperty("user.name") : cluster.getUsername());
+        }
+        if (args != null && args.size() > 0) {
+            for (String arg : args) {
+                argBuffer.append(arg + " ");
+            }
+        }
+        ProcessBuilder pb = new ProcessBuilder(pargs);
+        pb.environment().putAll(EventDriver.getEnvironment());
+        pb.environment().put(IP_LOCATION, node.getIp());
+        pb.environment().put(CLUSTER_ENV, envBuffer.toString());
+        pb.environment().put(SCRIPT, script);
+        pb.environment().put(ARGS, argBuffer.toString());
+        pb.environment().put(DAEMON, isDaemon ? "true" : "false");
+
+        Process p = pb.start();
+        if (!isDaemon) {
+            BufferedInputStream bis = new BufferedInputStream(p.getInputStream());
+            StringWriter writer = new StringWriter();
+            IOUtils.copy(bis, writer, "UTF-8");
+            String result = writer.getBuffer().toString();
+            OutputAnalysis analysis = outputHandler.reportEventOutput(pattern.getEvent(), result);
+            if (!analysis.isExpected()) {
+                throw new IOException(analysis.getErrorMessage());
+            }
+        }
+    }
+}
diff --git a/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/EventTask.java b/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/EventTask.java
new file mode 100644
index 0000000..aac2604
--- /dev/null
+++ b/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/EventTask.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2009-2012 by The Regents of the University of California
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * you may obtain a copy of the License from
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package edu.uci.ics.asterix.event.management;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Date;
+import java.util.List;
+import java.util.Timer;
+import java.util.TimerTask;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import edu.uci.ics.asterix.event.driver.EventDriver;
+import edu.uci.ics.asterix.event.schema.cluster.Node;
+import edu.uci.ics.asterix.event.schema.pattern.Pattern;
+import edu.uci.ics.asterix.event.schema.pattern.Period;
+
+public class EventTask extends TimerTask {
+
+    public static enum State {
+        INITIALIZED,
+        IN_PROGRESS,
+        COMPLETED,
+        FAILED
+    }
+
+    private static final Logger logger = Logger.getLogger(EventTask.class.getName());
+
+    private Pattern pattern;
+    private long interval = 0;
+    private long initialDelay = 0;
+    private int maxOccurs = Integer.MAX_VALUE;
+    private int occurrenceCount = 0;
+    private Timer timer;
+    private String taskScript;
+    private Node location;
+    private List<String> taskArgs;
+    private EventrixClient scheduler;
+    private List<Node> candidateLocations;
+    private boolean dynamicLocation = false;
+    private boolean reuseLocation = false;
+    private State state;
+
+    static {
+        logger.setLevel(Level.WARNING);
+    }
+
+    public EventTask(Pattern pattern, EventrixClient client) {
+        this.pattern = pattern;
+        this.scheduler = client;
+        Period period = pattern.getPeriod();
+        if (period != null && period.getAbsvalue() != null) {
+            this.interval = EventUtil.parseTimeInterval(period.getAbsvalue(), period.getUnit());
+        }
+        if (pattern.getDelay() != null) {
+            this.initialDelay = EventUtil.parseTimeInterval(new ValueType(pattern.getDelay().getValue()), pattern
+                    .getDelay().getUnit());
+        }
+        if (pattern.getMaxOccurs() != null) {
+            this.maxOccurs = pattern.getMaxOccurs();
+        }
+        this.timer = new Timer();
+        taskArgs = EventUtil.getEventArgs(pattern);
+        candidateLocations = EventUtil.getCandidateLocations(pattern, client.getCluster());
+        if (pattern.getEvent().getNodeid().getValue().getRandom() != null && period != null && maxOccurs > 1) {
+            dynamicLocation = true;
+            reuseLocation = pattern.getEvent().getNodeid().getValue().getRandom().getRange().isReuse();
+        } else {
+            location = EventUtil.getEventLocation(pattern, candidateLocations, scheduler.getCluster());
+        }
+        String scriptsDir;
+        if (location.getId().equals(EventDriver.CLIENT_NODE_ID)) {
+            scriptsDir = EventDriver.getHomeDir() + File.separator + "events.pkg";
+        } else {
+            scriptsDir = client.getCluster().getWorkingDir().getDir() + File.separator + "events.pkg";
+        }
+        taskScript = scriptsDir + File.separator + EventUtil.getEvent(pattern).getScript();
+        state = State.INITIALIZED;
+    }
+
+    public void start() {
+        if (interval > 0) {
+            timer.schedule(this, initialDelay, interval);
+        } else {
+            timer.schedule(this, initialDelay);
+        }
+    }
+
+    @Override
+    public void run() {
+        if (candidateLocations.size() == 0) {
+            timer.cancel();
+            scheduler.notifyCompletion(new EventTaskReport(this));
+        } else {
+            if (dynamicLocation) {
+                location = EventUtil.getEventLocation(pattern, candidateLocations, scheduler.getCluster());
+                if (!reuseLocation) {
+                    candidateLocations.remove(location);
+                }
+            }
+
+            logger.info(EventUtil.dateFormat.format(new Date()) + " " + "EVENT "
+                    + pattern.getEvent().getType().toUpperCase() + " at " + location.getId().toUpperCase());
+            try {
+                if (!scheduler.isDryRun()) {
+                    new EventExecutor().executeEvent(location, taskScript, taskArgs, EventUtil.getEvent(pattern)
+                            .isDaemon(), scheduler.getCluster(), pattern, scheduler.getErrorHandler());
+                }
+                occurrenceCount++;
+                if (occurrenceCount >= maxOccurs) {
+                    timer.cancel();
+                    scheduler.notifyCompletion(new EventTaskReport(this));
+                }
+            } catch (IOException ioe) {
+                timer.cancel();
+                scheduler.notifyCompletion(new EventTaskReport(this, false, ioe));
+            }
+        }
+
+    }
+
+    public Node getLocation() {
+        return location;
+    }
+
+    public long getInterval() {
+        return interval;
+    }
+
+    public long getInitialDelay() {
+        return initialDelay;
+    }
+
+    public Pattern getPattern() {
+        return pattern;
+    }
+
+    public State getState() {
+        return state;
+    }
+
+}
diff --git a/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/EventTaskReport.java b/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/EventTaskReport.java
new file mode 100644
index 0000000..7ad3682
--- /dev/null
+++ b/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/EventTaskReport.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2009-2012 by The Regents of the University of California
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * you may obtain a copy of the License from
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package edu.uci.ics.asterix.event.management;
+
+import java.io.Serializable;
+
+public class EventTaskReport implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+    private final EventTask task;
+    private final boolean success;
+    private final Exception e;
+
+    public EventTaskReport(EventTask task, boolean success, Exception e) {
+        this.task = task;
+        this.success = success;
+        this.e = e;
+    }
+
+    public EventTaskReport(EventTask task) {
+        this.task = task;
+        this.success = true;
+        this.e = null;
+    }
+
+    public Exception getException() {
+        return e;
+    }
+
+    public EventTask getTask() {
+        return task;
+    }
+
+    public boolean isSuccess() {
+        return success;
+    }
+
+}
diff --git a/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/EventUtil.java b/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/EventUtil.java
new file mode 100644
index 0000000..80bc0da
--- /dev/null
+++ b/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/EventUtil.java
@@ -0,0 +1,238 @@
+/*
+ * Copyright 2009-2012 by The Regents of the University of California
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * you may obtain a copy of the License from
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package edu.uci.ics.asterix.event.management;
+
+import java.io.IOException;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Logger;
+
+import edu.uci.ics.asterix.event.driver.EventDriver;
+import edu.uci.ics.asterix.event.management.ValueType.Type;
+import edu.uci.ics.asterix.event.schema.cluster.Cluster;
+import edu.uci.ics.asterix.event.schema.cluster.Node;
+import edu.uci.ics.asterix.event.schema.event.Event;
+import edu.uci.ics.asterix.event.schema.pattern.Pattern;
+
+public class EventUtil {
+
+    public static final String EVENTS_DIR = "events";
+    public static final String CLUSTER_CONF = "config/cluster.xml";
+    public static final String PATTERN_CONF = "config/pattern.xml";
+    private static final String IP_LOCATION = "IP_LOCATION";
+    private static final String CLUSTER_ENV = "ENV";
+    private static final String SCRIPT = "SCRIPT";
+    private static final String ARGS = "ARGS";
+    private static final String EXECUTE_SCRIPT = "events/execute.sh";
+
+    public static final DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
+
+    private static final Logger logger = Logger.getLogger(EventDriver.class.getName());
+
+    public static long parseTimeInterval(ValueType v, String unit) throws IllegalArgumentException {
+        int val = 0;
+        switch (v.getType()) {
+            case ABS:
+                val = Integer.parseInt(v.getAbsoluteValue());
+                break;
+            case RANDOM_MIN_MAX:
+                val = Randomizer.getInstance().getRandomInt(v.getMin(), v.getMax());
+                break;
+            case RANDOM_RANGE:
+                String[] values = v.getRangeSet();
+                val = Integer.parseInt(values[Randomizer.getInstance().getRandomInt(0, values.length - 1)]);
+                break;
+        }
+        return computeInterval(val, unit);
+    }
+
+    public static long parseTimeInterval(String v, String unit) throws IllegalArgumentException {
+        int value = Integer.parseInt(v);
+        return computeInterval(value, unit);
+    }
+
+    private static long computeInterval(int val, String unit) {
+        int vmult = 1;
+        if ("hr".equalsIgnoreCase(unit)) {
+            vmult = 3600 * 1000;
+        } else if ("min".equalsIgnoreCase(unit)) {
+            vmult = 60 * 1000;
+        } else if ("sec".equalsIgnoreCase(unit)) {
+            vmult = 1000;
+        } else
+            throw new IllegalArgumentException(" invalid unit value specified for frequency (hr,min,sec)");
+        return val * vmult;
+
+    }
+
+    public static Event getEvent(Pattern pattern) {
+        for (Event event : EventDriver.getEvents().getEvent()) {
+            if (event.getType().equals(pattern.getEvent().getType())) {
+                return event;
+            }
+        }
+        throw new IllegalArgumentException(" Unknown event type" + pattern.getEvent().getType());
+    }
+
+    public static Node getEventLocation(Pattern pattern, List<Node> candidateLocations, Cluster cluster) {
+        ValueType value = new ValueType(pattern.getEvent().getNodeid().getValue());
+        Node location = null;
+        Type vtype = value.getType();
+
+        switch (vtype) {
+            case ABS:
+                location = getNodeFromId(value.getAbsoluteValue(), cluster);
+                break;
+            case RANDOM_RANGE:
+                int nodeIndex = Randomizer.getInstance().getRandomInt(0, candidateLocations.size() - 1);
+                location = candidateLocations.get(nodeIndex);
+                break;
+            case RANDOM_MIN_MAX:
+                throw new IllegalStateException(" Canont configure a min max value range for location");
+        }
+        return location;
+
+    }
+
+    public static List<Node> getCandidateLocations(Pattern pattern, Cluster cluster) {
+        ValueType value = new ValueType(pattern.getEvent().getNodeid().getValue());
+        List<Node> candidateList = new ArrayList<Node>();
+        switch (value.getType()) {
+            case ABS:
+                candidateList.add(getNodeFromId(value.getAbsoluteValue(), cluster));
+                break;
+            case RANDOM_RANGE:
+                boolean anyOption = false;
+                String[] values = value.getRangeSet();
+                for (String v : values) {
+                    if (v.equalsIgnoreCase("ANY")) {
+                        anyOption = true;
+                    }
+                }
+                if (anyOption) {
+                    for (Node node : cluster.getNode()) {
+                        candidateList.add(node);
+                    }
+                } else {
+                    boolean found = false;
+                    for (String v : values) {
+                        for (Node node : cluster.getNode()) {
+                            if (node.getId().equals(v)) {
+                                candidateList.add(node);
+                                found = true;
+                                break;
+                            }
+                        }
+                        if (!found) {
+                            throw new IllegalStateException("Unknonw nodeId : " + v);
+                        }
+                        found = false;
+                    }
+
+                }
+                String[] excluded = value.getRangeExcluded();
+                if (excluded != null && excluded.length > 0) {
+                    List<Node> markedForRemoval = new ArrayList<Node>();
+                    for (String exclusion : excluded) {
+                        for (Node node : candidateList) {
+                            if (node.getId().equals(exclusion)) {
+                                markedForRemoval.add(node);
+                            }
+                        }
+                    }
+                    candidateList.removeAll(markedForRemoval);
+                }
+                break;
+            case RANDOM_MIN_MAX:
+                throw new IllegalStateException(" Invalid value configured for location");
+        }
+        return candidateList;
+    }
+
+    private static Node getNodeFromId(String nodeid, Cluster cluster) {
+        if (nodeid.equals(EventDriver.CLIENT_NODE.getId())) {
+            return EventDriver.CLIENT_NODE;
+        }
+
+        if (nodeid.equals(cluster.getMasterNode().getId())) {
+            return new Node(cluster.getMasterNode().getId(), cluster.getMasterNode().getIp(), null, null, null);
+        }
+
+        List<Node> nodeList = cluster.getNode();
+        for (Node node : nodeList) {
+            if (node.getId().equals(nodeid)) {
+                return node;
+            }
+        }
+        StringBuffer buffer = new StringBuffer();
+        buffer.append(EventDriver.CLIENT_NODE.getId() + ",");
+        buffer.append(cluster.getMasterNode().getId() + ",");
+        for (Node v : cluster.getNode()) {
+            buffer.append(v.getId() + ",");
+        }
+        buffer.deleteCharAt(buffer.length() - 1);
+        throw new IllegalArgumentException("Unknown node id :" + nodeid + " valid ids:" + buffer);
+    }
+
+    public static void executeEventScript(Node node, String script, List<String> args, Cluster cluster)
+            throws IOException, InterruptedException {
+        List<String> pargs = new ArrayList<String>();
+        pargs.add("/bin/bash");
+        pargs.add(EventDriver.getHomeDir() + "/" + EXECUTE_SCRIPT);
+        StringBuffer argBuffer = new StringBuffer();
+        String env = EventDriver.getStringifiedEnv(cluster) + " " + IP_LOCATION + "=" + node.getIp();
+        if (args != null) {
+            for (String arg : args) {
+                argBuffer.append(arg + " ");
+            }
+        }
+        ProcessBuilder pb = new ProcessBuilder(pargs);
+        pb.environment().putAll(EventDriver.getEnvironment());
+        pb.environment().put(IP_LOCATION, node.getIp());
+        pb.environment().put(CLUSTER_ENV, env);
+        pb.environment().put(SCRIPT, script);
+        pb.environment().put(ARGS, argBuffer.toString());
+        pb.start();
+    }
+
+    public static void executeLocalScript(Node node, String script, List<String> args) throws IOException,
+            InterruptedException {
+        List<String> pargs = new ArrayList<String>();
+        pargs.add("/bin/bash");
+        pargs.add(script);
+        if (args != null) {
+            pargs.addAll(args);
+        }
+        ProcessBuilder pb = new ProcessBuilder(pargs);
+        pb.environment().putAll(EventDriver.getEnvironment());
+        pb.environment().put(IP_LOCATION, node.getIp());
+        pb.start();
+    }
+
+    public static List<String> getEventArgs(Pattern pattern) {
+        List<String> pargs = new ArrayList<String>();
+        if (pattern.getEvent().getPargs() == null) {
+            return pargs;
+        }
+        String[] args = pattern.getEvent().getPargs().split(" ");
+        for (String arg : args) {
+            pargs.add(arg.trim());
+        }
+        return pargs;
+    }
+
+}
diff --git a/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/EventrixClient.java b/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/EventrixClient.java
new file mode 100644
index 0000000..3792eb8
--- /dev/null
+++ b/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/EventrixClient.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2009-2012 by The Regents of the University of California
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * you may obtain a copy of the License from
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package edu.uci.ics.asterix.event.management;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.logging.Logger;
+
+import edu.uci.ics.asterix.event.driver.EventDriver;
+import edu.uci.ics.asterix.event.schema.cluster.Cluster;
+import edu.uci.ics.asterix.event.schema.cluster.Node;
+import edu.uci.ics.asterix.event.schema.pattern.Event;
+import edu.uci.ics.asterix.event.schema.pattern.Nodeid;
+import edu.uci.ics.asterix.event.schema.pattern.Pattern;
+import edu.uci.ics.asterix.event.schema.pattern.Patterns;
+import edu.uci.ics.asterix.event.schema.pattern.Value;
+
+public class EventrixClient {
+
+    private static final Logger LOGGER = Logger.getLogger(EventrixClient.class.getName());
+
+    private EventTask[] tasks;
+    private boolean dryRun = false;
+    private LinkedBlockingQueue<EventTaskReport> msgInbox = new LinkedBlockingQueue<EventTaskReport>();
+    private AtomicInteger pendingTasks = new AtomicInteger(0);
+    private final Cluster cluster;
+    private IPatternListener listener;
+    private IOutputHandler outputHandler;
+
+    public EventrixClient(Cluster cluster, boolean dryRun, IOutputHandler outputHandler) throws Exception {
+        this.cluster = cluster;
+        this.dryRun = dryRun;
+        this.outputHandler = outputHandler;
+        if (!dryRun) {
+            initializeCluster();
+        }
+    }
+
+    public void submit(Patterns patterns) throws Exception {
+        initTasks(patterns);
+        try {
+            waitForCompletion();
+        } catch (InterruptedException ie) {
+            LOGGER.info("Interrupted exception :" + ie);
+        } catch (Exception e) {
+            throw e;
+        }
+
+    }
+
+    public void submit(Patterns patterns, IPatternListener listener) throws Exception {
+        this.listener = listener;
+        initTasks(patterns);
+    }
+
+    private void initTasks(Patterns patterns) {
+        tasks = new EventTask[patterns.getPattern().size()];
+        pendingTasks.set(tasks.length);
+        int index = 0;
+        for (Pattern pattern : patterns.getPattern()) {
+            tasks[index] = new EventTask(pattern, this);
+            tasks[index].start();
+            index++;
+        }
+    }
+
+    public Cluster getCluster() {
+        return cluster;
+    }
+
+    public boolean isDryRun() {
+        return dryRun;
+    }
+
+    public void notifyCompletion(EventTaskReport report) {
+
+        if (report.isSuccess()) {
+            pendingTasks.decrementAndGet();
+            if (listener != null) {
+                listener.eventCompleted(report);
+                if (pendingTasks.get() == 0) {
+                    listener.jobCompleted();
+                }
+            } else {
+                try {
+                    msgInbox.put(report);
+                } catch (InterruptedException e) {
+                }
+            }
+        } else {
+            for (EventTask t : tasks) {
+                if (t.getState() == EventTask.State.INITIALIZED || t.getState() == EventTask.State.IN_PROGRESS) {
+                    t.cancel();
+                }
+            }
+            if (listener != null) {
+                listener.jobFailed(report);
+            } else {
+                try {
+                    msgInbox.put(report);
+                } catch (InterruptedException e) {
+                }
+            }
+        }
+    }
+
+    public void notifyFailure(EventTaskReport report) {
+
+    }
+
+    private void waitForCompletion() throws Exception {
+        while (true) {
+            EventTaskReport report = msgInbox.take();
+            if (report.isSuccess()) {
+                if (pendingTasks.get() == 0) {
+                    break;
+                }
+            } else {
+                throw new RuntimeException(report.getException().getMessage());
+            }
+        }
+    }
+
+    private void initializeCluster() throws Exception {
+        Patterns patterns = initPattern();
+        submit(patterns);
+    }
+
+    private Patterns initPattern() {
+        Nodeid nodeid = new Nodeid(new Value(null, EventDriver.CLIENT_NODE.getId()));
+        List<Pattern> patternList = new ArrayList<Pattern>();
+        String workingDir = cluster.getWorkingDir().getDir();
+        File eventsPkg = new File(EventDriver.getHomeDir() + File.separator + "events.pkg.tar");
+        if (!eventsPkg.exists()) {
+            throw new IllegalStateException(" Events package does not exist (" + eventsPkg.getAbsolutePath() + ")");
+        }
+
+        String username = cluster.getUsername() == null ? System.getProperty("user.name") : cluster.getUsername();
+        patternList.add(getFileTransferPattern(username, eventsPkg.getAbsolutePath(), nodeid, cluster.getMasterNode()
+                .getIp(), workingDir, true));
+
+        if (!cluster.getWorkingDir().isNFS()) {
+            for (Node node : cluster.getNode()) {
+                patternList.add(getFileTransferPattern(username, eventsPkg.getAbsolutePath(), nodeid, node.getIp(),
+                        workingDir, true));
+            }
+        }
+        Patterns patterns = new Patterns(patternList);
+        return patterns;
+    }
+
+    private Pattern getFileTransferPattern(String username, String src, Nodeid srcNode, String destNodeIp,
+            String destDir, boolean unpack) {
+        String pargs = username + " " + src + " " + destNodeIp + " " + destDir + " " + "unpack";
+        Event event = new Event("file_transfer", srcNode, pargs);
+        return new Pattern(null, 1, null, event);
+    }
+
+    public IOutputHandler getErrorHandler() {
+        return outputHandler;
+    }
+}
diff --git a/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/IOutputHandler.java b/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/IOutputHandler.java
new file mode 100644
index 0000000..c7929cb
--- /dev/null
+++ b/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/IOutputHandler.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2009-2012 by The Regents of the University of California
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * you may obtain a copy of the License from
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package edu.uci.ics.asterix.event.management;
+
+import edu.uci.ics.asterix.event.schema.pattern.Event;
+
+public interface IOutputHandler {
+
+    public OutputAnalysis reportEventOutput(Event event, String output);
+}
diff --git a/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/IPatternListener.java b/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/IPatternListener.java
new file mode 100644
index 0000000..06a56cf
--- /dev/null
+++ b/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/IPatternListener.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2009-2012 by The Regents of the University of California
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * you may obtain a copy of the License from
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package edu.uci.ics.asterix.event.management;
+
+public interface IPatternListener {
+
+    public void eventCompleted(EventTaskReport report);
+
+    public void jobCompleted();
+
+    public void jobFailed(EventTaskReport report);
+}
diff --git a/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/OutputAnalysis.java b/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/OutputAnalysis.java
new file mode 100644
index 0000000..2845ede
--- /dev/null
+++ b/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/OutputAnalysis.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2009-2012 by The Regents of the University of California
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * you may obtain a copy of the License from
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package edu.uci.ics.asterix.event.management;
+
+public class OutputAnalysis {
+
+    private final boolean expected;
+    private final String errorMessage;
+
+    public OutputAnalysis(boolean expected, String errorMessage) {
+        this.expected = expected;
+        this.errorMessage = errorMessage;
+    }
+
+    public boolean isExpected() {
+        return expected;
+    }
+
+    public String getErrorMessage() {
+        return errorMessage;
+    }
+}
diff --git a/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/Randomizer.java b/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/Randomizer.java
new file mode 100644
index 0000000..e59e154
--- /dev/null
+++ b/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/Randomizer.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2009-2012 by The Regents of the University of California
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * you may obtain a copy of the License from
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package edu.uci.ics.asterix.event.management;
+
+import java.util.Random;
+import java.util.logging.Logger;
+
+public class Randomizer {
+
+	private static final Logger LOGGER = Logger.getLogger(Randomizer.class
+			.getName());
+	private static Randomizer INSTANCE;
+	private final Random random;
+	private final int seed;
+
+	public static Randomizer getInstance(int seed) {
+		if (INSTANCE == null) {
+			INSTANCE = new Randomizer(seed);
+		}
+		return INSTANCE;
+	}
+
+	public static Randomizer getInstance() {
+		if (INSTANCE == null) {
+			INSTANCE = new Randomizer();
+		}
+		return INSTANCE;
+	}
+
+	private Randomizer() {
+		Random rm = new Random();
+		seed = rm.nextInt(10000);
+		random = new Random(seed);
+		LOGGER.info("SEED:" + seed);
+	}
+
+	private Randomizer(int seed) {
+		this.seed = seed;
+		random = new Random(seed);
+		LOGGER.info("SEED:" + seed);
+	}
+
+	public Random getRandom() {
+		return random;
+	}
+
+	public int getSeed() {
+		return seed;
+	}
+
+	public int getRandomInt(int min, int max) {
+		return min + random.nextInt(max - min + 1);
+	}
+}
diff --git a/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/ValueType.java b/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/ValueType.java
new file mode 100644
index 0000000..8aa5cc5
--- /dev/null
+++ b/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/ValueType.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2009-2012 by The Regents of the University of California
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * you may obtain a copy of the License from
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package edu.uci.ics.asterix.event.management;
+
+import edu.uci.ics.asterix.event.schema.pattern.Value;
+
+public class ValueType {
+
+	public static enum Type {
+		ABS, RANDOM_RANGE, RANDOM_MIN_MAX
+	}
+
+	private Value value;
+	private Type type;
+
+	public ValueType(Value value) {
+		this.value = value;
+		if (value.getAbsvalue() != null) {
+			type = Type.ABS;
+		} else if (value.getRandom() != null) {
+			if (value.getRandom().getMinmax() != null) {
+				type = Type.RANDOM_MIN_MAX;
+			} else if (value.getRandom().getRange() != null) {
+				type = Type.RANDOM_RANGE;
+			} else {
+				throw new IllegalStateException("Incorrect value type");
+			}
+		}
+	}
+
+	public int getMin() {
+		switch (type) {
+		case RANDOM_MIN_MAX:
+			return Integer.parseInt(value.getRandom().getMinmax().getMin());
+		default:
+			throw new IllegalStateException("");
+		}
+	}
+
+	public int getMax() {
+		switch (type) {
+		case RANDOM_MIN_MAX:
+			return Integer.parseInt(value.getRandom().getMinmax().getMax());
+		default:
+			throw new IllegalStateException("");
+		}
+	}
+
+	public String[] getRangeSet() {
+		switch (type) {
+		case RANDOM_RANGE:
+			return value.getRandom().getRange().getSet().split(" ");
+		default:
+			throw new IllegalStateException("");
+		}
+	}
+
+	public String[] getRangeExcluded() {
+		switch (type) {
+		case RANDOM_RANGE:
+			String exl = value.getRandom().getRange().getExclude();
+			return exl != null ? exl.split(" ") : null;
+		default:
+			throw new IllegalStateException("");
+		}
+	}
+
+	public String getAbsoluteValue() {
+		switch (type) {
+		case ABS:
+			return value.getAbsvalue();
+		default:
+			throw new IllegalStateException("");
+		}
+	}
+
+	public Type getType() {
+		return type;
+	}
+
+}
diff --git a/asterix-events/src/main/java/edu/uci/ics/asterix/event/xml/ConfigParser.java b/asterix-events/src/main/java/edu/uci/ics/asterix/event/xml/ConfigParser.java
new file mode 100644
index 0000000..b399226
--- /dev/null
+++ b/asterix-events/src/main/java/edu/uci/ics/asterix/event/xml/ConfigParser.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2009-2012 by The Regents of the University of California
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * you may obtain a copy of the License from
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package edu.uci.ics.asterix.event.xml;
+
+import java.io.File;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Unmarshaller;
+
+public class ConfigParser {
+
+	private static final String JAXB_PKG = "edu.uci.ics.asterix.event.trigger";
+	
+	public static void main(String [] args){
+		try {
+			String path = "config/event_pattern1.xml";
+			JAXBContext ctx =  JAXBContext.newInstance(JAXB_PKG);
+		    Unmarshaller unmarshaller = ctx.createUnmarshaller();
+		    Object o = unmarshaller.unmarshal(new File(path));
+	  } catch (JAXBException e) {
+			e.printStackTrace();
+		}
+
+	}
+}
diff --git a/asterix-events/src/main/java/edu/uci/ics/asterix/event/xml/PatternParser.java b/asterix-events/src/main/java/edu/uci/ics/asterix/event/xml/PatternParser.java
new file mode 100644
index 0000000..426279c
--- /dev/null
+++ b/asterix-events/src/main/java/edu/uci/ics/asterix/event/xml/PatternParser.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2009-2012 by The Regents of the University of California
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * you may obtain a copy of the License from
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package edu.uci.ics.asterix.event.xml;
+
+public class PatternParser {
+
+	public static void parsePattern(String path){
+		
+	}
+}
+
diff --git a/asterix-events/src/main/resources/schema/cluster.xsd b/asterix-events/src/main/resources/schema/cluster.xsd
new file mode 100644
index 0000000..e5c6511
--- /dev/null
+++ b/asterix-events/src/main/resources/schema/cluster.xsd
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:cl="cluster" targetNamespace="cluster" elementFormDefault="qualified">
+
+<!-- definition of simple types --> 
+<xs:element name="name" type="xs:string"/>
+<xs:element name="ram" type="xs:string"/>
+<xs:element name="logdir" type="xs:string"/>
+<xs:element name="id" type="xs:string"/>
+<xs:element name="ip" type="xs:string"/>
+<xs:element name="cluster-ip" type="xs:string"/>
+<xs:element name="key" type="xs:string"/>
+<xs:element name="value" type="xs:string"/>
+<xs:element name="dir" type="xs:string"/>
+<xs:element name="NFS" type="xs:boolean"/>
+<xs:element name="store" type="xs:string"/>
+<xs:element name="java_home" type="xs:string"/>
+<xs:element name="username" type="xs:string"/>
+
+<!-- definition of complex elements -->
+<xs:element name="workingDir">
+  <xs:complexType>
+    <xs:sequence>
+      <xs:element ref="cl:dir"/>
+      <xs:element ref="cl:NFS"/>
+    </xs:sequence>
+  </xs:complexType>
+</xs:element>
+
+<xs:element name="master-node">
+  <xs:complexType>
+    <xs:sequence>
+      <xs:element ref="cl:id"/>
+      <xs:element ref="cl:ip"/>
+      <xs:element ref="cl:cluster-ip"/>
+      <xs:element ref="cl:ram" minOccurs="0"/>
+      <xs:element ref="cl:logdir" minOccurs="0"/>
+    </xs:sequence>
+  </xs:complexType>
+</xs:element>
+
+<xs:element name="property">
+  <xs:complexType>
+    <xs:sequence>
+      <xs:element ref="cl:key"/>
+      <xs:element ref="cl:value"/>
+    </xs:sequence>
+  </xs:complexType>
+</xs:element>
+
+<xs:element name="env">
+  <xs:complexType>
+    <xs:sequence>
+      <xs:element ref="cl:property" minOccurs="0" maxOccurs="unbounded"/>
+    </xs:sequence>
+  </xs:complexType>
+</xs:element>
+
+<xs:element name="node">
+  <xs:complexType>
+    <xs:sequence>
+      <xs:element ref="cl:id"/>
+      <xs:element ref="cl:ip"/>
+      <xs:element ref="cl:ram" minOccurs="0"/>
+      <xs:element ref="cl:logdir" minOccurs="0"/>
+      <xs:element ref="cl:store" minOccurs="0"/>
+    </xs:sequence>
+  </xs:complexType>
+</xs:element>
+
+<xs:element name="cluster">
+  <xs:complexType>
+    <xs:sequence>
+      <xs:element ref="cl:name"/>
+      <xs:element ref="cl:username"/>
+      <xs:element ref="cl:env" minOccurs="0"/>
+      <xs:element ref="cl:ram" minOccurs="0"/>
+      <xs:element ref="cl:java_home" minOccurs="1"/>
+      <xs:element ref="cl:logdir" minOccurs="0"/>
+      <xs:element ref="cl:store" minOccurs="0"/>
+      <xs:element ref="cl:workingDir"/>
+      <xs:element ref="cl:master-node"/>
+      <xs:element ref="cl:node" maxOccurs="unbounded"/>
+    </xs:sequence>
+  </xs:complexType>
+</xs:element>
+
+</xs:schema>     
diff --git a/asterix-events/src/main/resources/schema/event.xsd b/asterix-events/src/main/resources/schema/event.xsd
new file mode 100644
index 0000000..a233c18
--- /dev/null
+++ b/asterix-events/src/main/resources/schema/event.xsd
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:es="events" targetNamespace="events" elementFormDefault="qualified">
+
+<!-- definition of simple types --> 
+<xs:element name="script" type="xs:string"/>
+<xs:element name="type" type="xs:string"/>
+<xs:element name="description" type="xs:string"/>
+<xs:element name="args" type="xs:string"/>
+<xs:element name="daemon" type="xs:boolean"/>
+
+<!-- definition of complex elements -->
+
+<xs:element name="event">
+  <xs:complexType>
+    <xs:sequence>
+      <xs:element ref="es:type"/>
+      <xs:element ref="es:script"/>
+      <xs:element ref="es:description"/>
+      <xs:element ref="es:args"/>
+      <xs:element ref="es:daemon"/>
+    </xs:sequence>
+  </xs:complexType>
+</xs:element>
+
+<xs:element name="events">
+  <xs:complexType>
+    <xs:sequence>
+      <xs:element ref="es:event" maxOccurs="unbounded"/>
+    </xs:sequence>
+  </xs:complexType>
+</xs:element>
+ 
+</xs:schema>     
diff --git a/asterix-events/src/main/resources/schema/jaxb-bindings.xjb b/asterix-events/src/main/resources/schema/jaxb-bindings.xjb
new file mode 100644
index 0000000..b5982e0
--- /dev/null
+++ b/asterix-events/src/main/resources/schema/jaxb-bindings.xjb
@@ -0,0 +1,9 @@
+<jxb:bindings version="1.0"
+xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
+xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+<jxb:globalBindings>
+  <jxb:serializable uid="1"/>
+</jxb:globalBindings>
+
+</jxb:bindings>
diff --git a/asterix-events/src/main/resources/schema/pattern.xsd b/asterix-events/src/main/resources/schema/pattern.xsd
new file mode 100644
index 0000000..4eee880
--- /dev/null
+++ b/asterix-events/src/main/resources/schema/pattern.xsd
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:eg="patterns" targetNamespace="patterns">
+
+
+<!-- definition of simple types --> 
+<xs:element name="maxOccurs" type = "xs:int"/> 
+<xs:element name="pargs" type="xs:string"/>
+<xs:element name="absvalue" type="xs:string"/>
+<xs:element name="unit" type="xs:string"/>
+<xs:element name="type" type="xs:string"/>
+<xs:element name="min" type="xs:string"/>
+<xs:element name="max" type="xs:string"/>
+<xs:element name="abs" type="xs:string"/>
+<xs:element name="set" type="xs:string"/>
+<xs:element name="exclude" type="xs:string"/>
+<xs:element name="reuse" type="xs:boolean"/>
+<!-- definition of attributes -->
+
+<!-- definition of complex elements -->
+
+<xs:element name="range">
+  <xs:complexType>
+    <xs:sequence>
+     <xs:element ref="eg:set"/>
+     <xs:element ref="eg:exclude" minOccurs="0"/>
+     <xs:element ref="eg:reuse" minOccurs="0"/>
+    </xs:sequence>
+  </xs:complexType>
+</xs:element>
+
+<xs:element name="minmax">
+  <xs:complexType>
+    <xs:sequence>
+      <xs:element ref="eg:min"/>
+      <xs:element ref="eg:max"/>
+    </xs:sequence>
+  </xs:complexType>
+</xs:element>
+
+
+<xs:element name="random">
+  <xs:complexType>
+    <xs:sequence>
+       <xs:element ref="eg:minmax" minOccurs="0"/>
+       <xs:element ref="eg:range" minOccurs="0"/>
+    </xs:sequence>
+  </xs:complexType>
+</xs:element>
+
+<xs:element name="value">
+  <xs:complexType>
+    <xs:sequence>
+      <xs:element ref="eg:random" minOccurs="0"/>
+      <xs:element ref="eg:absvalue" minOccurs="0"/>
+    </xs:sequence>
+  </xs:complexType>
+</xs:element>
+
+<xs:element name="nodeid">
+  <xs:complexType>
+    <xs:sequence>
+      <xs:element ref="eg:value"/>
+    </xs:sequence>
+  </xs:complexType>
+</xs:element>
+
+<xs:element name="period">
+  <xs:complexType>
+    <xs:sequence>
+      <xs:element ref="eg:absvalue"/>
+      <xs:element ref="eg:unit"/>
+    </xs:sequence>   
+  </xs:complexType>
+</xs:element>    
+
+<xs:element name="delay">
+  <xs:complexType>
+    <xs:sequence>
+      <xs:element ref="eg:value"/>
+      <xs:element ref="eg:unit"/>
+    </xs:sequence>   
+  </xs:complexType>
+</xs:element>    
+
+<xs:element name="event">
+  <xs:complexType>
+    <xs:sequence>
+      <xs:element ref="eg:type"/>
+      <xs:element ref="eg:nodeid"/>
+      <xs:element ref="eg:pargs"/>
+    </xs:sequence>
+  </xs:complexType>
+</xs:element>
+ 
+<xs:element name="pattern">
+  <xs:complexType>
+    <xs:sequence>
+      <xs:element ref="eg:delay"/>
+      <xs:element ref="eg:maxOccurs" maxOccurs="1" minOccurs="0"/>
+      <xs:element ref="eg:period"/>
+      <xs:element ref="eg:event"/>
+    </xs:sequence>
+  </xs:complexType>
+</xs:element>
+
+<xs:element name="patterns">
+  <xs:complexType>
+    <xs:sequence>
+      <xs:element ref="eg:pattern" maxOccurs="unbounded"/>
+    </xs:sequence>
+  </xs:complexType>
+</xs:element>
+
+</xs:schema>     
diff --git a/asterix-events/src/main/resources/scripts/execute.sh b/asterix-events/src/main/resources/scripts/execute.sh
new file mode 100755
index 0000000..114a12a
--- /dev/null
+++ b/asterix-events/src/main/resources/scripts/execute.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+val=0
+line=""
+for x in $@
+do
+ if [[ $val == 0 ]]
+ then
+    line="$x="
+    val=1
+ else
+    msg="$line$x"
+    echo $line >> envr
+    val=0
+ fi
+done
+cat ./envr
diff --git a/asterix-events/src/main/resources/scripts/prepare.sh b/asterix-events/src/main/resources/scripts/prepare.sh
new file mode 100755
index 0000000..e69de29
--- /dev/null
+++ b/asterix-events/src/main/resources/scripts/prepare.sh