package com.fs.pxe.bpel.dd;

import com.fs.pxe.bpel.o.OPartnerLink;
import com.fs.pxe.bpel.o.OProcess;
import com.fs.utils.DOMUtils;
import com.fs.utils.Namespaces;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;

import java.net.MalformedURLException;
import java.net.URL;

/**
 * Validates endpoint references declared in a deployment descriptor.
 */
public class EndpointValidator implements DDValidator {

  public void validate(TDeploymentDescriptor dd, OProcess oprocess) throws DDValidationException {
    // Validating that endpoints are declared on existing partner links
    if (dd.getEndpointRefs() != null) {
      for (TDeploymentDescriptor.EndpointRefs.EndpointRef epr : dd.getEndpointRefs().getEndpointRefList()) {
        boolean found = false;
        for (OPartnerLink plink : oprocess.getAllPartnerLinks()) {
          if (epr.getPartnerLinkName().equals(epr.getPartnerLinkName())
                  && plink.hasPartnerRole() && epr.getPartnerLinkRole().equals(TRoles.PARTNER_ROLE))
            found = true;
          if (epr.getPartnerLinkName().equals(epr.getPartnerLinkName())
                  && plink.hasMyRole() && epr.getPartnerLinkRole().equals(TRoles.MY_ROLE))
            found = true;
        }
        if (found) {
          validateEndpoint((Element) epr.getDomNode());
        } else throw new DDValidationException("Partner link " + epr.getPartnerLinkName() +
                  " could not be found with specified role in process definition.");
      }
    }
  }

  private void validateEndpoint(Element eprElmt) throws DDValidationException {
    Element root = DOMUtils.getFirstChildElement(eprElmt);
    String url = null;
    if (root == null) {
      throw new DDValidationException("Only soap:address elements or a wsa:Address element is accepted " +
              "as a valid endpoint in deployment descriptor.");
    } else if (root.getLocalName().equals("address")
            && root.getNamespaceURI().equals("http://schemas.xmlsoap.org/wsdl/soap/")) {
      url = root.getAttribute("location");
    } else if (root.getLocalName().equals("EndpointReference")
              && root.getNamespaceURI().equals(Namespaces.WS_ADDRESSING_NS)) {
      NodeList address = root.
              getElementsByTagNameNS(Namespaces.WS_ADDRESSING_NS, "Address");
      if (address.getLength() == 0)
        throw new DDValidationException("A WS-Addressing EndpointReference must enclose " +
                "a wsa:Address element.");
      url = "";
      for (int m = 0; m < address.item(0).getChildNodes().getLength(); m++) {
        Node txtNode = address.item(0).getChildNodes().item(m);
        if (txtNode.getNodeType() == Node.TEXT_NODE) {
          String txt = ((Text)txtNode).getWholeText();
          if (txt.trim().length() > 0) url = url + txt;
        }
      }
    }

    try {
      new URL(url);
    } catch (MalformedURLException e) {
      throw new DDValidationException("URL " + root.getAttribute("location") + " declared as endpoint reference " +
              "in deployment descriptor isn't a valid URL.");
    }
  }

}

@@ -2862,18 +2862,324 @@
  %7D%0A    %7D
-%0A%0A
+ else if (root.getLocalName().equals(%22end-point-reference%22)%0A            && root.getNamespaceURI().equals( Namespaces.JBI_END_POINT_REFERENCE)) %7B%0A      String serviceName = root.getAttribute(%22service-name%22);%0A      String endpointName = root.getAttribute(%22end-point-name%22);%0A    %7D%0A%0A    if ( url != null ) %7B%0A    
     try 
@@ -3180,16 +3180,20 @@
   try %7B%0A
+    
       ne
@@ -3208,16 +3208,20 @@
 l);%0A    
+  
+  
 %7D catch 
@@ -3244,24 +3244,28 @@
 eption e) %7B%0A
+    
       throw 
@@ -3382,16 +3382,20 @@
         
+    
 %22in depl
@@ -3430,24 +3430,34 @@
 lid URL.%22);%0A
+        %7D%0A
     %7D%0A  %7D%0A%0A%7D

Allow JBI endpoints