1
2
3
4
5
6
7
8
9
10
11 package org.astrogrid.jes.jobscheduler.locator;
12
13 import org.astrogrid.component.descriptor.ComponentDescriptor;
14 import org.astrogrid.jes.JesException;
15 import org.astrogrid.jes.jobscheduler.Locator;
16 import org.astrogrid.registry.RegistryException;
17
18 import org.astrogrid.registry.client.RegistryDelegateFactory;
19 import org.astrogrid.registry.client.query.RegistryService;
20 import org.astrogrid.workflow.beans.v1.Step;
21 import org.astrogrid.workflow.beans.v1.Tool;
22
23 import org.apache.axis.utils.XMLUtils;
24 import org.apache.commons.logging.Log;
25 import org.apache.commons.logging.LogFactory;
26 import org.w3c.dom.Document;
27 import org.w3c.dom.NodeList;
28
29 import java.io.StringWriter;
30 import java.net.MalformedURLException;
31 import java.net.URL;
32 import java.util.ArrayList;
33 import java.util.Arrays;
34 import java.util.Collections;
35 import java.util.HashSet;
36 import java.util.List;
37 import java.util.Random;
38 import java.util.Set;
39
40 import junit.framework.Test;
41
42 /*** Tool locator that resolves tools using the registry.
43 * @author Noel Winstanley nw@jb.man.ac.uk 08-Mar-2004
44 * @todo needs to be re-thought to allow calling of different types of service - resolving to endpoints is still valid - however, many registered services will have a single reg entry,
45 * rather than cea-application and cea-service - so query pattern is different
46 *
47 */
48 public class RegistryToolLocator implements Locator, ComponentDescriptor {
49 private static final Log logger = LogFactory.getLog(RegistryToolLocator.class);
50 /*** interface to configure registry with */
51 public interface RegistryEndpoint {
52 URL getURL();
53 }
54
55 public RegistryToolLocator(RegistryEndpoint endpoint) {
56 url = endpoint.getURL();
57 delegate = RegistryDelegateFactory.createQuery(url);
58 }
59
60 protected final URL url;
61 protected final RegistryService delegate;
62 protected final Random rand = new Random();
63
64 /***
65 * @see org.astrogrid.jes.jobscheduler.Locator#locateTool(org.astrogrid.workflow.beans.v1.Step)
66 */
67 public String[] locateTool(Tool tool) throws JesException{
68 String name =tool.getName();
69 logger.info("Locating service endpoints for cea application " + name);
70
71 if (name == null ) {
72 throw reportError("Unnamed application - cannot locate it");
73 }
74 Document toolDocument;
75 try {
76 toolDocument = delegate.getResourceByIdentifier(name);
77 }
78 catch (RegistryException e) {
79 throw reportError("Could not find registry entry for cea application " + name,e);
80 }
81
82 String toolId = null;
83
84 String[] toolIds = getIdentifiers(toolDocument);
85 if (toolIds.length == 0) {
86 throw reportError("No identifiers in registry entry for cea application" + name);
87 }
88 toolId = toolIds[0];
89
90
91
92
93
94 logger.debug("found cea application: " + toolId);
95
96
97
98 String queryString = buildQueryString(toolId);
99 logger.debug("ADQL Query to find services " + queryString);
100 Document results = null;
101 try {
102
103 results = delegate.searchFromSADQL(queryString);
104 } catch (RegistryException e) {
105 throw reportError("Failed to query registry for services providing tool " + name,e);
106 }
107
108 String[] serviceIds = null;
109
110 serviceIds = getIdentifiers(results);
111 logger.info("Found " + serviceIds.length + " matching cea services");
112 if (serviceIds.length == 0) {
113 throw reportError("Tool " + name + " has no known service providers");
114 }
115
116
117
118
119
120
121
122 logger.debug("Resolving services to endpoints");
123 Set endpoints = new HashSet();
124 for (int i = 0; i < serviceIds.length ; i++) {
125 String serviceName = serviceIds[i];
126 try {
127
128
129 String endpoint = delegate.getEndPointByIdentifier(serviceName);
130 if (endpoint != null && endpoint.trim().length() > 0) {
131 try {
132 URL ep = new URL(endpoint);
133 endpoints.add(ep.toString());
134 } catch (MalformedURLException e) {
135 logger.warn("Service " + serviceName + "has duff endpoint URL",e);
136 }
137 }
138 logger.debug("Service " + serviceName + " resolved to endpoint " + endpoint);
139 } catch (RegistryException e) {
140 logger.warn("Resolvng endpoint for " + serviceName + " failed",e);
141 }
142 }
143
144
145 if (endpoints.size() == 0) {
146 throw reportError("No service providers for Tool " + name +" have a valid endpoint");
147 } else if (endpoints.size() == 1) {
148 logger.info("Service Endpoints for CEA application " + name + ": " + endpoints);
149 return new String[]{endpoints.iterator().next().toString()};
150 } else {
151 logger.debug("More that one available service - shuffling..");
152 List endpointsList = new ArrayList(endpoints);
153 Collections.shuffle(endpointsList);
154 logger.info("Service Endpoints for CEA application " + name + ": " + endpointsList);
155 return (String[])endpointsList.toArray(new String[endpointsList.size()]);
156 }
157 }
158
159
160 private JesException reportError(String s, Exception e) {
161 logger.error(s,e);
162 return new JesException(s,e);
163 }
164 private JesException reportError(String s) {
165 logger.error(s);
166 return new JesException(s);
167 }
168
169
170 private String buildQueryString(String toolId) {
171 String queryString = "Select * from Registry where " +
172 "cea:ManagedApplications/cea:ApplicationReference='" + toolId + "'";
173 return queryString;
174
175 }
176
177 /***
178 queries registry to get tool entry, extract details from this.
179 */
180 private String[] getIdentifiers(Document doc) {
181 logger.debug("Extracting Identifiers");
182 NodeList nl = doc.getElementsByTagNameNS("*","Resource");
183 String[] results = new String[nl.getLength()];
184 for (int i = 0; i < nl.getLength(); i++) {
185 results[i] = ((org.w3c.dom.Element)nl.item(i)).getElementsByTagNameNS("*","identifier")
186 .item(0).getFirstChild().getNodeValue();
187 logger.debug(results[i]);
188 }
189 return results;
190 }
191
192 /***
193 * @see org.astrogrid.jes.jobscheduler.Locator#getToolInterface(org.astrogrid.workflow.beans.v1.Step)
194 */
195 public String getToolInterface(Step js) throws JesException {
196 logger.error("Deprecated method, not used");
197 return null;
198 }
199 /***
200 * @see org.astrogrid.jes.component.ComponentDescriptor#getName()
201 */
202 public String getName() {
203 return "Registry Tool Locator";
204 }
205 /***
206 * @see org.astrogrid.jes.component.ComponentDescriptor#getDescription()
207 */
208 public String getDescription() {
209 return "Resolve Tool locations using an astrogrid registry" +
210 "\n Currently looking in registry at " + url.toString();
211 }
212 /*** @todo check we can resolve endpoint
213 * @see org.astrogrid.jes.component.ComponentDescriptor#getInstallationTest()
214 */
215 public Test getInstallationTest() {
216 return null;
217 }
218 }
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289