diff --git a/dnet-core-components/pom.xml b/dnet-core-components/pom.xml
index c147c77..50db0a8 100644
--- a/dnet-core-components/pom.xml
+++ b/dnet-core-components/pom.xml
@@ -16,10 +16,22 @@
org.apache.commons
commons-lang3
+
+ commons-lang
+ commons-lang
+
commons-codec
commons-codec
+
+ commons-io
+ commons-io
+
+
+ com.mycila
+ xmltool
+
dom4j
dom4j
@@ -48,27 +60,136 @@
com.google.guava
guava
-
-
- org.mockito
- mockito-core
- test
+ com.google.code.gson
+ gson
+
junit
junit
test
+
+
+ log4j
+ log4j
+
+
+ com.sun.jmx
+ jmxri
+
+
+ com.sun.jdmk
+ jmxtools
+
+
+
+
+
+ runcc
+ runcc
+
+
+ org.antlr
+ stringtemplate
+
+
+ jparsec
+ jparsec
+
+
+ apache
+ oro
+
+
+
+
+ org.quartz-scheduler
+ quartz
+
+
+
+ org.apache.solr
+ solr-solrj
+
+
+ org.apache.lucene
+ lucene-queryparser
+
+
+
+ org.mongodb
+ mongo-java-driver
+
+
+ joda-time
+ joda-time
+
+
+ org.z3950.zing
+ cql-java
+
+
+
+ org.mockito
+ mockito-core
+
+
+
+
+ org.springframework
+ spring-beans
+
+
+ org.springframework
+ spring-web
+
org.springframework
spring-test
- false
- commons-io
- commons-io
- test
+ org.springframework
+ spring-aop
+
+
+ org.springframework
+ spring-webmvc
+
+
+ org.springframework
+ spring-tx
+
+
+
+
+
+ org.apache.cxf
+ cxf-core
+
+
+ org.apache.cxf
+ cxf-rt-bindings-soap
+
+
+ org.apache.cxf
+ cxf-rt-transports-http
+
+
+ org.apache.cxf
+ cxf-rt-frontend-jaxws
+
+
+
+ javax.servlet
+ javax.servlet-api
+
+
+
+
+ org.apache.tomcat
+ tomcat-catalina
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/common/rmi/APIDeprecatedException.java b/dnet-core-components/src/main/java/eu/dnetlib/common/rmi/APIDeprecatedException.java
new file mode 100644
index 0000000..6772560
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/common/rmi/APIDeprecatedException.java
@@ -0,0 +1,10 @@
+package eu.dnetlib.common.rmi;
+
+public class APIDeprecatedException extends RuntimeException {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -5606373588445519515L;
+
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/common/rmi/BaseService.java b/dnet-core-components/src/main/java/eu/dnetlib/common/rmi/BaseService.java
new file mode 100644
index 0000000..6f94f72
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/common/rmi/BaseService.java
@@ -0,0 +1,34 @@
+package eu.dnetlib.common.rmi;
+
+import javax.jws.WebMethod;
+import javax.jws.WebParam;
+import javax.jws.WebService;
+
+@WebService(targetNamespace = "http://services.dnetlib.eu/")
+public interface BaseService {
+
+ /**
+ * All DRIVER services must implement method notify() in order to communicate with the IS_SN
+ *
+ * @param subsrciptionId
+ * @param topic
+ * @param isId
+ * @param message
+ */
+ @WebMethod(operationName = "notify")
+ public void notify(@WebParam(name = "subscrId") String subscriptionId,
+ @WebParam(name = "topic") String topic,
+ @WebParam(name = "is_id") String isId,
+ @WebParam(name = "message") String message);
+
+ /**
+ * Identifies the service's version. Version syntax: ${NAME}-${MAJOR}.${MINOR}.${MICRO}[-${LABEL}]
+ *
+ * @return the service's version
+ */
+ @WebMethod(operationName = "identify")
+ public String identify();
+
+ public void start();
+
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/common/rmi/DNetRestDocumentation.java b/dnet-core-components/src/main/java/eu/dnetlib/common/rmi/DNetRestDocumentation.java
new file mode 100644
index 0000000..5dc6adf
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/common/rmi/DNetRestDocumentation.java
@@ -0,0 +1,16 @@
+package eu.dnetlib.common.rmi;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Created by claudio on 30/11/2016.
+ * to be used in REST controllers, and autodiscovered to build and publish their documentation
+ */
+@Target({ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface DNetRestDocumentation {
+
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/common/rmi/RMIException.java b/dnet-core-components/src/main/java/eu/dnetlib/common/rmi/RMIException.java
new file mode 100644
index 0000000..0ec7ab4
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/common/rmi/RMIException.java
@@ -0,0 +1,28 @@
+package eu.dnetlib.common.rmi;
+
+/**
+ *
+ * All RMI exception thrown from the service remote method invocation interfaces inherit this class
+ *
+ * @author marko
+ *
+ */
+abstract public class RMIException extends Exception { // NOPMD
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 428841258652765265L;
+
+ public RMIException(final Throwable exception) {
+ super(exception);
+ }
+
+ public RMIException(final String string) {
+ super(string);
+ }
+
+ public RMIException(final String string, final Throwable exception) {
+ super(string, exception);
+ }
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/common/rmi/UnimplementedException.java b/dnet-core-components/src/main/java/eu/dnetlib/common/rmi/UnimplementedException.java
new file mode 100644
index 0000000..3d8b408
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/common/rmi/UnimplementedException.java
@@ -0,0 +1,10 @@
+package eu.dnetlib.common.rmi;
+
+public class UnimplementedException extends RuntimeException {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 6040968020696349497L;
+
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/conf/AbstractWebappContextProperty.java b/dnet-core-components/src/main/java/eu/dnetlib/conf/AbstractWebappContextProperty.java
new file mode 100644
index 0000000..5188d8d
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/conf/AbstractWebappContextProperty.java
@@ -0,0 +1,60 @@
+package eu.dnetlib.conf;
+
+import javax.servlet.ServletContext;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.web.context.ServletContextAware;
+
+/**
+ * This spring bean detects the webapp context path, from the ServletContext. It requires servlet-api 2.5 (tomcat6 and
+ * jetty 6.x).
+ *
+ *
+ * Concrete subclasses will know what to do with this information
+ *
+ *
+ * @author marko
+ *
+ */
+public abstract class AbstractWebappContextProperty implements ServletContextAware {
+
+ /**
+ * logger.
+ */
+ private static final Log log = LogFactory.getLog(AbstractWebappContextProperty.class); // NOPMD by marko on 11/24/08 5:02 PM
+
+ /**
+ * web application context.
+ */
+ protected String context;
+
+ /**
+ * saved servlet context.
+ */
+ protected ServletContext servletContext;
+
+ @Override
+ public void setServletContext(final ServletContext servletContext) {
+ this.servletContext = servletContext;
+
+ try {
+ context = servletContext.getContextPath().substring(1);
+ } catch (final NoSuchMethodError e) {
+ log.warn("cannot detect servlet context path. servlet-api 2.5 is required, falling back to property based configuration", e);
+ }
+ }
+
+ public String getContext() {
+ return context;
+ }
+
+ public void setContext(final String context) {
+ this.context = context;
+ }
+
+ public ServletContext getServletContext() {
+ return servletContext;
+ }
+
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/conf/PropertyFetcher.java b/dnet-core-components/src/main/java/eu/dnetlib/conf/PropertyFetcher.java
new file mode 100644
index 0000000..25996a4
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/conf/PropertyFetcher.java
@@ -0,0 +1,87 @@
+package eu.dnetlib.conf;
+
+import java.util.Map.Entry;
+import java.util.Properties;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
+import org.springframework.beans.factory.config.PropertyResourceConfigurer;
+
+/**
+ * PropertyFletcher
+ *
+ * @author marko
+ *
+ */
+public class PropertyFetcher extends PropertyResourceConfigurer implements InitializingBean {
+
+ private static final Log log = LogFactory.getLog(PropertyFetcher.class); // NOPMD by marko on 11/24/08 5:02 PM
+
+ boolean unchangedHostname = false;
+ boolean unchangedPort = true;
+
+ private Properties props;
+
+ @Override
+ public void afterPropertiesSet() throws Exception {
+ this.props = mergeProperties();
+
+ // Convert the merged properties, if necessary.
+ convertProperties(props);
+
+ log.debug("FOUND A container.hostname property " + props.getProperty("container.hostname"));
+
+ if ("localhost".equals(props.getProperty("container.hostname"))) {
+ unchangedHostname = true;
+ }
+ if (props.getProperty("container.port") != null) {
+ log.debug("FOUND A container.port property " + props.getProperty("container.port"));
+ unchangedPort = false;
+ }
+
+ if (log.isDebugEnabled()) {
+ log.debug("HOST unchanged? " + unchangedHostname);
+ log.debug("PORT unchanged? " + unchangedPort);
+ for (Entry, ?> e : props.entrySet()) {
+ log.debug("system property: " + e.getKey() + " --> " + e.getValue());
+ }
+ }
+ }
+
+ @Override
+ protected void processProperties(final ConfigurableListableBeanFactory arg0, final Properties props) throws BeansException {
+
+ }
+
+ public boolean isUnchangedHostname() {
+ return unchangedHostname;
+ }
+
+ public void setUnchangedHostname(final boolean unchangedHostname) {
+ this.unchangedHostname = unchangedHostname;
+ }
+
+ public boolean isUnchangedPort() {
+ return unchangedPort;
+ }
+
+ public void setUnchangedPort(final boolean unchangedPort) {
+ this.unchangedPort = unchangedPort;
+ }
+
+ public String getProperty(final String key) {
+ return props.getProperty(key);
+ }
+
+ public Properties getProps() {
+ return props;
+ }
+
+ public void setProps(final Properties props) {
+ this.props = props;
+ }
+
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/conf/WebappContextPropertyLocationFactory.java b/dnet-core-components/src/main/java/eu/dnetlib/conf/WebappContextPropertyLocationFactory.java
new file mode 100644
index 0000000..35886cb
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/conf/WebappContextPropertyLocationFactory.java
@@ -0,0 +1,66 @@
+package eu.dnetlib.conf;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.beans.factory.FactoryBean;
+
+/**
+ * This class wraps a list of property file paths and expands the @{webapp} placeholder with the name of the webapp taken from servlet-api
+ * 2.5.
+ *
+ * @author marko
+ *
+ */
+public class WebappContextPropertyLocationFactory extends AbstractWebappContextProperty implements FactoryBean> {
+
+ /**
+ * logger.
+ */
+ private static final Log log = LogFactory.getLog(WebappContextPropertyLocationFactory.class); // NOPMD by marko on 11/24/08 5:02 PM
+
+ private List locations;
+
+ @Override
+ public List getObject() throws Exception {
+ List expanded = new ArrayList();
+
+ for (String loc : locations) {
+ expanded.add(expand(loc).trim());
+ }
+
+ if (log.isInfoEnabled()) {
+ for (String location : expanded) {
+ log.info("Searching property file: " + location);
+ }
+ }
+
+ return expanded;
+ }
+
+ private String expand(final String loc) {
+ if (getContext() == null) return loc;
+ return loc.replace("@{webapp}", getContext());
+ }
+
+ @Override
+ public Class> getObjectType() {
+ return locations.getClass();
+ }
+
+ @Override
+ public boolean isSingleton() {
+ return true;
+ }
+
+ public List getLocations() {
+ return locations;
+ }
+
+ public void setLocations(final List locations) {
+ this.locations = locations;
+ }
+
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/conf/WebappContextProperyFactory.java b/dnet-core-components/src/main/java/eu/dnetlib/conf/WebappContextProperyFactory.java
new file mode 100644
index 0000000..d47e140
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/conf/WebappContextProperyFactory.java
@@ -0,0 +1,146 @@
+package eu.dnetlib.conf;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Properties;
+
+import javax.servlet.ServletContext;
+
+import org.apache.catalina.Container;
+import org.apache.catalina.connector.Connector;
+import org.apache.catalina.core.StandardContext;
+import org.apache.catalina.core.StandardEngine;
+import org.apache.commons.lang.reflect.FieldUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.beans.factory.FactoryBean;
+import org.springframework.beans.factory.annotation.Required;
+
+/**
+ * This factory generates default properties based on the amount of information available from the servlet container.
+ *
+ * @author marko
+ *
+ */
+public class WebappContextProperyFactory extends AbstractWebappContextProperty implements FactoryBean {
+
+ /**
+ * logger.
+ */
+ private static final Log log = LogFactory.getLog(WebappContextProperyFactory.class); // NOPMD by marko on
+ // 11/24/08 5:02 PM
+
+ /**
+ * If false, the ip address will be returned, otherwise a best effort attemp will be made to retrieve a meaningful host name. There is a
+ * risk that the hostname is obtained without domain and thus completely useless.
+ */
+ private boolean resolveHostname = false;
+
+ private PropertyFetcher propertyFetcher;
+
+ @Override
+ public Properties getObject() throws Exception {
+ Properties props = new Properties();
+
+ if (getContext() == null) return props;
+
+ props.setProperty("container.context", getContext());
+
+ log.debug("trying to autodetect port and hostame");
+
+ // if the user didn't customize, then autodetect, otherwise honour the
+ // user!
+ if (propertyFetcher.isUnchangedPort()) {
+ log.debug("PORT IS NOT OVERRIDDEN, autodetecting");
+ int port = getPort(getServletContext());
+ if (port > 0) {
+ props.setProperty("container.port", Integer.toString(port));
+ }
+ } else {
+ log.debug("PORT IS OVERRIDDEN, NOT autodetecting");
+ }
+
+ if (propertyFetcher.isUnchangedHostname()) {
+ log.debug("HOST IS NOT OVERRIDDEN, autodetecting");
+ String hostname = getHost(getServletContext());
+ if (hostname != null) {
+ props.setProperty("container.hostname", hostname);
+ }
+ } else {
+ log.debug("HOST IS OVERRIDDEN, NOT autodetecting");
+ }
+
+ return props;
+ }
+
+ @Override
+ public Class> getObjectType() {
+ return Properties.class;
+ }
+
+ @Override
+ public boolean isSingleton() {
+ return true;
+ }
+
+ private int getPort(final ServletContext servletContext) {
+ try {
+ return getContainerPort(servletContext);
+ } catch (Throwable e) {
+ log.warn("cannot obtain port from container...strange: I thought it would work both on jetty and tomcat7...)", e);
+ return 0;
+ }
+ }
+
+ private int getContainerPort(final ServletContext servletContext) {
+ try {
+ Object o = FieldUtils.readField(servletContext, "context", true);
+ StandardContext sCtx = (StandardContext) FieldUtils.readField(o, "context", true);
+ Container container = sCtx;
+
+ Container c = container.getParent();
+ while ((c != null) && !(c instanceof StandardEngine)) {
+ c = c.getParent();
+ }
+
+ if (c != null) {
+ StandardEngine engine = (StandardEngine) c;
+ for (Connector connector : engine.getService().findConnectors()) {
+ if (connector.getPort() > 0) return connector.getPort();
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return 0;
+ }
+
+ private String getHost(final ServletContext servletContext) {
+ try {
+ if (resolveHostname) return InetAddress.getLocalHost().getCanonicalHostName();
+ else return InetAddress.getLocalHost().toString().split("/")[1];
+ } catch (UnknownHostException e) {
+ log.warn("cannot obtain hostname from JVM", e);
+ }
+
+ return null;
+ }
+
+ public boolean isResolveHostname() {
+ return resolveHostname;
+ }
+
+ public void setResolveHostname(final boolean resolveHostname) {
+ this.resolveHostname = resolveHostname;
+ }
+
+ public PropertyFetcher getPropertyFetcher() {
+ return propertyFetcher;
+ }
+
+ @Required
+ public void setPropertyFetcher(final PropertyFetcher propertyFetcher) {
+ this.propertyFetcher = propertyFetcher;
+ }
+
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/data/information/collectionservice/rmi/CollectionService.java b/dnet-core-components/src/main/java/eu/dnetlib/data/information/collectionservice/rmi/CollectionService.java
new file mode 100644
index 0000000..b720e52
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/data/information/collectionservice/rmi/CollectionService.java
@@ -0,0 +1,28 @@
+package eu.dnetlib.data.information.collectionservice.rmi;
+
+import java.util.List;
+
+import javax.jws.WebParam;
+import javax.jws.WebService;
+
+import eu.dnetlib.common.rmi.BaseService;
+
+/**
+ * The Collection Service is used to ...
+ *
+ *
+ */
+
+@WebService(targetNamespace = "http://services.dnetlib.eu/")
+public interface CollectionService extends BaseService {
+
+ public String getCollection(@WebParam(name = "collId") final String collId) throws CollectionServiceException;
+
+ public List getCollections(@WebParam(name = "collIds") final List collIds) throws CollectionServiceException;
+
+ public void updateCollection(@WebParam(name = "coll") final String coll) throws CollectionServiceException;
+
+ public void deleteCollection(@WebParam(name = "collId") final String collId) throws CollectionServiceException;
+
+ public String createCollection(@WebParam(name = "coll") final String coll) throws CollectionServiceException;
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/data/information/collectionservice/rmi/CollectionServiceException.java b/dnet-core-components/src/main/java/eu/dnetlib/data/information/collectionservice/rmi/CollectionServiceException.java
new file mode 100644
index 0000000..9ae20f3
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/data/information/collectionservice/rmi/CollectionServiceException.java
@@ -0,0 +1,28 @@
+package eu.dnetlib.data.information.collectionservice.rmi;
+
+
+import javax.xml.ws.WebFault;
+
+import eu.dnetlib.common.rmi.RMIException;
+
+@WebFault
+public class CollectionServiceException extends RMIException {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 8094008463553904905L;
+
+ public CollectionServiceException(Throwable e) {
+ super(e);
+ }
+
+ public CollectionServiceException(String message, Throwable e) {
+ super(message, e);
+ }
+
+ public CollectionServiceException(String message) {
+ super(message);
+ }
+
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/data/information/publisher/rmi/PublisherService.java b/dnet-core-components/src/main/java/eu/dnetlib/data/information/publisher/rmi/PublisherService.java
new file mode 100644
index 0000000..128a2ec
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/data/information/publisher/rmi/PublisherService.java
@@ -0,0 +1,50 @@
+package eu.dnetlib.data.information.publisher.rmi;
+
+import java.util.List;
+
+import javax.jws.WebMethod;
+import javax.jws.WebParam;
+import javax.jws.WebService;
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import eu.dnetlib.common.rmi.BaseService;
+
+/**
+ * Publisher service. Provides access to metadata records and objects.
+ *
+ * @author marko
+ *
+ */
+@WebService(targetNamespace = "http://services.dnetlib.eu/")
+public interface PublisherService extends BaseService {
+
+ /**
+ * Get a (metadata) resource by ID.
+ *
+ * @param id
+ * @param format
+ * @param layout
+ * @param interpretation
+ * @return
+ */
+ @WebMethod
+ String getResourceById(@WebParam(name = "id") final String id,
+ @WebParam(name = "format") final String format,
+ @WebParam(name = "layout") final String layout,
+ @WebParam(name = "interpretation") final String interpretation);
+
+ /**
+ * Get (metadata) resources by IDs.
+ *
+ * @param ids
+ * @param format
+ * @param layout
+ * @param interpretation
+ * @return
+ */
+ @WebMethod
+ W3CEndpointReference getResourcesByIds(@WebParam(name = "ids") final List ids,
+ @WebParam(name = "format") final String format,
+ @WebParam(name = "layout") final String layout,
+ @WebParam(name = "interpretation") final String interpretation);
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/data/mdstore/DocumentNotFoundException.java b/dnet-core-components/src/main/java/eu/dnetlib/data/mdstore/DocumentNotFoundException.java
new file mode 100644
index 0000000..610f4a0
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/data/mdstore/DocumentNotFoundException.java
@@ -0,0 +1,29 @@
+package eu.dnetlib.data.mdstore;
+
+/**
+ * Signals that a metadata record cannot be found in a given MDStore.
+ */
+public class DocumentNotFoundException extends MDStoreServiceException {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 5188036989114250548L;
+
+ public DocumentNotFoundException(final String s, final Throwable e) {
+ super(s, e);
+ }
+
+ public DocumentNotFoundException(final String s) {
+ super(s);
+ }
+
+ public DocumentNotFoundException(final Throwable e) {
+ super(e);
+ }
+
+ public DocumentNotFoundException() {
+ super();
+ }
+
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/data/mdstore/MDStoreService.java b/dnet-core-components/src/main/java/eu/dnetlib/data/mdstore/MDStoreService.java
new file mode 100644
index 0000000..6e7de14
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/data/mdstore/MDStoreService.java
@@ -0,0 +1,105 @@
+package eu.dnetlib.data.mdstore;
+
+import java.util.List;
+
+import javax.jws.WebMethod;
+import javax.jws.WebParam;
+import javax.jws.WebService;
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import eu.dnetlib.common.rmi.BaseService;
+
+@WebService(targetNamespace = "http://services.dnetlib.eu/")
+public interface MDStoreService extends BaseService {
+
+ /**
+ * Identifies service and version.
+ *
+ * @return
+ */
+ @Override
+ public String identify();
+
+ /**
+ * Returns ResultSet EPR for delivered mdstore records.
+ *
+ * @param mdId
+ * @param from
+ * @param until
+ * @param recordFilter
+ * REGEX on the metadata record
+ * @return ResultSet EPR
+ * @throws MDStoreServiceException
+ */
+ public W3CEndpointReference deliverMDRecords(@WebParam(name = "mdId") final String mdId,
+ @WebParam(name = "from") final String from,
+ @WebParam(name = "until") final String until,
+ @WebParam(name = "recordsFilter") final String recordFilter) throws MDStoreServiceException;
+
+ /**
+ * Deliver single record from selected mdstore.
+ *
+ * @param mdId
+ * @param recordId
+ * @return record
+ * @throws MDStoreServiceException
+ */
+ public String deliverRecord(@WebParam(name = "mdId") final String mdId, @WebParam(name = "recordId") final String recordId) throws MDStoreServiceException,
+ DocumentNotFoundException;
+
+ /**
+ * Returns list of all stored indices.
+ *
+ * @return list of all stored indices
+ */
+ public List getListOfMDStores() throws MDStoreServiceException;
+
+ public List listMDStores(@WebParam(name = "format") final String format,
+ @WebParam(name = "layout") final String layout,
+ @WebParam(name = "interpretation") final String interpretation) throws MDStoreServiceException;
+
+ public W3CEndpointReference bulkDeliverMDRecords(@WebParam(name = "format") final String format,
+ @WebParam(name = "layout") final String layout,
+ @WebParam(name = "interpretation") final String interpretation) throws MDStoreServiceException;
+
+ /**
+ * Store md records from a result set
+ *
+ * @param mdId
+ * @param rsId
+ * @param storingType
+ * @return returns true immediately.
+ * @throws MDStoreServiceException
+ */
+ @Deprecated
+ public boolean storeMDRecordsFromRS(@WebParam(name = "mdId") final String mdId,
+ @WebParam(name = "rsId") final String rsId,
+ @WebParam(name = "storingType") final String storingType) throws MDStoreServiceException;
+
+ /**
+ * Gets the size of the mdstore with the given identifier.
+ *
+ * @param mdId
+ * identifier of an mdstore
+ * @return the number of records in the store
+ */
+ @WebMethod(operationName = "size")
+ public int size(@WebParam(name = "mdId") final String mdId) throws MDStoreServiceException;
+
+ /**
+ * Gets the sum of records stored in all mdstore with the given format, layout , interpretation
+ *
+ * @param format
+ * format
+ * @param layout
+ * layout
+ * @param interpretation
+ * interpretation
+ * @return the total number of records in the mdstores of the given type
+ */
+ @WebMethod(operationName = "sizeByFormat")
+ public int size(@WebParam(name = "format") final String format,
+ @WebParam(name = "layout") final String layout,
+ @WebParam(name = "interpretation") final String interpretation) throws MDStoreServiceException;
+
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/data/mdstore/MDStoreServiceException.java b/dnet-core-components/src/main/java/eu/dnetlib/data/mdstore/MDStoreServiceException.java
new file mode 100644
index 0000000..73ab244
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/data/mdstore/MDStoreServiceException.java
@@ -0,0 +1,32 @@
+package eu.dnetlib.data.mdstore;
+
+/**
+ * General mdstore service exception.
+ * @author claudio atzori
+ * @version 1.0.0
+ *
+ */
+public class MDStoreServiceException extends Exception {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -6772977735282310658L;
+
+ public MDStoreServiceException(String s, Throwable e) {
+ super(s, e);
+ }
+
+ public MDStoreServiceException(String s) {
+ super(s);
+ }
+
+ public MDStoreServiceException(Throwable e) {
+ super(e);
+ }
+
+ public MDStoreServiceException() {
+ super();
+ }
+
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/data/provision/index/rmi/BrowsingRow.java b/dnet-core-components/src/main/java/eu/dnetlib/data/provision/index/rmi/BrowsingRow.java
new file mode 100644
index 0000000..3081d1d
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/data/provision/index/rmi/BrowsingRow.java
@@ -0,0 +1,65 @@
+package eu.dnetlib.data.provision.index.rmi;
+
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ *
+ * serialization of the browsing result.
+ *
+ * facetFieldValue 1
+ *
+ * facetFieldValue 1
+ *
+ *
+ *
+ * @author claudio
+ *
+ */
+@XmlRootElement(namespace = "", name = "row")
+@XmlAccessorType(XmlAccessType.FIELD)
+public class BrowsingRow {
+
+ @XmlElement(name = "groupresult", required = true)
+ private List groupresult;
+
+ public BrowsingRow() {}
+
+ public BrowsingRow(final List groupresult) {
+ this.groupresult = groupresult;
+ }
+
+ /**
+ * adds a GroupResult.
+ *
+ * @param fieldName
+ * @param fieldValue
+ * @param count
+ */
+ public void addBrowsingRow(final String fieldName, final String fieldValue, final int count) {
+ groupresult.add(new GroupResult(fieldName, fieldValue, count));
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+
+ if (!(obj instanceof BrowsingRow)) return false;
+
+ final BrowsingRow brws = (BrowsingRow) obj;
+
+ return groupresult.equals(brws.getGroupResult());
+ }
+
+ public List getGroupResult() {
+ return groupresult;
+ }
+
+ public void setGroupResult(final List groupresult) {
+ this.groupresult = groupresult;
+ }
+
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/data/provision/index/rmi/GroupResult.java b/dnet-core-components/src/main/java/eu/dnetlib/data/provision/index/rmi/GroupResult.java
new file mode 100644
index 0000000..ee6dd3d
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/data/provision/index/rmi/GroupResult.java
@@ -0,0 +1,76 @@
+package eu.dnetlib.data.provision.index.rmi;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ *
+ * {@code
+ *
+ * facetFieldValue
+ * 1
+ *
+ * }
+ *
+ *
+ * @author claudio
+ *
+ */
+@XmlRootElement(namespace = "", name = "groupresult")
+public class GroupResult {
+
+ private String name;
+
+ private String value;
+
+ private int count;
+
+ public GroupResult() {}
+
+ /**
+ * Builds a groupResult.
+ *
+ * @param fieldName
+ * @param fieldValue
+ * @param count
+ */
+ public GroupResult(final String name, final String value, final int count) {
+ this.name = name;
+ this.value = value;
+ this.count = count;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (!(obj instanceof GroupResult)) return false;
+ final GroupResult g = (GroupResult) obj;
+ if ((this.getCount() == g.getCount()) && this.getName().equals(g.getName()) && this.getValue().equals(g.getValue())) return true;
+ return false;
+ }
+
+ @XmlAttribute(name = "field", required = true)
+ public String getName() {
+ return name;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ public int getCount() {
+ return count;
+ }
+
+ public void setName(final String name) {
+ this.name = name;
+ }
+
+ public void setValue(final String value) {
+ this.value = value;
+ }
+
+ public void setCount(final int count) {
+ this.count = count;
+ }
+
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/data/provision/index/rmi/IndexService.java b/dnet-core-components/src/main/java/eu/dnetlib/data/provision/index/rmi/IndexService.java
new file mode 100644
index 0000000..b518396
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/data/provision/index/rmi/IndexService.java
@@ -0,0 +1,27 @@
+package eu.dnetlib.data.provision.index.rmi;
+
+import java.util.List;
+
+import javax.jws.WebMethod;
+import javax.jws.WebService;
+
+import eu.dnetlib.common.rmi.BaseService;
+
+/**
+ * Interface for the IndexService.
+ *
+ * @author alessia
+ *
+ */
+@WebService(targetNamespace = "http://services.dnetlib.eu/")
+public interface IndexService extends BaseService {
+
+ /**
+ * Returns list of all stored indices.
+ *
+ * @return list of all stored indices
+ * @throws IndexServiceException
+ */
+ @WebMethod(operationName = "getListOfIndices", action = "getListOfIndices")
+ public List getListOfIndices() throws IndexServiceException;
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/data/provision/index/rmi/IndexServiceException.java b/dnet-core-components/src/main/java/eu/dnetlib/data/provision/index/rmi/IndexServiceException.java
new file mode 100644
index 0000000..766a60d
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/data/provision/index/rmi/IndexServiceException.java
@@ -0,0 +1,23 @@
+package eu.dnetlib.data.provision.index.rmi;
+
+public class IndexServiceException extends Exception {
+
+ private static final long serialVersionUID = 8330264706967294512L;
+
+ public IndexServiceException() {
+ super();
+ }
+
+ public IndexServiceException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public IndexServiceException(String message) {
+ super(message);
+ }
+
+ public IndexServiceException(Throwable cause) {
+ super(cause);
+ }
+
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/data/provision/index/rmi/protocols/IndexProtocols.java b/dnet-core-components/src/main/java/eu/dnetlib/data/provision/index/rmi/protocols/IndexProtocols.java
new file mode 100644
index 0000000..f75fb87
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/data/provision/index/rmi/protocols/IndexProtocols.java
@@ -0,0 +1,5 @@
+package eu.dnetlib.data.provision.index.rmi.protocols;
+
+public enum IndexProtocols {
+ SOLR, SOLR_CLOUD
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/data/utility/objectpackaging/rmi/ObjectPackagingException.java b/dnet-core-components/src/main/java/eu/dnetlib/data/utility/objectpackaging/rmi/ObjectPackagingException.java
new file mode 100644
index 0000000..0ed1277
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/data/utility/objectpackaging/rmi/ObjectPackagingException.java
@@ -0,0 +1,28 @@
+package eu.dnetlib.data.utility.objectpackaging.rmi;
+
+import javax.xml.ws.WebFault;
+
+import eu.dnetlib.common.rmi.RMIException;
+
+@WebFault
+public class ObjectPackagingException extends RMIException {
+
+ private static final long serialVersionUID = 3468254939586031822L;
+
+ /**
+ *
+ */
+
+ public ObjectPackagingException(Throwable e) {
+ super(e);
+ }
+
+ public ObjectPackagingException(String message, Throwable e) {
+ super(message, e);
+ }
+
+ public ObjectPackagingException(String message) {
+ super(message);
+ }
+
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/data/utility/objectpackaging/rmi/ObjectPackagingService.java b/dnet-core-components/src/main/java/eu/dnetlib/data/utility/objectpackaging/rmi/ObjectPackagingService.java
new file mode 100644
index 0000000..4fd7ace
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/data/utility/objectpackaging/rmi/ObjectPackagingService.java
@@ -0,0 +1,35 @@
+package eu.dnetlib.data.utility.objectpackaging.rmi;
+
+import java.util.List;
+
+import javax.jws.WebParam;
+import javax.jws.WebService;
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import eu.dnetlib.common.rmi.BaseService;
+
+/** The Object Packaging Service is used to combine the records spread
+ * into one information package, namely an Object Record.
+ */
+
+
+@WebService(targetNamespace = "http://services.dnetlib.eu/")
+public interface ObjectPackagingService extends BaseService {
+ /** Return the EPR of the resultSet containing the generated packages
+ *
+ * @param eprs A list of EPRs used to access the input resultSets. ResultSets MUST be ordered using an order key identified by xpath_ID
+ * @param xpath_ID A valid xpath, used to access the ordered ID of the elements of the input resultSets.
+ * @return EPR of the generated resultset
+ */
+ W3CEndpointReference generatePackages(@WebParam(name="eprs") List eprs,
+ @WebParam(name="xpath_ID") String xpath_ID) throws ObjectPackagingException;
+
+ /** Return the EPR of the resultSet containing the unpackaged element
+ *
+ * @param epr The epr used to access the resultset that contains input packages, packages are xml record in this format: REC1REC2REC3
+ * @return EPR of the generated resultset
+ */
+ W3CEndpointReference splitPackages(@WebParam(name="epr") W3CEndpointReference epr) throws ObjectPackagingException;
+
+
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/enabling/common/Stoppable.java b/dnet-core-components/src/main/java/eu/dnetlib/enabling/common/Stoppable.java
new file mode 100644
index 0000000..99a3440
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/enabling/common/Stoppable.java
@@ -0,0 +1,7 @@
+package eu.dnetlib.enabling.common;
+
+public interface Stoppable {
+ void stop();
+ void resume();
+ StoppableDetails getStopDetails();
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/enabling/common/StoppableDetails.java b/dnet-core-components/src/main/java/eu/dnetlib/enabling/common/StoppableDetails.java
new file mode 100644
index 0000000..a342a4a
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/enabling/common/StoppableDetails.java
@@ -0,0 +1,45 @@
+package eu.dnetlib.enabling.common;
+
+public class StoppableDetails {
+
+ public enum StopStatus {
+ RUNNING, STOPPED, STOPPING
+ }
+
+ private String name;
+ private String message;
+ private StopStatus status;
+
+ public StoppableDetails() {}
+
+ public StoppableDetails(String name, String message, StopStatus status) {
+ this.name = name;
+ this.message = message;
+ this.status = status;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public StopStatus getStatus() {
+ return status;
+ }
+
+ public void setStatus(StopStatus status) {
+ this.status = status;
+ }
+
+}
\ No newline at end of file
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/enabling/dlm/rmi/DlmService.java b/dnet-core-components/src/main/java/eu/dnetlib/enabling/dlm/rmi/DlmService.java
new file mode 100644
index 0000000..c7403f5
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/enabling/dlm/rmi/DlmService.java
@@ -0,0 +1,18 @@
+package eu.dnetlib.enabling.dlm.rmi;
+
+import javax.jws.WebService;
+
+import eu.dnetlib.common.rmi.BaseService;
+
+/**
+ * Distributed lock manager. Currently is used mostly to start the underlying lock manager (e.g. zookeeper) and let
+ * client interface directly with it.
+ *
+ * The DLM service profile contains the entry point of the underlying locking service.
+ *
+ * @author marko
+ *
+ */
+@WebService(targetNamespace = "http://services.dnetlib.eu/")
+public interface DlmService extends BaseService {
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/enabling/hcm/rmi/HostingContextManagerService.java b/dnet-core-components/src/main/java/eu/dnetlib/enabling/hcm/rmi/HostingContextManagerService.java
new file mode 100644
index 0000000..fd03ebe
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/enabling/hcm/rmi/HostingContextManagerService.java
@@ -0,0 +1,20 @@
+package eu.dnetlib.enabling.hcm.rmi;
+
+import javax.jws.WebService;
+
+import eu.dnetlib.common.rmi.BaseService;
+
+/**
+ * Like a HostingNodeManager, but any webapp (web context) can have its own.
+ *
+ * useful for dispatching notifications shared by all the services local to a single context.
+ *
+ *
+ * @author marko
+ * @author antonis
+ *
+ */
+@WebService(targetNamespace = "http://services.dnetlib.eu/")
+public interface HostingContextManagerService extends BaseService {
+
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/enabling/hnm/rmi/HostingNodeManagerService.java b/dnet-core-components/src/main/java/eu/dnetlib/enabling/hnm/rmi/HostingNodeManagerService.java
new file mode 100644
index 0000000..e4d699f
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/enabling/hnm/rmi/HostingNodeManagerService.java
@@ -0,0 +1,17 @@
+package eu.dnetlib.enabling.hnm.rmi;
+
+import javax.jws.WebParam;
+import javax.jws.WebService;
+
+import eu.dnetlib.common.rmi.BaseService;
+
+/**
+ * The HostingNodeManager Service is used to ...
+ *
+ *
+ */
+
+@WebService(targetNamespace = "http://services.dnetlib.eu/")
+public interface HostingNodeManagerService extends BaseService {
+ public String echo(@WebParam(name = "s") String s);
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/enabling/is/lookup/rmi/ISLookUpDocumentNotFoundException.java b/dnet-core-components/src/main/java/eu/dnetlib/enabling/is/lookup/rmi/ISLookUpDocumentNotFoundException.java
new file mode 100644
index 0000000..e58fceb
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/enabling/is/lookup/rmi/ISLookUpDocumentNotFoundException.java
@@ -0,0 +1,47 @@
+package eu.dnetlib.enabling.is.lookup.rmi;
+
+import javax.xml.ws.WebFault;
+
+
+/**
+ * Thrown when a given document is not found.
+ *
+ * @author marko
+ *
+ */
+@WebFault
+public class ISLookUpDocumentNotFoundException extends ISLookUpException {
+
+ /**
+ * exception chain + message.
+ *
+ * @param message message
+ * @param e
+ */
+ public ISLookUpDocumentNotFoundException(String message, Throwable e) {
+ super(message, e);
+ }
+
+ /**
+ * exception chain constructor.
+ * @param e
+ */
+ public ISLookUpDocumentNotFoundException(Throwable e) {
+ super(e);
+ }
+
+ /**
+ * exception message.
+ *
+ * @param message
+ */
+ public ISLookUpDocumentNotFoundException(String message) {
+ super(message);
+ }
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 2295995755165801937L;
+
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/enabling/is/lookup/rmi/ISLookUpException.java b/dnet-core-components/src/main/java/eu/dnetlib/enabling/is/lookup/rmi/ISLookUpException.java
new file mode 100644
index 0000000..07044ac
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/enabling/is/lookup/rmi/ISLookUpException.java
@@ -0,0 +1,27 @@
+package eu.dnetlib.enabling.is.lookup.rmi;
+
+import javax.xml.ws.WebFault;
+
+import eu.dnetlib.common.rmi.RMIException;
+
+@WebFault
+public class ISLookUpException extends RMIException {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -5626136963653382533L;
+
+ public ISLookUpException(Throwable e) {
+ super(e);
+ }
+
+ public ISLookUpException(String message, Throwable e) {
+ super(message, e);
+ }
+
+ public ISLookUpException(String message) {
+ super(message);
+ }
+
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/enabling/is/lookup/rmi/ISLookUpService.java b/dnet-core-components/src/main/java/eu/dnetlib/enabling/is/lookup/rmi/ISLookUpService.java
new file mode 100644
index 0000000..ff1ade4
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/enabling/is/lookup/rmi/ISLookUpService.java
@@ -0,0 +1,53 @@
+package eu.dnetlib.enabling.is.lookup.rmi;
+
+import java.util.List;
+
+import javax.jws.WebParam;
+import javax.jws.WebService;
+
+import eu.dnetlib.common.rmi.BaseService;
+
+@WebService(targetNamespace = "http://services.dnetlib.eu/")
+public interface ISLookUpService extends BaseService {
+
+ Boolean flushCachedResultSets();
+
+ @Deprecated
+ String getCollection(@WebParam(name = "profId") String profId, @WebParam(name = "format") String format) throws ISLookUpException;
+
+ String retrieveCollection(@WebParam(name = "profId") String profId) throws ISLookUpException;
+
+ String getResourceProfile(@WebParam(name = "profId") String profId) throws ISLookUpException, ISLookUpDocumentNotFoundException;
+
+ String getResourceProfileByQuery(@WebParam(name = "XQuery") String XQuery) throws ISLookUpException, ISLookUpDocumentNotFoundException;
+
+ String getResourceQoSParams(@WebParam(name = "id") String id) throws ISLookUpException;
+
+ String getResourceTypeSchema(@WebParam(name = "resourceType") String resourceType) throws ISLookUpException, ISLookUpDocumentNotFoundException;
+
+ List listCollections(
+ @WebParam(name = "format") String format,
+ @WebParam(name = "idfather") String idfather,
+ @WebParam(name = "owner") String owner) throws ISLookUpException;
+
+ @Deprecated
+ List listDHNIDs() throws ISLookUpException;
+
+ List listResourceTypes() throws ISLookUpException;
+
+ @Deprecated
+ List listServiceIDs(@WebParam(name = "serviceType") String serviceType) throws ISLookUpException;
+
+ @Deprecated
+ List listServiceTypes() throws ISLookUpException;
+
+ /**
+ * Like searchProfile(), but bypassing the resultset. Useful for short xquery results.
+ *
+ * @param xquery xquery to be executed
+ * @return list of strings (never null)
+ * @throws ISLookUpException could happen
+ */
+ List quickSearchProfile(@WebParam(name = "XQuery") String xquery) throws ISLookUpException;
+
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/enabling/is/registry/ISRegistryDocumentNotFoundException.java b/dnet-core-components/src/main/java/eu/dnetlib/enabling/is/registry/ISRegistryDocumentNotFoundException.java
new file mode 100644
index 0000000..3082a24
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/enabling/is/registry/ISRegistryDocumentNotFoundException.java
@@ -0,0 +1,27 @@
+package eu.dnetlib.enabling.is.registry;
+
+import eu.dnetlib.enabling.is.registry.rmi.ISRegistryException;
+
+public class ISRegistryDocumentNotFoundException extends ISRegistryException {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -1304948213334188538L;
+
+ public ISRegistryDocumentNotFoundException(String string, Throwable e) {
+ super(string, e);
+ // TODO Auto-generated constructor stub
+ }
+
+ public ISRegistryDocumentNotFoundException(String string) {
+ super(string);
+ // TODO Auto-generated constructor stub
+ }
+
+ public ISRegistryDocumentNotFoundException(Throwable e) {
+ super(e);
+ // TODO Auto-generated constructor stub
+ }
+
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/enabling/is/registry/rmi/ISRegistryException.java b/dnet-core-components/src/main/java/eu/dnetlib/enabling/is/registry/rmi/ISRegistryException.java
new file mode 100644
index 0000000..a077b8a
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/enabling/is/registry/rmi/ISRegistryException.java
@@ -0,0 +1,24 @@
+package eu.dnetlib.enabling.is.registry.rmi;
+
+import eu.dnetlib.common.rmi.RMIException;
+
+public class ISRegistryException extends RMIException {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -3347405941287624771L;
+
+ public ISRegistryException(Throwable e) {
+ super(e);
+ }
+
+ public ISRegistryException(String string) {
+ super(string);
+ }
+
+ public ISRegistryException(String string, Throwable e) {
+ super(string, e);
+ }
+
+}
\ No newline at end of file
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/enabling/is/registry/rmi/ISRegistryService.java b/dnet-core-components/src/main/java/eu/dnetlib/enabling/is/registry/rmi/ISRegistryService.java
new file mode 100644
index 0000000..b502989
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/enabling/is/registry/rmi/ISRegistryService.java
@@ -0,0 +1,75 @@
+package eu.dnetlib.enabling.is.registry.rmi;
+
+import java.util.List;
+
+import javax.jws.WebService;
+
+import eu.dnetlib.common.rmi.BaseService;
+import eu.dnetlib.enabling.is.registry.ISRegistryDocumentNotFoundException;
+
+@WebService(targetNamespace = "http://services.dnetlib.eu/")
+public interface ISRegistryService extends BaseService {
+
+ boolean addOrUpdateResourceType(String resourceType, String resourceSchema) throws ISRegistryException;
+
+ boolean addResourceType(String resourceType, String resourceSchema) throws ISRegistryException;
+
+ boolean deleteProfile(String profId) throws ISRegistryException, ISRegistryDocumentNotFoundException;
+
+ @Deprecated
+ boolean deleteProfiles(List arrayprofId) throws ISRegistryException;
+
+ /**
+ * @param resourceType
+ * @param hierarchical
+ * remove subscription topics
+ * @return
+ * @throws ISRegistryException
+ */
+ boolean deleteResourceType(String resourceType, Boolean hierarchical) throws ISRegistryException;
+
+ boolean executeXUpdate(String XQuery) throws ISRegistryException;
+
+ String insertProfileForValidation(String resourceType, String resourceProfile) throws ISRegistryException;
+
+ String invalidateProfile(String profId) throws ISRegistryException;
+
+ boolean refreshProfile(String profId, String resourceType) throws ISRegistryException;
+
+ /**
+ * register a XML Profile.
+ *
+ * @param resourceProfile
+ * xml profile
+ * @return profile id
+ * @throws ISRegistryException
+ */
+ String registerProfile(String resourceProfile) throws ISRegistryException;
+
+ String registerSecureProfile(String resourceProfId, String secureProfId) throws ISRegistryException;
+
+ boolean updateProfile(String profId, String resourceProfile, String resourceType) throws ISRegistryException;
+
+ @Deprecated
+ String updateProfileDHN(String resourceProfile) throws ISRegistryException;
+
+ boolean addProfileNode(String profId, String xpath, String node) throws ISRegistryException;
+
+ boolean updateProfileNode(String profId, String xpath, String node) throws ISRegistryException;
+
+ boolean removeProfileNode(String profId, String nodeId) throws ISRegistryException;
+
+ @Deprecated
+ boolean updateRegionDescription(String profId, String resourceProfile) throws ISRegistryException;
+
+ String validateProfile(String profId) throws ISRegistryException;
+
+ @Deprecated
+ List validateProfiles(List profIds) throws ISRegistryException;
+
+ void addBlackBoardMessage(String profId, String messageId, String message) throws ISRegistryException;
+
+ void replyBlackBoardMessage(String profId, String message) throws ISRegistryException;
+
+ void deleteBlackBoardMessage(String profId, String messageId) throws ISRegistryException;
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/enabling/is/registry/schema/OpaqueResourceValidator.java b/dnet-core-components/src/main/java/eu/dnetlib/enabling/is/registry/schema/OpaqueResourceValidator.java
new file mode 100644
index 0000000..540f171
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/enabling/is/registry/schema/OpaqueResourceValidator.java
@@ -0,0 +1,19 @@
+package eu.dnetlib.enabling.is.registry.schema;
+
+import eu.dnetlib.enabling.tools.OpaqueResource;
+
+/**
+ * validates the conformity of a resource to a give resource type.
+ *
+ * @author marko
+ *
+ */
+public interface OpaqueResourceValidator {
+ /**
+ * check if the given resource is valid according to it's schema.
+ *
+ * @param resource opaque resource
+ * @throws ValidationException thrown if the validation fails, along with a description of the cause.
+ */
+ void validate(OpaqueResource resource) throws ValidationException;
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/enabling/is/registry/schema/ValidationException.java b/dnet-core-components/src/main/java/eu/dnetlib/enabling/is/registry/schema/ValidationException.java
new file mode 100644
index 0000000..4f750db
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/enabling/is/registry/schema/ValidationException.java
@@ -0,0 +1,35 @@
+package eu.dnetlib.enabling.is.registry.schema;
+
+
+/**
+ * encapsulates a schema validation exception.
+ *
+ * @author marko
+ *
+ */
+public class ValidationException extends Exception {
+
+ /**
+ * version.
+ */
+ private static final long serialVersionUID = -6886927707534508655L;
+
+ /**
+ * construct a validation exception based upon an encapsulated cause.
+ * @param cause cause
+ */
+ public ValidationException(final Throwable cause) {
+ super(cause);
+ }
+
+ /**
+ * construct a validation exception with a message.
+ *
+ * @param message message
+ */
+ public ValidationException(final String message) {
+ super(message);
+ }
+
+
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/enabling/is/sn/rmi/ISSNException.java b/dnet-core-components/src/main/java/eu/dnetlib/enabling/is/sn/rmi/ISSNException.java
new file mode 100644
index 0000000..ac878c6
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/enabling/is/sn/rmi/ISSNException.java
@@ -0,0 +1,24 @@
+package eu.dnetlib.enabling.is.sn.rmi;
+
+import eu.dnetlib.common.rmi.RMIException;
+
+public class ISSNException extends RMIException {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -7384073901457430004L;
+
+ public ISSNException(final Throwable e) {
+ super(e);
+ }
+
+ public ISSNException(final String message) {
+ super(message);
+ }
+
+ public ISSNException(final String message, final Throwable e) {
+ super(message, e);
+ }
+
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/enabling/is/sn/rmi/ISSNService.java b/dnet-core-components/src/main/java/eu/dnetlib/enabling/is/sn/rmi/ISSNService.java
new file mode 100644
index 0000000..98999b5
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/enabling/is/sn/rmi/ISSNService.java
@@ -0,0 +1,129 @@
+package eu.dnetlib.enabling.is.sn.rmi;
+
+import java.util.List;
+
+import javax.jws.WebParam;
+import javax.jws.WebService;
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import eu.dnetlib.common.rmi.BaseService;
+
+@WebService(targetNamespace = "http://services.dnetlib.eu/")
+public interface ISSNService extends BaseService {
+
+ /**
+ * fossil.
+ *
+ * @param topic
+ * @return
+ * @throws ISSNException
+ */
+ String getCurrentMessage(@WebParam(name = "topic") String topic) throws ISSNException;
+
+ /**
+ * puts a subcription in a paused state. paused subscription are not notified even when triggered.
+ *
+ * @param subscrId
+ * subscription identifier
+ * @return returns false if the subscription is already paused.
+ * @throws ISSNException
+ * may happen
+ */
+ boolean pauseSubscription(@WebParam(name = "subscrId") String subscrId) throws ISSNException;
+
+ /**
+ * Used to renew the subscription before it expires.
+ *
+ *
+ * In practice it resets the ttl to another value, so it can be used to reset a infinte ttl subscription to a finite
+ * value.
+ *
+ *
+ * @param subscrId
+ * subscription id
+ * @param terminationTime
+ * new ttl (from now), or 0 (infinite)
+ * @return true if successful
+ * @throws ISSNException
+ * may happen
+ */
+ boolean renew(@WebParam(name = "subscrId") String subscrId, @WebParam(name = "terminationTime") int terminationTime) throws ISSNException;
+
+ /**
+ * resumes a paused subscription.
+ *
+ * @param subscrId
+ * subscription id
+ * @return true if resumed. false if it was not paused.
+ * @throws ISSNException
+ * may happen
+ */
+ boolean resumeSubscription(@WebParam(name = "subscrId") String subscrId) throws ISSNException;
+
+ /**
+ * @param consumerReference
+ * epr to be called when the notification is triggered
+ * @param topicExpression
+ * topic expression to register
+ * @param initialTerminationTime
+ * ttl in seconds (0 = infinite)
+ * @return subscription id
+ * @throws ISSNException
+ * may happen
+ */
+ String subscribe(
+ @WebParam(name = "consumerReference") W3CEndpointReference consumerReference,
+ @WebParam(name = "topicExpression") String topicExpression,
+ @WebParam(name = "initialTerminationTime") int initialTerminationTime) throws ISSNException, SubscriptionRequestRejectedException;
+
+ boolean unsubscribe(@WebParam(name = "subscrId") String subscrId) throws ISSNException;
+
+ /**
+ * fossil.
+ *
+ * @param resourceType
+ * @param profileId
+ * @param profile
+ * @return
+ * @throws ISSNException
+ */
+ boolean actionCreatePerformed(
+ @WebParam(name = "resourceType") String resourceType,
+ @WebParam(name = "profileId") String profileId,
+ @WebParam(name = "profile") String profile) throws ISSNException;
+
+ /**
+ * fossil.
+ *
+ * @param resourceType
+ * @param profileId
+ * @param profileBefore
+ * @param profileAfter
+ * @return
+ * @throws ISSNException
+ */
+ boolean actionUpdatePerformed(
+ @WebParam(name = "resourceType") String resourceType,
+ @WebParam(name = "profileId") String profileId,
+ @WebParam(name = "profileBefore") String profileBefore,
+ @WebParam(name = "profileAfter") String profileAfter) throws ISSNException;
+
+ /**
+ * fossil.
+ *
+ * @param resourceType
+ * @param profileId
+ * @return
+ * @throws ISSNException
+ */
+ boolean actionDeletePerformed(@WebParam(name = "resourceType") String resourceType, @WebParam(name = "profileId") String profileId)
+ throws ISSNException;
+
+ /**
+ * list all subscriptions. Mostly for debug reasons.
+ *
+ * @return list of subscription ids.
+ */
+ List listSubscriptions();
+
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/enabling/is/sn/rmi/SubscriptionRequestRejectedException.java b/dnet-core-components/src/main/java/eu/dnetlib/enabling/is/sn/rmi/SubscriptionRequestRejectedException.java
new file mode 100644
index 0000000..bd23923
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/enabling/is/sn/rmi/SubscriptionRequestRejectedException.java
@@ -0,0 +1,21 @@
+package eu.dnetlib.enabling.is.sn.rmi;
+
+/**
+ * Thrown when a subscription request is rejected.
+ *
+ * @author claudio
+ *
+ */
+public class SubscriptionRequestRejectedException extends ISSNException {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 263095606953662098L;
+
+ public SubscriptionRequestRejectedException(String message) {
+ super(message);
+ // TODO Auto-generated constructor stub
+ }
+
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/enabling/is/store/AbstractContentInitializer.java b/dnet-core-components/src/main/java/eu/dnetlib/enabling/is/store/AbstractContentInitializer.java
new file mode 100644
index 0000000..db189e6
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/enabling/is/store/AbstractContentInitializer.java
@@ -0,0 +1,135 @@
+package eu.dnetlib.enabling.is.store;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.net.URL;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.xpath.XPathExpressionException;
+
+import org.apache.commons.io.FilenameUtils;
+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 org.xml.sax.SAXException;
+
+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.StreamOpaqueResource;
+
+/**
+ * Abstract resource loading code.
+ *
+ * @author marko, michele
+ *
+ */
+public class AbstractContentInitializer {
+
+ /**
+ * logger.
+ */
+ private static final Log log = LogFactory.getLog(AbstractContentInitializer.class); // NOPMD by marko on 11/24/08 5:02 PM
+ /**
+ * service locator.
+ */
+ private UniqueServiceLocator serviceLocator;
+ /**
+ * helper class used to bypass the registry and import resources as-is from a backup dump.
+ */
+ private BulkResourceImporter bulkImporter;
+
+ private int timeToSleep;
+
+ /**
+ * register a schema from a local resource.
+ *
+ * @param url
+ * url
+ * @throws IOException
+ * happens
+ * @throws ISRegistryException
+ * could happen
+ */
+ protected void registerSchema(final URL url) throws IOException, ISRegistryException {
+ final String resourceType = FilenameUtils.getBaseName(url.getPath());
+ log.debug("registering schema: " + resourceType);
+
+ final StringWriter writer = new StringWriter();
+ IOUtils.copy(url.openStream(), writer);
+ ISRegistryService service = null;
+ while (service == null) {
+ try {
+ service = serviceLocator.getService(ISRegistryService.class, true);
+ service.addResourceType(resourceType, writer.getBuffer().toString());
+ log.info("The is registry service is ready ");
+ } catch (Exception e) {
+ log.fatal("The is registry service is not ready ", e);
+ try {
+ Thread.sleep(timeToSleep);
+ } catch (InterruptedException e1) {
+ log.error(e1);
+ }
+ }
+ }
+
+ }
+
+ /**
+ * register a profile from a local resource.
+ *
+ * @param url
+ * url
+ * @throws IOException
+ * could happen
+ * @throws ISRegistryException
+ * could happen
+ * @throws ParserConfigurationException
+ * could happen
+ * @throws SAXException
+ * could happen
+ * @throws XPathExpressionException
+ * could happen
+ */
+ protected void registerProfile(final URL url) throws IOException, ISRegistryException, XPathExpressionException, SAXException, ParserConfigurationException {
+ log.debug("registering profile: " + url);
+
+ bulkImporter.importResource(new StreamOpaqueResource(url.openStream()));
+ }
+
+ @Required
+ public void setBulkImporter(final BulkResourceImporter bulkImporter) {
+ this.bulkImporter = bulkImporter;
+ }
+
+ public BulkResourceImporter getBulkImporter() {
+ return bulkImporter;
+ }
+
+ /**
+ * @return the timeToSleep
+ */
+ public int getTimeToSleep() {
+ return timeToSleep;
+ }
+
+ /**
+ * @param timeToSleep
+ * the timeToSleep to set
+ */
+ @Required
+ public void setTimeToSleep(final int timeToSleep) {
+ this.timeToSleep = timeToSleep;
+ }
+
+ public UniqueServiceLocator getServiceLocator() {
+ return serviceLocator;
+ }
+
+ @Required
+ public void setServiceLocator(final UniqueServiceLocator serviceLocator) {
+ this.serviceLocator = serviceLocator;
+ }
+
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/enabling/is/store/BulkResourceImporter.java b/dnet-core-components/src/main/java/eu/dnetlib/enabling/is/store/BulkResourceImporter.java
new file mode 100644
index 0000000..9304a29
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/enabling/is/store/BulkResourceImporter.java
@@ -0,0 +1,115 @@
+package eu.dnetlib.enabling.is.store;
+
+import org.springframework.beans.factory.annotation.Required;
+
+import eu.dnetlib.enabling.is.registry.rmi.ISRegistryException;
+import eu.dnetlib.enabling.is.registry.schema.OpaqueResourceValidator;
+import eu.dnetlib.enabling.is.registry.schema.ValidationException;
+import eu.dnetlib.enabling.is.store.rmi.ISStoreException;
+import eu.dnetlib.enabling.is.store.rmi.ISStoreService;
+import eu.dnetlib.enabling.locators.UniqueServiceLocator;
+import eu.dnetlib.enabling.tools.OpaqueResource;
+import eu.dnetlib.enabling.tools.XQueryUtils;
+
+/**
+ * This class implements a bulk resource import, i.e. importing stuff straight into the store, bypassing checks and policies imposed by the
+ * registry service.
+ *
+ * TODO: move from registry based to store based.
+ *
+ * @author marko
+ *
+ */
+public class BulkResourceImporter {
+
+ /**
+ * xquery utils, needed to map resources with the xmldb collection names.
+ */
+ private XQueryUtils xqueryUtils;
+
+ /**
+ * service locator.
+ */
+ private UniqueServiceLocator serviceLocator;
+
+ /**
+ * resource validator.
+ */
+ private OpaqueResourceValidator resourceValidator;
+
+ /**
+ * set to false to skip validation.
+ */
+ private boolean validating = true;
+
+ /**
+ * bulk loading enabled.
+ */
+ private boolean enabled = true;
+
+ /**
+ * register a resource bypassing the checks.
+ *
+ * @param resource
+ * a resource
+ * @throws ISRegistryException
+ * could happen
+ */
+ public void importResource(final OpaqueResource resource) throws ISRegistryException {
+ try {
+ if (validating) {
+ resourceValidator.validate(resource);
+ }
+ serviceLocator.getService(ISStoreService.class, true).insertXML(xqueryUtils.getFileName(resource), xqueryUtils.getCollectionAbsPath(resource),
+ resource.asString());
+ } catch (final ISStoreException e) {
+ throw new ISRegistryException(e);
+ } catch (final ValidationException e) {
+ throw new ISRegistryException(e);
+ }
+ }
+
+ public XQueryUtils getXqueryUtils() {
+ return xqueryUtils;
+ }
+
+ @Required
+ public void setXqueryUtils(final XQueryUtils xqueryUtils) {
+ this.xqueryUtils = xqueryUtils;
+ }
+
+ @Required
+ public void setResourceValidator(final OpaqueResourceValidator resourceValidator) {
+ this.resourceValidator = resourceValidator;
+ }
+
+ public OpaqueResourceValidator getResourceValidator() {
+ return resourceValidator;
+ }
+
+ public void setValidating(final boolean validating) {
+ this.validating = validating;
+ }
+
+ public boolean isValidating() {
+ return validating;
+ }
+
+ public boolean isEnabled() {
+ return enabled;
+ }
+
+ public void setEnabled(final boolean enabled) {
+ this.enabled = enabled;
+ }
+
+ public UniqueServiceLocator getServiceLocator() {
+ return serviceLocator;
+ }
+
+ @Required
+ public void setServiceLocator(final UniqueServiceLocator serviceLocator) {
+ this.serviceLocator = serviceLocator;
+ }
+
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/enabling/is/store/rmi/ISStoreException.java b/dnet-core-components/src/main/java/eu/dnetlib/enabling/is/store/rmi/ISStoreException.java
new file mode 100644
index 0000000..96c7721
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/enabling/is/store/rmi/ISStoreException.java
@@ -0,0 +1,24 @@
+package eu.dnetlib.enabling.is.store.rmi;
+
+import eu.dnetlib.common.rmi.RMIException;
+
+public class ISStoreException extends RMIException {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 8683126829156096420L;
+
+ public ISStoreException(Throwable e) {
+ super(e);
+ }
+
+ public ISStoreException(String message, Throwable e) {
+ super(message, e);
+ }
+
+ public ISStoreException(String message) {
+ super(message);
+ }
+
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/enabling/is/store/rmi/ISStoreService.java b/dnet-core-components/src/main/java/eu/dnetlib/enabling/is/store/rmi/ISStoreService.java
new file mode 100644
index 0000000..4a7282a
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/enabling/is/store/rmi/ISStoreService.java
@@ -0,0 +1,44 @@
+package eu.dnetlib.enabling.is.store.rmi;
+
+import java.util.List;
+
+import javax.jws.WebParam;
+import javax.jws.WebService;
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import eu.dnetlib.common.rmi.BaseService;
+
+@WebService(targetNamespace = "http://services.dnetlib.eu/")
+public interface ISStoreService extends BaseService {
+
+ boolean createFileColl(@WebParam(name = "fileColl") String fileColl) throws ISStoreException;
+
+ boolean deleteFileColl(@WebParam(name = "fileColl") String fileColl) throws ISStoreException;
+
+ boolean deleteXML(@WebParam(name = "fileName") String fileName, @WebParam(name = "fileColl") String fileColl) throws ISStoreException;
+
+ boolean executeXUpdate(@WebParam(name = "query") String query) throws ISStoreException;
+
+ List getFileColls() throws ISStoreException;
+
+ List getFileNames(@WebParam(name = "fileColl") String fileColl) throws ISStoreException;
+
+ String getXML(@WebParam(name = "fileName") String fileName, @WebParam(name = "fileColl") String fileColl) throws ISStoreException;
+
+ String getXMLbyQuery(@WebParam(name = "query") String query) throws ISStoreException;
+
+ boolean insertXML(@WebParam(name = "fileName") String fileName, @WebParam(name = "fileColl") String fileColl, @WebParam(name = "file") String file)
+ throws ISStoreException;
+
+ boolean reindex();
+
+ List quickSearchXML(@WebParam(name = "query") String query) throws ISStoreException;
+
+ boolean sync();
+
+ boolean updateXML(@WebParam(name = "fileName") String fileName, @WebParam(name = "fileColl") String fileColl, @WebParam(name = "file") String file)
+ throws ISStoreException;
+
+ String backup() throws ISStoreException;
+
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/enabling/locators/DefaultUniqueServiceLocator.java b/dnet-core-components/src/main/java/eu/dnetlib/enabling/locators/DefaultUniqueServiceLocator.java
new file mode 100644
index 0000000..39b88ea
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/enabling/locators/DefaultUniqueServiceLocator.java
@@ -0,0 +1,264 @@
+package eu.dnetlib.enabling.locators;
+
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.util.*;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import eu.dnetlib.common.rmi.BaseService;
+import eu.dnetlib.enabling.is.lookup.rmi.ISLookUpException;
+import eu.dnetlib.enabling.is.lookup.rmi.ISLookUpService;
+import eu.dnetlib.enabling.tools.registration.ServiceNameResolver;
+import eu.dnetlib.enabling.tools.registration.ValidatingServiceRegistrationManagerImpl;
+import eu.dnetlib.miscutils.collections.EnsureCollection;
+import eu.dnetlib.soap.cxf.StandaloneCxfEndpointReferenceBuilder;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.math.NumberUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.dom4j.Document;
+import org.dom4j.DocumentException;
+import org.dom4j.Element;
+import org.dom4j.io.SAXReader;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Required;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+
+public class DefaultUniqueServiceLocator implements UniqueServiceLocator, ApplicationContextAware {
+
+ private ApplicationContext appContext;
+
+ private Comparator defaultComparator; // = new
+ // PreferLocalRunningInstanceComparator();
+
+ /**
+ * An instance of isLookupService (local or stub)
+ */
+ @Autowired
+ private ISLookUpService isLookupService;
+
+ @Autowired
+ private ServiceNameResolver serviceNameResolver;
+
+ /**
+ * XML Parser
+ */
+ private SAXReader reader = new SAXReader();
+
+ /**
+ * build epr.
+ */
+ @Autowired
+ private StandaloneCxfEndpointReferenceBuilder eprBuilder;
+
+ /**
+ * logger.
+ */
+ private static final Log log = LogFactory.getLog(DefaultUniqueServiceLocator.class);
+
+ @Override
+ public T getService(final Class clazz) {
+ return getService(clazz, true);
+ }
+
+ @Override
+ public T getService(final Class clazz, final Comparator comparator) {
+ final String serviceName = serviceNameResolver.getName(clazz);
+ return findRunningInstances(serviceName, comparator).get(0).obtainClient(clazz, eprBuilder);
+ }
+
+ @Override
+ public T getService(final Class clazz, final String profileId) {
+ final String profile = obtainServiceProfile(profileId);
+
+ try {
+ return obtainRunningInstance(profile, obtainLocalServices()).obtainClient(clazz, eprBuilder);
+ } catch (Exception e) {
+ log.error("cannot instantiate service from id: " + profileId, e);
+ throw new IllegalStateException("cannot instantiate service from id: " + profileId, e);
+ }
+ }
+
+ @Override
+ public T getService(final Class clazz, final boolean local) {
+ if (clazz.isInstance(isLookupService)) return clazz.cast(isLookupService);
+
+ if (local) {
+ try {
+ final Map beans = appContext.getBeansOfType(clazz);
+ if ((beans != null) && !beans.isEmpty()) return beans.values().iterator().next();
+ } catch (Throwable e) {
+ log.warn("No beans found in context, class " + clazz);
+ }
+ }
+
+ return getService(clazz, defaultComparator);
+ }
+
+ @Override
+ public String getServiceId(final Class clazz) {
+ return getServiceId(clazz, defaultComparator);
+ }
+
+ @Override
+ public String getServiceId(final Class clazz, final Comparator comparator) {
+ return findRunningInstances(serviceNameResolver.getName(clazz), comparator).get(0).getServiceId();
+ }
+
+ @Override
+ public String getServiceId(final Class clazz, final String profileId) {
+ final String profile = obtainServiceProfile(profileId);
+ final ServiceRunningInstance instance = obtainRunningInstance(profile, obtainLocalServices());
+ return instance.getServiceId();
+ }
+
+ @Override
+ public Set getAllServices(final Class clazz) {
+ final Set res = Sets.newHashSet();
+ for (ServiceRunningInstance instance : findRunningInstances(serviceNameResolver.getName(clazz), null)) {
+ res.add(instance.obtainClient(clazz, eprBuilder));
+ }
+ return res;
+ }
+
+ @Override
+ public Set getAllServiceIds(final Class clazz) {
+ final Set res = Sets.newHashSet();
+ for (ServiceRunningInstance instance : findRunningInstances(serviceNameResolver.getName(clazz), null)) {
+ res.add(instance.getServiceId());
+ }
+ return res;
+ }
+
+ private synchronized ServiceRunningInstance obtainRunningInstance(final String profile, final Map locals) {
+ try {
+ final Document doc = reader.read(new StringReader(profile));
+ final String url = doc.valueOf("//PROTOCOL[@name = 'SOAP']/@address");
+ final String id = doc.valueOf("//RESOURCE_IDENTIFIER/@value");
+ final Map props = Maps.newHashMap();
+ final BaseService local = locals.containsKey(id) ? locals.get(id) : null;
+ final int usedDiskpace = NumberUtils.toInt(doc.valueOf("//USED_DISKSPACE"), 0);
+ final int handledDatastructures = NumberUtils.toInt(doc.valueOf("//HANDLED_DATASTRUCTURE"), 0);;
+
+ for (Object o : doc.selectNodes("//SERVICE_PROPERTIES/PROPERTY")) {
+ final Element p = (Element) o;
+ props.put(p.valueOf("@key"), p.valueOf("@value"));
+ }
+
+ return new ServiceRunningInstance(id, url, local, usedDiskpace, handledDatastructures, props);
+ } catch (DocumentException e) {
+ log.error("Error parsing profile: " + profile, e);
+ throw new RuntimeException("Error parsing profile: " + profile, e);
+ }
+ }
+
+ private List findRunningInstances(final String serviceName, final Comparator comparator) {
+ final List list = findRegisteredServices(serviceName);
+
+ if (list.isEmpty()) {
+ log.error("Service not found, name: " + serviceName);
+ throw new RuntimeException("Service not found, name: " + serviceName);
+ }
+
+ if (comparator != null) {
+ Collections.sort(list, comparator);
+ }
+
+ return list;
+ }
+
+ private List findRegisteredServices(final String serviceName) {
+ log.debug("searching for service: " + serviceName);
+
+ final String xquery = "for $x in collection('/db/DRIVER/ServiceResources/" + serviceName + "ResourceType') return $x";
+ log.debug(xquery);
+
+ try {
+ final List services = isLookupService.quickSearchProfile(xquery);
+ final List instances = Lists.newArrayList();
+ final Map locals = obtainLocalServices();
+
+ for (final String source : EnsureCollection.list(services)) {
+ final ServiceRunningInstance instance = obtainRunningInstance(source, locals);
+ instances.add(instance);
+ }
+ return instances;
+ } catch (final Exception e) {
+ throw new IllegalStateException("cannot locate service " + serviceName, e);
+ }
+ }
+
+ private Map obtainLocalServices() {
+ final Map locals = Maps.newHashMap();
+
+ for (ValidatingServiceRegistrationManagerImpl r : appContext.getBeansOfType(ValidatingServiceRegistrationManagerImpl.class).values()) {
+ if (r.getService() instanceof BaseService) {
+ if (!StringUtils.isBlank(r.getProfileId())) {
+ final BaseService baseService = (BaseService) r.getService();
+ if (baseService != null) {
+ locals.put(r.getProfileId(), baseService);
+ log.debug(" -> Service: " + r.getService().getClass().getName() + " has id " + r.getServiceProfile().getResourceId());
+ }
+ }
+ }
+ }
+ return locals;
+ }
+
+ private String obtainServiceProfile(final String profileId) {
+ final StringWriter sw = new StringWriter();
+ sw.append("let $uri:=/RESOURCE_PROFILE/HEADER[./RESOURCE_IDENTIFIER/@value='");
+ sw.append(profileId);
+ sw.append("']/RESOURCE_URI/@value/string()");
+ sw.append("\n\n");
+ sw.append("for $x in collection('/db/DRIVER/ServiceResources')");
+ sw.append("\n");
+ sw.append("where $x/RESOURCE_PROFILE/HEADER/RESOURCE_URI/@value = $uri");
+ sw.append("\n");
+ sw.append("return $x");
+
+ final String xq = sw.toString();
+
+ try {
+ return isLookupService.getResourceProfileByQuery(xq);
+ } catch (ISLookUpException e) {
+ log.error("cannot locate service using query: " + xq, e);
+ throw new IllegalStateException("cannot locate service using query: " + xq, e);
+ }
+ }
+
+ @Override
+ public void setApplicationContext(final ApplicationContext appContext) throws BeansException {
+ this.appContext = appContext;
+ }
+
+ public Comparator getDefaultComparator() {
+ return defaultComparator;
+ }
+
+ @Required
+ public void setDefaultComparator(final Comparator defaultComparator) {
+ this.defaultComparator = defaultComparator;
+ }
+
+ public ISLookUpService getIsLookupService() {
+ return isLookupService;
+ }
+
+ public void setIsLookupService(final ISLookUpService isLookupService) {
+ this.isLookupService = isLookupService;
+ }
+
+ public ServiceNameResolver getServiceNameResolver() {
+ return serviceNameResolver;
+ }
+
+ public void setServiceNameResolver(final ServiceNameResolver serviceNameResolver) {
+ this.serviceNameResolver = serviceNameResolver;
+ }
+
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/enabling/locators/ServiceRunningInstance.java b/dnet-core-components/src/main/java/eu/dnetlib/enabling/locators/ServiceRunningInstance.java
new file mode 100644
index 0000000..eb510ca
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/enabling/locators/ServiceRunningInstance.java
@@ -0,0 +1,102 @@
+package eu.dnetlib.enabling.locators;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.xml.ws.WebServiceFeature;
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import eu.dnetlib.common.rmi.BaseService;
+import eu.dnetlib.soap.cxf.StandaloneCxfEndpointReferenceBuilder;
+
+/**
+ * This bean packages the minimum information for describing a service running instance.
+ */
+public class ServiceRunningInstance {
+
+ private String serviceId;
+ private String url;
+ private BaseService localService;
+ private int usedDiskSpace = 0;
+ private int handledDatastructures = 0;
+ private Map serviceProperties = new HashMap();
+
+ public ServiceRunningInstance() {}
+
+ public ServiceRunningInstance(final String serviceId, final String url) {
+ this.serviceId = serviceId;
+ this.url = url;
+ }
+
+ public ServiceRunningInstance(final String serviceId, final String url, final BaseService localService, final int usedDiskSpace,
+ final int handledDatastructures, final Map serviceProperties) {
+ this.serviceId = serviceId;
+ this.url = url;
+ this.localService = localService;
+ this.usedDiskSpace = usedDiskSpace;
+ this.handledDatastructures = handledDatastructures;
+ this.serviceProperties = serviceProperties;
+ }
+
+ public boolean isLocal() {
+ return localService != null;
+ }
+
+ synchronized public T obtainClient(final Class clazz, final StandaloneCxfEndpointReferenceBuilder eprBuilder) {
+ if (isLocal() && clazz.isInstance(localService)) {
+ return clazz.cast(localService);
+ } else {
+ final W3CEndpointReference epr = eprBuilder.getEndpointReference(url, null, null, url + "?wsdl", null, null);
+ return epr.getPort(clazz, new WebServiceFeature[] {});
+ }
+ }
+
+ public String getServiceId() {
+ return serviceId;
+ }
+
+ public void setServiceId(final String serviceId) {
+ this.serviceId = serviceId;
+ }
+
+ public String getUrl() {
+ return url;
+ }
+
+ public void setUrl(final String url) {
+ this.url = url;
+ }
+
+ public BaseService getLocalService() {
+ return localService;
+ }
+
+ public void setLocalService(final BaseService localService) {
+ this.localService = localService;
+ }
+
+ public Map getServiceProperties() {
+ return serviceProperties;
+ }
+
+ public void setServiceProperties(final Map serviceProperties) {
+ this.serviceProperties = serviceProperties;
+ }
+
+ public int getUsedDiskSpace() {
+ return usedDiskSpace;
+ }
+
+ public void setUsedDiskSpace(final int usedDiskSpace) {
+ this.usedDiskSpace = usedDiskSpace;
+ }
+
+ public int getHandledDatastructures() {
+ return handledDatastructures;
+ }
+
+ public void setHandledDatastructures(final int handledDatastructures) {
+ this.handledDatastructures = handledDatastructures;
+ }
+
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/enabling/locators/UniqueServiceLocator.java b/dnet-core-components/src/main/java/eu/dnetlib/enabling/locators/UniqueServiceLocator.java
new file mode 100644
index 0000000..985148d
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/enabling/locators/UniqueServiceLocator.java
@@ -0,0 +1,20 @@
+package eu.dnetlib.enabling.locators;
+
+import java.util.Comparator;
+import java.util.Set;
+
+import eu.dnetlib.common.rmi.BaseService;
+
+public interface UniqueServiceLocator {
+ T getService(Class clazz);
+ T getService(Class clazz, Comparator comparator);
+ T getService(Class clazz, String profileId);
+ T getService(Class clazz, boolean local);
+
+ String getServiceId(Class clazz);
+ String getServiceId(Class clazz, Comparator comparator);
+ String getServiceId(Class clazz, String profileId);
+
+ Set getAllServices(Class clazz);
+ Set getAllServiceIds(Class clazz);
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/enabling/locators/comparators/DiskSpaceComparator.java b/dnet-core-components/src/main/java/eu/dnetlib/enabling/locators/comparators/DiskSpaceComparator.java
new file mode 100644
index 0000000..f5962d5
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/enabling/locators/comparators/DiskSpaceComparator.java
@@ -0,0 +1,14 @@
+package eu.dnetlib.enabling.locators.comparators;
+
+import java.util.Comparator;
+
+import eu.dnetlib.enabling.locators.ServiceRunningInstance;
+
+public class DiskSpaceComparator implements Comparator {
+
+ @Override
+ public int compare(final ServiceRunningInstance s0, ServiceRunningInstance s1) {
+ return Integer.compare(s0.getUsedDiskSpace(), s1.getUsedDiskSpace());
+ }
+
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/enabling/locators/comparators/HandledDatastructuresComparator.java b/dnet-core-components/src/main/java/eu/dnetlib/enabling/locators/comparators/HandledDatastructuresComparator.java
new file mode 100644
index 0000000..d782e92
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/enabling/locators/comparators/HandledDatastructuresComparator.java
@@ -0,0 +1,14 @@
+package eu.dnetlib.enabling.locators.comparators;
+
+import java.util.Comparator;
+
+import eu.dnetlib.enabling.locators.ServiceRunningInstance;
+
+public class HandledDatastructuresComparator implements Comparator {
+
+ @Override
+ public int compare(final ServiceRunningInstance s1, final ServiceRunningInstance s2) {
+ return Integer.compare(s1.getHandledDatastructures(), s2.getHandledDatastructures());
+ }
+
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/enabling/locators/comparators/PreferLocalRunningInstanceComparator.java b/dnet-core-components/src/main/java/eu/dnetlib/enabling/locators/comparators/PreferLocalRunningInstanceComparator.java
new file mode 100644
index 0000000..8cd8b63
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/enabling/locators/comparators/PreferLocalRunningInstanceComparator.java
@@ -0,0 +1,20 @@
+package eu.dnetlib.enabling.locators.comparators;
+
+import java.util.Comparator;
+
+import eu.dnetlib.enabling.locators.ServiceRunningInstance;
+
+public class PreferLocalRunningInstanceComparator implements Comparator {
+
+ @Override
+ public int compare(final ServiceRunningInstance s1, final ServiceRunningInstance s2) {
+ if (s1.isLocal()) {
+ return -1;
+ } else if (s2.isLocal()) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/enabling/resultset/rmi/ResultSetException.java b/dnet-core-components/src/main/java/eu/dnetlib/enabling/resultset/rmi/ResultSetException.java
new file mode 100644
index 0000000..455c8dc
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/enabling/resultset/rmi/ResultSetException.java
@@ -0,0 +1,21 @@
+package eu.dnetlib.enabling.resultset.rmi;
+
+import eu.dnetlib.common.rmi.RMIException;
+
+public class ResultSetException extends RMIException {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -7130554407601059627L;
+
+ public ResultSetException(Throwable e) {
+ super(e);
+ // TODO Auto-generated constructor stub
+ }
+
+ public ResultSetException(String string) {
+ super(string);
+ }
+
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/enabling/resultset/rmi/ResultSetService.java b/dnet-core-components/src/main/java/eu/dnetlib/enabling/resultset/rmi/ResultSetService.java
new file mode 100644
index 0000000..269dd83
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/enabling/resultset/rmi/ResultSetService.java
@@ -0,0 +1,142 @@
+package eu.dnetlib.enabling.resultset.rmi;
+
+import java.util.List;
+
+import javax.jws.WebMethod;
+import javax.jws.WebParam;
+import javax.jws.WebService;
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import eu.dnetlib.common.rmi.BaseService;
+
+/**
+ * ResultSet service interface.
+ *
+ * TODO: implement other compatibility methods as needed.
+ *
+ * @author marko
+ *
+ */
+@WebService(targetNamespace = "http://services.dnetlib.eu/")
+public interface ResultSetService extends BaseService {
+ /**
+ * create a new pull rs.
+ *
+ * @param bdId
+ * bulk data identifier
+ * @param initialPageSize
+ * page size for the polling on the server side.
+ * @param expiryTime
+ * RS expiry time
+ * @return
+ */
+ W3CEndpointReference createPullRSEPR(
+ @WebParam(name = "dataProviderServiceAddress") W3CEndpointReference dataProviderEPR,
+ @WebParam(name = "bdId") String bdId,
+ @WebParam(name = "initialPageSize") int initialPageSize,
+ @WebParam(name = "expiryTime") int expiryTime,
+ @WebParam(name = "styleSheet") String styleSheet,
+ @WebParam(name = "keepAliveTime") Integer keepAliveTime,
+ @WebParam(name = "total") Integer total);
+
+ /**
+ * create a new pull rs.
+ *
+ * compatibility version
+ *
+ * @param bdId
+ * bulk data identifier
+ * @param initialPageSize
+ * page size for the polling on the server side.
+ * @param expiryTime
+ * RS expiry time
+ * @return
+ */
+ W3CEndpointReference createPullRS(
+ @WebParam(name = "dataProviderServiceAddress") String dataProviderServiceAddress,
+ @WebParam(name = "bdId") String bdId,
+ @WebParam(name = "initialPageSize") int initialPageSize,
+ @WebParam(name = "expiryTime") int expiryTime,
+ @WebParam(name = "styleSheet") String styleSheet,
+ @WebParam(name = "keepAliveTime") Integer keepAliveTime,
+ @WebParam(name = "total") Integer total);
+
+ /**
+ * close a result set. A closed resultset is guaranteed not to grow.
+ *
+ * @param rsId
+ */
+ void closeRS(@WebParam(name = "rsId") String rsId);
+
+ /**
+ * get one 'page' of results.
+ *
+ * TODO: define how results are returned when the range is not present in the result set.
+ *
+ * @param fromPosition
+ * counting from 1
+ * @param toPosition
+ * included
+ * @param requestMode
+ * @return a page of data
+ */
+ List getResult(
+ @WebParam(name = "rsId") String rsId,
+ @WebParam(name = "fromPosition") int fromPosition,
+ @WebParam(name = "toPosition") int toPosition,
+ @WebParam(name = "requestMode") String requestMode) throws ResultSetException;
+
+ /**
+ * get the number of result elements present in the resultset.
+ *
+ * @param rsId
+ * result set identifier
+ * @return number of results available in the resultset
+ * @throws ResultSetException
+ */
+ int getNumberOfElements(@WebParam(name = "rsId") String rsId) throws ResultSetException;
+
+ /**
+ * create a new push resultset.
+ *
+ * @param expiryTime RS expiry time
+ * @param keepAliveTime keep alive time
+ * @return epr of new resultset
+ * @throws ResultSetException
+ */
+ W3CEndpointReference createPushRS(@WebParam(name = "expiryTime") int expiryTime, @WebParam(name = "keepAliveTime") int keepAliveTime)
+ throws ResultSetException;
+
+ /**
+ * add new data to a push resultset.
+ *
+ * @param rsId resultset id
+ * @param elements list of elements to be addded
+ * @return dummy value
+ * @throws ResultSetException
+ */
+ String populateRS(@WebParam(name = "rsId") String rsId, @WebParam(name = "elements") List elements) throws ResultSetException;
+
+ /**
+ * return current status of a resultset.
+ *
+ * @param rsId resultset id
+ * @return status
+ * @throws ResultSetException
+ */
+ String getRSStatus(@WebParam(name = "rsId") String rsId) throws ResultSetException;
+
+ /**
+ * read a resultset property.
+ *
+ * @param rsId resultset id
+ * @param name property value
+ * @return property value
+ * @throws ResultSetException
+ */
+ String getProperty(@WebParam(name = "rsId") String rsId, @WebParam(name = "name") String name) throws ResultSetException;
+
+ @WebMethod(operationName = "identify")
+ public String identify();
+
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/enabling/soap/AbstractEndpointReferenceBuilder.java b/dnet-core-components/src/main/java/eu/dnetlib/enabling/soap/AbstractEndpointReferenceBuilder.java
new file mode 100644
index 0000000..9d5343a
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/enabling/soap/AbstractEndpointReferenceBuilder.java
@@ -0,0 +1,46 @@
+package eu.dnetlib.soap;
+
+import java.util.Map;
+
+import javax.xml.namespace.QName;
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+/**
+ *
+ * default implementation short methods.
+ *
+ * @author marko
+ *
+ * @param
+ */
+public abstract class AbstractEndpointReferenceBuilder implements EndpointReferenceBuilder {
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see eu.dnetlib.soap.EndpointReferenceBuilder#getEndpointReference(java.lang.Object)
+ */
+ @Override
+ public W3CEndpointReference getEndpointReference(final T endpoint) {
+ return getEndpointReference(endpoint, (Map)null);
+ }
+
+ /**
+ * {@inheritDoc}
+ * @see eu.dnetlib.soap.EndpointReferenceBuilder#getEndpointReference(java.lang.Object, java.lang.String)
+ */
+ @Override
+ public W3CEndpointReference getEndpointReference(final T endpoint, final String referenceParam) {
+ return getEndpointReference(endpoint, referenceParam, null);
+ }
+
+ /**
+ * {@inheritDoc}
+ * @see eu.dnetlib.soap.EndpointReferenceBuilder#getEndpointReference(java.lang.Object, java.util.Map)
+ */
+ @Override
+ public W3CEndpointReference getEndpointReference(final T endpoint, final Map attrs) {
+ return getEndpointReference(endpoint, null, attrs);
+ }
+
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/enabling/soap/DataStructureLookupEndpointReferenceBuilder.java b/dnet-core-components/src/main/java/eu/dnetlib/enabling/soap/DataStructureLookupEndpointReferenceBuilder.java
new file mode 100644
index 0000000..d88918d
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/enabling/soap/DataStructureLookupEndpointReferenceBuilder.java
@@ -0,0 +1,88 @@
+package eu.dnetlib.enabling.soap;
+
+import java.util.Map;
+
+import javax.xml.namespace.QName;
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.springframework.beans.factory.annotation.Required;
+
+import eu.dnetlib.enabling.is.lookup.rmi.ISLookUpService;
+import eu.dnetlib.enabling.locators.UniqueServiceLocator;
+import eu.dnetlib.enabling.tools.OpaqueResource;
+import eu.dnetlib.enabling.tools.StringOpaqueResource;
+import eu.dnetlib.soap.AbstractEndpointReferenceBuilder;
+import eu.dnetlib.soap.EndpointReferenceBuilder;
+
+/**
+ * Builds an epr given an ID to a datastructure.
+ *
+ * @author marko
+ *
+ */
+public class DataStructureLookupEndpointReferenceBuilder extends AbstractEndpointReferenceBuilder implements EndpointReferenceBuilder {
+
+ /**
+ * service locator.
+ */
+ private UniqueServiceLocator serviceLocator;
+
+ /**
+ * underlying ds epr builder.
+ */
+ private DataStructureProfileEndpointReferenceBuilder dsEprBuilder;
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see eu.dnetlib.soap.EndpointReferenceBuilder#getAddress(java.lang.Object)
+ */
+ @Override
+ public String getAddress(final String pid) {
+ return dsEprBuilder.getAddress(getProfile(pid));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see eu.dnetlib.soap.EndpointReferenceBuilder#getEndpointReference(java.lang.Object, java.lang.String, java.util.Map)
+ */
+ @Override
+ public W3CEndpointReference getEndpointReference(final String pid, final String referenceParam, final Map attrs) {
+ return dsEprBuilder.getEndpointReference(getProfile(pid), attrs);
+ }
+
+ /**
+ * obtain the ds profile
+ *
+ * @param pid
+ * datastructure profile
+ * @return resource
+ */
+ private OpaqueResource getProfile(final String pid) {
+ try {
+ return new StringOpaqueResource(serviceLocator.getService(ISLookUpService.class).getResourceProfile(pid));
+ } catch (Exception e) { // TODO: remove this hack (conversion to unchecked exception)
+ throw new IllegalStateException(e);
+ }
+ }
+
+ public DataStructureProfileEndpointReferenceBuilder getDsEprBuilder() {
+ return dsEprBuilder;
+ }
+
+ @Required
+ public void setDsEprBuilder(final DataStructureProfileEndpointReferenceBuilder dsEprBuilder) {
+ this.dsEprBuilder = dsEprBuilder;
+ }
+
+ public UniqueServiceLocator getServiceLocator() {
+ return serviceLocator;
+ }
+
+ @Required
+ public void setServiceLocator(final UniqueServiceLocator serviceLocator) {
+ this.serviceLocator = serviceLocator;
+ }
+
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/enabling/soap/DataStructureProfileEndpointReferenceBuilder.java b/dnet-core-components/src/main/java/eu/dnetlib/enabling/soap/DataStructureProfileEndpointReferenceBuilder.java
new file mode 100644
index 0000000..885acc1
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/enabling/soap/DataStructureProfileEndpointReferenceBuilder.java
@@ -0,0 +1,76 @@
+package eu.dnetlib.enabling.soap;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.xml.namespace.QName;
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import eu.dnetlib.enabling.tools.OpaqueResource;
+import eu.dnetlib.soap.AbstractEndpointReferenceBuilder;
+import eu.dnetlib.soap.EndpointReferenceBuilder;
+import eu.dnetlib.soap.cxf.CxfEndpointReferenceBuilder;
+
+/**
+ * Build an epr from a data structure.
+ *
+ * @author marko
+ *
+ */
+public class DataStructureProfileEndpointReferenceBuilder extends AbstractEndpointReferenceBuilder implements
+ EndpointReferenceBuilder {
+
+ private static final Log log = LogFactory.getLog(DataStructureProfileEndpointReferenceBuilder.class); // NOPMD by marko on 11/24/08 5:02 PM
+
+
+ /**
+ * low level epr builder used to create the actual epr.
+ *
+ * TODO: factor out the address based epr building out of CXF specific code.
+ *
+ */
+ private transient CxfEndpointReferenceBuilder lowEprBuilder = new CxfEndpointReferenceBuilder();
+
+ /**
+ * {@inheritDoc}
+ * @see eu.dnetlib.soap.EndpointReferenceBuilder#getAddress(java.lang.Object)
+ */
+ @Override
+ public String getAddress(OpaqueResource profile) {
+ return profile.getResourceUri().replace("?wsdl", "");
+ }
+
+ /**
+ * {@inheritDoc}
+ * @see eu.dnetlib.soap.AbstractEndpointReferenceBuilder#getEndpointReference(java.lang.Object, java.util.Map)
+ */
+ @Override
+ public W3CEndpointReference getEndpointReference(OpaqueResource profile, Map attrs) {
+ return getEndpointReference(profile, profile.getResourceId(), attrs);
+ }
+
+ /**
+ * {@inheritDoc}
+ * @see eu.dnetlib.soap.AbstractEndpointReferenceBuilder#getEndpointReference(java.lang.Object)
+ */
+ @Override
+ public W3CEndpointReference getEndpointReference(OpaqueResource profile) {
+ log.info("GETTING EPR short");
+
+ return getEndpointReference(profile, profile.getResourceId());
+ }
+
+ /**
+ * {@inheritDoc}
+ * @see eu.dnetlib.soap.EndpointReferenceBuilder#getEndpointReference(java.lang.Object, java.lang.String, java.util.Map)
+ */
+ @Override
+ public W3CEndpointReference getEndpointReference(OpaqueResource profile, String referenceParam, Map attrs) {
+ return lowEprBuilder.getEndpointReference(getAddress(profile), null, null, getAddress(profile) + "?wsdl", referenceParam,
+ new HashMap());
+ }
+
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/enabling/soap/EndpointReferenceBuilder.java b/dnet-core-components/src/main/java/eu/dnetlib/enabling/soap/EndpointReferenceBuilder.java
new file mode 100644
index 0000000..c15dc52
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/enabling/soap/EndpointReferenceBuilder.java
@@ -0,0 +1,96 @@
+package eu.dnetlib.soap;
+
+import java.util.Map;
+
+import javax.xml.namespace.QName;
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+/**
+ * This is a generalization of org.apache.cxf.jaxws.EndpointReferenceBuilder and org.apache.cxf.jaxws.EndpointImpl
+ *
+ *
+ * javax.xml.ws.WebServiceContext org.apache.cxf.jaxws.EndpointReferenceBuilder doesn't expose the API for adding
+ * additional metadata while org.apache.cxf.jaxws.EndpointImpl doesn't take the correct endpoint address from the
+ * EndpointInfo object. org.apache.cxf.endpoint.Endpoint return a CXF proprietary endpoint reference and not the
+ * javax/w3c standard definition.
+ *
+ *
+ *
+ * This interface is intended to provide an abstract way to construct an endpoint reference for a given service,
+ * depending on the type of endpoint interface you have at hand (CXF abstract endpoint or jaxws endpoint)
+ *
+ *
+ *
+ * Normally the type parameter T will be bound to your endpoint type.
+ *
+ *
+ *
+ * In CXF jaxws applications you can easly get a WebServiceContext instance which returns an EndpointReference, however
+ * the API is cumbersome because it requires instantiating w3c DOM Element instances for each reference parameter, and
+ * it doesn't allow setting custom metadata elements.
+ *
+ *
+ *
+ * Implementors of this API will extract as many useful informations from the runtime besides the plain soap endpoint
+ * address.
+ *
+ *
+ * @author marko
+ * @param
+ * all endpoint builders are parameterized to specific endpoint type which on the used framework (not on the
+ * service)
+ *
+ */
+public interface EndpointReferenceBuilder {
+ /**
+ * get an endpoint reference with default metadata attached.
+ *
+ * @param endpoint
+ * the endpoint
+ * @return an endpoint reference
+ */
+ W3CEndpointReference getEndpointReference(T endpoint);
+
+ /**
+ * get an endpoint reference with custom metadata attached.
+ *
+ * @param endpoint
+ * the endpoint
+ * @param attrs
+ * metadata attribute map
+ * @return an endpoint reference
+ */
+ W3CEndpointReference getEndpointReference(T endpoint, Map attrs);
+
+ /**
+ * get an endpoint reference with a WSA reference parameter.
+ *
+ * @param endpoint
+ * the endpoint
+ * @param referenceParam
+ * reference parameters
+ * @return an endpoint reference
+ */
+ W3CEndpointReference getEndpointReference(T endpoint, String referenceParam);
+
+ /**
+ * get an endpoint reference with custom metadata attached and WSA reference parameter.
+ *
+ * @param endpoint
+ * endpoint
+ * @param referenceParam
+ * reference parameters
+ * @param attrs
+ * metadata attribute map
+ * @return an endpoint reference
+ */
+ W3CEndpointReference getEndpointReference(T endpoint, String referenceParam, Map attrs);
+
+ /**
+ * Sometimes we need only the address.
+ *
+ * @param endpoint endpoint
+ * @return address
+ */
+ String getAddress(T endpoint);
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/enabling/soap/StaticEndpointReferenceBuilder.java b/dnet-core-components/src/main/java/eu/dnetlib/enabling/soap/StaticEndpointReferenceBuilder.java
new file mode 100644
index 0000000..35d6313
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/enabling/soap/StaticEndpointReferenceBuilder.java
@@ -0,0 +1,60 @@
+package eu.dnetlib.soap;
+
+import java.util.Map;
+
+import javax.xml.namespace.QName;
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+import javax.xml.ws.wsaddressing.W3CEndpointReferenceBuilder;
+
+/**
+ * This endpoint reference builder builds always the same epr, with a fixed address, for any incoming endpoint (even
+ * null endpoints). Useful when registering service profiles for external services like the old perl Aggregator.
+ *
+ * @author marko
+ *
+ * @param
+ * endpoint type
+ */
+public class StaticEndpointReferenceBuilder implements EndpointReferenceBuilder {
+
+ /**
+ * service address.
+ */
+ private String address;
+
+ @Override
+ public String getAddress(final T endpoint) {
+ return address;
+ }
+
+ @Override
+ public W3CEndpointReference getEndpointReference(final T endpoint) {
+ final W3CEndpointReferenceBuilder builder = new W3CEndpointReferenceBuilder();
+ builder.address(address);
+ return builder.build();
+ }
+
+ @Override
+ public W3CEndpointReference getEndpointReference(final T endpoint, final Map attrs) {
+ return getEndpointReference(endpoint);
+ }
+
+ @Override
+ public W3CEndpointReference getEndpointReference(final T endpoint, final String referenceParam) {
+ return getEndpointReference(endpoint);
+ }
+
+ @Override
+ public W3CEndpointReference getEndpointReference(final T endpoint, final String referenceParam, final Map attrs) {
+ return getEndpointReference(endpoint);
+ }
+
+ public String getAddress() {
+ return address;
+ }
+
+ public void setAddress(final String address) {
+ this.address = address;
+ }
+
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/enabling/soap/cxf/CxfEndpointReferenceBuilder.java b/dnet-core-components/src/main/java/eu/dnetlib/enabling/soap/cxf/CxfEndpointReferenceBuilder.java
new file mode 100644
index 0000000..3c23a54
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/enabling/soap/cxf/CxfEndpointReferenceBuilder.java
@@ -0,0 +1,206 @@
+package eu.dnetlib.soap.cxf;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import javax.xml.namespace.QName;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+import javax.xml.ws.wsaddressing.W3CEndpointReferenceBuilder;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.cxf.endpoint.Endpoint;
+import org.apache.oro.text.perl.Perl5Util;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import eu.dnetlib.soap.AbstractEndpointReferenceBuilder;
+
+/**
+ * The cxf endpoint is an internal cross-toolkit implementation of the messaging endpoint.
+ *
+ *
+ * End users will normally access jaxws endpoints, since jaxws is the mostly used cxf frontend. However, generic code,
+ * like interceptors, will handle cxf endpoints, so sometimes you may need to construct endpoint references from them.
+ *
+ *
+ *
+ * <ns3:Address>http://localhost:8090/app/services/isStore</ns3:Address>
+ * <ns3:ReferenceParameters/>
+ * <ns3:Metadata>
+ * <wsaw:InterfaceName>ns1:ISStoreService</wsaw:InterfaceName>
+ * <wsaw:ServiceName EndpointName="ISStoreServicePort">ns2:ISStoreServiceService</wsaw:ServiceName>
+ * <infrastructure:infrastructure>development</infrastructure:infrastructure>
+ * </ns3:Metadata>
+ *
+ *
+ * Users can easily define default system or service wide custom metadata to endpoint references by setting a
+ * defaultMetadata property:
+ *
+ *
+ * <bean name="cxfEndpointReferenceBuilder" class="eu.dnetlib.soap.cxf.CxfEndpointReferenceBuilder">
+ * <property name="defaultMetadata">
+ * <map>
+ * <entry key="{http://dnetlib.eu/endpointReference}infrastructure" value="${infrastructure.name}" />
+ * </map>
+ * </property>
+ * </bean>
+ *
+ *
+ *
+ * @author marko
+ *
+ */
+public class CxfEndpointReferenceBuilder extends AbstractEndpointReferenceBuilder {
+ /**
+ * logger.
+ */
+ private static final Log log = LogFactory.getLog(CxfEndpointReferenceBuilder.class); // NOPMD by marko on 11/24/08 4:55
+
+ /**
+ * users can put some default metadata elements into all EPRs.
+ */
+ private Map defaultMetadata;
+
+ /**
+ * regexp utility.
+ */
+ private final transient Perl5Util matcher = new Perl5Util();
+
+ /**
+ * namespace of the ResourceIdentifier reference parameter.
+ */
+ private String riNamespace = "http://www.driver.org";
+
+ /**
+ * element name of the ResourceIdentifier reference parameter.
+ */
+ private String riElementName = "ResourceIdentifier";
+
+ /**
+ * {@inheritDoc}
+ *
+ * TODO: refactor.
+ *
+ * @see eu.dnetlib.soap.EndpointReferenceBuilder#getEndpointReference(java.lang.Object, java.util.Map)
+ */
+
+ @Override
+ public W3CEndpointReference getEndpointReference(final Endpoint endpoint, final String referenceParam, final Map attributes) {
+ final String address = getAddress(endpoint);
+ return getEndpointReference(address, endpoint.getService().getName(), endpoint.getEndpointInfo().getName(), null, referenceParam,
+ attributes);
+ }
+
+ /**
+ * low level method which allows the construction of a endpoint reference knowing all basic data as the address, service name etc.
+ *
+ * @param address
+ * @param serviceName
+ * @param endpointName
+ * @param wsdl
+ * @param referenceParam
+ * @param attributes
+ * @return
+ */
+ public W3CEndpointReference getEndpointReference(
+ final String address,
+ final QName serviceName,
+ final QName endpointName,
+ final String wsdl,
+ final String referenceParam,
+ final Map attributes) {
+ Map attrs = attributes;
+
+ final W3CEndpointReferenceBuilder builder = new W3CEndpointReferenceBuilder();
+ builder.address(address);
+ if(serviceName != null)
+ builder.serviceName(serviceName);
+ if(endpointName != null)
+ builder.endpointName(endpointName);
+ builder.wsdlDocumentLocation(wsdl);
+
+ if (defaultMetadata != null) {
+ if (attrs == null)
+ attrs = new HashMap();
+ for (Entry entry : defaultMetadata.entrySet())
+ attrs.put(splitQNameString(entry.getKey()), entry.getValue());
+ }
+
+ try {
+ final Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); // NOPMD
+ if (referenceParam != null) {
+ final Element referenceElement = doc.createElementNS(getRiNamespace(), getRiElementName());
+ referenceElement.setTextContent(referenceParam);
+ builder.referenceParameter(referenceElement);
+ }
+
+ if (attrs != null && !attrs.isEmpty()) {
+ for (Entry entry : attrs.entrySet()) {
+ final QName qname = entry.getKey();
+ final Element element = doc.createElementNS(qname.getNamespaceURI(), qname.getLocalPart());
+ element.setTextContent((String) entry.getValue());
+ builder.metadata(element);
+ }
+ }
+ } catch (ParserConfigurationException e) {
+ log.fatal("cannot extend EPR", e);
+ throw new IllegalStateException("cannot extend EPR", e);
+ }
+
+ return builder.build();
+ }
+
+ /**
+ * compute an endpoint address.
+ *
+ * @param endpoint
+ * endpoint
+ * @return url as string
+ */
+ @Override
+ public String getAddress(final Endpoint endpoint) {
+ return endpoint.getEndpointInfo().getAddress();
+ }
+
+ /**
+ * helper method for converting "{namespace}elementName" strings to QNames.
+ *
+ * @param key
+ * "{namespace}elementName" string
+ * @return qname
+ */
+ private QName splitQNameString(final String key) {
+ matcher.match("m/{(.*)}(.*)/", key);
+
+ return new QName(matcher.group(1), matcher.group(2));
+ }
+
+ public Map getDefaultMetadata() {
+ return defaultMetadata;
+ }
+
+ public void setDefaultMetadata(final Map defaultMetadata) {
+ this.defaultMetadata = defaultMetadata;
+ }
+
+ public String getRiNamespace() {
+ return riNamespace;
+ }
+
+ public void setRiNamespace(final String riNamespace) {
+ this.riNamespace = riNamespace;
+ }
+
+ public String getRiElementName() {
+ return riElementName;
+ }
+
+ public void setRiElementName(final String riElementName) {
+ this.riElementName = riElementName;
+ }
+
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/enabling/soap/cxf/JaxwsEndpointReferenceBuilder.java b/dnet-core-components/src/main/java/eu/dnetlib/enabling/soap/cxf/JaxwsEndpointReferenceBuilder.java
new file mode 100644
index 0000000..5e1d7df
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/enabling/soap/cxf/JaxwsEndpointReferenceBuilder.java
@@ -0,0 +1,64 @@
+package eu.dnetlib.soap.cxf;
+
+import java.util.Map;
+
+import javax.xml.namespace.QName;
+import javax.xml.ws.Endpoint;
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+import org.apache.cxf.jaxws.EndpointImpl;
+import org.springframework.beans.factory.annotation.Required;
+
+import eu.dnetlib.soap.AbstractEndpointReferenceBuilder;
+
+/**
+ * This EndpointReferenceBuilder implementation takes a jaxws endpoint and extracts the cxf endpoint from it.
+ *
+ * jaxws endpoints are the most readily available endpoint objects since they constructed from jaxws:endpoint spring
+ * beans, as shown in the CXF documentation.
+ *
+ * Since this implementation forwards the job to CxfEndpointReferenceBuilder, the 'builder' property has to be set:
+ *
+ *
+ * <bean name="jaxwsEndpointReferenceBuilder" class="eu.dnetlib.soap.cxf.JaxwsEndpointReferenceBuilder"
+ * p:builder-ref="cxfEndpointReferenceBuilder" />
+ *
+ *
+ * @author marko
+ * @see CxfEndpointReferenceBuilder
+ *
+ */
+public class JaxwsEndpointReferenceBuilder extends AbstractEndpointReferenceBuilder {
+
+ /**
+ * required reference to the cxf endpoint builder.
+ */
+ private CxfEndpointReferenceBuilder builder = null;
+
+ /**
+ * simply unpacks the cxf endpoint from the jaxws endpoint and forwards it to CxfEndpointReferenceBuilder.
+ *
+ * {@inheritDoc}
+ *
+ * @see eu.dnetlib.soap.EndpointReferenceBuilder#getEndpointReference(java.lang.Object, java.util.Map)
+ */
+ @Override
+ public W3CEndpointReference getEndpointReference(final Endpoint endpoint, final String referenceParam, final Map attrs) {
+ return builder.getEndpointReference(((EndpointImpl) endpoint).getServer().getEndpoint(), referenceParam, attrs);
+ }
+
+ public CxfEndpointReferenceBuilder getBuilder() {
+ return builder;
+ }
+
+ @Required
+ public void setBuilder(final CxfEndpointReferenceBuilder builder) {
+ this.builder = builder;
+ }
+
+ @Override
+ public String getAddress(Endpoint endpoint) {
+ return builder.getAddress(((EndpointImpl) endpoint).getServer().getEndpoint());
+ }
+
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/enabling/soap/cxf/StandaloneCxfEndpointReferenceBuilder.java b/dnet-core-components/src/main/java/eu/dnetlib/enabling/soap/cxf/StandaloneCxfEndpointReferenceBuilder.java
new file mode 100644
index 0000000..938a58e
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/enabling/soap/cxf/StandaloneCxfEndpointReferenceBuilder.java
@@ -0,0 +1,97 @@
+package eu.dnetlib.soap.cxf;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import javax.annotation.PostConstruct;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.cxf.endpoint.Endpoint;
+import org.springframework.beans.factory.annotation.Required;
+
+/**
+ * CxfEndpointReferenceBuilder is not able to create correct endpoint addresses outside a http request context. This means that service
+ * initialization code cannot obtain the service address and thus cannot register himself.
+ *
+ * This subclass allows putting a local address (ip/dns + port) to be used when the runtime servlet context is not available.
+ *
+ * TODO: automated tomcat port detection, trough org.apache.catalina.ServerFactory.getServer().getServices() TODO: automated jetty port
+ * detection
+ *
+ *
+ * @author marko
+ *
+ */
+public class StandaloneCxfEndpointReferenceBuilder extends CxfEndpointReferenceBuilder {
+
+ private static final Log log = LogFactory.getLog(StandaloneCxfEndpointReferenceBuilder.class); // NOPMD by marko on 11/24/08 5:02 PM
+
+ /**
+ * base url where all services are exported.
+ */
+ private String baseAddress;
+
+ private String absoluteBase;
+
+ private boolean forceLocalAddress = false;
+
+ public String getBaseAddress() {
+ return baseAddress;
+ }
+
+ public void setBaseAddress(final String baseAddress) {
+ this.baseAddress = baseAddress;
+ }
+
+ @PostConstruct
+ public void init() throws URISyntaxException {
+ URI base = new URI(baseAddress);
+ log.info("base address: " + baseAddress);
+
+ this.absoluteBase = (new URI(base.getScheme(), base.getUserInfo(), base.getHost(), base.getPort(), null, null, null)).toString().trim();
+ log.info("absolute base address: " + absoluteBase);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see eu.dnetlib.soap.cxf.CxfEndpointReferenceBuilder#getAddress(org.apache.cxf.endpoint.Endpoint)
+ */
+ @Override
+ public String getAddress(final Endpoint endpoint) {
+ final String address = super.getAddress(endpoint);
+
+ if (forceLocalAddress) {
+ try {
+ URI uri = new URI(address);
+ if (!address.startsWith("http://")) {
+ String res = baseAddress + uri.getPath();
+ if (log.isDebugEnabled()) {
+ log.debug("fixing address to: " + res);
+ }
+ return res;
+ }
+ String res = absoluteBase + uri.getPath();
+ if (log.isDebugEnabled()) {
+ log.debug("forcing address to: " + res);
+ }
+ return res;
+ } catch (URISyntaxException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ if (!address.startsWith("http://") && (baseAddress != null)) { return baseAddress + address; }
+ return address;
+ }
+
+ public boolean isForceLocalAddress() {
+ return forceLocalAddress;
+ }
+
+ @Required
+ public void setForceLocalAddress(final boolean forceLocalAddress) {
+ this.forceLocalAddress = forceLocalAddress;
+ }
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/AbstractBaseService.java b/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/AbstractBaseService.java
new file mode 100644
index 0000000..0957d65
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/AbstractBaseService.java
@@ -0,0 +1,85 @@
+package eu.dnetlib.enabling.tools;
+
+import javax.jws.WebService;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.context.Lifecycle;
+
+import eu.dnetlib.common.rmi.BaseService;
+
+/**
+ * This class contains default definition for BaseService contract and basic service lifecycle.
+ *
+ * TODO: split BaseService contract implementation from lifecycle and other helper method
+ *
+ * @author marko
+ *
+ */
+@WebService(targetNamespace = "http://services.dnetlib.eu/")
+public abstract class AbstractBaseService implements BaseService, Lifecycle {
+
+ /**
+ * logger.
+ */
+ private static final Log log = LogFactory // NOPMD by marko on 11/24/08 5:02 PM
+ .getLog(AbstractBaseService.class);
+
+ private boolean started = false;
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see eu.dnetlib.common.rmi.BaseService#identify()
+ */
+ @Override
+ public String identify() {
+ return getClass().getName();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see eu.dnetlib.common.rmi.BaseService#notify(java.lang.String, java.lang.String, java.lang.String, java.lang.String)
+ */
+ @Override
+ public void notify(final String subscriptionId, final String topic, final String isId, final String message) {
+ log.debug("got notification: " + topic + ", profile: " + isId + ", body: " + message);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see eu.dnetlib.common.rmi.BaseService#start()
+ */
+ @Override
+ public void start() {
+ log.info("Starting service " + identify());
+ if (started) {
+ log.warn("Service " + this + "already started, check bean initializations!");
+ }
+ started = true;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.springframework.context.Lifecycle#isRunning()
+ */
+ @Override
+ public boolean isRunning() {
+ log.debug("called isRunning " + this);
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.springframework.context.Lifecycle#stop()
+ */
+ @Override
+ public void stop() {
+ log.info("Stopping service " + this);
+ }
+
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/AbstractServiceLocator.java b/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/AbstractServiceLocator.java
new file mode 100644
index 0000000..7e9002a
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/AbstractServiceLocator.java
@@ -0,0 +1,119 @@
+package eu.dnetlib.enabling.tools;
+
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.util.Map;
+
+import javax.annotation.Resource;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathFactory;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+
+import com.google.common.collect.Maps;
+
+import eu.dnetlib.enabling.is.lookup.rmi.ISLookUpException;
+import eu.dnetlib.enabling.is.lookup.rmi.ISLookUpService;
+import eu.dnetlib.soap.cxf.StandaloneCxfEndpointReferenceBuilder;
+
+@Deprecated
+public abstract class AbstractServiceLocator implements ServiceLocator {
+
+ /**
+ * lookup locator.
+ */
+ @Resource(name="lookupLocator")
+ private ServiceLocator lookUpLocator;
+
+ /**
+ * build epr.
+ */
+ @Resource
+ private StandaloneCxfEndpointReferenceBuilder eprBuilder;
+
+ /**
+ * service resolver. used to create proxies for discovered services.
+ */
+ @Resource(name="serviceResolver")
+ private ServiceResolver serviceResolver;
+
+ /**
+ * logger.
+ */
+ private static final Log log = LogFactory.getLog(AbstractServiceLocator.class); // NOPMD by marko on 11/24/08 5:02 PM
+
+
+ @Override
+ public T getService(final String profileId, final Class clazz) {
+ final String profile = executeQuery(profileId, null);
+
+ try {
+ final XPathFactory factory = XPathFactory.newInstance();
+ final XPath xpath = factory.newXPath();
+
+ final DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
+ final DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
+
+ final Document doc = docBuilder.parse(new InputSource(new StringReader(profile)));
+ final String url = xpath.evaluate("//url", doc);
+ final String serviceId = xpath.evaluate("//id", doc);
+
+ final NodeList propElements = (NodeList) xpath.evaluate("//PROPERTY", doc, XPathConstants.NODESET);
+ final Map props = Maps.newHashMap();
+
+ for (int i = 0; i < propElements.getLength(); i++) {
+ Element propElement = (Element) propElements.item(i);
+ props.put(propElement.getAttribute("key"), propElement.getAttribute("value"));
+ }
+
+ final W3CEndpointReference epr = eprBuilder.getEndpointReference(url, null, null, url + "?wsdl", null, null);
+
+ final ServiceRunningInstance instance = new ServiceRunningInstance(epr, serviceId, url, props);
+
+ return serviceResolver.getService(clazz, instance.getEpr());
+ } catch(Exception e) {
+ log.error("cannot instantiate service from id: " + profileId, e);
+ throw new IllegalStateException("cannot instantiate service from id: " + profileId, e);
+ }
+ }
+
+ @Override
+ public String getServiceId(final String profileId) {
+ return executeQuery(profileId, "/RESOURCE_PROFILE/HEADER/RESOURCE_IDENTIFIER/@value/string()");
+ }
+
+ private String executeQuery(final String profileId, final String xpath) {
+ final StringWriter sw = new StringWriter();
+ sw.append("let $uri:=/RESOURCE_PROFILE/HEADER[./RESOURCE_IDENTIFIER/@value='");
+ sw.append(profileId);
+ sw.append("']/RESOURCE_URI/@value/string()");
+ sw.append("\n\n");
+ sw.append("for $x in collection('/db/DRIVER/ServiceResources')/RESOURCE_PROFILE/HEADER");
+ sw.append("\n");
+ sw.append("where $x/RESOURCE_PROFILE/HEADER/RESOURCE_URI/@value = $uri");
+ sw.append("\n");
+ sw.append("return $x");
+ if (xpath != null) {
+ sw.append(xpath);
+ }
+ final String xq = sw.toString();
+
+ try {
+ return lookUpLocator.getService().getResourceProfileByQuery(xq);
+ } catch (ISLookUpException e) {
+ log.error("cannot locate service using query: " + xq, e);
+ throw new IllegalStateException("cannot locate service using query: " + xq, e);
+ }
+ }
+
+
+}
\ No newline at end of file
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/AbstractServiceResolverImpl.java b/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/AbstractServiceResolverImpl.java
new file mode 100644
index 0000000..63e9fec
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/AbstractServiceResolverImpl.java
@@ -0,0 +1,32 @@
+package eu.dnetlib.enabling.tools;
+
+import javax.xml.transform.dom.DOMResult;
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
+
+/**
+ * implement common functionality of ServiceResolvers.
+ *
+ * @author marko
+ *
+ */
+public abstract class AbstractServiceResolverImpl implements ServiceResolver {
+
+ /**
+ * {@inheritDoc}
+ * @see eu.dnetlib.enabling.tools.ServiceResolver#getResourceIdentifier(javax.xml.ws.wsaddressing.W3CEndpointReference)
+ */
+ @Override
+ public String getResourceIdentifier(final W3CEndpointReference epr) {
+ final DOMResult dom = new DOMResult();
+ epr.writeTo(dom);
+
+ try {
+ return XPathFactory.newInstance().newXPath().evaluate("//*[local-name() = 'ResourceIdentifier']", dom.getNode());
+ } catch (XPathExpressionException e) {
+ throw new IllegalStateException("cannot construct xpath expression", e);
+ }
+ }
+
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/DOMOpaqueResource.java b/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/DOMOpaqueResource.java
new file mode 100644
index 0000000..6c298e1
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/DOMOpaqueResource.java
@@ -0,0 +1,264 @@
+package eu.dnetlib.enabling.tools;
+
+import java.io.StringWriter;
+import java.util.Date;
+
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.TransformerFactoryConfigurationError;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import eu.dnetlib.miscutils.datetime.DateUtils;
+
+/**
+ * OpaqueResource holding a plain old DOM document.
+ *
+ * @author marko
+ *
+ */
+public class DOMOpaqueResource implements OpaqueResource {
+ /**
+ * xpath expression error message.
+ */
+ private static final String XPATH_ERROR = "cannot compile xpath expression";
+
+ /**
+ * value attribute.
+ */
+ private static final String VALUE_ATTR = "value";
+
+ /**
+ * logger.
+ */
+ private static final Log log = LogFactory.getLog(DOMOpaqueResource.class); // NOPMD by marko on 11/24/08 5:02 PM
+
+ /**
+ * resource identifier.
+ */
+ private String resourceId;
+
+ /**
+ * resource type.
+ */
+ private String resourceType;
+
+ /**
+ * resource kind.
+ */
+ private String resourceKind;
+
+ /**
+ * resource uri.
+ */
+ private String resourceUri;
+
+ /**
+ * modification time stamp.
+ */
+ private Date modificationDate;
+
+ /**
+ * original document DOM.
+ */
+ private Document dom;
+
+ /**
+ * xslt transformer instance.
+ */
+ private Transformer transformer;
+
+ /**
+ * construct a DOMOpaqueInstance from a W3C DOM document.
+ *
+ * @param dom
+ * DOM document
+ * @throws XPathExpressionException
+ * happens
+ */
+ public DOMOpaqueResource(final Document dom) throws XPathExpressionException {
+ this.dom = dom;
+
+ try {
+ transformer = TransformerFactory.newInstance().newTransformer();
+ } catch (TransformerConfigurationException e) {
+ throw new IllegalStateException("transformer configuration", e);
+ } catch (TransformerFactoryConfigurationError e) {
+ throw new IllegalStateException("transformer configuration", e);
+ }
+
+ final XPath xpath = XPathFactory.newInstance().newXPath();
+
+ this.resourceId = xpath.evaluate("/RESOURCE_PROFILE/HEADER/RESOURCE_IDENTIFIER/@value", dom);
+ this.resourceType = xpath.evaluate("/RESOURCE_PROFILE/HEADER/RESOURCE_TYPE/@value", dom);
+ this.resourceKind = xpath.evaluate("/RESOURCE_PROFILE/HEADER/RESOURCE_KIND/@value", dom);
+ this.resourceUri = xpath.evaluate("/RESOURCE_PROFILE/HEADER/RESOURCE_URI/@value", dom);
+
+ String modificationDateSource = xpath.evaluate("/RESOURCE_PROFILE/HEADER/DATE_OF_CREATION/@value", dom);
+
+ try {
+ this.modificationDate = new DateUtils().parse(modificationDateSource);
+ } catch (IllegalStateException e) {
+ log.debug("invalid date '" + modificationDateSource + "'", e);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see eu.dnetlib.enabling.tools.OpaqueResource#asDom()
+ */
+ @Override
+ public Document asDom() {
+ return getDom();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see eu.dnetlib.enabling.tools.OpaqueResource#asString()
+ */
+ @Override
+ public String asString() {
+ final StringWriter writer = new StringWriter();
+
+ try {
+ transformer.transform(new DOMSource(getDom()), new StreamResult(writer));
+ } catch (TransformerException e) {
+ log.fatal("cannot serialize document", e);
+ return null;
+ }
+ return writer.toString();
+ }
+
+ public Document getDom() {
+ return dom;
+ }
+
+ public void setDom(final Document dom) {
+ this.dom = dom;
+ }
+
+ @Override
+ public String getResourceId() {
+ return resourceId;
+ }
+
+ @Override
+ public String getResourceType() {
+ return resourceType;
+ }
+
+ public void setResourceType(final String resourceType) {
+ this.resourceType = resourceType;
+ }
+
+ @Override
+ public String getResourceKind() {
+ return resourceKind;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see eu.dnetlib.enabling.tools.OpaqueResource#setResourceKind(java.lang.String)
+ */
+ @Override
+ public void setResourceKind(final String resourceKind) {
+ try {
+ final XPath xpath = XPathFactory.newInstance().newXPath();
+ final Element kindEl = (Element) xpath.evaluate("/RESOURCE_PROFILE/HEADER/RESOURCE_KIND", asDom(), XPathConstants.NODE);
+ kindEl.setAttribute(VALUE_ATTR, resourceKind);
+ this.resourceKind = resourceKind;
+ } catch (XPathExpressionException e) {
+ throw new IllegalStateException(XPATH_ERROR, e);
+ }
+
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see eu.dnetlib.enabling.tools.OpaqueResource#setResourceId(java.lang.String)
+ */
+ @Override
+ public void setResourceId(final String identifier) {
+ try {
+ final XPath xpath = XPathFactory.newInstance().newXPath();
+ final Element idEl = (Element) xpath.evaluate("/RESOURCE_PROFILE/HEADER/RESOURCE_IDENTIFIER", asDom(), XPathConstants.NODE);
+ idEl.setAttribute(VALUE_ATTR, identifier);
+ resourceId = identifier;
+ } catch (XPathExpressionException e) {
+ throw new IllegalStateException(XPATH_ERROR, e);
+ }
+ }
+
+ @Override
+ public Date getModificationDate() {
+ return modificationDate;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see eu.dnetlib.enabling.tools.OpaqueResource#setModificationDate(java.util.Date)
+ */
+ @Override
+ public void setModificationDate(final Date modificationDate) {
+ try {
+ final XPath xpath = XPathFactory.newInstance().newXPath();
+ final Element idEl = (Element) xpath.evaluate("/RESOURCE_PROFILE/HEADER/DATE_OF_CREATION", asDom(), XPathConstants.NODE);
+ if (idEl == null) {
+ log.warn("resource with type " + getResourceType() + " has no date of creation element");
+ return;
+ }
+ idEl.setAttribute(VALUE_ATTR, new DateUtils(modificationDate).getDateAsISO8601String());
+ this.modificationDate = modificationDate;
+ } catch (XPathExpressionException e) {
+ throw new IllegalStateException(XPATH_ERROR, e);
+ }
+
+ }
+
+ @Override
+ public String getResourceUri() {
+ return resourceUri;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see eu.dnetlib.enabling.tools.OpaqueResource#setResourceUri(java.lang.String)
+ */
+ @Override
+ public void setResourceUri(final String resourceUri) {
+ try {
+ final XPath xpath = XPathFactory.newInstance().newXPath();
+ final Element uriEl = (Element) xpath.evaluate("/RESOURCE_PROFILE/HEADER/RESOURCE_URI", asDom(), XPathConstants.NODE);
+ uriEl.setAttribute(VALUE_ATTR, resourceUri);
+ this.resourceUri = resourceUri;
+ } catch (XPathExpressionException e) {
+ throw new IllegalStateException(XPATH_ERROR, e);
+ }
+ }
+
+ public Transformer getTransformer() {
+ return transformer;
+ }
+
+ public void setTransformer(final Transformer transformer) {
+ this.transformer = transformer;
+ }
+
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/DefaultServiceLocatorLocationScorer.java b/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/DefaultServiceLocatorLocationScorer.java
new file mode 100644
index 0000000..874c7f1
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/DefaultServiceLocatorLocationScorer.java
@@ -0,0 +1,107 @@
+package eu.dnetlib.enabling.tools;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import javax.annotation.Resource;
+
+import eu.dnetlib.soap.cxf.StandaloneCxfEndpointReferenceBuilder;
+
+/**
+ * Assign better scores for near services. Can be configured.
+ *
+ * @author marko
+ *
+ */
+@Deprecated
+public class DefaultServiceLocatorLocationScorer implements DynamicServiceLocatorLocationScorer {
+
+ /**
+ * default score assigned when the other service has the same host.
+ */
+ private static final int LOCAL_HOST_SCORE = 5;
+
+ /**
+ * default score assigned when the other service has the same host and port (same container).
+ */
+ private static final int LOCAL_PORT_SCORE = 10;
+
+ /**
+ * default score assigned when the other service has the same host and port (same container and context).
+ */
+ private static final int LOCAL_SRV_SCORE = 15;
+
+
+ /**
+ * score assigned when the other service has the same host.
+ */
+ private int localHostScore = LOCAL_HOST_SCORE;
+
+ /**
+ * score assigned when the other service has the same host and port (same container).
+ */
+ private int localPortScore = LOCAL_PORT_SCORE;
+
+ /**
+ * score assigned when the other service has the same host and port (same container and context).
+ */
+ private int localSrvScore = LOCAL_SRV_SCORE;
+
+ /**
+ * build epr.
+ */
+ @Resource
+ private StandaloneCxfEndpointReferenceBuilder eprBuilder;
+
+ /**
+ * {@inheritDoc}
+ * @throws MalformedURLException
+ * @see eu.dnetlib.enabling.tools.DynamicServiceLocatorLocationScorer#score(java.net.URL)
+ */
+ @Override
+ public int score(final URL url) throws MalformedURLException {
+ final URL localBase = new URL(eprBuilder.getBaseAddress());
+ if (url.toString().startsWith(localBase.toString()))
+ return localSrvScore;
+
+ if (localBase.getHost().equals(url.getHost())) {
+ if (localBase.getPort() == url.getPort())
+ return localPortScore;
+ return localHostScore;
+ }
+ return 0;
+ }
+
+ public StandaloneCxfEndpointReferenceBuilder getEprBuilder() {
+ return eprBuilder;
+ }
+
+ public void setEprBuilder(final StandaloneCxfEndpointReferenceBuilder eprBuilder) {
+ this.eprBuilder = eprBuilder;
+ }
+
+ public int getLocalHostScore() {
+ return localHostScore;
+ }
+
+ public void setLocalHostScore(final int localHostScore) {
+ this.localHostScore = localHostScore;
+ }
+
+ public int getLocalPortScore() {
+ return localPortScore;
+ }
+
+ public void setLocalPortScore(final int localPortScore) {
+ this.localPortScore = localPortScore;
+ }
+
+ public int getLocalSrvScore() {
+ return localSrvScore;
+ }
+
+ public void setLocalSrvScore(final int localSrvScore) {
+ this.localSrvScore = localSrvScore;
+ }
+
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/DynamicHNMLocator.java b/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/DynamicHNMLocator.java
new file mode 100644
index 0000000..6ac18f4
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/DynamicHNMLocator.java
@@ -0,0 +1,62 @@
+package eu.dnetlib.enabling.tools;
+
+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.locators.UniqueServiceLocator;
+
+/**
+ * Locates a registered HNM running on a given url.
+ *
+ * @author marko
+ *
+ */
+@Deprecated
+public class DynamicHNMLocator implements HNMLocator {
+
+ /**
+ * logger.
+ */
+ private static final Log log = LogFactory.getLog(DynamicHNMLocator.class); // NOPMD by marko on 11/24/08 5:02 PM
+
+ /**
+ * service locator.
+ */
+ UniqueServiceLocator serviceLocator;
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see eu.dnetlib.enabling.tools.HNMLocator#getHNMForUrl(java.lang.String)
+ */
+ @Override
+ public String getHNMForUrl(final String url) {
+
+ final String prefix = url.substring(0, url.indexOf('/', "http://".length()));
+ final String query = "collection('')//RESOURCE_PROFILE[.//RESOURCE_TYPE/@value = 'HostingNodeManagerServiceResourceType' and starts-with(.//RESOURCE_URI/@value, '"
+ + prefix + "')]//RESOURCE_IDENTIFIER/@value/string()";
+
+ try {
+ return serviceLocator.getService(ISLookUpService.class).getResourceProfileByQuery(query);
+ } catch (final ISLookUpDocumentNotFoundException e) {
+ log.debug("doument not found for query: " + query);
+ return null;
+ } catch (final ISLookUpException e) {
+ throw new IllegalStateException("cannot search hnm", e);
+ }
+ }
+
+ public UniqueServiceLocator getServiceLocator() {
+ return serviceLocator;
+ }
+
+ @Required
+ public void setServiceLocator(UniqueServiceLocator serviceLocator) {
+ this.serviceLocator = serviceLocator;
+ }
+
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/DynamicServiceEnumerator.java b/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/DynamicServiceEnumerator.java
new file mode 100644
index 0000000..9ab9b70
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/DynamicServiceEnumerator.java
@@ -0,0 +1,182 @@
+package eu.dnetlib.enabling.tools;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.annotation.Resource;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.beans.factory.annotation.Required;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+import eu.dnetlib.enabling.is.lookup.rmi.ISLookUpException;
+import eu.dnetlib.enabling.is.lookup.rmi.ISLookUpService;
+import eu.dnetlib.enabling.tools.registration.ServiceNameResolver;
+import eu.dnetlib.miscutils.collections.EnsureCollection;
+import eu.dnetlib.soap.cxf.StandaloneCxfEndpointReferenceBuilder;
+
+/**
+ * Enumerates all services of a given type.
+ *
+ * @author marko
+ *
+ * @param
+ * service class
+ */
+@Deprecated
+public class DynamicServiceEnumerator implements ServiceEnumerator {
+
+ /**
+ * logger.
+ */
+ private static final Log log = LogFactory.getLog(DynamicServiceEnumerator.class); // NOPMD by marko on 11/24/08 5:02 PM
+
+ /**
+ * service class
+ */
+ private Class clazz;
+
+ /**
+ * lookup locator.
+ */
+ private ServiceLocator lookUpLocator;
+
+ /**
+ * service name resolver.
+ */
+ @Resource
+ private ServiceNameResolver serviceNameResolver; // NOPMD
+
+ /**
+ * build epr.
+ */
+ @Resource
+ private StandaloneCxfEndpointReferenceBuilder eprBuilder;
+
+ /**
+ * default constructor, useful for spring based instantiation.
+ */
+ public DynamicServiceEnumerator() {
+ // default
+ }
+
+ /**
+ * Build a dynamic service enumerator for a given class
+ *
+ * @param clazz
+ * class
+ */
+ public DynamicServiceEnumerator(final Class clazz) {
+ super();
+ this.clazz = clazz;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see eu.dnetlib.enabling.tools.ServiceEnumerator#getServices()
+ */
+ @Override
+ public List> getServices() {
+ final String serviceName = serviceNameResolver.getName(clazz);
+ log.debug("searching for service: " + serviceName);
+
+ final String xquery = "for $x in collection('/db/DRIVER/ServiceResources')//RESOURCE_PROFILE[.//RESOURCE_TYPE/@value/string() = '"
+ + serviceName
+ + "ResourceType'] return {$x//RESOURCE_IDENTIFIER/@value/string()}{$x//PROTOCOL[@name = 'SOAP']/@address/string()}{$x//SERVICE_PROPERTIES/PROPERTY}";
+ log.debug(xquery);
+
+ final XPathFactory factory = XPathFactory.newInstance();
+ final XPath xpath = factory.newXPath();
+
+ final DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
+
+ try {
+ final DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
+
+ final List services = lookUpLocator.getService().quickSearchProfile(xquery);
+ final List> instances = new ArrayList>();
+
+ for (final String source : EnsureCollection.list(services)) {
+ final Document doc = docBuilder.parse(new InputSource(new StringReader(source)));
+ final String url = xpath.evaluate("//url", doc);
+ final String serviceId = xpath.evaluate("//id", doc);
+
+ final NodeList propElements = (NodeList) xpath.evaluate("//PROPERTY", doc, XPathConstants.NODESET);
+ Map props = new HashMap();
+
+ for (int i = 0; i < propElements.getLength(); i++) {
+ Element propElement = (Element) propElements.item(i);
+ props.put(propElement.getAttribute("key"), propElement.getAttribute("value"));
+ }
+
+ final W3CEndpointReference epr = eprBuilder.getEndpointReference(url, null, null, url + "?wsdl", null, null);
+
+ instances.add(new ServiceRunningInstance(epr, serviceId, url, props));
+ }
+
+ return instances;
+ } catch (final ISLookUpException e) {
+ throw new IllegalStateException("cannot locate service " + serviceName, e);
+ } catch (final XPathExpressionException e) {
+ throw new IllegalStateException("cannot locate service " + serviceName, e);
+ } catch (final SAXException e) {
+ throw new IllegalStateException("cannot locate service " + serviceName, e);
+ } catch (final IOException e) {
+ throw new IllegalStateException("cannot locate service " + serviceName, e);
+ } catch (final ParserConfigurationException e) {
+ throw new IllegalStateException("cannot locate service " + serviceName, e);
+ }
+ }
+
+ public Class getClazz() {
+ return clazz;
+ }
+
+ @Required
+ public void setClazz(final Class clazz) {
+ this.clazz = clazz;
+ }
+
+ public ServiceLocator getLookUpLocator() {
+ return lookUpLocator;
+ }
+
+ public void setLookUpLocator(final ServiceLocator lookUpLocator) {
+ this.lookUpLocator = lookUpLocator;
+ }
+
+ public ServiceNameResolver getServiceNameResolver() {
+ return serviceNameResolver;
+ }
+
+ public void setServiceNameResolver(final ServiceNameResolver serviceNameResolver) {
+ this.serviceNameResolver = serviceNameResolver;
+ }
+
+ public StandaloneCxfEndpointReferenceBuilder getEprBuilder() {
+ return eprBuilder;
+ }
+
+ public void setEprBuilder(StandaloneCxfEndpointReferenceBuilder eprBuilder) {
+ this.eprBuilder = eprBuilder;
+ }
+
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/DynamicServiceLocator.java b/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/DynamicServiceLocator.java
new file mode 100644
index 0000000..120ca5a
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/DynamicServiceLocator.java
@@ -0,0 +1,205 @@
+package eu.dnetlib.enabling.tools;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.Resource;
+
+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.ISLookUpService;
+import eu.dnetlib.enabling.tools.registration.ServiceNameResolver;
+import eu.dnetlib.soap.cxf.StandaloneCxfEndpointReferenceBuilder;
+
+/**
+ * Locates a service through dynamic service discovery.
+ *
+ * @author marko
+ *
+ * @param
+ */
+@Deprecated
+public class DynamicServiceLocator extends AbstractServiceLocator {
+
+ /**
+ * logger.
+ */
+ private static final Log log = LogFactory.getLog(DynamicServiceLocator.class); // NOPMD by marko on 11/24/08 5:02 PM
+
+ /**
+ * service interface.
+ */
+ private Class clazz;
+
+ /**
+ * lookup locator.
+ */
+ private ServiceLocator lookUpLocator;
+
+ /**
+ * service name resolver.
+ */
+ @Resource
+ private ServiceNameResolver serviceNameResolver; // NOPMD
+
+ /**
+ * build epr.
+ * TODO: obsolete, replace by full enumerator injection
+ */
+ @Resource
+ private StandaloneCxfEndpointReferenceBuilder eprBuilder;
+
+ /**
+ * service resolver. used to create proxies for discovered services.
+ */
+ private ServiceResolver serviceResolver;
+
+ /**
+ * delegate the score computation to this component. By default use a DefaultServiceLocatorLocationScorer.
+ */
+ private DynamicServiceLocatorLocationScorer scorer;
+
+ /**
+ * service enumerator.
+ */
+ private ServiceEnumerator enumerator;
+
+ /**
+ * By default use a DefaultServiceLocatorLocationScorer if no scorer is defined.
+ */
+ @PostConstruct
+ protected void init() {
+ if (scorer == null) {
+ final DefaultServiceLocatorLocationScorer tmp = new DefaultServiceLocatorLocationScorer();
+ tmp.setEprBuilder(eprBuilder);
+ scorer = tmp;
+ }
+
+ if (enumerator == null) {
+ final DynamicServiceEnumerator tmp = new DynamicServiceEnumerator(clazz);
+ tmp.setLookUpLocator(lookUpLocator);
+ tmp.setServiceNameResolver(serviceNameResolver);
+ tmp.setEprBuilder(eprBuilder);
+ enumerator = tmp;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see eu.dnetlib.enabling.tools.ServiceLocator#getService()
+ */
+ @Override
+ public T getService() {
+ return serviceResolver.getService(clazz, findFirstCandidate().getEpr());
+ }
+
+ @Override
+ public String getServiceId() {
+ return findFirstCandidate().getServiceId();
+ }
+
+ private ServiceRunningInstance findFirstCandidate() {
+ final String serviceName = serviceNameResolver.getName(clazz);
+ log.debug("searching for service: " + serviceName);
+
+ // TODO: backward compat hack
+ if(enumerator == null) {
+ log.warn("Enumerator is null in " + this + ". Postconstruct not called by spring, please check. Now called manually to workaround this problem");
+ init();
+ }
+
+
+ final List> candidates = enumerator.getServices();
+ if (candidates == null || candidates.isEmpty())
+ throw new IllegalStateException("cannot locate service " + serviceName + ", no matching service profile found");
+
+ Collections.sort(candidates, new Comparator>() {
+ @Override
+ public int compare(final ServiceRunningInstance o1, final ServiceRunningInstance o2) {
+ try {
+ final Integer u1Score = computeScore(new URL(o1.getUrl()));
+ final Integer u2Score = computeScore(new URL(o2.getUrl()));
+ return -u1Score.compareTo(u2Score);
+ } catch (MalformedURLException e) {
+ log.warn("ignoring service with malformed url", e);
+ return 0;
+ }
+ }
+ });
+ log.debug(candidates);
+
+ return candidates.get(0);
+ }
+
+ /**
+ * compute the score for a given service url.
+ *
+ * @param url
+ * url to be scored
+ * @return score
+ * @throws MalformedURLException
+ * happens
+ */
+ protected int computeScore(final URL url) throws MalformedURLException {
+ return scorer.score(url);
+ }
+
+ public Class getClazz() {
+ return clazz;
+ }
+
+ @Required
+ public void setClazz(final Class clazz) {
+ this.clazz = clazz;
+ }
+
+ public ServiceLocator getLookUpLocator() {
+ return lookUpLocator;
+ }
+
+ @Required
+ public void setLookUpLocator(final ServiceLocator lookUpLocator) {
+ this.lookUpLocator = lookUpLocator;
+ }
+
+ public ServiceNameResolver getServiceNameResolver() {
+ return serviceNameResolver;
+ }
+
+ public void setServiceNameResolver(final ServiceNameResolver serviceNameResolver) { // NOPMD
+ this.serviceNameResolver = serviceNameResolver;
+ }
+
+ public StandaloneCxfEndpointReferenceBuilder getEprBuilder() {
+ return eprBuilder;
+ }
+
+ public void setEprBuilder(final StandaloneCxfEndpointReferenceBuilder eprBuilder) {
+ this.eprBuilder = eprBuilder;
+ }
+
+ @Required
+ public ServiceResolver getServiceResolver() {
+ return serviceResolver;
+ }
+
+ public void setServiceResolver(final ServiceResolver serviceResolver) {
+ this.serviceResolver = serviceResolver;
+ }
+
+ public DynamicServiceLocatorLocationScorer getScorer() {
+ return scorer;
+ }
+
+ public void setScorer(final DynamicServiceLocatorLocationScorer scorer) {
+ this.scorer = scorer;
+ }
+
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/DynamicServiceLocatorLocationScorer.java b/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/DynamicServiceLocatorLocationScorer.java
new file mode 100644
index 0000000..59f3684
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/DynamicServiceLocatorLocationScorer.java
@@ -0,0 +1,21 @@
+package eu.dnetlib.enabling.tools;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+/**
+ * Implementors of this interface provide custom methods to assign scores to services based solely on their location.
+ * @author marko
+ *
+ */
+@Deprecated
+public interface DynamicServiceLocatorLocationScorer {
+ /**
+ * Compute the score assigned to a given service location (url).
+ *
+ * @param url service url
+ * @return score (the higher the better)
+ * @throws MalformedURLException could happen
+ */
+ int score(URL url) throws MalformedURLException;
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/HNMLocator.java b/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/HNMLocator.java
new file mode 100644
index 0000000..a308efe
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/HNMLocator.java
@@ -0,0 +1,19 @@
+package eu.dnetlib.enabling.tools;
+
+/**
+ * finds an HNM profile for a giver service url.
+ *
+ * @author marko
+ *
+ */
+public interface HNMLocator {
+
+ /**
+ * finds an HNM profile for a giver service url.
+ *
+ * @param url
+ * service address
+ * @return hnm id
+ */
+ String getHNMForUrl(String url);
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/JaxwsServiceResolverImpl.java b/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/JaxwsServiceResolverImpl.java
new file mode 100644
index 0000000..77bfce9
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/JaxwsServiceResolverImpl.java
@@ -0,0 +1,25 @@
+package eu.dnetlib.enabling.tools;
+
+import javax.xml.ws.WebServiceFeature;
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+/**
+ * This service resolver asks jaxws to obtain a proxy to a remote service.
+ *
+ * @author marko
+ *
+ */
+public class JaxwsServiceResolverImpl extends AbstractServiceResolverImpl implements ServiceResolver {
+
+ /**
+ * {@inheritDoc}
+ * @see eu.dnetlib.enabling.tools.ServiceResolver#getService(java.lang.Class, javax.xml.ws.wsaddressing.W3CEndpointReference)
+ */
+ @Override
+ public T getService(final Class clazz, final W3CEndpointReference epr) {
+ synchronized(this) {
+ return epr.getPort(clazz, new WebServiceFeature[] {});
+ }
+ }
+
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/LocalServiceResolverImpl.java b/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/LocalServiceResolverImpl.java
new file mode 100644
index 0000000..34960cb
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/LocalServiceResolverImpl.java
@@ -0,0 +1,91 @@
+package eu.dnetlib.enabling.tools;
+
+import java.io.StringReader;
+import java.util.Map;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.xml.sax.InputSource;
+
+/**
+ * This service resolver parses the EPR and returns a local reference to a service instance if the EPR refers to the
+ * local node.
+ *
+ * @author marko
+ *
+ */
+public class LocalServiceResolverImpl extends AbstractServiceResolverImpl implements ServiceResolver, ApplicationContextAware {
+ private static final Log log = LogFactory.getLog(LocalServiceResolverImpl.class); // NOPMD by marko on 11/24/08 5:02 PM
+
+ private String baseAddress;
+
+ private ApplicationContext applicationContext;
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see eu.dnetlib.enabling.tools.ServiceResolver#getService(java.lang.Class,
+ * javax.xml.ws.wsaddressing.W3CEndpointReference)
+ */
+ @Override
+ public T getService(final Class clazz, final W3CEndpointReference epr) {
+
+ // backward compat
+ if (baseAddress == null) {
+ log.warn("please set baseAddress in " + this);
+ return null;
+ }
+
+ try {
+ // TODO: measure performance impact of this. I wrote it this way just to be sure of thread safety
+ String address = XPathFactory.newInstance().newXPath().evaluate("/*[local-name() ='EndpointReference']/*[local-name() = 'Address']",
+ new InputSource(new StringReader(epr.toString())));
+ if (log.isDebugEnabled())
+ log.debug("epr address " + address);
+
+ if (address.startsWith(baseAddress))
+ return resolveLocalService(clazz, epr);
+ } catch (XPathExpressionException e) {
+ log.warn("cannot parse epr", e);
+ }
+
+ return null;
+ }
+
+ private T resolveLocalService(final Class clazz, W3CEndpointReference epr) {
+ log.debug("resolving local service " + clazz);
+
+ Map services = (Map) applicationContext.getBeansOfType(clazz, false, false);
+
+ log.debug("found services: " + services);
+ if(services.size() > 0)
+ for(T service : services.values())
+ return service;
+
+ return null;
+ }
+
+ public String getBaseAddress() {
+ return baseAddress;
+ }
+
+ public void setBaseAddress(String baseAddress) {
+ this.baseAddress = baseAddress;
+ }
+
+ public ApplicationContext getApplicationContext() {
+ return applicationContext;
+ }
+
+ @Override
+ public void setApplicationContext(ApplicationContext applicationContext) {
+ this.applicationContext = applicationContext;
+ }
+
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/NullHNMLocator.java b/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/NullHNMLocator.java
new file mode 100644
index 0000000..30dc2d0
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/NullHNMLocator.java
@@ -0,0 +1,21 @@
+package eu.dnetlib.enabling.tools;
+
+/**
+ * simplest HNM locator: doesn't find any.
+ *
+ * @author marko
+ *
+ */
+public class NullHNMLocator implements HNMLocator {
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see eu.dnetlib.enabling.tools.HNMLocator#getHNMForUrl(java.lang.String)
+ */
+ @Override
+ public String getHNMForUrl(final String url) {
+ return "";
+ }
+
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/OpaqueResource.java b/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/OpaqueResource.java
new file mode 100644
index 0000000..7cab9f7
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/OpaqueResource.java
@@ -0,0 +1,98 @@
+package eu.dnetlib.enabling.tools;
+
+import java.util.Date;
+
+import org.w3c.dom.Document;
+
+/**
+ * Some services, in particular the enabling layer, needs to manipulate all types of resources without knowing the exact
+ * structure of their content, but only some well defined properties defined here.
+ *
+ *
+ * Different wrappers can be provided for different kind of resources. For example resources returned from the xmldb
+ * layer can be cheaply mapped to an OpaqueResource, without going to full xml->bean conversion.
+ *
+ *
+ * @author marko
+ *
+ */
+public interface OpaqueResource {
+ /**
+ * Resource type.
+ *
+ * @return resource type string
+ */
+ String getResourceType();
+
+ /**
+ * Resource kind.
+ *
+ * @return resource kind string
+ */
+ String getResourceKind();
+
+ /**
+ * Resource identifier.
+ *
+ * @return resource identifier string
+ */
+ String getResourceId();
+
+ /**
+ * Resource URI.
+ *
+ * @return resource uri string
+ */
+ String getResourceUri();
+
+ /**
+ * get modification time stamp.
+ *
+ * @return time stamp
+ */
+ Date getModificationDate();
+
+ /**
+ * Implementors may need to serialize the resource to a xml string representation.
+ *
+ * @return xml serialization
+ */
+ String asString();
+
+ /**
+ * Implementors may store the DOM in the first place. Otherwise they should
+ * return a parsed w3c DOM instance.
+ *
+ * @return DOM document
+ */
+ Document asDom();
+
+ /**
+ * change the resource identifier.
+ *
+ * @param identifier new identifier
+ */
+ void setResourceId(String identifier);
+
+ /**
+ * change the resource kind.
+ *
+ * @param kind new kind
+ */
+ void setResourceKind(String kind);
+
+ /**
+ * change the resource uri.
+ *
+ * @param uri new uri
+ */
+ void setResourceUri(String uri);
+
+ /**
+ * set modification timestamp.
+ *
+ * @param timeStamp modification time stamp
+ */
+ void setModificationDate(Date timeStamp);
+
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/ResourceIdentifierResolver.java b/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/ResourceIdentifierResolver.java
new file mode 100644
index 0000000..1c6add9
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/ResourceIdentifierResolver.java
@@ -0,0 +1,30 @@
+package eu.dnetlib.enabling.tools;
+
+/**
+ * Resource identifiers may carry, implicitly or explicity, some informations about the location of the resource in the
+ * hierarchical xmldb namespace.
+ *
+ * Implementors of this interface may take different approachs to the problem.
+ *
+ * @author marko
+ *
+ */
+public interface ResourceIdentifierResolver {
+ /**
+ * get the xmldb filename associated to this resource identifier, usually extracted from the identifier itself.
+ *
+ * @param resId resource identifier
+ * @return xmldb file name
+ */
+ String getFileName(String resId);
+
+ /**
+ * get the xmldb collection name associated to this resource identifier.
+ * Implementors may decide to encode it in the identifier itself or use a secondary associative memory.
+ * to quickly transform identifiers.
+ *
+ * @param resId resource identifier
+ * @return xmldb collection name
+ */
+ String getCollectionName(String resId);
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/ResourceLoaderHelper.java b/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/ResourceLoaderHelper.java
new file mode 100644
index 0000000..1c48148
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/ResourceLoaderHelper.java
@@ -0,0 +1,44 @@
+package eu.dnetlib.enabling.tools;
+
+import org.springframework.context.ResourceLoaderAware;
+import org.springframework.core.io.ResourceLoader;
+import org.springframework.core.io.support.ResourcePatternResolver;
+import org.springframework.core.io.support.ResourcePatternUtils;
+
+/**
+ * Some beans aren't directly instantiated (like quartz jobs for instance), so they cannot receive the resource loader
+ * by implementing the ResourceLoaderAware interface.
+ *
+ * This class is a temporary solution to this problem until we find a way to obtain a bean reference to the
+ * application context (the actual resource loader) itself and inject it directly. It could be done by turning this
+ * class into a bean factory and expose the resource loader through it.
+ *
+ * @author marko
+ *
+ */
+public class ResourceLoaderHelper implements ResourceLoaderAware {
+
+ /**
+ * injected resource loader.
+ */
+ private ResourceLoader resourceLoader;
+
+ /**
+ * obtain a resource pattern resolver for a given resource loader.
+ *
+ * @return pattern resolver
+ */
+ public ResourcePatternResolver getResourcePatternResolver() {
+ return ResourcePatternUtils.getResourcePatternResolver(getResourceLoader());
+ }
+
+ public ResourceLoader getResourceLoader() {
+ return resourceLoader;
+ }
+
+ @Override
+ public void setResourceLoader(final ResourceLoader resourceLoader) {
+ this.resourceLoader = resourceLoader;
+ }
+
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/ServiceEnumerator.java b/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/ServiceEnumerator.java
new file mode 100644
index 0000000..c791616
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/ServiceEnumerator.java
@@ -0,0 +1,19 @@
+package eu.dnetlib.enabling.tools;
+
+import java.util.List;
+
+/**
+ * A service enumerator returns a bunch of service descriptions. The logic depends on the service enumerator.
+ *
+ * @author marko
+ *
+ */
+@Deprecated
+public interface ServiceEnumerator {
+ /**
+ * Obtain a list of services.
+ *
+ * @return a list of service running instance descriptions
+ */
+ List> getServices();
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/ServiceLocator.java b/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/ServiceLocator.java
new file mode 100644
index 0000000..2c4abaa
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/ServiceLocator.java
@@ -0,0 +1,47 @@
+package eu.dnetlib.enabling.tools;
+
+/**
+ * A service locator provides a reference to a, possibly remote, service.
+ *
+ * @author marko
+ *
+ * @param
+ * the type of the service to return
+ * @deprecated As of release 2.0.0, use instead {@link eu.dnetlib.enabling.locators.DefaultUniqueServiceLocator}
+ */
+@Deprecated
+public interface ServiceLocator {
+
+ /**
+ * locate and return a service of this type.
+ *
+ * @return a service client instance
+ */
+ T getService();
+
+ /**
+ * Locate using a profileID (service or datastructure) the service of this type.
+ *
+ * @param profileId
+ * @param clazz
+ * @return a service client instance
+ */
+ T getService(final String profileId, final Class clazz);
+
+ /**
+ * locate and return a service ID.
+ *
+ * @return a service ID
+ */
+ String getServiceId();
+
+ /**
+ * locate and return a service ID.
+ *
+ * @param profileId
+ * (the id of the service or the id of one of its datastructures)
+ * @return a service ID.
+ */
+ String getServiceId(final String profileId);
+
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/ServiceLocatorChain.java b/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/ServiceLocatorChain.java
new file mode 100644
index 0000000..d1225e3
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/ServiceLocatorChain.java
@@ -0,0 +1,69 @@
+package eu.dnetlib.enabling.tools;
+
+import java.util.Collection;
+
+/**
+ * This class allows chaining several service locators and return the first one matching. Usually this is usefully when
+ * we want a StaticLocator as a fallback if the DynamicLocator cannot find anything.
+ *
+ * @author marko
+ *
+ * @param
+ * service type
+ */
+@Deprecated
+public class ServiceLocatorChain extends AbstractServiceLocator {
+
+ /**
+ * service locators, iterated in order.
+ */
+ private Collection> locators;
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see eu.dnetlib.enabling.tools.ServiceLocator#getService()
+ */
+ @Override
+ public T getService() {
+ IllegalStateException lastException = null; // NOPMD
+
+ for (ServiceLocator locator : locators) {
+ try {
+ return locator.getService();
+ } catch (IllegalStateException e) {
+ lastException = e;
+ }
+ }
+ if (lastException != null) {
+ throw new IllegalStateException("cannot find any matching service. Last locator in the chain reported as cause", lastException);
+ }
+ throw new IllegalStateException("cannot find any matching service: the service locator chain is empty");
+ }
+
+ @Override
+ public String getServiceId() {
+ IllegalStateException lastException = null; // NOPMD
+
+ for (ServiceLocator locator : locators) {
+ try {
+ return locator.getServiceId();
+ } catch (IllegalStateException e) {
+ lastException = e;
+ }
+ }
+ if (lastException != null) {
+ throw new IllegalStateException("cannot find any matching service. Last locator in the chain reported as cause", lastException);
+ }
+ throw new IllegalStateException("cannot find any matching service: the service locator chain is empty");
+ }
+
+ public Collection> getLocators() {
+ return locators;
+ }
+
+ public void setLocators(final Collection> locators) {
+ this.locators = locators;
+ }
+
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/ServiceResolver.java b/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/ServiceResolver.java
new file mode 100644
index 0000000..3888ecb
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/ServiceResolver.java
@@ -0,0 +1,32 @@
+package eu.dnetlib.enabling.tools;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+/**
+ * Instances of this type resolve EPR references to service endpoints.
+ *
+ * @author marko
+ *
+ */
+public interface ServiceResolver {
+ /**
+ * return a service client given an EPR instance.
+ *
+ * @param
+ * the service type
+ * @param clazz
+ * needed for type inference of type parameter
+ * @param epr
+ * EPR
+ * @return a service client reference
+ */
+ T getService(Class clazz, W3CEndpointReference epr);
+
+ /**
+ * Extract the resource identifier embedded in the EPR.
+ *
+ * @param epr end point reference
+ * @return resource identifier
+ */
+ String getResourceIdentifier(W3CEndpointReference epr);
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/ServiceResolverChain.java b/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/ServiceResolverChain.java
new file mode 100644
index 0000000..a512c25
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/ServiceResolverChain.java
@@ -0,0 +1,61 @@
+package eu.dnetlib.enabling.tools;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+/**
+ * This resolver chains a list of resolvers.
+ *
+ * @author marko
+ *
+ */
+public class ServiceResolverChain implements ServiceResolver {
+
+ /**
+ * service resolvers in decreasing order or priority.
+ */
+ private List resolvers = new ArrayList();
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see eu.dnetlib.enabling.tools.ServiceResolver#getService(java.lang.Class,
+ * javax.xml.ws.wsaddressing.W3CEndpointReference)
+ */
+ @Override
+ public T getService(final Class clazz, final W3CEndpointReference epr) {
+ for (ServiceResolver resolver : getResolvers()) {
+ final T service = resolver.getService(clazz, epr);
+
+ if (service != null)
+ return service;
+ }
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @see eu.dnetlib.enabling.tools.ServiceResolver#getResourceIdentifier(javax.xml.ws.wsaddressing.W3CEndpointReference)
+ */
+ @Override
+ public String getResourceIdentifier(final W3CEndpointReference epr) {
+ for (ServiceResolver resolver : getResolvers()) {
+ final String rsId = resolver.getResourceIdentifier(epr);
+
+ if (rsId != null)
+ return rsId;
+ }
+ return null;
+ }
+
+ public List getResolvers() {
+ return resolvers;
+ }
+
+ public void setResolvers(final List resolvers) {
+ this.resolvers = resolvers;
+ }
+
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/ServiceRunningInstance.java b/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/ServiceRunningInstance.java
new file mode 100644
index 0000000..cc1bfba
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/ServiceRunningInstance.java
@@ -0,0 +1,95 @@
+package eu.dnetlib.enabling.tools;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.xml.ws.wsaddressing.W3CEndpointReference;
+
+/**
+ * This bean packages the minimum information for describing a service running instance.
+ *
+ * @author marko
+ *
+ */
+@Deprecated
+public class ServiceRunningInstance {
+ /**
+ * service endpoint.
+ */
+ private W3CEndpointReference epr;
+
+ /**
+ * service resource id.
+ */
+ private String serviceId;
+
+ /**
+ * service endpoint url.
+ */
+ private String url;
+
+ /**
+ * arbitrary service properties stored in the profile.
+ */
+ private Map serviceProperties;
+
+ /**
+ * Create a service running instance.
+ *
+ * @param epr service epr
+ * @param serviceId service profile resource id
+ * @param url service endpoint url
+ */
+ public ServiceRunningInstance(final W3CEndpointReference epr, final String serviceId, final String url) {
+ this(epr, serviceId, url, new HashMap());
+ }
+
+ /**
+ * Create a service running instance.
+ *
+ * @param epr service epr
+ * @param serviceId service profile resource id
+ * @param url service endpoint url
+ * @param serviceProperties service property map
+ */
+ public ServiceRunningInstance(final W3CEndpointReference epr, final String serviceId, final String url, final Map serviceProperties) {
+ super();
+ this.epr = epr;
+ this.serviceId = serviceId;
+ this.url = url;
+ this.serviceProperties = serviceProperties;
+ }
+
+ public W3CEndpointReference getEpr() {
+ return epr;
+ }
+
+ public void setEpr(final W3CEndpointReference epr) {
+ this.epr = epr;
+ }
+
+ public String getServiceId() {
+ return serviceId;
+ }
+
+ public void setServiceId(final String serviceId) {
+ this.serviceId = serviceId;
+ }
+
+ public Map getServiceProperties() {
+ return serviceProperties;
+ }
+
+ public void setServiceProperties(final Map serviceProperties) {
+ this.serviceProperties = serviceProperties;
+ }
+
+ public String getUrl() {
+ return url;
+ }
+
+ public void setUrl(String url) {
+ this.url = url;
+ }
+
+}
diff --git a/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/SplittedQueryExecutor.java b/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/SplittedQueryExecutor.java
new file mode 100644
index 0000000..fbf1b42
--- /dev/null
+++ b/dnet-core-components/src/main/java/eu/dnetlib/enabling/tools/SplittedQueryExecutor.java
@@ -0,0 +1,171 @@
+package eu.dnetlib.enabling.tools;
+
+import java.util.List;
+import java.util.Map;
+
+import org.springframework.beans.factory.annotation.Required;
+
+import com.google.common.collect.Lists;
+
+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.locators.UniqueServiceLocator;
+import eu.dnetlib.miscutils.collections.PositionalStringMapGenerator;
+
+/**
+ * Utility class which interacts with a lookup, performs a query and fills a java domain object splitting the result into constructor
+ * arguments.
+ *
+ * @author marko
+ *
+ */
+public class SplittedQueryExecutor {
+
+ /**
+ * service locator.
+ */
+ private UniqueServiceLocator serviceLocator;
+
+ /**
+ * default constructor. lookupLocator has to be injected.
+ */
+ public SplittedQueryExecutor() {
+ // empty
+ }
+
+ /**
+ * Commodity constructor for constructor injection.
+ *
+ * @param lookupLocator
+ * lookup locator
+ */
+ public SplittedQueryExecutor(final UniqueServiceLocator serviceLocator) {
+ super();
+ this.serviceLocator = serviceLocator;
+ }
+
+ /**
+ * Performs the query, splits the result at ":-:".
+ *
+ * @param
+ * domain class type
+ * @param clazz
+ * domain class
+ * @param query
+ * xquery
+ * @return iterable of domain class instances
+ */
+ public Iterable query(final Class clazz, final String query) {
+ return query(clazz, query, ":-:");
+ }
+
+ /**
+ * Performs the query, splits the result at separator
+ *
+ * @param
+ * domain class type
+ * @param clazz
+ * domain class
+ * @param query
+ * xquery
+ * @param separator
+ * split separator
+ * @return iterable of domain class instances
+ */
+ public Iterable query(final Class clazz, final String query, final String separator) {
+ return new PositionalStringMapGenerator().split(clazz, performQuery(query), separator);
+ }
+
+ /**
+ * Return a list of maps of splitted query results
+ *
+ * @param query
+ * xquery
+ * @param keys
+ * list of keys
+ * @return collection of key/value pairs
+ */
+ public Iterable