/**
  * Constructs the URL used to obtain meta data for a given document type identifier of a given
  * participant identifier.
  */
 URL constructDocumentTypeURL(
     ParticipantId participantId, PeppolDocumentTypeId documentTypeIdentifier) {
   String scheme = ParticipantId.getScheme();
   String value = participantId.stringValue();
   String hostname = null;
   String urlString = null;
   try {
     hostname = "B-" + Util.calculateMD5(value.toLowerCase()) + "." + scheme + "." + smlHost;
     String encodedParticipant = URLEncoder.encode(scheme + "::" + value, "UTF-8");
     String encodedDocumentId =
         URLEncoder.encode(
             PeppolDocumentTypeIdAcronym.getScheme() + "::" + documentTypeIdentifier.toString(),
             "UTF-8");
     urlString =
         "http://" + hostname + "/" + encodedParticipant + "/services/" + encodedDocumentId;
     return new URL(urlString);
   } catch (MessageDigestException e) {
     throw new IllegalStateException(
         "Unable to calculate message digest for: "
             + participantId
             + ", doc.type:"
             + documentTypeIdentifier,
         e);
   } catch (UnsupportedEncodingException e) {
     throw new IllegalStateException("Unable to encode _" + scheme + "::" + value, e);
   } catch (MalformedURLException e) {
     throw new IllegalArgumentException("Unable to create URL from string:" + urlString, e);
   }
 }
 /**
  * Retrieves an instance of the complete EndpointType for a given participant and the given
  * document type identifier. Given by the following XPath:
  *
  * <pre>
  *     //ServiceMetadata/ServiceInformation/ProcessList/Process[0]/ServiceEndpointList/Endpoint[0]
  * </pre>
  *
  * @param participant the participant identifier
  * @param documentTypeIdentifier the document type identifier
  * @return the JAXB generated EndpointType object
  */
 private EndpointType getEndpointType(
     ParticipantId participant, PeppolDocumentTypeId documentTypeIdentifier) {
   try {
     SignedServiceMetadataType serviceMetadata =
         getServiceMetaData(participant, documentTypeIdentifier);
     return selectOptimalEndpoint(serviceMetadata);
   } catch (Exception e) {
     String pid =
         (participant == null)
             ? "participant missing"
             : "for participant " + participant.toString();
     String did =
         (documentTypeIdentifier == null)
             ? "document type missing"
             : "document type " + documentTypeIdentifier.toString();
     throw new RuntimeException("Problem with SMP lookup " + pid + " and " + did, e);
   }
 }
 /** Provides the end point data required for transmission of a message. */
 @Override
 public PeppolEndpointData getEndpointTransmissionData(
     ParticipantId participantId, PeppolDocumentTypeId documentTypeIdentifier) {
   EndpointType endpointType = getEndpointType(participantId, documentTypeIdentifier);
   String transportProfile = endpointType.getTransportProfile();
   String address = getEndPointUrl(endpointType);
   X509Certificate x509Certificate = getX509CertificateFromEndpointType(endpointType);
   try {
     return new PeppolEndpointData(
         new URL(address),
         BusDoxProtocol.instanceFrom(transportProfile),
         CommonName.valueOf(x509Certificate.getSubjectX500Principal()));
   } catch (Exception e) {
     throw new IllegalStateException(
         "Unable to provide end point data for "
             + participantId
             + " for "
             + documentTypeIdentifier.toString());
   }
 }