public interface IWorkflowDAO {
	public void insertOozieApp(OozieApp oozieApp) throws Exception;

	public void deleteOozieApp(String appName) throws Exception;
	
	public List<OozieApp> selectOozieApp() throws Exception;

	public void insertOozieJob(OozieJob oozieJob) throws Exception;

	public void updateOozieJob(OozieJob oozieJob) throws Exception;

	public List<OozieJob> selectOozieJob(String jobName) throws Exception;

	public List<OozieJob> selectOozieJobByApp(String appName) throws Exception;

	public void deleteOozieJob(String jobName) throws Exception;

	public void insertOozieJobHistory(OozieJobHistory oozieJobHistory) throws Exception;

	public void deleteOozieJobHistory(String jobName) throws Exception;

	public List<OozieJobHistory> selectOozieJobHistory(String jobName, Timestamp from, Timestamp to) throws Exception;
} @Repository("workflowDAO")
public class WorkflowDAO extends SqlMapBase implements IWorkflowDAO {
	@Override
	public void insertOozieApp(OozieApp oozieApp) throws Exception {
		//this.sqlMapClient.insert("workflowSQL.insertOozieApp", oozieApp);
	}

	@Override
	public void deleteOozieApp(String appName) throws Exception {
		//this.sqlMapClient.delete("workflowSQL.deleteOozieApp", appName);
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<OozieApp> selectOozieApp() throws Exception {
		//return (List<OozieApp>)this.sqlMapClient.queryForList("workflowSQL.selectOozieApp");
		return null;
	}
	
	@Override
	public void insertOozieJobHistory(OozieJobHistory oozieJobHistory) throws Exception {
		this.sqlMapClient.insert("workflowSQL.insertOozieJobHistory", oozieJobHistory);
	}

	@Override
	public void deleteOozieJobHistory(String jobName) throws Exception {
		this.sqlMapClient.insert("workflowSQL.deleteOozieJobHistory", jobName);
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<OozieJobHistory> selectOozieJobHistory(String jobName, Timestamp from, Timestamp to) throws Exception {
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("jobName", jobName);
		if(from != null) {
			params.put("from", from);
			params.put("to", to);
		}
		return (List<OozieJobHistory>)this.sqlMapClient.queryForList("workflowSQL.selectOozieJobHistory", params);
	}
	
	@Override
	public void insertOozieJob(OozieJob oozieJob) throws Exception {
		this.sqlMapClient.insert("workflowSQL.insertOozieJob", oozieJob);
	}

	@Override
	public void updateOozieJob(OozieJob oozieJob) throws Exception {
		this.sqlMapClient.update("workflowSQL.updateOozieJob", oozieJob);
	}

	@Override
	public void deleteOozieJob(String jobName) throws Exception {
		this.sqlMapClient.delete("workflowSQL.deleteOozieJob", jobName);
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<OozieJob> selectOozieJob(String jobName) throws Exception {
		Map<String, String> params = new HashMap<String, String>();
		if(jobName != null && !jobName.isEmpty()) {
			params.put("jobName", jobName);
		}
		return (List<OozieJob>)this.sqlMapClient.queryForList("workflowSQL.selectOozieJob", params);
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public List<OozieJob> selectOozieJobByApp(String appName) throws Exception {
		Map<String, String> params = new HashMap<String, String>();
		params.put("appName", appName);
		return (List<OozieJob>)this.sqlMapClient.queryForList("workflowSQL.selectOozieJob", params);
	}
} public class AppLibFile {
	private String appName;
	private String fileName;
	private String libPath;
	private String fullPath;
	private long length;
	private long lastModifiedTime;
	
	//class type -> class list
	private Map<String, List<String>> classList;
	
	public String getFileName() {
		return fileName;
	}
	public void setFileName(String fileName) {
		this.fileName = fileName;
	}
	public String getFullPath() {
		return fullPath;
	}
	public void setFullPath(String fullPath) {
		this.fullPath = fullPath;
	}
	public long getLength() {
		return length;
	}
	public void setLength(long length) {
		this.length = length;
	}
	public long getLastModifiedTime() {
		return lastModifiedTime;
	}
	public void setLastModifiedTime(long lastModifiedTime) {
		this.lastModifiedTime = lastModifiedTime;
	}
	public Map<String, List<String>> getClassList() {
		return classList;
	}
	public void setClassList(Map<String, List<String>> classList) {
		this.classList = classList;
	}
	public String getAppName() {
		return appName;
	}
	public void setAppName(String appName) {
		this.appName = appName;
	}
	public String getLibPath() {
		return libPath;
	}
	public void setLibPath(String libPath) {
		this.libPath = libPath;
	}
} public class OozieApp {
	public static final Log LOG = LogFactory.getLog(OozieApp.class);
	
	private String appName;
	private String xml;
	private String creator;
	private String description;
	private String appPath;
	private String positions;
	private List<OozieAppItem> items = new ArrayList<OozieAppItem>();
	
	public String getAppName() {
		return appName;
	}
	public void setAppName(String appName) {
		this.appName = appName;
	}
	public String getXml() {
		return xml;
	}
	public void setXml(String xml) {
		this.xml = xml;
	}
	public List<OozieAppItem> getItems() {
		return items;
	}
	public void setItems(List<OozieAppItem> items) {
		this.items = items;
	}
	public String getCreator() {
		return creator;
	}
	public void setCreator(String creator) {
		this.creator = creator;
	}
	public String getDescription() {
		return description;
	}
	public void setDescription(String description) {
		this.description = description;
	}
	public String getAppPath() {
		return appPath;
	}
	public void setAppPath(String appPath) {
		this.appPath = appPath;
	}
	public String getPositions() {
		return positions;
	}
	public void setPositions(String positions) {
		this.positions = positions;
	}

	public void parseXml() throws Exception {
		if(xml == null || xml.isEmpty()) {
			//throw new IOException("No xml info");
			return;
		}
		
		String xmlStr = xml;
		if(!xmlStr.startsWith("<?xml")) {
			xmlStr = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + xml;
		}
    DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
    docBuilderFactory.setIgnoringComments(true);
    //docBuilderFactory.setNamespaceAware(true);
    /*
    try {
        docBuilderFactory.setXIncludeAware(true);
    } catch (UnsupportedOperationException e) {
      LOG.error("Failed to set setXIncludeAware(true) for parser " + docBuilderFactory + ":" + e, e);
    }
    */
    DocumentBuilder builder = docBuilderFactory.newDocumentBuilder();
    Document doc = builder.parse(new ByteArrayInputStream(xmlStr.getBytes()));
    Element root = doc.getDocumentElement();

    NodeList itemNodes = root.getChildNodes();
    for (int i = 0; i < itemNodes.getLength(); i++) {
      Node propNode = itemNodes.item(i);
      if (!(propNode instanceof Element)) {
      	continue;
      }
      Element prop = (Element)propNode;
 
      items.add(OozieAppItem.makeItem(prop));
    }
	}

	@Override
	public String toString() {
		return appName;
	}
	
	public static void main(String[] args) throws Exception {
		InputStream in = new FileInputStream("/Users/babokim/work/program/oozie-3.2.0-incubating/examples/apps/map-reduce/workflow.xml1");
		
		byte[] buf = new byte[1024 * 1024];
		
		int length = in.read(buf);
		
		OozieApp app = new OozieApp();
		app.setXml(new String(buf, 0, length));
		
		app.parseXml();
		
		System.out.println(app.toString());
	}
} public class OozieClusterInfo {
	private String appRootPath;
	private List<String> jobTrackers;
	private List<String> nameNodes;
	
	public String getAppRootPath() {
		return appRootPath;
	}
	public void setAppRootPath(String appRootPath) {
		this.appRootPath = appRootPath;
	}
	public List<String> getJobTrackers() {
		return jobTrackers;
	}
	public void setJobTrackers(List<String> jobTrackers) {
		this.jobTrackers = jobTrackers;
	}
	public List<String> getNameNodes() {
		return nameNodes;
	}
	public void setNameNodes(List<String> nameNodes) {
		this.nameNodes = nameNodes;
	}
} public class OozieHiveQuery {
	private String category;
	private String queryName;
	private String query;
	private long createdAt;
	public String getCategory() {
		return category;
	}
	public void setCategory(String category) {
		this.category = category;
	}
	public String getQuery() {
		return query;
	}
	public void setQuery(String query) {
		this.query = query;
	}
	public long getCreatedAt() {
		return createdAt;
	}
	public void setCreatedAt(long createdAt) {
		this.createdAt = createdAt;
	}
	public String getQueryName() {
		return queryName;
	}
	public void setQueryName(String queryName) {
		this.queryName = queryName;
	}
} public class OozieJob implements ScheduledJob {
	private String appName;
	private String jobName;
	private String userName;
	private String mailTo;
	private String mailOnlyFail;
	private String xml;							//readonly
	private String description;
	private String scheduleInfo;
	private String jobParams;				//readonly
	private String lastJobId;
	private String lastStatus;
	private Timestamp lastExecutionTime;
	
	private Map<String, String> jobParamMap = new HashMap<String, String>();
	private List<OozieJobHistory> jobHistories;
	
	public String getAppName() {
		return appName;
	}
	public void setAppName(String appName) {
		this.appName = appName;
	}
	public String getJobName() {
		return jobName;
	}
	public void setJobName(String jobName) {
		this.jobName = jobName;
	}
	public String getXml() {
		return xml;
	}
	public void setXml(String xml) {
		this.xml = xml;
	}
	public String getDescription() {
		return description;
	}
	public void setDescription(String description) {
		this.description = description;
	}
	public String getJobParams() {
		return jobParams;
	}
	public void setJobParams(String jobParams) {
		this.jobParams = jobParams;
		if(jobParams != null) {
			try {
				this.jobParamMap = WorkflowService.om.readValue(jobParams, new TypeReference<HashMap<String, String>>(){});
			} catch (Exception e) {
				WorkflowService.LOG.warn(e.getMessage(), e);
			}
		}
	}
	public Map<String, String> getJobParamMap() {
		return jobParamMap;
	}
	public String getScheduleInfo() {
		return scheduleInfo;
	}
	public void setScheduleInfo(String scheduleInfo) {
		this.scheduleInfo = scheduleInfo;
	}
	public void setJobParamMap(Map<String, String> jobParamMap) {
		this.jobParamMap = jobParamMap;
	}
	public String getLastStatus() {
		return lastStatus;
	}
	public void setLastStatus(String lastStatus) {
		this.lastStatus = lastStatus;
	}
	public Timestamp getLastExecutionTime() {
		return lastExecutionTime;
	}
	public void setLastExecutionTime(Timestamp lastExecutionTime) {
		this.lastExecutionTime = lastExecutionTime;
	}
	public String getLastJobId() {
		return lastJobId;
	}
	public void setLastJobId(String lastJobId) {
		this.lastJobId = lastJobId;
	}
	public List<OozieJobHistory> getJobHistories() {
		return jobHistories;
	}
	public void setJobHistories(List<OozieJobHistory> jobHistories) {
		this.jobHistories = jobHistories;
	}
	public String getUserName() {
		return userName;
	}
	public void setUserName(String userName) {
		this.userName = userName;
	}
	public String getMailTo() {
		return mailTo;
	}
	public void setMailTo(String mailTo) {
		this.mailTo = mailTo;
	}
	public String getMailOnlyFail() {
		return mailOnlyFail;
	}
	public void setMailOnlyFail(String mailOnlyFail) {
		this.mailOnlyFail = mailOnlyFail;
	}
} public class OozieJobAction {
  private String id;
  private String name;
  private String cred;
  private String type;
  private String conf;
  private String status;
  private int retries;
  private int userRetryCount;
  private int userRetryMax;
  private int userRetryInterval;
  private long startTime;
  private long endTime;
  private String transition;
  private String data;
  private String stats;
  private String externalChildIDs;
  private String externalId;
  private String externalStatus;
  private String trackerUri;
  private String consoleUrl;
  private String errorCode;
  private String errorMessage;
  
	public OozieJobAction() {
		
	}
	
	public OozieJobAction(WorkflowAction eachAction) {
	  this.id = eachAction.getId();
	  this.name = eachAction.getName();
	  this.cred = eachAction.getCred();
	  this.type = eachAction.getType();
	  this.conf = eachAction.getConf();
	  this.status = eachAction.getStatus().toString();
	  this.retries = eachAction.getRetries();
	  this.userRetryCount = eachAction.getUserRetryCount();
	  this.userRetryMax = eachAction.getUserRetryMax();
	  this.userRetryInterval = eachAction.getUserRetryInterval();
	  if(eachAction.getStartTime() != null) {
	  	this.startTime = eachAction.getStartTime().getTime();
	  }
	  
	  if(eachAction.getEndTime() != null) {
	  	this.endTime = eachAction.getEndTime().getTime();
	  }
	  this.transition = eachAction.getTransition();
	  this.data = eachAction.getData();
	  this.stats = eachAction.getStats();
	  this.externalChildIDs = eachAction.getExternalChildIDs();
	  this.externalId = eachAction.getExternalId();
	  this.externalStatus = eachAction.getExternalStatus();
	  this.trackerUri = eachAction.getTrackerUri();
	  this.consoleUrl = eachAction.getConsoleUrl();
	  this.errorCode = eachAction.getErrorCode();
	  this.errorMessage = eachAction.getErrorMessage();
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getCred() {
		return cred;
	}

	public void setCred(String cred) {
		this.cred = cred;
	}

	public String getType() {
		return type;
	}

	public void setType(String type) {
		this.type = type;
	}

	public String getConf() {
		return conf;
	}

	public void setConf(String conf) {
		this.conf = conf;
	}

	public String getStatus() {
		return status;
	}

	public void setStatus(String status) {
		this.status = status;
	}

	public int getRetries() {
		return retries;
	}

	public void setRetries(int retries) {
		this.retries = retries;
	}

	public int getUserRetryCount() {
		return userRetryCount;
	}

	public void setUserRetryCount(int userRetryCount) {
		this.userRetryCount = userRetryCount;
	}

	public int getUserRetryMax() {
		return userRetryMax;
	}

	public void setUserRetryMax(int userRetryMax) {
		this.userRetryMax = userRetryMax;
	}

	public int getUserRetryInterval() {
		return userRetryInterval;
	}

	public void setUserRetryInterval(int userRetryInterval) {
		this.userRetryInterval = userRetryInterval;
	}

	public long getStartTime() {
		return startTime;
	}

	public void setStartTime(long startTime) {
		this.startTime = startTime;
	}

	public long getEndTime() {
		return endTime;
	}

	public void setEndTime(long endTime) {
		this.endTime = endTime;
	}

	public String getTransition() {
		return transition;
	}

	public void setTransition(String transition) {
		this.transition = transition;
	}

	public String getData() {
		return data;
	}

	public void setData(String data) {
		this.data = data;
	}

	public String getStats() {
		return stats;
	}

	public void setStats(String stats) {
		this.stats = stats;
	}

	public String getExternalChildIDs() {
		return externalChildIDs;
	}

	public void setExternalChildIDs(String externalChildIDs) {
		this.externalChildIDs = externalChildIDs;
	}

	public String getExternalId() {
		return externalId;
	}

	public void setExternalId(String externalId) {
		this.externalId = externalId;
	}

	public String getExternalStatus() {
		return externalStatus;
	}

	public void setExternalStatus(String externalStatus) {
		this.externalStatus = externalStatus;
	}

	public String getTrackerUri() {
		return trackerUri;
	}

	public void setTrackerUri(String trackerUri) {
		this.trackerUri = trackerUri;
	}

	public String getConsoleUrl() {
		return consoleUrl;
	}

	public void setConsoleUrl(String consoleUrl) {
		this.consoleUrl = consoleUrl;
	}

	public String getErrorCode() {
		return errorCode;
	}

	public void setErrorCode(String errorCode) {
		this.errorCode = errorCode;
	}

	public String getErrorMessage() {
		return errorMessage;
	}

	public void setErrorMessage(String errorMessage) {
		this.errorMessage = errorMessage;
	}
} public class OozieJobHistory {
	private String jobName;
	private String jobId;
	private Timestamp execTime;
	
	public String getJobName() {
		return jobName;
	}
	public void setJobName(String jobName) {
		this.jobName = jobName;
	}
	public String getJobId() {
		return jobId;
	}
	public void setJobId(String jobId) {
		this.jobId = jobId;
	}
	public Timestamp getExecTime() {
		return execTime;
	}
	public void setExecTime(Timestamp execTime) {
		this.execTime = execTime;
	}
} public class OozieJobStatus {
	private String appPath;
	private String jobName;
	private String id;
	private String parentId;
	private String conf;
	private String xml;
	private String status;
	private long createdTime;
	private long startTime;
	private long lastModifiedTime;
	private long endTime;
	private String user;
	private String group;
	private int run;
	
	private String consoleUrl;
	
	private List<OozieJobAction> actions;
	
	Map<String, String> configMap = new HashMap<String, String>();
	
	public OozieJobStatus() {
	}
	
	public OozieJobStatus(WorkflowJobBean workflowJobBean) {
		appPath = workflowJobBean.getAppPath();
		jobName = workflowJobBean.getAppName();
		id = workflowJobBean.getId();
		parentId  = workflowJobBean.getParentId();
		conf = workflowJobBean.getConf();
		status = workflowJobBean.getStatusStr();
		
		if(workflowJobBean.getCreatedTime() != null) {
			createdTime = workflowJobBean.getCreatedTime().getTime();
		}
		
		if(workflowJobBean.getStartTime() != null) {
			startTime = workflowJobBean.getStartTime().getTime();
		}
		
		if(workflowJobBean.getLastModifiedTime() != null) {
			lastModifiedTime = workflowJobBean.getLastModifiedTime().getTime();
		}
		
		if(workflowJobBean.getEndTime() != null){		
			endTime = workflowJobBean.getEndTime().getTime();
		}
		user = workflowJobBean.getUser();
		group = workflowJobBean.getGroup();
		run = workflowJobBean.getRun();
		consoleUrl= workflowJobBean.getConsoleUrl();
		
		if(conf != null) {
			StringReader reader = new StringReader(conf);
			try {
				XConfiguration config = new XConfiguration(reader);
				for(Map.Entry<String, String> entry: config) {
					configMap.put(entry.getKey(), entry.getValue());
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	public Map<String, String> getConfigMap() {
		return configMap;
	}
	
	public String getAppPath() {
		return appPath;
	}
	public void setAppPath(String appPath) {
		this.appPath = appPath;
	}
	public String getJobName() {
		return jobName;
	}
	public void setJobName(String jobName) {
		this.jobName = jobName;
	}
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getParentId() {
		return parentId;
	}
	public void setParentId(String parentId) {
		this.parentId = parentId;
	}
	public String getConf() {
		return conf;
	}
	public void setConf(String conf) {
		this.conf = conf;
	}
	public String getStatus() {
		return status;
	}
	public void setStatus(String status) {
		this.status = status;
	}
	public long getCreatedTime() {
		return createdTime;
	}
	public void setCreatedTime(long createdTime) {
		this.createdTime = createdTime;
	}
	public long getStartTime() {
		return startTime;
	}
	public void setStartTime(long startTime) {
		this.startTime = startTime;
	}
	public long getLastModifiedTime() {
		return lastModifiedTime;
	}
	public void setLastModifiedTime(long lastModifiedTime) {
		this.lastModifiedTime = lastModifiedTime;
	}
	public long getEndTime() {
		return endTime;
	}
	public void setEndTime(long endTime) {
		this.endTime = endTime;
	}
	public String getUser() {
		return user;
	}
	public void setUser(String user) {
		this.user = user;
	}
	public String getGroup() {
		return group;
	}
	public void setGroup(String group) {
		this.group = group;
	}
	public int getRun() {
		return run;
	}
	public void setRun(int run) {
		this.run = run;
	}

	public String getConsoleUrl() {
		return consoleUrl;
	}

	public void setConsoleUrl(String consoleUrl) {
		this.consoleUrl = consoleUrl;
	}

	public List<OozieJobAction> getActions() {
		return actions;
	}

	public void setActions(List<OozieJobAction> actions) {
		this.actions = actions;
	}

	public String getXml() {
		return xml;
	}

	public void setXml(String xml) {
		this.xml = xml;
	}
} public class HadoopCluster {
	String clusterName;
	
	public HadoopCluster() {
	}
	
	public String getClusterName() {
		return clusterName;
	}

	public void setClusterName(String clusterName) {
		this.clusterName = clusterName;
	}
} public class HiveConnection {
	private int id;
	private String name;
	private String description;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	/**
	 * @param description the description to set
	 */
	public void setDescription(String description) {
		this.description = description;
	}

	/**
	 * @return the description
	 */
	public String getDescription() {
		return description;
	}
} public class HiveQuery {
	private int id;
	private String queryName;
	private String categoryName;
	private String query;
	private String creatorName;
	private Timestamp createDate;
	private String description;
	private int connectionId;
	
	public String getQueryName() {
		return queryName;
	}
	public void setQueryName(String queryName) {
		this.queryName = queryName;
	}
	public String getCategoryName() {
		return categoryName;
	}
	public void setCategoryName(String categoryName) {
		this.categoryName = categoryName;
	}
	public String getQuery() {
		return query;
	}
	public void setQuery(String query) {
		this.query = query;
	}
	public String getCreatorName() {
		return creatorName;
	}
	public void setCreatorName(String creatorName) {
		this.creatorName = creatorName;
	}
	public Timestamp getCreateDate() {
		return createDate;
	}
	public void setCreateDate(Timestamp createDate) {
		this.createDate = createDate;
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getDescription() {
		return description;
	}
	public void setDescription(String description) {
		this.description = description;
	}
	public int getConnectionId() {
		return connectionId;
	}
	public void setConnectionId(int connectionId) {
		this.connectionId = connectionId;
	}
} public interface IAlarmService {

	public void sendAlarm(String clusterType, String clusterName, String server, String alarmType, String subject, List<String> alarmTargets, Map<String, String> messageParams);

} public interface IConfService {

	public String get(String key, String defaultValue);
	public String get(String key);
	public boolean getBoolean(String ket, boolean defaultValue);

} public interface IHadoopService {

	public List<HadoopCluster> listHadoopClusters();

} public interface IHiveMetaStoreService {

	public List<HiveConnection> getConnections();

} public interface IHiveQueryService {

	public List<HiveQuery> getHiveQueryList(int id);

} public interface IMapReduceService {

	public List<HadoopCluster> listMapReduceClusters();

} @Service("oozieExternalService")
public class OozieExternalService implements IConfService, IHadoopService, 
							IHiveMetaStoreService, IHiveQueryService, IMapReduceService, IAlarmService {
	
	private Properties managerConf = new Properties();
	
	public OozieExternalService() {
		try {
			managerConf.load(this.getClass().getResourceAsStream("/settings.properties"));
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	@Override
	public String get(String key) {
		return (String)managerConf.get(key);
	}
	
	@Override
	public String get(String key, String defaultValue) {
		String value = this.get(key);
		if(value == null) {
			return defaultValue;
		} else {
			return value;
		}
	}

	@Override
	public List<HiveConnection> getConnections() {
		return new ArrayList<HiveConnection>();
	}

	@Override
	public boolean getBoolean(String key, boolean defaultValue) {
		String value = this.get(key);
		if(value == null) {
			return defaultValue;
		} else {
			return "true".equalsIgnoreCase(value);
		}
	}

	@Override
	public List<HadoopCluster> listHadoopClusters() {
		return new ArrayList<HadoopCluster>();
	}

	@Override
	public List<HiveQuery> getHiveQueryList(int id) {
		return new ArrayList<HiveQuery>();
	}

	@Override
	public List<HadoopCluster> listMapReduceClusters() {
		return new ArrayList<HadoopCluster>();
	}

	@Override
	public void sendAlarm(String clusterType, String clusterName, String server, 
			String alarmType, String subject, List<String> alarmTargets, Map<String, String> messageParams) {
		
	}

} public interface JobRunner {
	public List<ScheduledJob> getScheduledJobs();
	public void runScheduledJob(ScheduledJob eachJob);
} public class JobTimer extends Thread {
	private static final Logger LOG = LoggerFactory.getLogger(JobTimer.class);
	
	private static AtomicBoolean alreadyStarted = new AtomicBoolean(false);
	
	private AtomicBoolean stop = new AtomicBoolean(false);
	private JobRunner jobRunner;
	
	public JobTimer(JobRunner jobRunner) {
		this.jobRunner = jobRunner;
	}
	
	public void callStop() {
		stop.set(true);
		this.interrupt();
	}
	
	@Override
	public void run() {
		synchronized(alreadyStarted) {
			if(alreadyStarted.get()) {
				LOG.warn("==================>Scheduler timer already started");
				return;
			}
			alreadyStarted.set(true);
		}
		//initial sleep
		try {
			Thread.sleep(30 * 1000);
		} catch (InterruptedException e1) {
		}
		
		final AtomicLong currentTime = new AtomicLong(System.currentTimeMillis());
		long nextMinute = ((currentTime.get() / 60000) + 1) * 60000;
		
		LOG.info("==>Job Scheduler Timer started");
		while(!stop.get()) {
			long sleepTime = (nextMinute - System.currentTimeMillis());
			if (sleepTime > 0) {
				try {
					sleepDuration(sleepTime);
				} catch (InterruptedException e) {
					break;
				}
			}
			currentTime.set(System.currentTimeMillis());
			final List<ScheduledJob> jobs = jobRunner.getScheduledJobs();
			Thread t = new Thread() {
				public void run() {
					long time = currentTime.get();
					for(ScheduledJob eachJob: jobs) {
						try {
							CronPattern pattern = new CronPattern(eachJob.getScheduleInfo());
							if(pattern == null) {
								LOG.warn("No pattern info:" + eachJob.getJobName());
								continue;
							}
							
							if(pattern.match(time)) {
								LOG.info("LaunchJob: " + eachJob.getJobName());
								jobRunner.runScheduledJob(eachJob);
							}
						} catch (Exception e) {
							LOG.warn(e.getMessage(), e);
						}
					}
				}
			};
			t.start();
			nextMinute = ((currentTime.get() / 60000) + 1) * 60000;
		}
	}
	
	private void sleepDuration(long duration) throws InterruptedException {
		long sum = 0;
		do {
			long before = System.currentTimeMillis();
			sleep(duration - sum);
			long after = System.currentTimeMillis();
			sum += (after - before);
		} while (sum < duration);
	}
} public interface ScheduledJob {
	public String getScheduleInfo();
	public String getJobName();
} public class CloumonOozieServicesLoader implements ServletContextListener {
  public static Services services;

  /**
   * Initialize Oozie services.
   *
   * @param event context event.
   */
  public void contextInitialized(ServletContextEvent event) {
      try {
          services = new Services();
          services.init();
      }
      catch (Throwable ex) {
          System.out.println();
          System.out.println("ERROR: Oozie could not be started");
          System.out.println();
          System.out.println("REASON: " + ex.toString());
          System.out.println();
          System.out.println("Stacktrace:");
          System.out.println("-----------------------------------------------------------------");
          ex.printStackTrace(System.out);
          System.out.println("-----------------------------------------------------------------");
          System.out.println();
          System.exit(1);
      }
  }

  /**
   * Destroy Oozie services.
   *
   * @param event context event.
   */
  public void contextDestroyed(ServletContextEvent event) {
      services.destroy();
  }

}
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.TreeSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hive.conf.HiveConf;
import org.apache.hadoop.io.Writable;
import org.apache.hadoop.mapred.InputFormat;
import org.apache.hadoop.mapred.JobConf;
import org.apache.hadoop.mapred.Mapper;
import org.apache.hadoop.mapred.OutputFormat;
import org.apache.hadoop.mapred.Reducer;
import org.apache.oozie.DagEngine;
import org.apache.oozie.DagEngineException;
import org.apache.oozie.ErrorCode;
import org.apache.oozie.WorkflowJobBean;
import org.apache.oozie.WorkflowsInfo;
import org.apache.oozie.client.OozieClient;
import org.apache.oozie.client.WorkflowAction;
import org.apache.oozie.service.DagEngineService;
import org.apache.oozie.service.Services;
import org.apache.oozie.servlet.XServletException;
import org.apache.oozie.util.JobUtils;
import org.apache.oozie.util.XConfiguration;
import org.cloumon.gruter.oozie.dao.IWorkflowDAO;
import org.cloumon.gruter.oozie.dao.WorkflowDAO;
import org.cloumon.gruter.oozie.model.AppLibFile;
import org.cloumon.gruter.oozie.model.OozieApp;
import org.cloumon.gruter.oozie.model.OozieClusterInfo;
import org.cloumon.gruter.oozie.model.OozieHiveQuery;
import org.cloumon.gruter.oozie.model.OozieJob;
import org.cloumon.gruter.oozie.model.OozieJobAction;
import org.cloumon.gruter.oozie.model.OozieJobHistory;
import org.cloumon.gruter.oozie.model.OozieJobStatus;
import org.cloumon.gruter.oozie.service.external.HadoopCluster;
import org.cloumon.gruter.oozie.service.external.HiveConnection;
import org.cloumon.gruter.oozie.service.external.HiveQuery;
import org.cloumon.gruter.oozie.service.external.IAlarmService;
import org.cloumon.gruter.oozie.service.external.IConfService;
import org.cloumon.gruter.oozie.service.external.IHadoopService;
import org.cloumon.gruter.oozie.service.external.IHiveMetaStoreService;
import org.cloumon.gruter.oozie.service.external.IHiveQueryService;
import org.cloumon.gruter.oozie.service.external.IMapReduceService;
import org.cloumon.gruter.oozie.service.external.OozieExternalService;
import org.cloumon.gruter.oozie.service.timer.JobRunner;
import org.cloumon.gruter.oozie.service.timer.JobTimer;
import org.cloumon.gruter.oozie.service.timer.ScheduledJob;
import org.cloumon.gruter.oozie.web.CloumonOozieServicesLoader;
import org.codehaus.jackson.map.DeserializationConfig;
import org.codehaus.jackson.map.ObjectMapper;
import org.springframework.stereotype.Service;
package org.cloumon.gruter.oozie.service;




@Service("workflowService")
public class WorkflowService implements IWorkflowService, JobRunner {
	//TOOD Job이 실행된 후 luanch job에서 에러가 발생한 경우 결과 처리(job counter의 oozie.launcher	oozie.launcher.error = 1)
	public static final Log LOG = LogFactory.getLog(WorkflowService.class);
	
	public static final String APP_XML_FILE = "workflow.xml";
	
	public static final String APP_DATA_FILE = "cloumon.dat";
	
//	public static final String OOZIE_COMMON_LIB = "common_lib";
	
	private static Pattern varPat = Pattern.compile("\\$\\{[^\\}\\$\u0020]+\\}");

	public static ObjectMapper om = new ObjectMapper();
	static {
		om.getDeserializationConfig().disable(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES);
	}

	@Resource(type = WorkflowDAO.class)
	IWorkflowDAO workflowDAO;

	@Resource(type=OozieExternalService.class)
	IHadoopService hadoopService;
	
	@Resource(type=OozieExternalService.class)
	IMapReduceService mapReduceService;
	
	@Resource(type=OozieExternalService.class)
	IHiveMetaStoreService hiveMetaStoreService;
	
	@Resource(type=OozieExternalService.class)
	IHiveQueryService hiveQueryService;
	
	private Configuration hdfsConf;

	@Resource(type = OozieExternalService.class)
	private IConfService confService;