/*
* Copyright (C) 2011 Google Inc.
*
* 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 org.ros.internal.node.topic;
import org.apache.commons.logging.Log;
import org.ros.exception.RemoteException;
import org.ros.internal.node.client.SlaveClient;
import org.ros.internal.node.response.Response;
import org.ros.internal.node.server.NodeIdentifier;
import org.ros.internal.node.server.SlaveServer;
import org.ros.internal.node.xmlrpc.XmlRpcTimeoutException;
import org.ros.internal.transport.ProtocolDescription;
import org.ros.internal.transport.ProtocolNames;
import org.ros.log.RosLogFactory;
import org.ros.node.topic.Publisher;
import org.ros.node.topic.Subscriber;
/**
* A {@link Runnable} which is used whenever new publishers are being added to a
* {@link DefaultSubscriber}. It takes care of registration between the
* {@link Subscriber} and remote {@link Publisher}.
*
* @author damonkohler@google.com (Damon Kohler)
*/
class UpdatePublisherRunnable<MessageType> implements Runnable {
private static final Log log = RosLogFactory.getLog(UpdatePublisherRunnable.class);
private final DefaultSubscriber<MessageType> subscriber;
private final PublisherIdentifier publisherIdentifier;
private final NodeIdentifier nodeIdentifier;
/**
* @param subscriber
* @param nodeIdentifier
* {@link NodeIdentifier} of the {@link Subscriber}'s
* {@link SlaveServer}
* @param publisherIdentifier
* {@link PublisherIdentifier} of the new {@link Publisher}
*/
public UpdatePublisherRunnable(DefaultSubscriber<MessageType> subscriber,
NodeIdentifier nodeIdentifier, PublisherIdentifier publisherIdentifier) {
this.subscriber = subscriber;
this.nodeIdentifier = nodeIdentifier;
this.publisherIdentifier = publisherIdentifier;
}
@Override
public void run() {
SlaveClient slaveClient;
try {
slaveClient = new SlaveClient(nodeIdentifier.getName(), publisherIdentifier.getNodeUri());
Response<ProtocolDescription> response =
slaveClient.requestTopic(subscriber.getTopicName(), ProtocolNames.SUPPORTED);
// TODO(kwc): all of this logic really belongs in a protocol handler
// registry.
ProtocolDescription selected = response.getResult();
if (ProtocolNames.SUPPORTED.contains(selected.getName())) {
subscriber.addPublisher(publisherIdentifier, selected.getAddress());
} else {
log.error("Publisher returned unsupported protocol selection: " + response);
}
} catch (RemoteException e) {
// TODO(damonkohler): Retry logic is needed at the XML-RPC layer.
log.error(e);
} catch (XmlRpcTimeoutException e) {
// TODO(damonkohler): see above note re: retry
log.error(e);
} catch (RuntimeException e) {
// TODO(kwc):
// org.apache.xmlrpc.XmlRpcException/java.net.ConnectException's are
// leaking through as java.lang.reflect.UndeclaredThrowableExceptions.
// This is happening whenever the node attempts to connect to a stale
// publisher (i.e. a publisher that is no longer online).
log.error(e);
}
}
}