1
2
3
4
5
6
7
8
9
10
11 package org.astrogrid.applications.component;
12
13 import org.apache.commons.logging.Log;
14 import org.apache.commons.logging.LogFactory;
15
16 import org.astrogrid.applications.description.ApplicationDescription;
17 import org.astrogrid.applications.description.ApplicationDescriptionLibrary;
18 import org.astrogrid.applications.description.BaseApplicationDescriptionLibrary;
19 import org.astrogrid.applications.description.CompositeApplicationDescriptionLibrary;
20 import org.astrogrid.applications.description.base.ApplicationDescriptionEnvironment;
21 import org.astrogrid.applications.description.registry.RegistryAdminLocator;
22 import org.astrogrid.applications.description.registry.RegistryEntryBuilder;
23 import org.astrogrid.applications.description.registry.RegistryUploader;
24 import org.astrogrid.applications.manager.CeaThreadPool;
25 import org.astrogrid.applications.manager.DefaultMetadataService;
26 import org.astrogrid.applications.manager.DefaultQueryService;
27 import org.astrogrid.applications.manager.ExecutionController;
28 import org.astrogrid.applications.manager.MetadataService;
29 import org.astrogrid.applications.manager.QueryService;
30 import org.astrogrid.applications.manager.ThreadPoolExecutionController;
31 import org.astrogrid.applications.manager.idgen.GloballyUniqueIdGen;
32 import org.astrogrid.applications.manager.idgen.IdGen;
33 import org.astrogrid.applications.manager.persist.ExecutionHistory;
34 import org.astrogrid.applications.manager.persist.FileStoreExecutionHistory;
35 import org.astrogrid.applications.manager.persist.InMemoryExecutionHistory;
36 import org.astrogrid.applications.parameter.protocol.AgslProtocol;
37 import org.astrogrid.applications.parameter.protocol.DefaultProtocolLibrary;
38 import org.astrogrid.applications.parameter.protocol.FileProtocol;
39 import org.astrogrid.applications.parameter.protocol.FtpProtocol;
40 import org.astrogrid.applications.parameter.protocol.HttpProtocol;
41 import org.astrogrid.applications.parameter.protocol.IvornProtocol;
42 import org.astrogrid.applications.parameter.protocol.Protocol;
43 import org.astrogrid.applications.parameter.protocol.ProtocolLibrary;
44 import org.astrogrid.component.EmptyComponentManager;
45 import org.astrogrid.config.Config;
46 import org.astrogrid.registry.client.RegistryDelegateFactory;
47 import org.astrogrid.registry.client.admin.RegistryAdminService;
48
49 import org.picocontainer.ComponentAdapter;
50 import org.picocontainer.MutablePicoContainer;
51 import org.picocontainer.Startable;
52
53 import EDU.oswego.cs.dl.util.concurrent.PooledExecutor;
54
55 import java.io.File;
56 import java.net.MalformedURLException;
57 import java.net.URL;
58 import java.util.Iterator;
59
60 /*** empty implementation of {@link org.astrogrid.applications.component.CEAComponentManager}
61 * provides implementations of the accessor methods, but no componets are registered with the container. (this should be done in subclasses).
62 * <p>
63 * Registers a single validity-checking component, that depends on all the publicaly-accessible compoennts (i.e.QueryService, MetaData, etc).
64 * As picontainer checks that all dependencies can be resolved on startup, this component enforces the requirement that all component managers will have
65 * instances of the publically-accesible components. How thiese components are built up and registered is left free to the subclasses.
66 * <p/>
67 * This class also provides a set of static helper method that register 'clusters' of commonly-used components. These
68 * can be called from implementations of component manager to quickly set up the basic parts of the system
69 * @author Noel Winstanley nw@jb.man.ac.uk 04-May-2004
70 * @see org.astrogrid.applications.component.JavaClassCEAComponentManager for example of how to assemble a server using this class.
71 *
72 */
73 public abstract class EmptyCEAComponentManager extends EmptyComponentManager implements CEAComponentManager{
74 /***
75 * Commons Logger for this class
76 */
77 private static final Log logger = LogFactory
78 .getLog(EmptyCEAComponentManager.class);
79
80 /*** Construct a new EmptyCEAComponentManager
81 *
82 */
83 public EmptyCEAComponentManager() {
84 super();
85 pico.registerComponentImplementation(VerifyRequiredComponents.class);
86 }
87
88 /***
89 * @see org.astrogrid.applications.component.CEAComponentManager#getController()
90 */
91 public final ExecutionController getExecutionController() {
92 return (ExecutionController)this.pico.getComponentInstanceOfType(ExecutionController.class);
93 }
94
95 /***
96 * @see org.astrogrid.applications.component.CEAComponentManager#getMetaData()
97 */
98 public final MetadataService getMetadataService() {
99 return (MetadataService)this.pico.getComponentInstanceOfType(MetadataService.class);
100 }
101
102 public final QueryService getQueryService() {
103 return (QueryService)this.pico.getComponentInstanceOfType(QueryService.class);
104 }
105
106 public final RegistryUploader getRegistryUploaderService() {
107 return (RegistryUploader)this.pico.getComponentInstance(RegistryUploader.class);
108 }
109 /*** dummy component that ensures required componets are registered with the container
110 * not interesting, but needs to be publc so that picocontainer can instantiate it */
111 public static final class VerifyRequiredComponents {
112 /***
113 * Commons Logger for this class
114 */
115 private static final Log logger = LogFactory
116 .getLog(VerifyRequiredComponents.class);
117
118 public VerifyRequiredComponents(ExecutionController ignored,MetadataService ignoredToo, QueryService dontcare) {
119 }
120 }
121
122
123
124
125 /*** register the default top-level services core of CEA
126 * registers default implementations of {@link QueryService}, {@link MetadataService} and {@link ExecutionController},
127 * plus the {@link ApplicationDescriptionEnvironment}
128 * also registers a composite application description library, and a container application description library.
129 * @see #registerCompositeApplicationDescriptionLibrary(MutablePicoContainer)
130 * @see #registerContainerApplicationDescriptionLibrary(MutablePicoContainer)
131 * */
132 protected static final void registerDefaultServices(MutablePicoContainer pico) {
133 log.info("Registering default services");
134 pico.registerComponentImplementation(ApplicationDescriptionEnvironment.class,ApplicationDescriptionEnvironment.class);
135
136 pico.registerComponentImplementation(ExecutionController.class,ThreadPoolExecutionController.class);
137 pico.registerComponentImplementation(PooledExecutor.class,CeaThreadPool.class);
138 pico.registerComponentImplementation(MetadataService.class, DefaultMetadataService.class);
139 pico.registerComponentImplementation(QueryService.class,DefaultQueryService.class);
140 registerCompositeApplicationDescriptionLibrary(pico);
141
142
143 }
144
145 /*** registers the default implementaiton of the indirection protocol library
146 * NB: does not register any protocols with the library. These must be added to the container separately
147 * any protocols added to the container wil be detected and added to the library on startup
148 * @see #registerStandardIndirectionProtocols(MutablePicoContainer)
149 * @see #registerAstrogridIndirectionProtocols(MutablePicoContainer)*/
150 protected static final void registerProtocolLibrary(final MutablePicoContainer pico) {
151 log.info("Registering default indirection protocol library");
152 pico.registerComponentImplementation(ProtocolLibrary.class,DefaultProtocolLibrary.class);
153
154 pico.registerComponentInstance(new Startable() {
155 public void start() {
156 DefaultProtocolLibrary lib = (DefaultProtocolLibrary) pico.getComponentInstanceOfType(DefaultProtocolLibrary.class);
157 for (Iterator i = pico.getComponentAdaptersOfType(Protocol.class).iterator(); i.hasNext(); ) {
158 ComponentAdapter ca = (ComponentAdapter)i.next();
159 Protocol p = (Protocol)ca.getComponentInstance();
160 lib.addProtocol(p);
161 }
162 }
163
164 public void stop() {
165 }
166 });
167 }
168
169 /*** registers the standard indirection protocols - http:, ftp:, file: */
170 protected static final void registerStandardIndirectionProtocols(MutablePicoContainer pico) {
171 pico.registerComponentImplementation(HttpProtocol.class);
172 pico.registerComponentImplementation(FtpProtocol.class);
173 pico.registerComponentImplementation(FileProtocol.class);
174 }
175
176 /*** registers the astorgird-specific protocols - ivo: and agsl:*/
177 protected static final void registerAstrogridIndirectionProtocols(MutablePicoContainer pico) {
178 pico.registerComponentImplementation(AgslProtocol.class);
179 pico.registerComponentImplementation(IvornProtocol.class);
180 }
181
182 /*** key used to determing from config where to store execution history files
183 * @see #registerDefaultPersistence(MutablePicoContainer, Config) */
184 public static final String FILESTORE_BASEDIR = "cea.filestore.basedir";
185
186 /*** key used to determine which persistence back-end to use -
187 * <br> valid values - <tt>file</tt>, <tt>memory</tt>
188 * <br>optional- defaults to <tt>file</tt>*/
189 public static final String PERSISTENCE_BACKEND = "cea.persistence.backend";
190
191 /*** register the standard persistence system - globally unique id generation, and file-based exection history
192 * configured by {@link #FILESTORE_BASEDIR}
193 * */
194 protected static final void registerDefaultPersistence(MutablePicoContainer pico, final Config config) {
195
196 String backend = System.getProperty(PERSISTENCE_BACKEND,"file").toLowerCase().trim();
197 if (backend.equals("memory")) {
198 log.warn("Only using memory-based persistence system - all history will be lost on restart");
199 pico.registerComponentImplementation(ExecutionHistory.class,InMemoryExecutionHistory.class);
200 } else {
201 if (! backend.equals("file")) {
202 log.error("Unrecognized value '" + backend + "' for key " + PERSISTENCE_BACKEND + " - defaulting to file-based persistence");
203 }
204 log.info("Registering file-based persistence system");
205 pico.registerComponentImplementation(ExecutionHistory.class,FileStoreExecutionHistory.class);
206 pico.registerComponentInstance(FileStoreExecutionHistory.StoreDir.class, new FileStoreExecutionHistory.StoreDir(){
207 private final File dir= new File(config.getString(FILESTORE_BASEDIR,System.getProperty("java.io.tmpdir")));
208 public File getDir() {
209 return dir;
210 }
211 });
212 }
213 pico.registerComponentImplementation(IdGen.class,GloballyUniqueIdGen.class);
214 }
215
216
217 /*** key to query config for the url of the registry template to use (optional, default='/CEARegistryTemplate.xml' on classpath)
218 * @see #registerDefaultVOProvider(MutablePicoContainer, Config)*/
219 public static final String REGISTRY_TEMPLATE_URL ="cea.registry.template.url";
220 /*** key to query config for the url of this services endpoint (optional, recommended, otherwise makes a best guess)
221 * @see #registerDefaultVOProvider(MutablePicoContainer, Config)*/
222 public static final String SERVICE_ENDPOINT_URL = "cea.service.endpoint.url";
223
224 /***
225 * key to look in config under for the authorityid to add provided
226 * applications to (optional, defaults to 'org.astrogrid.localhost')
227 *
228 * @see #registerDefaultVOProvider(MutablePicoContainer, Config)
229 */
230 public final static String AUTHORITY_NAME = "cea.application.authorityid";
231
232 /*** register the standard VO Provider - the component that generates the registry entry.
233 * standard provider operates by constructing VODecription from applicationDescriptions in library
234 * @param pico
235 * @param config
236 * @see #REGISTRY_TEMPLATE_URL
237 * @see #SERVICE_ENDPOINT_URL
238 */
239 protected static final void registerDefaultVOProvider(MutablePicoContainer pico, final Config config) {
240 log.info("Registering default vo provider");
241 try {
242 pico.registerComponentImplementation(ProvidesVODescription.class, RegistryEntryBuilder.class);
243 pico.registerComponentInstance(RegistryEntryBuilder.URLs.class, new RegistryEntryBuilder.URLs() {
244 private final URL registryTemplate = config.getUrl(REGISTRY_TEMPLATE_URL,EmptyCEAComponentManager.class.getResource("/CEARegistryTemplate.xml"));
245 private final URL serviceEndpoint = config.getUrl(SERVICE_ENDPOINT_URL,new URL("http://localhost:8080/astrogrid-cea-server/services/CommonExecutionConnectorService"));
246 public URL getRegistryTemplate() {
247 return registryTemplate;
248 }
249 public URL getServiceEndpoint() {
250 return serviceEndpoint;
251 }
252 });
253 pico.registerComponentInstance(new BaseApplicationDescriptionLibrary.AppAuthorityIDResolver() {
254 protected final String auth = config.getString(AUTHORITY_NAME, "org.astrogrid.localhost");
255
256 public String getAuthorityID() {
257 return auth;
258 }
259 });
260
261 } catch (MalformedURLException e) {
262
263 log.fatal("Could could not register the vo provider " + e);
264 }
265
266 }
267 /*** register optional component that uploads vodescription to registry on startup. */
268 protected static final void registerDefaultRegistryUploader(MutablePicoContainer pico) {
269 log.info("Registering default registry uploader");
270 pico.registerComponentImplementation(RegistryUploader.class);
271 pico.registerComponentInstance(RegistryAdminLocator.class,new RegistryAdminLocator() {
272
273 public RegistryAdminService getClient() {
274 return RegistryDelegateFactory.createAdmin();
275 }
276 });
277 }
278
279 /*** register the {@link CompositeApplicationDescriptionLibrary} - this will assemble other implementations of {@link ApplicationDescriptionLibrary}
280 * registered in the container into a single unified library - allowing multiple
281 * providers to be merged.
282 * <p/>
283 * For this to work, other app description libs must be registered with pico under their own classname - <b>not</b>
284 * the interface {@link ApplicationDescriptionLIbrary}
285 * @param pico
286 */
287 protected static final void registerCompositeApplicationDescriptionLibrary(final MutablePicoContainer pico) {
288 pico.registerComponentImplementation(ApplicationDescriptionLibrary.class,CompositeApplicationDescriptionLibrary.class);
289
290 pico.registerComponentInstance(new Startable() {
291 public void start() {
292 logger.info("Registering application description libraries in composite");
293 CompositeApplicationDescriptionLibrary uberLib = (CompositeApplicationDescriptionLibrary)pico.getComponentInstanceOfType(CompositeApplicationDescriptionLibrary.class);
294 for (Iterator i = pico.getComponentAdaptersOfType(ApplicationDescriptionLibrary.class).iterator(); i.hasNext(); ) {
295 ComponentAdapter ca = (ComponentAdapter)i.next();
296 ApplicationDescriptionLibrary lib = (ApplicationDescriptionLibrary)ca.getComponentInstance();
297
298 if (lib != uberLib) {
299 uberLib.addLibrary(lib);
300 }
301 }
302 }
303
304 public void stop() {
305 }
306 });
307 }
308 /*** register an {@link ApplicationDescriptionLibrary} that will assemble all {@link ApplicationDescription} components registered with the container
309 * - this allows applicatonDescriptions to be setup and configured individually at the picocontainer level.
310 * @author Noel Winstanley nw@jb.man.ac.uk 05-Jul-2004
311 *
312 */
313 public static void registerContainerApplicationDescriptionLibrary(final MutablePicoContainer pico) {
314 pico.registerComponentImplementation(BaseApplicationDescriptionLibrary.class);
315
316 pico.registerComponentInstance(new Startable() {
317
318 public void start() {
319 BaseApplicationDescriptionLibrary lib = (BaseApplicationDescriptionLibrary)pico.getComponentInstanceOfType(BaseApplicationDescriptionLibrary.class);
320 for (Iterator i = pico.getComponentAdaptersOfType(ApplicationDescription.class).iterator(); i.hasNext();) {
321 ComponentAdapter ca = (ComponentAdapter)i.next();
322 ApplicationDescription appDesc = (ApplicationDescription)ca.getComponentInstance();
323 lib.addApplicationDescription(appDesc);
324 }
325 }
326 public void stop() {
327 }
328 });
329 }
330
331 }
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388