/*
* Copyright 2012 Research Studios Austria Forschungsges.m.b.H.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package won.owner.messaging;
import org.apache.jena.riot.Lang;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import won.protocol.jms.MessagingService;
import won.protocol.message.WonMessage;
import won.protocol.message.WonMessageEncoder;
import won.protocol.message.processor.impl.KeyForNewNeedAddingProcessor;
import won.protocol.message.processor.impl.SignatureAddingWonMessageProcessor;
import won.protocol.message.sender.WonMessageSender;
import won.protocol.model.WonNode;
import won.protocol.repository.WonNodeRepository;
import won.protocol.util.RdfUtils;
import java.net.URI;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* User: LEIH-NB
* Date: 17.10.13
*
* Instance of this class receives events upon which it tries to register at the default won node using JMS.
*/
public class OwnerWonMessageSenderJMSBased implements ApplicationListener<WonNodeRegistrationEvent>, WonMessageSender
{
private final Logger logger = LoggerFactory.getLogger(getClass());
private boolean isDefaultWonNodeRegistered = false;
private MessagingService messagingService;
private URI defaultNodeURI;
//todo: make this configurable
private String startingEndpoint;
@Autowired
private OwnerProtocolCommunicationServiceImpl ownerProtocolCommunicationServiceImpl;
@Autowired
private WonNodeRepository wonNodeRepository;
@Autowired
private SignatureAddingWonMessageProcessor signatureAddingProcessor ;
@Autowired
private KeyForNewNeedAddingProcessor needKeyGeneratorAndAdder;
public void sendWonMessage(WonMessage wonMessage) {
try {
// TODO check if there is a better place for applying signing logic
wonMessage = doSigningOnOwner(wonMessage);
if (logger.isDebugEnabled()){
logger.debug("sending this message: {}", RdfUtils.writeDatasetToString(wonMessage.getCompleteDataset(), Lang.TRIG));
}
// ToDo (FS): change it to won node URI and create method in the MessageEvent class
URI wonNodeUri = wonMessage.getSenderNodeURI();
if (wonNodeUri == null){
//obtain the sender won node from the sender need
throw new IllegalStateException("a message needs a SenderNodeUri otherwise we can't determine the won node " +
"via which to send it");
}
String ownerApplicationId = getOwnerApplicationIdAndRegisterIfNecessary(wonNodeUri);
//String ep = camelConfiguration.getEndpoint()
String ep = ownerProtocolCommunicationServiceImpl.getProtocolCamelConfigurator()
.getEndpoint(wonNodeUri);
Map<String, Object> headerMap = new HashMap<>();
headerMap.put("ownerApplicationID", ownerApplicationId);
headerMap.put("remoteBrokerEndpoint",ep);
messagingService
.sendInOnlyMessage(null, headerMap, WonMessageEncoder.encode(wonMessage, Lang.TRIG), startingEndpoint);
//camelContext.getShutdownStrategy().setSuppressLoggingOnTimeout(true);
} catch (Exception e){
throw new RuntimeException("could not send message", e);
}
}
private String getOwnerApplicationIdAndRegisterIfNecessary(final URI wonNodeUri) throws Exception {
ownerProtocolCommunicationServiceImpl.register(wonNodeUri, messagingService);
List<WonNode> wonNodeList = wonNodeRepository.findByWonNodeURI(wonNodeUri);
String ownerApplicationId = wonNodeList.get(0).getOwnerApplicationID();
return ownerApplicationId;
}
//TODO: adding public keys and signing can be removed when it happens in the browser
//in that case owner will have to sign only system messages, or in case it adds information to the message
//TODO exceptions
private WonMessage doSigningOnOwner(final WonMessage wonMessage)
throws Exception {
// add public key of the newly created need
WonMessage outMessage = needKeyGeneratorAndAdder.process(wonMessage);
// add signature:
return signatureAddingProcessor.processOnBehalfOfNeed(outMessage);
}
/**
* The owner application calls the register() method node upon initalization (and during fixed time intervals)
* to connect to the default won node.
*
* @param wonNodeRegistrationEvent
*/
@Override
public void onApplicationEvent(final WonNodeRegistrationEvent wonNodeRegistrationEvent) {
if (!isDefaultWonNodeRegistered) {
try {
new Thread()
{
@Override
public void run() {
try {
logger.info("register at default won node {}", defaultNodeURI);
ownerProtocolCommunicationServiceImpl.register(defaultNodeURI, messagingService);
// try the registration as long as no exception occurs
logger.info("successfully registered at default won node {}", defaultNodeURI);
isDefaultWonNodeRegistered = true;
} catch (Exception e) {
logger.warn("Could not register with default won node {}. Try again later ... (reason is logged at " +
"loglevel 'DEBUG')",
defaultNodeURI);
logger.debug("Exceptions is: ", e);
}
}
}.start();
} catch (Exception e) {
logger.warn("Could not register with default won node {}. Try again later ...", defaultNodeURI);
logger.debug("Exceptions is: ", e);
}
}
}
public void setMessagingService(MessagingService messagingService) {
this.messagingService = messagingService;
}
public void setDefaultNodeURI(URI defaultNodeURI) {
this.defaultNodeURI = defaultNodeURI;
}
public void setStartingEndpoint(String startingEndpoint) {
this.startingEndpoint = startingEndpoint;
}
}