package org.cagrid.serviceregistration; import java.util.ArrayList; import java.util.Calendar; import java.util.GregorianCalendar; import java.util.List; import javax.xml.namespace.QName; import javax.xml.ws.BindingProvider; import javax.xml.ws.Holder; import org.apache.cxf.headers.Header; import org.cagrid.serviceregistration.model.ServiceGroupRegistrationParameters; import org.oasis_open.docs.wsrf._2004._06.wsrf_ws_resourcelifetime_1_2_draft_01.SetTerminationTime; import org.oasis_open.docs.wsrf._2004._06.wsrf_ws_resourcelifetime_1_2_draft_01_wsdl.ScheduledResourceTermination; import org.oasis_open.docs.wsrf._2004._06.wsrf_ws_servicegroup_1_2_draft_01.Add; import org.oasis_open.docs.wsrf._2004._06.wsrf_ws_servicegroup_1_2_draft_01_wsdl.ServiceGroupRegistration; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.quartz.StatefulJob; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.xmlsoap.schemas.ws._2004._03.addressing.EndpointReferenceType; import org.xmlsoap.schemas.ws._2004._03.addressing.ReferencePropertiesType; public class RegistrationJob implements StatefulJob { private final static Logger logger = LoggerFactory .getLogger(RegistrationJob.class); static final private int LIFETIMECONST = 2; /** * if we have decided that the remote entry has no resource lifetime * management operations/RPs, then we will set this to false so that we will * not try them again. Care needs to be taken to ensure that it is only set * to false by exceptions that indicate the appropriate RPs/ops do not * exist, rather than (for example) network / resource non-existence errors. */ private boolean maybeHasLifetime = true; private ServiceGroupRegistrationParameters parameters = null; /** * If we know about an existing ServiceGroupEntry EPR for this managed * registration, it will be stored here so that we can attempt to extend its * lifetime rather than adding a new entry. */ private EndpointReferenceType entryEPR = null; public RegistrationJob() { super(); } public ServiceGroupRegistrationParameters getParameters() { return this.parameters; } /** * Gets the current time, preferably from the remote resource specified, and * failing that from local system. */ private Calendar getCurrentTimePreferringRemote(EndpointReferenceType epr) { logger.info("Attempting to get current time, preferring remote."); Calendar now = new GregorianCalendar(); // if (epr != null && maybeHasLifetime) { // // try { // GetResourceProperty getRPPort = ServiceGroupClientFactory.createGetResourcePropertySoapClient(epr.getAddress().getValue()); // // Object sge = entryEPR.getReferenceProperties().getAny() // .get(0); // // List<Header> headersList = (List<Header>) ((BindingProvider) getRPPort) // .getRequestContext().get(Header.HEADER_LIST); // if (headersList == null) { // headersList = new ArrayList<Header>(); // } // // ReferencePropertiesType rp = new ReferencePropertiesType(); // // Header testSoapHeader1 = new Header(new QName( // "http://mds.globus.org/bigindex/2008/11/24", // "ServiceGroupEntryKey"), sge); // headersList.add(testSoapHeader1); // // // Add SOAP headers to the web service request // ((BindingProvider) getRPPort).getRequestContext().put( // Header.HEADER_LIST, headersList); // // ((BindingProvider) getRPPort).getRequestContext().put( // BindingProvider.ENDPOINT_ADDRESS_PROPERTY, // entryEPR.getAddress().getValue()); // // // GetResourcePropertyResponse resp = getRPPort // .getResourceProperty(WSRFConstants.CURRENT_TIME); // // JAXBElement<Calendar> cal = (JAXBElement<Calendar>)resp.getAny().get(0); // System.out.println(cal.getValue()); // //Calendar date = (String)resp.getAny().get(0).toString() // System.out.println("Service returned time of " + resp.getAny().get(0).toString()); // //return null; // // } catch (Exception e) { // e.printStackTrace(); // /* // * some other exception occurred. return null, but don't change // * maybeHasLifetime // */ // ; // } // } // // // if the above hasn't produced a time, then pull time from // // local clock // if (now == null) { // System.out // .println("No remote current time available. Getting from local clock instead."); // now = Calendar.getInstance(); // } return now; } @Override public void execute(JobExecutionContext arg0) throws JobExecutionException { this.parameters = (ServiceGroupRegistrationParameters) arg0 .getJobDetail().getJobDataMap().get("params"); this.entryEPR = (EndpointReferenceType) arg0.getJobDetail() .getJobDataMap().get("epr"); if (this.parameters == null) { String msg = "Error: Registration event got null parameters (Registration event will be canceled)"; logger.error(msg); return; } /* * Check the target Service Group EPR. First, check to see if a target * ServiceGroupEPR exists in the supplied parameters object. If not, * fall back on the default value which should either initially be set * automatically from the BaseClient -e or -s arguments (if BaseClient * used) OR set on this object programatically as a global default. */ EndpointReferenceType epr = (parameters.getServiceGroupEPR() != null) ? parameters .getServiceGroupEPR() : null; EndpointReferenceType registrantEPR = (parameters.getRegistrantEPR() != null) ? parameters .getRegistrantEPR() : null; try { ServiceGroupRegistration port = ServiceGroupClientFactory .createServiceGroupRegistrationSoapClient(epr.getAddress() .getValue()); logger.info("Renewing/Adding: " + parameters.getRegistrantEPR()); /* * Get current time (preferably from resource, but local otherwise) */ Calendar term = getCurrentTimePreferringRemote(entryEPR); /* bump it up to the desired lifetime */ term.add(Calendar.SECOND, LIFETIMECONST * parameters.getRefreshIntervalSecs()); /* store termTime back into the parameters block */ parameters.setInitialTerminationTime(term); /* * TODO at this interaction, should also perhaps perform clock skew * for sanity checking that local and remote clocks are in sync? The * WS-Lifetime spec also suggests that clock skew could be * determined and compensated for, which might be desirable here * too. */ /* * First attempt to extend the lifetime of existing entry, if we * know about one. If we cannot do that, (entry may have * disappeared, entry may not exist) add a new entry and cache that. * * TODO: if we cannot extend lifetime because there is no * setlifetime operation, but the entry resource still exists, then * we should not do an add; instead just leave the entry to exist. * If it subsequently disappears, we can catch it and add it next * time round. */ boolean successfullyRenewed = false; if (entryEPR != null && maybeHasLifetime) { try { // TODO: append hostname of EPR here? logger.info("Attempting lifetime extension of entry"); ScheduledResourceTermination lifetimePort = ServiceGroupClientFactory .createLifetimeSoapClient(entryEPR.getAddress() .getValue()); Object sge = entryEPR.getReferenceProperties().getAny() .get(0); List<Header> headersList = (List<Header>) ((BindingProvider) lifetimePort) .getRequestContext().get(Header.HEADER_LIST); if (headersList == null) { headersList = new ArrayList<Header>(); } ReferencePropertiesType rp = new ReferencePropertiesType(); Header testSoapHeader1 = new Header(new QName( "http://mds.globus.org/bigindex/2008/11/24", "ServiceGroupEntryKey"), sge); headersList.add(testSoapHeader1); // Add SOAP headers to the web service request ((BindingProvider) lifetimePort).getRequestContext().put( Header.HEADER_LIST, headersList); ((BindingProvider) lifetimePort).getRequestContext().put( BindingProvider.ENDPOINT_ADDRESS_PROPERTY, entryEPR.getAddress().getValue()); logger.debug("SETTING TERM TIME to address: " + entryEPR.getAddress().getValue() + " to " + term.getTime()); SetTerminationTime setTermTimeReq = new SetTerminationTime(); setTermTimeReq.setRequestedTerminationTime(parameters .getInitialTerminationTime()); lifetimePort.setTerminationTime(setTermTimeReq .getRequestedTerminationTime(), new Holder<Calendar>(term), new Holder<Calendar>( new GregorianCalendar())); logger.info("Successfully Renewed registration " + registrantEPR.getAddress().getValue() + " to servicegroup at " + epr.getAddress().getValue() + " until: " + term.getTime()); /* * if we get this far without exception, then we have * successfully renewed lifetime. */ successfullyRenewed = true; } catch (Exception e) { logger.warn("Exception renewing entry lifetime of a registration for " + entryEPR.getAddress().getValue() + " - " + e); } } if (!successfullyRenewed) { /* * Next, if we couldn't renew then attempt an add instead * * We don't cancel the timer here on any sort of failure, as we * need to keep trying to make this registration in the future. * Note, the only exception to this is if we receive a false * return value from a setRegistrationStatus method call to a * previously set ServiceGroupRegistrationClientCallback object. * * (TODO: we should perhaps perform some kind of backoff?) */ logger.info("Attempting to add new registration for " + registrantEPR.getAddress().getValue() + " to servicegroup at " + epr.getAddress().getValue()); Add request = new Add(); request.setMemberEPR(registrantEPR); request.setContent(parameters.getContent()); if (parameters.getInitialTerminationTime() == null) { logger.info("No termination time computed for new registation."); } request.setInitialTerminationTime(parameters .getInitialTerminationTime()); entryEPR = port.add(request); arg0.getJobDetail().getJobDataMap().remove("epr"); arg0.getJobDetail().getJobDataMap().put("epr", entryEPR); // if (callback != null) { // if (!callback.setRegistrationStatus(parameters, true, // false, null)) { // this.cancel(timer); // if (ServiceGroupRegistrationClient.this.isDebug) { // ServiceGroupRegistrationClient.this.status( // LOG_D, // "Canceled registration event for: " // + entryEPR.getAddress()); // } // return; // } // } String msg; msg = "Successfully registered " + registrantEPR.getAddress().getValue() + " to servicegroup at " + epr.getAddress().getValue(); logger.info(msg); } } catch (Exception e) { e.printStackTrace(); String msg; msg = "Warning: Could not register " + registrantEPR.getAddress().getValue() + " to servicegroup at " + epr.getAddress().getValue() + " -- check the URL and that the remote service is up. " + " Remote exception was " + e.getMessage(); logger.warn(msg); // if (callback != null) { // if (!callback.setRegistrationStatus(parameters, false, // false, e)) { // this.cancel(timer); // if (ServiceGroupRegistrationClient.this.isDebug) { // ServiceGroupRegistrationClient.this.status(LOG_D, // "Canceled registration event for: " // + entryEPR.getAddress()); // } // return; // } // } } } }