View Javadoc
1   package org.argeo.slc.core.execution;
2   
3   import java.net.URI;
4   import java.net.URLEncoder;
5   import java.util.ArrayList;
6   import java.util.Arrays;
7   import java.util.Iterator;
8   import java.util.List;
9   import java.util.Map;
10  
11  import org.apache.commons.logging.Log;
12  import org.apache.commons.logging.LogFactory;
13  import org.argeo.slc.DefaultNameVersion;
14  import org.argeo.slc.NameVersion;
15  import org.argeo.slc.SlcException;
16  import org.argeo.slc.execution.ExecutionFlowDescriptor;
17  import org.argeo.slc.execution.ExecutionModuleDescriptor;
18  import org.argeo.slc.execution.ExecutionSpec;
19  import org.argeo.slc.execution.ExecutionSpecAttribute;
20  import org.argeo.slc.execution.SlcAgent;
21  import org.argeo.slc.execution.SlcAgentCli;
22  
23  /**
24   * Authenticates thread and executes synchronously a command line execution.
25   * Reference implementation of args to URIs algorithm.
26   */
27  public class DefaultAgentCli implements SlcAgentCli {
28  	private final static Log log = LogFactory.getLog(DefaultAgentCli.class);
29  
30  	private final static String UTF8 = "UTF-8";
31  	private SlcAgent agent;
32  //	private AuthenticationManager authenticationManager;
33  
34  	private Long timeout = 24 * 60 * 60 * 1000l;
35  
36  	public String process(String[] args) {
37  //		if (SecurityContextHolder.getContext().getAuthentication() == null) {
38  //			OsAuthenticationToken oat = new OsAuthenticationToken();
39  //			Authentication authentication = authenticationManager
40  //					.authenticate(oat);
41  //			SecurityContextHolder.getContext()
42  //					.setAuthentication(authentication);
43  //		}
44  
45  		if (args.length > 0 && args[0].equals("help")) {
46  			StringBuilder buf = new StringBuilder();
47  			help(args, buf);
48  			log.info("\n" + buf);
49  			return buf.toString();
50  		} else {
51  			List<URI> uris = asURIs(args);
52  			String processUuid = agent.process(uris);
53  			agent.waitFor(processUuid, timeout);
54  			return processUuid;
55  		}
56  	}
57  
58  	protected void help(String[] rawArgs, StringBuilder buf) {
59  		String[] args = Arrays.copyOfRange(rawArgs, 1, rawArgs.length);
60  		if (args.length == 0) {// modules
61  			for (ExecutionModuleDescriptor emd : agent
62  					.listExecutionModuleDescriptors()) {
63  				appendModule(emd, buf);
64  			}
65  		} else if (args.length == 1 && !args[0].contains("/")) {// single module
66  			NameVersion nameVersion = new DefaultNameVersion(args[0]);
67  			ExecutionModuleDescriptor emd = agent.getExecutionModuleDescriptor(
68  					nameVersion.getName(), nameVersion.getVersion());
69  			appendModule(emd, buf);
70  
71  			// flows
72  			for (ExecutionFlowDescriptor efd : emd.getExecutionFlows()) {
73  				buf.append(" ").append(efd.getName());
74  				if (efd.getDescription() != null
75  						&& !efd.getDescription().trim().equals(""))
76  					buf.append(" : ").append(" ").append(efd.getDescription());
77  				buf.append('\n');
78  			}
79  			return;
80  		} else {
81  			List<URI> uris = asURIs(args);
82  			for (URI uri : uris) {
83  				appendUriHelp(uri, buf);
84  			}
85  		}
86  	}
87  
88  	protected void appendUriHelp(URI uri, StringBuilder buf) {
89  		String[] path = uri.getPath().split("/");
90  		NameVersion nameVersion = new DefaultNameVersion(path[1]);
91  		ExecutionModuleDescriptor emd = agent.getExecutionModuleDescriptor(
92  				nameVersion.getName(), nameVersion.getVersion());
93  
94  		StringBuilder flow = new StringBuilder();
95  		for (int i = 2; i < path.length; i++)
96  			flow.append('/').append(path[i]);
97  		String flowPath = flow.toString();
98  		ExecutionFlowDescriptor efd = findExecutionFlowDescriptor(emd, flowPath);
99  		if (efd == null)
100 			throw new SlcException("Flow " + uri + " not found");
101 
102 		appendModule(emd, buf);
103 
104 		buf.append(" ").append(efd.getName());
105 		if (efd.getDescription() != null
106 				&& !efd.getDescription().trim().equals(""))
107 			buf.append(" : ").append(" ").append(efd.getDescription());
108 		buf.append('\n');
109 		Map<String, Object> values = DefaultAgent.getQueryMap(uri.getQuery());
110 		ExecutionSpec spec = efd.getExecutionSpec();
111 		for (String attrKey : spec.getAttributes().keySet()) {
112 			ExecutionSpecAttribute esa = spec.getAttributes().get(attrKey);
113 			buf.append("  --").append(attrKey);
114 			if (values.containsKey(attrKey))
115 				buf.append(" ").append(values.get(attrKey));
116 			if (esa.getValue() != null)
117 				buf.append(" (").append(esa.getValue()).append(')');
118 			buf.append('\n');
119 		}
120 	}
121 
122 	private void appendModule(ExecutionModuleDescriptor emd, StringBuilder buf) {
123 		buf.append("# ").append(emd.getName());
124 		if (emd.getDescription() != null
125 				&& !emd.getDescription().trim().equals(""))
126 			buf.append(" : ").append(emd.getDescription());
127 		if (emd.getVersion() != null)
128 			buf.append(" (v").append(emd.getVersion()).append(")");
129 		buf.append('\n');
130 	}
131 
132 	public static List<URI> asURIs(String[] args) {
133 		try {
134 			List<URI> uris = new ArrayList<URI>();
135 			List<String> leftOvers = new ArrayList<String>();
136 
137 			Boolean hasArgs = false;
138 			String currKey = null;
139 			StringBuilder currUri = null;
140 			Iterator<String> argIt = Arrays.asList(args).iterator();
141 			while (argIt.hasNext()) {
142 				String arg = argIt.next();
143 				if (!arg.startsWith("-")) {
144 					if (currKey != null) {// value
145 						currUri.append(URLEncoder.encode(arg, UTF8));
146 						currKey = null;
147 					} else { // module
148 						if (currUri != null) {
149 							uris.add(new URI(currUri.toString()));
150 						}
151 						currUri = new StringBuilder("flow:");
152 
153 						String currModule = arg;
154 						currUri.append('/').append(currModule);
155 						if (!arg.contains("/")) {
156 							// flow path not in arg go to next arg
157 							if (!argIt.hasNext())
158 								throw new SlcException("No flow found");
159 							String currFlow = argIt.next();
160 							if (!currFlow.startsWith("/"))
161 								currFlow = "/" + currFlow;
162 							currUri.append(currFlow);
163 						}
164 					}
165 				} else {
166 					if (currUri == null) {// first args
167 						leftOvers.add(arg);
168 					} else {
169 						String key;
170 						if (arg.startsWith("--"))
171 							key = arg.substring(2);
172 						else if (arg.startsWith("-"))
173 							key = arg.substring(1);
174 						else {
175 							throw new SlcException("Cannot intepret key: "
176 									+ arg);
177 						}
178 
179 						if (!hasArgs) {
180 							currUri.append('?');
181 							hasArgs = true;
182 						} else {
183 							currUri.append('&');
184 						}
185 
186 						// deal with boolean keys
187 						if (currKey != null) {// value
188 							currUri.append(URLEncoder.encode("true", UTF8));
189 							currKey = null;
190 						}
191 
192 						currKey = key;
193 						currUri.append(URLEncoder.encode(key, UTF8))
194 								.append('=');
195 					}
196 				}
197 			}
198 			if (currUri != null)
199 				uris.add(new URI(currUri.toString()));
200 			return uris;
201 		} catch (Exception e) {
202 			throw new SlcException("Cannot convert " + Arrays.toString(args)
203 					+ " to flow URI", e);
204 		}
205 	}
206 
207 	private ExecutionFlowDescriptor findExecutionFlowDescriptor(
208 			ExecutionModuleDescriptor emd, String flowPath) {
209 		ExecutionFlowDescriptor flowDescriptor = null;
210 		for (ExecutionFlowDescriptor efd : emd.getExecutionFlows()) {
211 			String name = efd.getName();
212 			// normalize name as flow path
213 			if (!name.startsWith("/"))
214 				name = "/" + name;
215 			if (name.endsWith("/"))
216 				name = name.substring(0, name.length() - 1);
217 			if (name.equals(flowPath)) {
218 				flowDescriptor = efd;
219 				break;
220 			}
221 		}
222 		return flowDescriptor;
223 	}
224 
225 	public void setAgent(SlcAgent agent) {
226 		this.agent = agent;
227 	}
228 
229 //	public void setAuthenticationManager(
230 //			AuthenticationManager authenticationManager) {
231 //		this.authenticationManager = authenticationManager;
232 //	}
233 
234 	public void setTimeout(Long timeout) {
235 		this.timeout = timeout;
236 	}
237 
238 }