ws-muse-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rluce...@xecu.net
Subject Re: RE: Issue in EndpointReference.equals() method
Date Mon, 28 Apr 2008 16:00:33 GMT
 Related to MUSE-241, I did a more extensive patch to
EndpointReference and experimented with refreshing the IP addresses
assigned to the local host.  I maintain a static collection of IP
addresses assigned to the JVM that is periodically refreshed.  The
refresh uses the java.util.concurrent capabilities in JDK 5.0, but
there is a backport available for earlier JVM's
(http://backport-jsr166.sourceforge.net). [1]
 The EPR equals() method compares the two EPR's, with the actual IP
address comparison happening last only if necessary.  The comparison
of IP addresses normalizes addresses local to the JVM.  In a
multi-homed environment, EPRs with IP addresses assigned to the same
JVM would be equivalent.
 The patch for 2.2.0 is below, with the MUSE-270 stability changes
incorporated:
 Index:
modules/muse-wsa-soap/src/org/apache/muse/ws/addressing/EndpointReference.java
 ===================================================================
 ---
modules/muse-wsa-soap/src/org/apache/muse/ws/addressing/EndpointReference.java
   (revision 648324)
 +++
modules/muse-wsa-soap/src/org/apache/muse/ws/addressing/EndpointReference.java
   (working copy)
 @@ -20,20 +20,29 @@
  package org.apache.muse.ws.addressing;
 +import java.net.InetAddress;
 +import java.net.NetworkInterface;
 +import java.net.SocketException;
 +import java.net.UnknownHostException;
  import java.net.URI;
 +import java.util.Enumeration;
 +import java.util.HashSet;
 +import java.util.Set;
 +import java.util.Iterator;
 +import java.util.concurrent.Executors;
 +import java.util.concurrent.ScheduledExecutorService;
 +import java.util.concurrent.TimeUnit;
  import javax.xml.namespace.QName;
 -import org.w3c.dom.Document;
 -import org.w3c.dom.Element;
 -import org.w3c.dom.Node;
 -import org.w3c.dom.NodeList;
 -
  import org.apache.muse.util.messages.Messages;
  import org.apache.muse.util.messages.MessagesFactory;
  import org.apache.muse.util.xml.XmlSerializable;
  import org.apache.muse.util.xml.XmlUtils;
  import org.apache.muse.ws.addressing.soap.SoapFault;
 +import org.w3c.dom.Document;
 +import org.w3c.dom.Element;
 +import org.w3c.dom.Node;
  /**
   *
 @@ -56,6 +65,39 @@
      //
      private static Messages _MESSAGES =
MessagesFactory.get(EndpointReference.class);
 +    private static Set hostAddresses = new HashSet();
 +    private static ScheduledExecutorService hostRefreshScheduler =
 +        Executors.newSingleThreadScheduledExecutor();
 +    private static final long REFRESH_DELAY = 60;  // one minute
 +    static {
 +        Runtime.getRuntime().addShutdownHook(new Thread() {
 +            public void run() {
 +                hostRefreshScheduler.shutdownNow();
 +            }
 +        });
 +
 +        hostRefreshScheduler.scheduleWithFixedDelay(new Runnable()
{
 +            public void run() {
 +                HashSet updateHostAddresses = new HashSet();
 +                try {
 +                    Enumeration interfaces =
NetworkInterface.getNetworkInterfaces();
 +                    while (interfaces.hasMoreElements()) {
 +                      NetworkInterface intf =
(NetworkInterface)interfaces.nextElement();
 +                      Enumeration addresses =
intf.getInetAddresses();
 +                      while (addresses.hasMoreElements()) {
 +                        InetAddress addr =
(InetAddress)addresses.nextElement();
 +                       
updateHostAddresses.add(addr.getHostAddress());
 +                      }
 +                    }
 +
 +                    hostAddresses = updateHostAddresses;
 +                } catch(SocketException se) {
 +                    // log fatal
 +                }
 +            }
 +        }, 0, REFRESH_DELAY, TimeUnit.SECONDS);
 +    }
 +
      private URI _address = null;
      //
 @@ -121,7 +163,7 @@
          // option #1 - make our own copy of the XML sub-tree
          //
          if (makeDeepCopyOfXML)
 -            _xml = (Element)XmlUtils.EMPTY_DOC.importNode(root,
true);
 +            _xml =
(Element)XmlUtils.createDocument().importNode(root, true);
          //
          // option #2 - just use the existing fragment
 @@ -172,19 +214,16 @@
          // create the root element - we can't just importNode
because the 
          // QName might be different
          //
 -        Document doc = XmlUtils.EMPTY_DOC;
 +        Document doc = XmlUtils.createDocument();
          _xml = XmlUtils.createElement(doc, typeName);
          //
          // now copy all child elements...
          //
 -        NodeList children = copy.toXML().getChildNodes();
 -        int length = children.getLength();
 -        
 -        for (int n = 0; n < length; ++n)
 -        {
 -            Node next = doc.importNode(children.item(n), true);
 -            _xml.appendChild(next);
 +        XmlUtils.NodeChildrenIterator itr = new
XmlUtils.NodeChildrenIterator(copy.toXML());
 +        while(itr.hasNext()) {
 +            Node imp = doc.importNode(itr.next(), true);
 +            _xml.appendChild(imp);
          }
          try
 @@ -236,7 +275,7 @@
          _address = address;
 -        Document doc = XmlUtils.EMPTY_DOC;        
 +        Document doc = XmlUtils.createDocument();        
          _xml = XmlUtils.createElement(doc, typeName);
          //
 @@ -318,6 +357,27 @@
      /**
       * 
 +     * This converts the given address to "localhost" if the
address matches
 +     * an IP address assigned to this host.   Otherwise, the IP
address is
 +     * returned for the given domain name or address.
 +     *
 +     */
 +    private String convertHostAddress(String addr) {
 +        String result = addr;
 +        try {
 +            InetAddress ipAddr = InetAddress.getByName(addr);
 +            result = ipAddr.getHostAddress();
 +            if (hostAddresses.contains(result))
 +                result = "localhost";
 +        } catch(UnknownHostException uhe) {
 +            // log unknown host exception
 +        }
 +
 +        return result;
 +    }
 +    
 +    /**
 +     * 
       * @return True, if:
       *         
       *         The argument is not null.
 @@ -338,6 +398,13 @@
          EndpointReference that = (EndpointReference)obj;
 +        // compare the ports used by both endpoints
 +        int thisPort = getAddress().getPort();
 +        int thatPort = that.getAddress().getPort();
 +
 +        if (thisPort != thatPort)
 +            return false;
 +
          //
          // compare wsa:Address - EXCLUDING the host. this allows us

          // to compare EPRs that have equivalent IP addresses and 
 @@ -364,6 +431,18 @@
                  return false;
          //
 +        // if everthing else is the same, compare the addresses to
see if
 +        // they're also the same (NOTE: all addresses assigned to
this host are
 +        // considered the same).
 +        //
 +        String thisAddr =
convertHostAddress(getAddress().getHost());
 +        String thatAddr =
convertHostAddress(that.getAddress().getHost());
 +
 +        // if different addresses
 +        if (!thisAddr.equals(thatAddr))
 +            return false;
 +
 +        //
          // if we made it this far, all values were equal
          //
          return true;
 @@ -380,14 +459,15 @@
      }
      /**
 -     *
 +     * For reasons of thread safety this value is calculated.  For
performance, if the parameters
 +     * themselves are used then retrieve the length from the
getParameters array-
       * @return The current number of elements in the
wsa:ReferenceParameters 
       *         section.
       *
       */
      public int getNumberOfParameters()
      {
 -        return _parameters.getChildNodes().getLength();
 +        return getParameters().length;
      }
      /**
 @@ -497,6 +577,9 @@
       */
      public int hashCode()
      {
 +        // include port number
 +        int port = getAddress().getPort();
 +
          String address = getAddress().getPath();
          Element[] parameters = getParameters();
 @@ -505,7 +588,9 @@
          for (int n = 0; n < parameters.length; ++n)
              paramHashCode += XmlUtils.getHashCode(parameters[n]);
 -        return address.hashCode() + paramHashCode;
 +        String ipAddr = convertHostAddress(getAddress().getHost());
 +                
 +        return port + address.hashCode() + paramHashCode +
ipAddr.hashCode();
      }
      /**
 On Mon 04/28/08 10:33 AM , Chris.Twiner@swisscom.com sent:
 I think it should make 3.0, it seems quite critical and counter 
 intuiative.  I would however like to know if others on this list
agree 
 with the idea before making a jira.  (although logic escapes me as
to 
 why we wouldn't want it ^_^ i've made a lot of nice errors recently
- 
 see the 270 patches's thread context classloader bugs for example -
and 
 I'd prefer a concensus on it)   
 -----Original Message----- 
 From: Eitan Plotnik []  
 Sent: Monday, April 28, 2008 4:30 PM 
 To:  
 Subject: RE: Issue in EndpointReference.equals() method 
 Chris, 
 Do you think this one should be fixed also in official release?
should I 
 file a Jira? 
 Would appreciate if you could please upload a patch once you have
the 
 fix. 
 Thanks, 
 Eitan. 
 Chris.Twiner wrote: 
 >  
 > I agree with the reason: 
 >  
 >         // 
 >         // compare wsa:Address - EXCLUDING the host. this allows
us  
 >         // to compare EPRs that have equivalent IP addresses and  
 >         // machine names/localhost 
 >         // 
 >  
 > given that localhost could also be the machine name and the ip  
 > address, or be multi homed. 
 >  
 > However it seems to be perfectly valid to run the same client
(with  
 > presumably the same url source path) from two seperate machines or
 
 > indeed multiple clients from a single machine. 
 >  
 > Its exceptionally difficult to make hostname lookup work in
general  
 > but I think its a valid enough requirement for the client to
provide a 
 > decent hostname: 
 >  
 > InetAddress addr = InetAddress.getLocalHost(); 
 >  
 > shouldn't be that hard to use. 
 >  
 > And IF need be have a simple rule for "localhost" vs the actual
local  
 > host name and default interface.  For multi-homed servers/clients
its  
 > normal to require them to choose an IP address / hostname. 
 >  
 > Its a simple fix but there may be something I've overlooked. 
 >  
 > PS (thanks for finding this Eitan, I'll certainly be fixing it on
my  
 > local version) 
 >  
 > -----Original Message----- 
 > From: Eitan Plotnik [] 
 > Sent: Monday, April 28, 2008 10:49 AM 
 > To:  
 > Subject: Issue in EndpointReference.equals() method 
 >  
 >  
 > I have a test client registering for notifications. 
 > When I run the client from 2 different machines at the same time, 

 > using the same server, some of the notifications are sent to the
wrong 
 client. 
 >  
 > I noticed that EndpointReference.equals() method explicitly
doesn't  
 > compare the IP address part. 
 >  
 > Does the test client must generate a unique (machine based?  
 > timestamp?) subscriber uri part after the IP address? 
 >  
 > Thanks, 
 > Eitan. 
 > -- 
 > View this message in context: 
 >
http://www.nabble.com/Issue-in-EndpointReference.equals%28%29-method-t

 > p1 
 > 6930964p16930964.html 
 > Sent from the Muse - Dev mailing list archive at Nabble.com. 
 >  
 >  
 >
--------------------------------------------------------------------- 
 > To unsubscribe, e-mail:  
 > For additional commands, e-mail:  
 >  
 >  
 >
--------------------------------------------------------------------- 
 > To unsubscribe, e-mail:  
 > For additional commands, e-mail:  
 >  
 >  
 >  
 -- 
 View this message in context: 

http://www.nabble.com/Issue-in-EndpointReference.equals%28%29-method-tp1

 6930964p16940189.html 
 Sent from the Muse - Dev mailing list archive at Nabble.com. 

--------------------------------------------------------------------- 
 To unsubscribe, e-mail:  
 For additional commands, e-mail:  

--------------------------------------------------------------------- 
 To unsubscribe, e-mail:  
 For additional commands, e-mail:  


Links:
------
[1] http://backport-jsr166.sourceforge.net).

Mime
View raw message