258 lines
7.7 KiB
Java
258 lines
7.7 KiB
Java
package eu.dnetlib.enabling.is.registry;
|
|
|
|
import javax.xml.transform.dom.DOMResult;
|
|
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.Node;
|
|
|
|
import eu.dnetlib.enabling.is.lookup.rmi.ISLookUpService;
|
|
import eu.dnetlib.enabling.is.registry.rmi.ISRegistryService;
|
|
import eu.dnetlib.enabling.tools.OpaqueResource;
|
|
import eu.dnetlib.enabling.tools.StringOpaqueResource;
|
|
import eu.dnetlib.enabling.tools.blackboard.BlackboardMessage;
|
|
import eu.dnetlib.miscutils.datetime.DateUtils;
|
|
import eu.dnetlib.miscutils.jaxb.JaxbFactory;
|
|
|
|
/**
|
|
* Simple registry blackboard manager implementation.
|
|
*
|
|
* @author marko
|
|
*
|
|
*/
|
|
public class RegistryBlackboardManagerImpl implements RegistryBlackboardManager { // NOPMD
|
|
|
|
/**
|
|
* logger.
|
|
*/
|
|
private static final Log log = LogFactory.getLog(RegistryBlackboardManagerImpl.class); // NOPMD by marko on 11/24/08 5:02 PM
|
|
|
|
/**
|
|
* timestamp padding.
|
|
*/
|
|
private static final String PADDING = "000";
|
|
|
|
/**
|
|
* milliseconds in a second.
|
|
*/
|
|
private static final int MILLIS = 1000;
|
|
|
|
/**
|
|
* IS Lookup
|
|
*/
|
|
private ISLookUpService isLookup;
|
|
|
|
/**
|
|
* the registry which is bound with this registry blackboard manager implementation.
|
|
*/
|
|
private ISRegistryService registryService;
|
|
|
|
/**
|
|
* blackboard message factory.
|
|
*/
|
|
private JaxbFactory<BlackboardMessage> messageFactory;
|
|
|
|
/**
|
|
* provides the current date. Testers can override.
|
|
*/
|
|
private MessageDater messageDater = new MessageDater();
|
|
|
|
/**
|
|
* Testers can override.
|
|
*
|
|
* @author marko
|
|
*
|
|
*/
|
|
public static class MessageDater {
|
|
|
|
public String getCurrentDate() {
|
|
return DateUtils.now_ISO8601();
|
|
}
|
|
|
|
public String getNumericStamp() {
|
|
return Long.toString(System.currentTimeMillis() / MILLIS) + "." + System.currentTimeMillis() % MILLIS + PADDING;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* LAST_REQUEST or LAST_RESPONSE blackboard time stamp holders.
|
|
*
|
|
* @author marko
|
|
*
|
|
*/
|
|
public enum LastStamp {
|
|
/**
|
|
* LAST_REQUEST, used when the blackboard message flows from the client to the server.
|
|
*/
|
|
REQUEST,
|
|
|
|
/**
|
|
* LAST_RESPONSE, used when the blackboard message flows from the server to the client, signaling the completion/progress of the
|
|
* action..
|
|
*/
|
|
RESPONSE
|
|
}
|
|
|
|
/**
|
|
* {@inheritDoc}
|
|
*
|
|
* @see eu.dnetlib.enabling.is.registry.RegistryBlackboardManager#addMessage(java.lang.String, java.lang.String, java.lang.String)
|
|
*/
|
|
@Override
|
|
public void addMessage(final String profId, final String messageId, final String message) { // NOPMD
|
|
try {
|
|
final BlackboardMessage bbm = messageFactory.parse(message);
|
|
bbm.setDate(messageDater.getCurrentDate()); // preserve compatibility.
|
|
|
|
if (bbm.getId() == null || !bbm.getId().equals(messageId)) { throw new IllegalArgumentException("invalid blackboard message id"); }
|
|
|
|
synchronized (this) {
|
|
final OpaqueResource serviceProfile = new StringOpaqueResource(isLookup.getResourceProfile(profId));
|
|
|
|
final Document doc = serviceProfile.asDom();
|
|
final Node bboard = (Node) XPathFactory.newInstance().newXPath().evaluate("//BLACKBOARD", doc, XPathConstants.NODE);
|
|
|
|
// delete current element if exists
|
|
final Node messageElement = (Node) XPathFactory.newInstance().newXPath().evaluate("//BLACKBOARD/MESSAGE[@id='" + messageId + "']", doc,
|
|
XPathConstants.NODE);
|
|
|
|
if (messageElement != null) {
|
|
bboard.removeChild(messageElement);
|
|
}
|
|
|
|
// append the serialized node to the blackboard node
|
|
messageFactory.serialize(bbm, new DOMResult(bboard));
|
|
|
|
updateLastStamps(doc, LastStamp.REQUEST, messageId);
|
|
|
|
registryService.updateProfile(profId, serviceProfile.asString(), serviceProfile.getResourceType());
|
|
}
|
|
} catch (Exception e) {
|
|
throw new IllegalStateException(e);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Helper method which updates the LAST_* stamps in the blackboard header.
|
|
*
|
|
* @param doc
|
|
* profile DOM document
|
|
* @param stamp
|
|
* which stamp to modify
|
|
* @param messageId
|
|
* message id to point the stamp to
|
|
* @throws XPathExpressionException
|
|
* could happen
|
|
*/
|
|
protected void updateLastStamps(final Document doc, final LastStamp stamp, final String messageId) throws XPathExpressionException {
|
|
final Element lastRequest = (Element) XPathFactory.newInstance().newXPath().evaluate("//BLACKBOARD/LAST_" + stamp, doc, XPathConstants.NODE);
|
|
lastRequest.setTextContent(messageId);
|
|
lastRequest.setAttribute("date", messageDater.getNumericStamp());
|
|
}
|
|
|
|
/**
|
|
* {@inheritDoc}
|
|
*
|
|
* @see eu.dnetlib.enabling.is.registry.RegistryBlackboardManager#deleteMessage(java.lang.String, java.lang.String)
|
|
*/
|
|
@Override
|
|
public void deleteMessage(final String profId, final String messageId) {
|
|
try {
|
|
synchronized (this) {
|
|
final OpaqueResource serviceProfile = new StringOpaqueResource(isLookup.getResourceProfile(profId));
|
|
final Document doc = serviceProfile.asDom();
|
|
|
|
final Node message = (Node) XPathFactory.newInstance().newXPath().evaluate("//BLACKBOARD/MESSAGE[@id='" + messageId + "']", doc,
|
|
XPathConstants.NODE);
|
|
|
|
message.getParentNode().removeChild(message);
|
|
|
|
registryService.updateProfile(profId, serviceProfile.asString(), serviceProfile.getResourceType());
|
|
}
|
|
log.debug("Deleted bb message " + messageId + " from profile " + profId);
|
|
} catch (Exception e) {
|
|
log.error("Error deleting bb message " + messageId + " from profile " + profId, e);
|
|
throw new IllegalStateException(e);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* {@inheritDoc}
|
|
*
|
|
* @see eu.dnetlib.enabling.is.registry.RegistryBlackboardManager#replyMessage(java.lang.String, java.lang.String)
|
|
*/
|
|
@Override
|
|
public void replyMessage(final String profId, final String message) {
|
|
try {
|
|
final BlackboardMessage bbm = messageFactory.parse(message);
|
|
bbm.setDate(messageDater.getCurrentDate()); // preserve compatibility.
|
|
|
|
final String messageId = bbm.getId();
|
|
|
|
synchronized (this) {
|
|
final OpaqueResource serviceProfile = new StringOpaqueResource(isLookup.getResourceProfile(profId));
|
|
final Document doc = serviceProfile.asDom();
|
|
|
|
final Node messageElement = (Node) XPathFactory.newInstance().newXPath().evaluate("//BLACKBOARD/MESSAGE[@id='" + messageId + "']", doc,
|
|
XPathConstants.NODE);
|
|
|
|
if (messageElement == null) { throw new IllegalArgumentException("no such blackboard message " + messageId + ". Unably to reply"); }
|
|
|
|
final Node bboard = messageElement.getParentNode();
|
|
bboard.removeChild(messageElement);
|
|
|
|
// append the serialized node to the blackboard node
|
|
messageFactory.serialize(bbm, new DOMResult(bboard));
|
|
|
|
updateLastStamps(doc, LastStamp.RESPONSE, messageId);
|
|
|
|
registryService.updateProfile(profId, serviceProfile.asString(), serviceProfile.getResourceType());
|
|
}
|
|
} catch (Exception e) {
|
|
throw new IllegalStateException(e);
|
|
}
|
|
}
|
|
|
|
public ISRegistryService getRegistryService() {
|
|
return registryService;
|
|
}
|
|
|
|
@Required
|
|
public void setRegistryService(final ISRegistryService registryService) {
|
|
this.registryService = registryService;
|
|
}
|
|
|
|
public JaxbFactory<BlackboardMessage> getMessageFactory() {
|
|
return messageFactory;
|
|
}
|
|
|
|
@Required
|
|
public void setMessageFactory(final JaxbFactory<BlackboardMessage> messageFactory) {
|
|
this.messageFactory = messageFactory;
|
|
}
|
|
|
|
public MessageDater getMessageDater() {
|
|
return messageDater;
|
|
}
|
|
|
|
public void setMessageDater(final MessageDater messageDater) {
|
|
this.messageDater = messageDater;
|
|
}
|
|
|
|
public ISLookUpService getIsLookup() {
|
|
return isLookup;
|
|
}
|
|
|
|
@Required
|
|
public void setIsLookup(final ISLookUpService isLookup) {
|
|
this.isLookup = isLookup;
|
|
}
|
|
|
|
}
|