package net.jxta.impl.endpoint; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import net.jxta.endpoint.EndpointAddress; import net.jxta.endpoint.Message; import net.jxta.endpoint.MessageElement; import net.jxta.endpoint.Messenger; import net.jxta.endpoint.OutgoingMessageEvent; import net.jxta.endpoint.StringMessageElement; import net.jxta.logging.Logger; import net.jxta.logging.Logging; /** * Provides some simple utility methods that are useful for transport implementations, as a complement * to those provided by IPUtils. * * @author Iain McGinniss (iain.mcginniss@onedrum.com) */ public class TransportUtils { private static final Logger LOG = Logging.getLogger(TransportUtils.class.getName()); /** * Will attempt to resolve the physical adapter's InetAddress for the given interface * address string (typically, a host name or string representation of an IP address). * If this cannot be resolved, {@link net.jxta.impl.endpoint.IPUtils#ANYADDRESS IPUtils.ANYADDRESS} * will be returned. */ public static InetAddress resolveInterfaceAddress(String interfaceAddressStr) { InetAddress interfaceAddress; if (interfaceAddressStr != null) { try { interfaceAddress = InetAddress.getByName(interfaceAddressStr); } catch (UnknownHostException failed) { Logging.logCheckedWarning(LOG, "Invalid address for local interface address, using ", IPUtils.ANYADDRESS, " instead" ); interfaceAddress = IPUtils.ANYADDRESS; } } else { interfaceAddress = IPUtils.ANYADDRESS; } return interfaceAddress; } /** * Takes an integer port range and creates a list containing all the integers in * that range, randomly ordered. If the start or end values are outside the * legal range for a TCP or UDP port (1-65535) then an IllegalArgumentException * will be thrown. */ public static List<Integer> rangeCheckShuffle(int start, int end) throws IllegalArgumentException { if ((start < 1) || (start > 65535)) { throw new IllegalArgumentException("Invalid start port"); } if ((end < 1) || (end > 65535) || (end < start)) { throw new IllegalArgumentException("Invalid end port"); } // fill the inRange array. List<Integer> inRange = new ArrayList<Integer>(); for (int eachInRange = start; eachInRange < end; eachInRange++) { inRange.add(eachInRange); } Collections.shuffle(inRange); return inRange; } public static Message retargetMessage(Message message, String service, String param, EndpointAddress localAddress, EndpointAddress defaultDestAddress) { MessageElement srcAddrElem = new StringMessageElement(EndpointServiceImpl.MESSAGE_SOURCE_NAME, localAddress.toString(), null); message.replaceMessageElement(EndpointServiceImpl.MESSAGE_SOURCE_NS, srcAddrElem); EndpointAddress destAddressToUse; destAddressToUse = getDestAddressToUse(service, param, defaultDestAddress); MessageElement dstAddressElement = new StringMessageElement(EndpointServiceImpl.MESSAGE_DESTINATION_NAME, destAddressToUse.toString(), null); message.replaceMessageElement(EndpointServiceImpl.MESSAGE_DESTINATION_NS, dstAddressElement); return message; } /** * Assemble a destination address for a message based upon the messenger * default destination address and the optional provided overrides. * * @param service The destination service or {@code null} to use default. * @param serviceParam The destination service parameter or {@code null} to * use default. */ public static EndpointAddress getDestAddressToUse(final String service, final String serviceParam, final EndpointAddress defaultAddress) { EndpointAddress result; if(null == service) { if(null == serviceParam) { // Use default service name and service params result = defaultAddress; } else { // use default service name, override service params result = new EndpointAddress(defaultAddress, defaultAddress.getServiceName(), serviceParam); } } else { if(null == serviceParam) { // override service name, use default service params (this one is pretty weird and probably not useful) result = new EndpointAddress(defaultAddress, service, defaultAddress.getServiceParameter()); } else { // override service name, override service params result = new EndpointAddress(defaultAddress, service, serviceParam); } } return result; } /** * Sets a message property on the provided message indicating that it could not be sent * due to messenger saturation. */ public static void markMessageWithOverflowFailure(Message message) { message.setMessageProperty(Messenger.class, OutgoingMessageEvent.OVERFLOW); } /** * Sets a message property on the provided message indicating that it could not be sent * due to the provided cause. */ public static void markMessageWithSendFailure(Message message, Throwable cause) { message.setMessageProperty(Messenger.class, new OutgoingMessageEvent(message, cause)); } /** * Sets a message property on the provided message indicating that it was successfully * sent. This does not, however, mean that the message has yet been successfully received * by the intended recipient. */ public static void markMessageWithSendSuccess(Message message) { message.setMessageProperty(Messenger.class, OutgoingMessageEvent.SUCCESS); } /** * @return whether or not the provided message has failed to send for whatever * reason (overflow or some other cause). */ public static boolean isMarkedWithFailure(Message msg) { Object property = msg.getMessageProperty(Messenger.class); if(property != null && property instanceof OutgoingMessageEvent) { OutgoingMessageEvent event = (OutgoingMessageEvent) property; return event == OutgoingMessageEvent.OVERFLOW || event.getFailure() != null; } return false; } public static boolean isMarkedWithOverflow(Message msg) { Object property = msg.getMessageProperty(Messenger.class); if(property != null && property instanceof OutgoingMessageEvent) { OutgoingMessageEvent event = (OutgoingMessageEvent) property; return event == OutgoingMessageEvent.OVERFLOW; } return false; } public static void clearOverflowMarker(Message msg) { msg.setMessageProperty(Messenger.class, null); } /** * @return the cause of the failure in sending this message. Note that if the message * failed due to messenger saturation, this method will return null. */ public static Throwable getFailureCause(Message msg) { Object property = msg.getMessageProperty(Messenger.class); if(property instanceof OutgoingMessageEvent) { OutgoingMessageEvent event = (OutgoingMessageEvent) property; return event.getFailure(); } return null; } /** * @return whether or not this message has been marked, stating that it has been * successfully sent. */ public static boolean isMarkedWithSuccess(Message msg) { return msg.getMessageProperty(Messenger.class) == OutgoingMessageEvent.SUCCESS; } public static void clearSendResult(Message msg) { msg.setMessageProperty(Messenger.class, null); } public static boolean isAnSRDIMessage(Message msg) { final MessageElement firstElement = msg.getMessageElements().next(); boolean sent = false; boolean aBoolean = firstElement.getElementName().equals("jxta-NetGroupSrdi"); return aBoolean; } }