1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package com.gridsystems.nextgrid.api.pom.components;
19
20 import java.io.File;
21 import java.io.IOException;
22 import java.net.URI;
23 import java.util.Collections;
24 import java.util.HashMap;
25 import java.util.Map;
26 import java.util.regex.Matcher;
27 import java.util.regex.Pattern;
28
29 import javax.xml.namespace.QName;
30
31 import nextgrid.api.env.ProcessEnvironment;
32 import nextgrid.api.pom.Grounding;
33 import nextgrid.api.pom.GroundingFactory;
34 import nextgrid.api.pom.ProcessException;
35 import nextgrid.api.pom.Reference;
36 import nextgrid.api.pom.Service;
37
38 import org.apache.commons.io.FileUtils;
39 import org.apache.commons.jxpath.JXPathContext;
40 import org.apache.commons.logging.Log;
41 import org.apache.commons.logging.LogFactory;
42
43 import com.gridsystems.nextgrid.api.pom.AbstractGroundingImpl;
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116 public class FileSystemGrounding extends AbstractGroundingImpl
117 implements GroundingFactory {
118
119
120
121
122 private static final long serialVersionUID = 4080593507919268762L;
123
124
125
126
127 private static final Map<QName, String> ATTRIBS;
128
129
130
131
132 private static final Log LOG = LogFactory.getLog(FileSystemGrounding.class);
133
134
135
136
137 public static final String OP_DELETE_FILE = "DeleteFile";
138
139
140
141
142 public static final String OP_CREATE_FROM_TEMPLATE = "CreateFileFromTemplate";
143
144
145
146
147 public static final String TYPE = "urn:file-system";
148
149
150
151
152 public static final URI TYPE_URI = URI.create("urn:file-system");
153
154 static {
155 Map<QName, String> attrs = new HashMap<QName, String>();
156 attrs.put(ATTR_OPERATION, "Operation name");
157 ATTRIBS = Collections.unmodifiableMap(attrs);
158 }
159
160
161
162
163 public FileSystemGrounding() {
164 super(TYPE_URI, ATTRIBS);
165 }
166
167
168
169
170 public void dispose() {
171 }
172
173
174
175
176 public void invoke(ProcessEnvironment env, Service service)
177 throws ProcessException {
178
179 String op = service.getAttribute(ATTR_OPERATION);
180 if (OP_DELETE_FILE.equalsIgnoreCase(op)) {
181 deleteFile(service);
182 } else if (OP_CREATE_FROM_TEMPLATE.equalsIgnoreCase(op)) {
183 createFromTemplate(service);
184 } else {
185 throw new ProcessException("Invalid operation '" + op + "'");
186 }
187 }
188
189
190
191
192
193
194
195 private void deleteFile(Service service) throws ProcessException {
196 Map<String, Reference<?>> inputs = service.getInputs();
197
198 for (String name : inputs.keySet()) {
199 Reference<?> ref = inputs.get(name);
200
201 try {
202 File f = toFile(ref);
203
204 if (f == null) {
205 LOG.warn("Skiping null file reference input '" + name + "'");
206 } else {
207 LOG.info("Deleting file " + f.getPath());
208 FileUtils.forceDelete(f);
209 }
210 } catch (IOException e) {
211 throw new ProcessException("Error executing grounding", e);
212 }
213 }
214 }
215
216
217
218
219
220
221
222 private void createFromTemplate(Service service) throws ProcessException {
223 try {
224
225
226 Reference<?> refDest = service.getInput("dest");
227 File dest = toFile(refDest);
228 if (dest == null) {
229 String path = service.getAttribute(NS_GROUNDING, "dest");
230 if (path != null) {
231 dest = new File(path);
232 }
233 }
234
235 if (dest == null) {
236 dest = File.createTempFile("fsg", ".tmp");
237 } else if (dest.isDirectory()) {
238 throw new ProcessException("Destination file is a directory");
239 }
240 LOG.info("Template destination: " + dest);
241
242
243 String template = null;
244
245 Reference<?> refTemplate = service.getInput("template");
246 if (refTemplate == null) {
247 String path = service.getAttribute(NS_GROUNDING, "template-path");
248 if (path == null) {
249 template = service.getAttribute(NS_GROUNDING, "template");
250 } else {
251 File f = new File(path);
252 if (f.isFile()) {
253 template = FileUtils.readFileToString(f);
254 } else {
255 throw new ProcessException("Invalid template path: " + path);
256 }
257 }
258 } else {
259 if (refTemplate.canCastTo(String.class)) {
260 template = (String)refTemplate.castTo(String.class);
261 }
262 }
263
264 if (template != null && template.length() > 0) {
265 String data = applyTemplate(template, service);
266 FileUtils.writeStringToFile(dest, data);
267 }
268
269 Reference<?> output = service.getOutput("file");
270 if (output != null) {
271 if (output.canCastFrom(File.class)) {
272 output.setValue(dest);
273 } else {
274 LOG.warn("Invalid output type. Output ignored.");
275 }
276 }
277
278
279 } catch (IOException e) {
280 throw new ProcessException("I/O error", e);
281 }
282 }
283
284
285
286
287
288
289
290
291
292 private String applyTemplate(String template, Service service) {
293 JXPathContext context = JXPathContext.newContext(service);
294
295 String result = template;
296
297
298 Pattern p = Pattern.compile(".*\\{\\{(.+)\\}\\}.*", Pattern.DOTALL);
299
300 boolean changed = true;
301 while (changed) {
302 changed = false;
303
304 Matcher m = p.matcher(result);
305 if (m.matches()) {
306 String expr = m.group(1);
307 try {
308 Object value = context.getValue(expr);
309 if (value != null) {
310 changed = true;
311 result = result.replaceAll("\\{\\{" + expr + "\\}\\}", value.toString());
312 }
313 } catch (Exception e) {
314 e.printStackTrace();
315 }
316 }
317 }
318 return result;
319 }
320
321
322
323
324
325
326
327
328 private File toFile(Reference<?> ref) throws ProcessException {
329 if (ref == null) {
330 return null;
331 } else if (ref.canCastTo(File.class)) {
332 return (File)ref.castTo(File.class);
333 } else if (ref.canCastTo(String.class)) {
334 return new File((String)ref.castTo(String.class));
335 } else {
336 throw new ProcessException("Invalid File reference");
337 }
338 }
339
340
341
342
343 public void validate() throws ProcessException {
344 }
345
346
347
348
349 public Grounding createGrounding() {
350 return this;
351 }
352
353 }