View Javadoc
1   /*
2    * Copyright (C) 2007-2012 Argeo GmbH
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *         http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.argeo.slc.jcr.execution;
17  
18  import java.util.ArrayList;
19  import java.util.Calendar;
20  import java.util.GregorianCalendar;
21  import java.util.List;
22  
23  import javax.jcr.Node;
24  import javax.jcr.NodeIterator;
25  import javax.jcr.Property;
26  import javax.jcr.Repository;
27  import javax.jcr.RepositoryException;
28  
29  import org.apache.commons.logging.Log;
30  import org.apache.commons.logging.LogFactory;
31  import org.argeo.jcr.JcrUtils;
32  import org.argeo.slc.NameVersion;
33  import org.argeo.slc.SlcException;
34  import org.argeo.slc.SlcNames;
35  import org.argeo.slc.SlcTypes;
36  import org.argeo.slc.core.execution.ProcessThread;
37  import org.argeo.slc.execution.ExecutionProcess;
38  import org.argeo.slc.execution.ExecutionStep;
39  import org.argeo.slc.execution.RealizedFlow;
40  import org.argeo.slc.jcr.SlcJcrUtils;
41  
42  /** Execution process implementation based on a JCR node. */
43  public class JcrExecutionProcess implements ExecutionProcess, SlcNames {
44  	private final static Log log = LogFactory.getLog(JcrExecutionProcess.class);
45  	private final Node node;
46  
47  	private Long nextLogLine = 1l;
48  
49  	public JcrExecutionProcess(Node node) {
50  		this.node = node;
51  	}
52  
53  	public synchronized String getUuid() {
54  		try {
55  			return node.getProperty(SLC_UUID).getString();
56  		} catch (RepositoryException e) {
57  			throw new SlcException("Cannot get uuid for " + node, e);
58  		}
59  	}
60  
61  	public synchronized String getStatus() {
62  		try {
63  			return node.getProperty(SLC_STATUS).getString();
64  		} catch (RepositoryException e) {
65  			log.error("Cannot get status: " + e);
66  			// we should re-throw exception because this information can
67  			// probably used for monitoring in case there are already unexpected
68  			// exceptions
69  			return UNKOWN;
70  		}
71  	}
72  
73  	public synchronized void setStatus(String status) {
74  		try {
75  			node.setProperty(SLC_STATUS, status);
76  			// last modified properties needs to be manually updated
77  			// see https://issues.apache.org/jira/browse/JCR-2233
78  			JcrUtils.updateLastModified(node);
79  			node.getSession().save();
80  		} catch (RepositoryException e) {
81  			JcrUtils.discardUnderlyingSessionQuietly(node);
82  			// we should re-throw exception because this information can
83  			// probably used for monitoring in case there are already unexpected
84  			// exceptions
85  			log.error("Cannot set status " + status + ": " + e);
86  		}
87  	}
88  
89  	/**
90  	 * Synchronized in order to make sure that there is no concurrent
91  	 * modification of {@link #nextLogLine}.
92  	 */
93  	public synchronized void addSteps(List<ExecutionStep> steps) {
94  		try {
95  			steps: for (ExecutionStep step : steps) {
96  				String type;
97  				if (step.getType().equals(ExecutionStep.TRACE))
98  					type = SlcTypes.SLC_LOG_TRACE;
99  				else if (step.getType().equals(ExecutionStep.DEBUG))
100 					type = SlcTypes.SLC_LOG_DEBUG;
101 				else if (step.getType().equals(ExecutionStep.INFO))
102 					type = SlcTypes.SLC_LOG_INFO;
103 				else if (step.getType().equals(ExecutionStep.WARNING))
104 					type = SlcTypes.SLC_LOG_WARNING;
105 				else if (step.getType().equals(ExecutionStep.ERROR))
106 					type = SlcTypes.SLC_LOG_ERROR;
107 				else
108 					// skip
109 					continue steps;
110 
111 				String relPath = SLC_LOG + '/'
112 						+ step.getThread().replace('/', '_') + '/'
113 						+ step.getLocation().replace('.', '/');
114 				String path = node.getPath() + '/' + relPath;
115 				// clean special character
116 				// TODO factorize in JcrUtils
117 				path = path.replace('@', '_');
118 
119 				Node location = JcrUtils.mkdirs(node.getSession(), path);
120 				Node logEntry = location.addNode(Long.toString(nextLogLine),
121 						type);
122 				logEntry.setProperty(SLC_MESSAGE, step.getLog());
123 				Calendar calendar = new GregorianCalendar();
124 				calendar.setTime(step.getTimestamp());
125 				logEntry.setProperty(SLC_TIMESTAMP, calendar);
126 
127 				// System.out.println("Logged " + logEntry.getPath());
128 
129 				nextLogLine++;
130 			}
131 
132 			// last modified properties needs to be manually updated
133 			// see https://issues.apache.org/jira/browse/JCR-2233
134 			JcrUtils.updateLastModified(node);
135 
136 			node.getSession().save();
137 		} catch (Exception e) {
138 			JcrUtils.discardUnderlyingSessionQuietly(node);
139 			e.printStackTrace();
140 		}
141 	}
142 
143 	// public Node getNode() {
144 	// return node;
145 	// }
146 
147 	public List<RealizedFlow> getRealizedFlows() {
148 		try {
149 			List<RealizedFlow> realizedFlows = new ArrayList<RealizedFlow>();
150 			Node rootRealizedFlowNode = node.getNode(SLC_FLOW);
151 			// we just manage one level for the time being
152 			NodeIterator nit = rootRealizedFlowNode.getNodes(SLC_FLOW);
153 			while (nit.hasNext()) {
154 				Node realizedFlowNode = nit.nextNode();
155 
156 				if (realizedFlowNode.hasNode(SLC_ADDRESS)) {
157 					String flowPath = realizedFlowNode.getNode(SLC_ADDRESS)
158 							.getProperty(Property.JCR_PATH).getString();
159 					NameVersion moduleNameVersion = SlcJcrUtils
160 							.moduleNameVersion(flowPath);
161 					((ProcessThread) Thread.currentThread())
162 							.getExecutionModulesManager().start(
163 									moduleNameVersion);
164 				}
165 
166 				RealizedFlow realizedFlow = new JcrRealizedFlow(
167 						realizedFlowNode);
168 				if (realizedFlow != null)
169 					realizedFlows.add(realizedFlow);
170 			}
171 			return realizedFlows;
172 		} catch (RepositoryException e) {
173 			throw new SlcException("Cannot get realized flows", e);
174 		}
175 	}
176 
177 	public String getNodePath() {
178 		try {
179 			return node.getPath();
180 		} catch (RepositoryException e) {
181 			throw new SlcException("Cannot get process node path for " + node,
182 					e);
183 		}
184 	}
185 
186 	public Repository getRepository() {
187 		try {
188 			return node.getSession().getRepository();
189 		} catch (RepositoryException e) {
190 			throw new SlcException("Cannot get process JCR repository for "
191 					+ node, e);
192 		}
193 	}
194 }