private InputSource fetchContentsOfSmpUrl(
     ParticipantId participant, PeppolDocumentTypeId documentTypeIdentifier, URL smpUrl)
     throws SmpSignedServiceMetaDataException {
   InputSource smpContents;
   try {
     Log.debug("Constructed SMP url: " + smpUrl.toExternalForm());
     smpContents = smpContentRetriever.getUrlContent(smpUrl);
   } catch (Exception e) {
     throw new SmpSignedServiceMetaDataException(participant, documentTypeIdentifier, smpUrl, e);
   }
   return smpContents;
 }
 /**
  * Produces the endpoint URL for the supplied participant and document type identifier.
  *
  * @param participant identifies the participant for which we are performing a lookup
  * @param documentTypeIdentifier the document type identifier, which constitutes the second half
  *     of the lookup key.
  * @return The endpoint address for the participant and DocumentId
  * @throws RuntimeException If the end point address cannot be resolved for the participant. This
  *     is caused by a {@link java.net.UnknownHostException}
  */
 @Override
 public URL getEndpointAddress(
     ParticipantId participant, PeppolDocumentTypeId documentTypeIdentifier) {
   EndpointType endpointType = getEndpointType(participant, documentTypeIdentifier);
   String address = getEndPointUrl(endpointType);
   Log.info("Found endpoint address for " + participant.stringValue() + " from SMP: " + address);
   try {
     return new URL(address);
   } catch (Exception e) {
     throw new RuntimeException("SMP returned invalid URL", e);
   }
 }
  /**
   * Retrieves a group of URLs representing the documents accepted by the given participant id
   *
   * @param participantId participant id to look up
   * @return list of URLs representing each document type accepted
   */
  @Override
  public List<PeppolDocumentTypeId> getServiceGroups(ParticipantId participantId)
      throws SmpLookupException, ParticipantNotRegisteredException {

    // Creates the URL for the service meta data for the supplied participant
    URL serviceGroupURL = constructServiceGroupURL(participantId);

    if (!isParticipantRegistered(serviceGroupURL)) {
      throw new ParticipantNotRegisteredException(participantId);
    }

    NodeList nodes;
    List<PeppolDocumentTypeId> result = new ArrayList<PeppolDocumentTypeId>();
    InputSource smpContents;

    /*
    When looking up ParticipantId("9908:976098897") we expected the SML not
    to resolve, but it actually did and we got a not found (HTTP 404) response
    from SMP instead (smp-basware.publisher.sml.peppolcentral.org).
    */
    try {
      smpContents = smpContentRetriever.getUrlContent(serviceGroupURL);
    } catch (ConnectionException ex) {
      if (404 == ex.getCode()) {
        // signal that we got a NOT FOUND for that participant in the SMP
        throw new ParticipantNotRegisteredException(participantId);
      } else {
        throw ex; // re-throw exception
      }
    }

    // Parses the XML response from the SMP
    try {

      DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
      documentBuilderFactory.setNamespaceAware(true);
      DocumentBuilder documentBuilder;
      Document document;

      documentBuilder = documentBuilderFactory.newDocumentBuilder();
      document = documentBuilder.parse(smpContents);

      // Locates the namespace URI of the root element
      String nameSpaceURI = document.getDocumentElement().getNamespaceURI();
      nodes = document.getElementsByTagNameNS(nameSpaceURI, "ServiceMetadataReference");

    } catch (Exception e) {
      throw new SmpLookupException(participantId, serviceGroupURL, e);
    }

    // Loop the SMR elements, if any, and populate the result list
    if (nodes != null) {
      for (int i = 0; i < nodes.getLength(); i++) {
        String docTypeAsString = null;
        try {

          // Fetch href attribute
          Element element = (Element) nodes.item(i);
          String hrefAsString = element.getAttribute("href");

          // Gets rid of all the funny %3A's...
          hrefAsString = URLDecoder.decode(hrefAsString, "UTF-8");

          // Grabs the entire text string after "busdox-docid-qns::"
          docTypeAsString =
              hrefAsString.substring(
                  hrefAsString.indexOf("busdox-docid-qns::") + "busdox-docid-qns::".length());

          // Parses and creates the document type id
          PeppolDocumentTypeId peppolDocumentTypeId = PeppolDocumentTypeId.valueOf(docTypeAsString);

          result.add(peppolDocumentTypeId);

        } catch (Exception e) {
          /* ignore unparseable document types at runtime */
          Log.warn(
              "Unable to create PeppolDocumentTypeId from "
                  + docTypeAsString
                  + ", got exception "
                  + e.getMessage());
        }
      }
    }

    return result;
  }