001: /*
002: * <copyright>
003: *
004: * Copyright 2002-2004 BBNT Solutions, LLC
005: * under sponsorship of the Defense Advanced Research Projects
006: * Agency (DARPA).
007: *
008: * You can redistribute this software and/or modify it under the
009: * terms of the Cougaar Open Source License as published on the
010: * Cougaar Open Source Website (www.cougaar.org).
011: *
012: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
013: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
014: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
015: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
016: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
017: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
018: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
019: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
020: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
021: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
022: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
023: *
024: * </copyright>
025: */
026:
027: package org.cougaar.servicediscovery.util.yp;
028:
029: import java.io.File;
030: import java.io.FileInputStream;
031: import java.util.ArrayList;
032: import java.util.Arrays;
033: import java.util.Collection;
034: import java.util.Iterator;
035: import java.util.Vector;
036:
037: import org.apache.xerces.parsers.DOMParser;
038:
039: import org.cougaar.core.agent.service.alarm.Alarm;
040: import org.cougaar.core.component.ComponentSupport;
041: import org.cougaar.core.service.AgentIdentificationService;
042: import org.cougaar.core.service.AlarmService;
043: import org.cougaar.core.service.LoggingService;
044: import org.cougaar.core.service.ThreadService;
045: import org.cougaar.servicediscovery.util.UDDIConstants;
046: import org.cougaar.util.StateMachine;
047: import org.cougaar.yp.YPProxy;
048: import org.cougaar.yp.YPService;
049: import org.cougaar.yp.YPStateMachine;
050:
051: import org.uddi4j.datatype.tmodel.TModel;
052: import org.uddi4j.response.AuthToken;
053: import org.uddi4j.response.TModelDetail;
054: import org.uddi4j.util.CategoryBag;
055: import org.uddi4j.util.KeyedReference;
056: import org.xml.sax.InputSource;
057:
058: /**
059: *
060: */
061: public class PublishTaxonomy extends ComponentSupport {
062: private static String UDDI_USERID = "cougaar";
063: private static String UDDI_PASSWORD = "cougaarPass";
064:
065: static {
066: UDDI_USERID = System.getProperty(
067: "org.cougaar.yp.juddi-users.username",
068: YPProxy.DEFAULT_UDDI_USERNAME);
069: UDDI_PASSWORD = System.getProperty(
070: "org.cougaar.yp.juddi-users.password",
071: YPProxy.DEFAULT_UDDI_PASSWORD);
072: }
073:
074: private static final String FILE_EXTENSION = "-yp.xml";
075:
076: private static int WARNING_SUPPRESSION_INTERVAL = 2;
077: private static final String TAXONOMY_GRACE_PERIOD = "org.cougaar.servicediscovery.util.yp.TaxonomyGracePeriod";
078: private long myWarningCutoffTime = -1;
079:
080: private YPProxy myYPProxy;
081:
082: private AlarmService myAlarmService;
083: private AgentIdentificationService myAgentIdentificationService;
084: private LoggingService myLoggingService;
085: private ThreadService myThreadService;
086: private YPService myYPService;
087:
088: private Alarm myAlarm;
089:
090: private ArrayList myTModelNames;
091:
092: private String myBasePath;
093:
094: private static String[] TMODELNAMES = {
095: UDDIConstants.MILITARY_SERVICE_SCHEME,
096: UDDIConstants.MILITARY_ECHELON_SCHEME,
097: UDDIConstants.ORGANIZATION_TYPES,
098: UDDIConstants.SOURCING_CAPABILITY_SCHEME,
099: UDDIConstants.SUPPORT_COMMAND_ASSIGNMENT };
100:
101: public void setAgentIdentificationService(
102: AgentIdentificationService ais) {
103: myAgentIdentificationService = ais;
104: }
105:
106: protected final AgentIdentificationService getAgentIdentificationService() {
107: return myAgentIdentificationService;
108: }
109:
110: public void setAlarmService(AlarmService as) {
111: myAlarmService = as;
112: }
113:
114: protected final AlarmService getAlarmService() {
115: return myAlarmService;
116: }
117:
118: public void setLoggingService(LoggingService ls) {
119: myLoggingService = ls;
120: }
121:
122: protected final LoggingService getLoggingService() {
123: return myLoggingService;
124: }
125:
126: public void setThreadService(ThreadService ts) {
127: myThreadService = ts;
128: }
129:
130: protected final ThreadService getThreadService() {
131: return myThreadService;
132: }
133:
134: public void setYPService(YPService yps) {
135: myYPService = yps;
136: }
137:
138: protected final YPService getYPService() {
139: return myYPService;
140: }
141:
142: public void setBasePath(String basePath) {
143: if (myBasePath == null) {
144: myBasePath = basePath;
145: } else {
146: getLoggingService().warn(
147: "setBasePath: attempt to reset basePath "
148: + " from " + myBasePath + " to " + basePath
149: + " ignored.");
150: }
151: }
152:
153: protected String getBasePath() {
154: if (myBasePath == null) {
155: return System.getProperty("org.cougaar.install.path")
156: + File.separator + "servicediscovery"
157: + File.separator + "data" + File.separator
158: + "taxonomies" + File.separator;
159: } else {
160: return myBasePath;
161: }
162: }
163:
164: public void initialize() {
165: super .initialize();
166:
167: setTModelNames(Arrays.asList(TMODELNAMES));
168: }
169:
170: public void load() {
171: super .load();
172:
173: // Don't mess around with community based lookup.
174: // Assume component loaded in the same agent as the YPServer
175: myYPProxy = getYPService().getYP(
176: getAgentIdentificationService().getMessageAddress());
177:
178: loadTaxonomies();
179: }
180:
181: protected void loadTaxonomies() {
182: new PublishTaxonomyMachine(new PublishTaxonomyCallback())
183: .start();
184: }
185:
186: public long getWarningCutoffTime() {
187: if (myWarningCutoffTime == -1) {
188: WARNING_SUPPRESSION_INTERVAL = Integer
189: .getInteger(TAXONOMY_GRACE_PERIOD,
190: WARNING_SUPPRESSION_INTERVAL).intValue();
191: myWarningCutoffTime = System.currentTimeMillis()
192: + (WARNING_SUPPRESSION_INTERVAL * 60000);
193: }
194:
195: return myWarningCutoffTime;
196: }
197:
198: public void setTModelNames(Collection tModelNames) {
199: myTModelNames = new ArrayList(tModelNames.size());
200: for (Iterator iterator = tModelNames.iterator(); iterator
201: .hasNext();) {
202: String tModelName = (String) iterator.next();
203: addTModelName(tModelName);
204: }
205: }
206:
207: public void addTModelName(String tModelName) {
208: myTModelNames.add(tModelName);
209: }
210:
211: private class PublishTaxonomyMachine extends YPStateMachine {
212: protected final PublishTaxonomyCallback myCallback;
213:
214: PublishTaxonomyMachine(PublishTaxonomyCallback callback) {
215: super (myYPService, myYPProxy, myThreadService);
216: myCallback = callback;
217: }
218:
219: public void transit(State s0, State s1) {
220: if (getLoggingService().isInfoEnabled()) {
221: getLoggingService().info(
222: "StateMachine transit: " + s0 + " to " + s1);
223: }
224: super .transit(s0, s1);
225: }
226:
227: protected void kick() {
228: if (getLoggingService().isInfoEnabled()) {
229: getLoggingService().info("kicked");
230: }
231: super .kick();
232: }
233:
234: public synchronized State add(State state) {
235: if (getLoggingService().isInfoEnabled()) {
236: getLoggingService().info("added - " + state);
237: }
238: return super .add(state);
239: }
240:
241: private int gentaxi = 0;
242:
243: protected void init() {
244: super .init();
245:
246: addLink("START", "getToken");
247: add(new SState("getToken") {
248: public void invoke() {
249: try {
250: call("getAuthToken", null, "gotToken");
251: } catch (Exception e) {
252: logHandledError(
253: "getAuthToken: Caught exception", e);
254: transit("DONE");
255: }
256: }
257: });
258: addLink("gotToken", "startTaxonomy");
259:
260: addLink("startTaxonomy", "genTax");
261: add(new SState("genTax") {
262: public void invoke() {
263: gentaxi = 0;
264: transit("genTax0");
265: }
266: });
267: add(new SState("genTax0") {
268: public void invoke() {
269: if (gentaxi < myTModelNames.size()) {
270: call("genTaxonomy", myTModelNames.get(gentaxi),
271: "genTax1");
272: } else {
273: transit("doneTaxonomy");
274: }
275: }
276: });
277:
278: add(new SState("genTax1") {
279: public void invoke() {
280: gentaxi++;
281: transit("genTax0");
282: }
283: });
284:
285: addLink("doneTaxonomy", "startTModels");
286:
287: addLink("startTModels", "tm0");
288: add(new SState("tm0") {
289: public void invoke() {
290: call("createBindingTModels", null, "doneTModels");
291: }
292: });
293: add(new SState("doneTModels") {
294: public void invoke() {
295: call("discardAuthToken", null, "DONE");
296: }
297: });
298:
299: // subroutines
300:
301: // genTaxonomy
302: add(new SState("genTaxonomy") {
303: public void invoke() {
304: String name = (String) getArgument();
305: String completeFileName = getBasePath() + name
306: + FILE_EXTENSION;
307:
308: if (validPath(completeFileName)) {
309: call("createTaxonomy", new String[] { name,
310: completeFileName }, "POP");
311: } else {
312: getLoggingService().error(
313: "Invalid Path: " + completeFileName);
314: transit("POP");
315: }
316: }
317: });
318:
319: // createTaxonomy
320: addTModelPush("createTaxonomy", "POP", new TModelThunk() {
321: public TModel make(Frame f) {
322: String[] args = (String[]) f.getArgument();
323: String name = args[0];
324: TModel tModel = new TModel();
325: tModel.setName(name);
326: return tModel;
327: }
328:
329: public TModel update(Frame f, TModelDetail tModelDetail) {
330: // get the args again
331: String[] args = (String[]) f.getArgument();
332: String name = args[0];
333: String file = args[1];
334:
335: String tModelKey = ((TModel) (tModelDetail
336: .getTModelVector().elementAt(0)))
337: .getTModelKey();
338:
339: TModel tmodel = null;
340:
341: try {
342: tmodel = createTaxonomy(name, file, tModelKey);
343: } catch (Exception e) {
344: logHandledError(
345: "createTaxonomy: Caught exception in "
346: + name, e);
347: transit("DONE");
348: }
349: return tmodel;
350: }
351: });
352:
353: //
354: // createBindingTModels
355: addLink("createBindingTModels", "createCougaarBinding");
356: addTModelPush("createCougaarBinding", "createSoapBinding",
357: new TModelThunk() {
358: public TModel make(Frame f) {
359: TModel cougaarTModel = new TModel("",
360: "COUGAAR:Binding");
361: cougaarTModel
362: .setDefaultDescriptionString("Protocol for COUGAAR services");
363: return cougaarTModel;
364: }
365:
366: public TModel update(Frame f,
367: TModelDetail tModelDetail) {
368: Vector tModels = tModelDetail
369: .getTModelVector();
370: return addCougaarBinding((TModel) tModels
371: .elementAt(0));
372: }
373: });
374: addTModelPush("createSoapBinding", "doneCBT",
375: new TModelThunk() {
376: public TModel make(Frame f) {
377: TModel soapTModel = new TModel("",
378: "SOAP:Binding");
379: soapTModel
380: .setDefaultDescriptionString("SOAP binding for non-COUGAAR services");
381: return soapTModel;
382: }
383:
384: public TModel update(Frame f,
385: TModelDetail tModelDetail) {
386: Vector tModels = tModelDetail
387: .getTModelVector();
388: return addSoapBinding((TModel) tModels
389: .elementAt(0));
390: }
391: });
392: addLink("doneCBT", "POP");
393:
394: addLink("YPError", "handleYPError");
395: add(new SState("handleYPError") {
396: public void invoke() {
397: getCallback().handle(
398: (Exception) getVar("YPErrorException"),
399: (String) getVar("YPErrorText"));
400: }
401: });
402:
403: }
404:
405: protected void logHandledError(String message, Throwable e) {
406: getCallback().handle(e, message);
407: }
408:
409: protected PublishTaxonomyCallback getCallback() {
410: return myCallback;
411: }
412: }
413:
414: private TModel createTaxonomy(String name, String file,
415: String tModelKey) throws java.io.IOException,
416: org.xml.sax.SAXException, org.uddi4j.UDDIException {
417: if (getLoggingService().isInfoEnabled()) {
418: getLoggingService().info(
419: "createTaxonomy: name = " + name + ", file = "
420: + file + ", tModelKey = " + tModelKey);
421: }
422:
423: FileInputStream fis = new FileInputStream(file);
424: DOMParser parser = new DOMParser();
425: parser.parse(new InputSource(fis));
426: TModel tModel = new TModel(parser.getDocument()
427: .getDocumentElement());
428:
429: tModel.setName(name);
430: tModel.setTModelKey(tModelKey);
431:
432: // Add TModelKey to KeyedReferences
433: CategoryBag categoryBag = tModel.getCategoryBag();
434: for (int index = 0; index < categoryBag.size(); index++) {
435: KeyedReference keyedReference = categoryBag.get(index);
436: keyedReference.setTModelKey(tModelKey);
437: }
438: return tModel;
439: }
440:
441: protected TModel addCougaarBinding(TModel tm) {
442: CategoryBag categoryBag = new CategoryBag();
443: KeyedReference wsdlKr = new KeyedReference("uddi-org:types",
444: "wsdlSpec");
445: wsdlKr.setTModelKey(tm.getTModelKey());
446: Vector krList = new Vector();
447: krList.add(wsdlKr);
448: categoryBag.setKeyedReferenceVector(krList);
449: tm.setCategoryBag(categoryBag);
450: return tm;
451: }
452:
453: protected TModel addSoapBinding(TModel tm) {
454: CategoryBag categoryBag = new CategoryBag();
455: KeyedReference soapKr = new KeyedReference("uddi-org:types",
456: "soapSpec");
457: soapKr.setTModelKey(tm.getTModelKey());
458: // described by WSDL
459: Vector krList = new Vector();
460: krList.add(soapKr);
461: KeyedReference wsdlKr = new KeyedReference("uddi-org:types",
462: "wsdlSpec");
463: wsdlKr.setTModelKey(tm.getTModelKey());
464: krList.add(wsdlKr);
465: categoryBag.setKeyedReferenceVector(krList);
466: tm.setCategoryBag(categoryBag);
467: return tm;
468: }
469:
470: private static boolean validPath(String path) {
471: return (new File(path)).exists();
472: }
473:
474: private class PublishTaxonomyCallback {
475: void handle(Throwable e, String exceptionText) {
476: int rand = (int) (Math.random() * 10000) + 1000;
477:
478: if (System.currentTimeMillis() > getWarningCutoffTime()) {
479: if (exceptionText == null) {
480: getLoggingService()
481: .error(
482: "Problem adding service discovery taxonomies, try again later.",
483: e);
484: } else {
485: getLoggingService().error(exceptionText, e);
486: getLoggingService()
487: .error(
488: "Problem adding service discovery taxonomies, try again later.");
489: }
490: } else if (getLoggingService().isDebugEnabled()) {
491: if (exceptionText == null) {
492: getLoggingService()
493: .debug(
494: "Problem adding service discovery taxonomies, try again later.",
495: e);
496: } else {
497: getLoggingService().debug(exceptionText, e);
498: getLoggingService()
499: .debug(
500: "Problem adding service discovery taxonomies, try again later.");
501: }
502: }
503:
504: myAlarm = new PublishAlarm(getAlarmService()
505: .currentTimeMillis()
506: + rand);
507: getAlarmService().addAlarm(myAlarm);
508:
509: }
510: }
511:
512: public class PublishAlarm implements Alarm {
513: private long expiresAt;
514: private boolean expired = false;
515:
516: public PublishAlarm(long expirationTime) {
517: expiresAt = expirationTime;
518: }
519:
520: public long getExpirationTime() {
521: return expiresAt;
522: }
523:
524: public synchronized void expire() {
525: if (!expired) {
526: expired = true;
527: loadTaxonomies();
528: }
529: }
530:
531: public boolean hasExpired() {
532: return expired;
533: }
534:
535: public synchronized boolean cancel() {
536: boolean was = expired;
537: expired = true;
538: return was;
539: }
540:
541: public String toString() {
542: return "<PublishAlarm " + expiresAt
543: + (expired ? "(Expired) " : " ")
544: + "for PublishTaxonomy at "
545: + getAgentIdentificationService().getName() + ">";
546: }
547: }
548: }
|