001package ca.uhn.hl7v2.hoh.llp; 002 003import java.io.IOException; 004import java.io.InputStream; 005import java.io.OutputStream; 006import java.nio.charset.Charset; 007 008import ca.uhn.hl7v2.app.TwoPortService; 009import ca.uhn.hl7v2.hoh.api.IAuthorizationClientCallback; 010import ca.uhn.hl7v2.hoh.api.IAuthorizationServerCallback; 011import ca.uhn.hl7v2.hoh.sign.ISigner; 012import ca.uhn.hl7v2.hoh.util.ServerRoleEnum; 013import ca.uhn.hl7v2.llp.HL7Reader; 014import ca.uhn.hl7v2.llp.HL7Writer; 015import ca.uhn.hl7v2.llp.LLPException; 016import ca.uhn.hl7v2.llp.LowerLayerProtocol; 017 018/** 019 * <p> 020 * LowerLayerProtocol implementation which use the HL7 over HTTP specification 021 * as a transport layer. 022 * </p> 023 * 024 * <p> 025 * Note that this implementation has limitations: 026 * <ul> 027 * <li>It will not work on a duel socket server such as {@link TwoPortService} 028 * </ul> 029 * </p> 030 */ 031public class Hl7OverHttpLowerLayerProtocol extends LowerLayerProtocol { 032 033 private IAuthorizationClientCallback myAuthorizationClientCallback; 034 private IAuthorizationServerCallback myAuthorizationServerCallback; 035 private HohLlpReader myNextReader; 036 private HohLlpWriter myNextWriter; 037 private ServerRoleEnum myRole; 038 private ISigner mySigner; 039 private String myUriPath = "/"; 040 private Charset myPreferredCharset; 041 042 public Hl7OverHttpLowerLayerProtocol(ServerRoleEnum theRole) { 043 myRole = theRole; 044 045 if (myRole == null) { 046 throw new NullPointerException("Role can not be null"); 047 } 048 } 049 /** 050 * @return the authorizationClientCallback 051 */ 052 IAuthorizationClientCallback getAuthorizationClientCallback() { 053 return myAuthorizationClientCallback; 054 } 055 056 /** 057 * Provide the authorization callback, if any 058 */ 059 IAuthorizationServerCallback getAuthorizationServerCallback() { 060 return myAuthorizationServerCallback; 061 } 062 063 /** 064 * {@inheritDoc} 065 */ 066 @Override 067 public HL7Reader getReader(InputStream theArg0) throws LLPException { 068 if (myNextReader == null && myNextWriter != null) { 069 myNextWriter = null; 070 throw new LLPException("Hl7OverHttpLowerLayerProtocol can not be used with a multi socket implementation"); 071 } 072 prepareReadersIfNeeded(); 073 HohLlpReader retVal = myNextReader; 074 try { 075 retVal.setInputStream(theArg0); 076 } catch (IOException e) { 077 throw new LLPException("Failed to set stream: " + e.getMessage(), e); 078 } 079 080 myNextReader = null; 081 return retVal; 082 } 083 084 /** 085 * Returns the server role this protocol implementation is being used for 086 */ 087 public ServerRoleEnum getRole() { 088 return myRole; 089 } 090 091 /** 092 * @return The signature profile signer 093 * @see #setSigner(ISigner) 094 */ 095 ISigner getSigner() { 096 return mySigner; 097 } 098 099 /** 100 * @return The URI to use for this LLP implementation 101 * @see #setUriPath(String) 102 */ 103 public String getUriPath() { 104 return myUriPath; 105 } 106 107 /** 108 * {@inheritDoc} 109 */ 110 @Override 111 public HL7Writer getWriter(OutputStream theArg0) throws LLPException { 112 if (myNextReader != null && myNextWriter == null) { 113 myNextReader = null; 114 throw new LLPException("Hl7OverHttpLowerLayerProtocol can not be used with a multi socket implementation"); 115 } 116 prepareReadersIfNeeded(); 117 HohLlpWriter retVal = myNextWriter; 118 retVal.setPreferredCharset(myPreferredCharset); 119 try { 120 retVal.setOutputStream(theArg0); 121 } catch (IOException e) { 122 throw new LLPException("Failed to set stream: " + e.getMessage(), e); 123 } 124 125 myNextWriter = null; 126 return retVal; 127 } 128 129 private void prepareReadersIfNeeded() { 130 if (myNextReader == null && myNextWriter == null) { 131 myNextReader = new HohLlpReader(this); 132 myNextWriter = new HohLlpWriter(this); 133 myNextReader.setWriter(myNextWriter); 134 } 135 } 136 137 /** 138 * Provides an authorization callback for authorizing incoming requests. This method 139 * must only be called of this LLP instance is in {@link ServerRoleEnum#SERVER SERVER} mode. 140 */ 141 public void setAuthorizationCallback(IAuthorizationClientCallback theAuthorizationClientCallback) { 142 if (myRole == ServerRoleEnum.SERVER) { 143 throw new IllegalStateException("This LLP implementation is in CLIENT mode, so it can not use an authorization callback"); 144 } 145 myAuthorizationClientCallback = theAuthorizationClientCallback; 146 } 147 148 /** 149 * Provides an authorization callback for authorizing incoming requests. This method 150 * must only be called of this LLP instance is in {@link ServerRoleEnum#SERVER SERVER} mode. 151 */ 152 public void setAuthorizationCallback(IAuthorizationServerCallback theAuthorizationCallback) { 153 if (myRole == ServerRoleEnum.CLIENT) { 154 throw new IllegalStateException("This LLP implementation is in CLIENT mode, so it can not use an authorization callback"); 155 } 156 myAuthorizationServerCallback = theAuthorizationCallback; 157 } 158 159 /** 160 * @param theSigner The signature profile signer 161 */ 162 public void setSigner(ISigner theSigner) { 163 mySigner = theSigner; 164 } 165 166 /** 167 * The URI path to use for this protocol. The URI path is the portion of the address (URL) which 168 * is being accessed which designates the location on the host (i.e. the "path"). By 169 * default this is set to "/" 170 * 171 * @param theUriPath the uri to set 172 */ 173 public void setUriPath(String theUriPath) { 174 myUriPath = theUriPath; 175 } 176 177 /** 178 * Sets the charset which will be used for any initiated outgoing messages. What this 179 * means is that if a message is sent as a response (e.g. an ACK) using this LLP, 180 * the LLP will ignore the charset provided by this method and will attempt to use 181 * the charset used in the original incoming message. On the other hand, if a new 182 * outgoing message is transmitted using this LLP (i.e. not an ACK), the charset 183 * specified here will be used. 184 */ 185 public void setPreferredCharset(Charset thePreferredCharset) { 186 myPreferredCharset = thePreferredCharset; 187 } 188 189}