docs: public int createAndSendURLMessage(String strMessageTransport, MessageDetailTarget recMessageDetailTarget, String strURL, Map<String,Object> properties)
      {
          String strBaseURL = strURL;
          URL url = this.getTask().getApplication().getResourceURL(strURL, null);
          strURL = url.toString();
          if ((this.getRecordOwner() != null)
              && (this.getRecordOwner().getProperty(DBParams.BASE_URL) != null))
                  strBaseURL = this.getRecordOwner().getProperty(DBParams.BASE_URL);
          else if (strURL.indexOf(strBaseURL) > 0)   // Make sure the xsl processor creates all the links with a full URL (since emails, etc probably need full URLs)
              strBaseURL = strURL.substring(0, strURL.indexOf(strBaseURL));
          else
              strBaseURL = null;
          if (strBaseURL != null)
              strURL = Utility.addURLParam(strURL, DBParams.BASE_URL, strBaseURL);
          
          // Now, transfer the URL data to the file or this string.
          String strMessage = Utility.transferURLStream(strURL, null);
          
          if ((strMessage != null) && (strMessage.length() > 0))
          {   // Note: properties include SEND_BY and DESTINATION
              if (properties == null)
                  properties = new Hashtable<String, Object>();
              Utility.parseArgs(properties, strURL);
              
              if (strMessage != null)
                  if (strMessage.startsWith("%PDF"))
                      if (properties.get("content-type") == null)
                          properties.put("content-type", "application/pdf");
          
              BaseMessage message = null;
              // First see if the use specifies a specific message
              TrxMessageHeader trxMessageHeader = null;
              MessageProcessInfo recMessageProcessInfo = this;
              if (recMessageProcessInfo.getEditMode() != DBConstants.EDIT_CURRENT)
              {   // If not, try to look up the correct message
                  String strMessageInfoType = MessageInfoType.REQUEST;
                  String strContactType = null; 
                  if (recMessageDetailTarget instanceof Record) // Usually
                      strContactType = ((Record)recMessageDetailTarget).getTableNames(false);
                  String strRequestType = RequestType.MANUAL;
                  String strMessageProcessType = MessageType.MESSAGE_OUT;
                  String strProcessType = ProcessType.INFO;
                  recMessageProcessInfo = (MessageProcessInfo)this.getMessageProcessInfo(strMessageInfoType, strContactType, strRequestType, strMessageProcessType, strProcessType);
              }
              if (recMessageProcessInfo != null)
                  if (recMessageProcessInfo.getEditMode() == DBConstants.EDIT_CURRENT)
              {
                  trxMessageHeader = recMessageProcessInfo.createProcessMessageHeader(recMessageDetailTarget, strMessageTransport);
                  if (trxMessageHeader.getMessageHeaderMap() == null)
                      trxMessageHeader.setMessageHeaderMap(properties);
                  else
                      trxMessageHeader.getMessageHeaderMap().putAll(properties); // These params override read params
                  message = BaseMessage.createMessage(trxMessageHeader);
              }
              if (message == null)
              {   // If all else fails, just create a manual message.
                  if (trxMessageHeader == null)
                      trxMessageHeader = new TrxMessageHeader(this, properties);
                  message = new ManualMessage(trxMessageHeader, strMessage);
              }
              else
                  message.put(ManualMessage.MESSAGE_PARAM, strMessage);  // The physical message
              if (trxMessageHeader.get(TrxMessageHeader.MESSAGE_PROCESSOR_CLASS) == null)
                  trxMessageHeader.put(TrxMessageHeader.MESSAGE_PROCESSOR_CLASS, BaseMessageOutProcessor.class.getName());   // Default processor
              
              if ((trxMessageHeader.get(TrxMessageHeader.DESTINATION_PARAM) == null) && (message.get(TrxMessageHeader.DESTINATION_PARAM) == null))
                  return this.getTask().setLastError(this.getTask().getString("No destination address in message"));
          
              MessageManager messageManager = ((Application)this.getTask().getApplication()).getMessageManager();
              if (messageManager != null)
                  messageManager.sendMessage(message);
          }
          return DBConstants.NORMAL_RETURN;
      }