dnet-core/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/registration/ServiceRegistrator.java

332 lines
9.9 KiB
Java

package eu.dnetlib.enabling.tools.registration;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;
import javax.xml.transform.dom.DOMResult;
import javax.xml.ws.Endpoint;
import javax.xml.ws.wsaddressing.W3CEndpointReference;
import org.antlr.stringtemplate.StringTemplate;
import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Required;
import eu.dnetlib.enabling.is.lookup.rmi.ISLookUpDocumentNotFoundException;
import eu.dnetlib.enabling.is.lookup.rmi.ISLookUpException;
import eu.dnetlib.enabling.is.lookup.rmi.ISLookUpService;
import eu.dnetlib.enabling.is.registry.rmi.ISRegistryException;
import eu.dnetlib.enabling.is.registry.rmi.ISRegistryService;
import eu.dnetlib.enabling.locators.UniqueServiceLocator;
import eu.dnetlib.enabling.tools.HNMLocator;
import eu.dnetlib.enabling.tools.NullHNMLocator;
import eu.dnetlib.soap.EndpointReferenceBuilder;
/**
* This class takes care of registering a service.
*
* TODO: merge the implementation
*
* @author marko
*
*/
public class ServiceRegistrator {
/**
* second.
*/
private static final int SECOND = 0;
/**
* logger.
*/
private static final Log log = LogFactory.getLog(ServiceRegistrator.class); // NOPMD
// by
// marko
// on
// 11/24/08
// 5:02
// PM
/**
* locator.
*/
private UniqueServiceLocator serviceLocator;
/**
* epr builder.
*/
private EndpointReferenceBuilder<Endpoint> eprBuilder;
/**
* component which finds an hnm profile.
*/
private HNMLocator hnmLocator = new NullHNMLocator();
/**
* Key-value pairs with service specific parameters which will appear in service profile.
*/
private Map<String, String> serviceProperties = new HashMap<String, String>();
/**
* Key-value pairs [name - endpoint] of extra protocols available in service profiles.
*/
private Map<String, String> extraProtocols = new HashMap<String, String>();
/**
* this bean helps us resolve service names from service instances.
*/
private ServiceNameResolver serviceNameResolver = new InterfaceServiceNameResolver(); // NOPMD
/**
* Register a service schema for a given service.
*
* @param service
* service
*/
public void registerServiceSchema(final Object service) {
registerServiceSchema(serviceNameResolver.getName(service));
}
/**
* Register a service schema for a particular service.
*
* @param serviceName
* service name
*/
public void registerServiceSchema(final String serviceName) {
try {
final InputStream schemaStream = getClass().getResourceAsStream("ServiceProfileSchemaTemplate.st");
if (schemaStream == null) { throw new IllegalStateException("cannot find service profile schema template"); }
final StringWriter schemaBuffer = new StringWriter();
IOUtils.copy(schemaStream, schemaBuffer);
final StringTemplate schema = new StringTemplate(schemaBuffer.toString());
final String resourceType = serviceName + "ResourceType";
schema.setAttribute("resourceType", resourceType);
if (serviceLocator == null) {
log.error("************* SERVICE LOCATOR IS NULL:" + serviceName);
return;
}
final ISRegistryService registry = serviceLocator.getService(ISRegistryService.class, true);
if (registry == null) {
log.error("************* REGISTRY SERVICE IS NULL");
return;
}
registry.addResourceType(resourceType, schema.toString());
} catch (final ISRegistryException e) {
throw new IllegalStateException("cannot register service profile schema", e);
} catch (final IOException e) {
throw new IllegalStateException("cannot read service profile schema template", e);
}
}
/**
* register a given service.
*
* @param service
* infers the service name from the class or annotations
* @param endpoint
* jaxws endpoint
* @return service profile id
*/
public String registerService(final Object service, final Endpoint endpoint) {
return registerService(serviceNameResolver.getName(service), endpoint);
}
/**
* register a service with a given service name. Return null if the service cannot be registered, for example because it's blocked if
* the HNM is missing.
*
* @param serviceName
* service name
* @param endpoint
* jaxws endpoint
* @return service profile id, or null if the service cannot be registered because blocked
*/
public String registerService(final String serviceName, final Endpoint endpoint) {
return registerService(serviceName, eprBuilder.getEndpointReference(endpoint));
}
/**
* register a service with a given service name.
*
* @param serviceName
* service name
* @param epr
* w3c endpoint reference
* @return service profile id
*/
public String registerService(final String serviceName, final W3CEndpointReference epr) {
ensureSchemaExists(serviceName);
final DOMResult result = new DOMResult();
epr.writeTo(result);
try {
final InputStream templateStream = getClass().getResourceAsStream("ServiceProfileTemplate.st");
if (templateStream == null) { throw new IllegalStateException("cannot find service profile template"); }
final StringWriter buffer = new StringWriter();
IOUtils.copy(templateStream, buffer);
final StringTemplate templ = new StringTemplate(buffer.toString());
final String resourceType = serviceName + "ResourceType";
final String address = result.getNode().getChildNodes().item(0).getChildNodes().item(0).getTextContent();
final String hnmId = hnmLocator.getHNMForUrl(address);
// skip registration if there is no HNM yet.
if (hnmId == null) {
log.warn(String.format("skipping %s service registration, can't find NHM service'", serviceName));
return null;
}
templ.setAttribute("resourceType", resourceType);
templ.setAttribute("serviceName", serviceName);
templ.setAttribute("address", address);
templ.setAttribute("protocols", getExtraProtocols());
templ.setAttribute("parentId", hnmId);
templ.setAttribute("properties", serviceProperties);
log.debug("template: " + templ.toString());
final String res = serviceLocator.getService(ISRegistryService.class, true).insertProfileForValidation(resourceType, templ.toString());
Thread.sleep(SECOND);
return res;
} catch (final IOException e) {
throw new IllegalStateException("cannot load service profile template", e);
} catch (final ISRegistryException e) {
throw new IllegalStateException("cannot register service profile", e);
} catch (final InterruptedException e) {
throw new IllegalStateException("cannot wait for register service profile", e);
}
}
/**
* Check that the service schema for this service already exists, and create it if it doesn't.
*
* @param serviceName
* service name
*/
protected void ensureSchemaExists(final String serviceName) {
try {
serviceLocator.getService(ISLookUpService.class).getResourceTypeSchema(serviceName);
//serviceLocator.getService(ISLookUpService.class).getResourceProfileByQuery(
// "//*[local-name() = 'complexType' and @name = 'RESOURCE_TYPEType']//*[local-name() = 'enumeration' and @value = '" + serviceName
// + "ResourceType']");
log.warn("schema for " + serviceName + " appears to exist");
} catch (final ISLookUpDocumentNotFoundException e) {
log.warn("registering schema for " + serviceName);
registerServiceSchema(serviceName);
} catch (final ISLookUpException e) {
throw new IllegalStateException(e);
}
}
/**
* validate the registered profile.
*
* TODO: XXX: huge hack. used right now to automatically register the blackboard. It won't work anymore once the services are validated
* from the GUI
*
* @param profId
* profile id
* @param endpoint
* service endpoint (hook for possible IS_SN automated registrations)
* @return new id.
*/
public String validateProfile(final String profId, final Endpoint endpoint) {
try {
Thread.sleep(SECOND);
} catch (final InterruptedException e) {
throw new IllegalStateException("interrupted", e);
}
try {
return serviceLocator.getService(ISRegistryService.class, true).validateProfile(profId);
} catch (final ISRegistryException e) {
throw new IllegalStateException("cannot validate service profile", e);
}
}
/**
* validate the registered profile.
*
* @param profId
* old profile identifier
* @return new profile identifier
*/
public String validateProfile(final String profId) {
return validateProfile(profId, null);
}
public EndpointReferenceBuilder<Endpoint> getEprBuilder() {
return eprBuilder;
}
@Required
public void setEprBuilder(final EndpointReferenceBuilder<Endpoint> eprBuilder) {
this.eprBuilder = eprBuilder;
}
public HNMLocator getHnmLocator() {
return hnmLocator;
}
public void setHnmLocator(final HNMLocator hnmLocator) {
this.hnmLocator = hnmLocator;
}
public ServiceNameResolver getServiceNameGen() {
return serviceNameResolver;
}
public void setServiceNameGen(final ServiceNameResolver serviceNameGen) {
this.serviceNameResolver = serviceNameGen;
}
public ServiceNameResolver getServiceNameResolver() {
return serviceNameResolver;
}
public void setServiceNameResolver(final ServiceNameResolver serviceNameRes) {
this.serviceNameResolver = serviceNameRes;
}
public Map<String, String> getServiceProperties() {
return serviceProperties;
}
public void setServiceProperties(final Map<String, String> serviceProperties) {
this.serviceProperties = serviceProperties;
}
public Map<String, String> getExtraProtocols() {
return extraProtocols;
}
public void setExtraProtocols(final Map<String, String> extraProtocols) {
this.extraProtocols = extraProtocols;
}
public UniqueServiceLocator getServiceLocator() {
return serviceLocator;
}
@Required
public void setServiceLocator(final UniqueServiceLocator serviceLocator) {
this.serviceLocator = serviceLocator;
}
}