1 package ca.uhn.hl7v2.hoh.encoder;
2
3 import static ca.uhn.hl7v2.hoh.util.StringUtils.*;
4
5 import java.io.ByteArrayOutputStream;
6 import java.io.IOException;
7 import java.io.OutputStream;
8 import java.io.OutputStreamWriter;
9 import java.text.DateFormat;
10 import java.text.SimpleDateFormat;
11 import java.util.Date;
12 import java.util.LinkedHashMap;
13 import java.util.Map;
14 import java.util.zip.GZIPOutputStream;
15
16 import ca.uhn.hl7v2.hoh.api.EncodeException;
17 import ca.uhn.hl7v2.hoh.api.ISendable;
18 import ca.uhn.hl7v2.hoh.sign.SignatureFailureException;
19 import ca.uhn.hl7v2.hoh.util.GZipUtils;
20 import ca.uhn.hl7v2.hoh.util.HTTPUtils;
21
22
23
24
25
26 public abstract class AbstractHl7OverHttpEncoder extends AbstractHl7OverHttp {
27
28 private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(AbstractHl7OverHttpEncoder.class);
29 private static DateFormat ourRfc1123DateFormat;
30
31 static {
32 ourRfc1123DateFormat = new SimpleDateFormat("EEE, dd MMM yy HH:mm:ss z");
33 }
34
35 private String myActionLine;
36 private boolean myGzipData;
37 private ISendable<?> mySendable;
38
39
40
41
42 public AbstractHl7OverHttpEncoder() {
43 super();
44 }
45
46
47
48
49
50 public void encode() throws EncodeException {
51 ourLog.trace("Entering encode()");
52 verifyNotUsed();
53
54 if (isBlank(getMessage()) && mySendable == null) {
55 throw new IllegalStateException("Either Message or Sendable must be set");
56 }
57 if (getMessage() != null) {
58 byte[] bytes = getMessage().getBytes(getCharset());
59 if (myGzipData) {
60 try {
61 bytes = GZipUtils.compress(bytes);
62 } catch (IOException e) {
63 throw new EncodeException("Failed to apply GZip coding", e);
64 }
65 }
66 setData(bytes);
67 } else {
68 ByteArrayOutputStream bos = new ByteArrayOutputStream();
69 OutputStream os;
70 if (myGzipData) {
71 try {
72 os = new GZIPOutputStream(bos);
73 } catch (IOException e) {
74 throw new EncodeException("Failed to create GZip encoder", e);
75 }
76 } else {
77 os = bos;
78 }
79
80 OutputStreamWriter w = new OutputStreamWriter(os, getCharset());
81 try {
82 mySendable.writeMessage(w);
83 } catch (IOException e) {
84 throw new EncodeException("Failed to convert message to sendable bytes");
85 }
86 setData(bos.toByteArray());
87 }
88
89 setActionLineAppropriately();
90
91 setHeaders(new LinkedHashMap<String, String>());
92
93 StringBuilder ctBuilder = new StringBuilder();
94 if (mySendable != null) {
95 ctBuilder.append(mySendable.getEncodingStyle().getContentType());
96 } else {
97 ctBuilder.append(EncodingStyle.detect(getMessage()).getContentType());
98 }
99 ctBuilder.append("; charset=");
100 ctBuilder.append(getCharset().name());
101 getHeaders().put("Content-Type", ctBuilder.toString());
102
103 getHeaders().put("Content-Length", Integer.toString(getData().length));
104
105 addSpecificHeaders();
106
107 synchronized (ourRfc1123DateFormat) {
108 getHeaders().put("Date", ourRfc1123DateFormat.format(new Date()));
109 }
110
111 if (getSigner() != null) {
112 try {
113 getHeaders().put(HTTP_HEADER_HL7_SIGNATURE, getSigner().sign(getData()));
114 } catch (SignatureFailureException e) {
115 throw new EncodeException(e);
116 }
117 }
118
119 ourLog.trace("Exiting encode()");
120 }
121
122 public void encodeToOutputStream(OutputStream theOutputStream) throws IOException, EncodeException {
123 encode();
124
125 ourLog.debug("Writing HTTP action: {}", getActionLine());
126
127 OutputStreamWriter w = new OutputStreamWriter(theOutputStream, HTTPUtils.DEFAULT_CHARSET);
128 w.write(getActionLine());
129 w.write("\r\n");
130
131 for (Map.Entry<String, String> next : getHeaders().entrySet()) {
132 ourLog.debug("Writing HTTP header- {}: {}", next.getKey(), next.getValue());
133
134 w.write(next.getKey());
135 w.write(": ");
136 w.write(next.getValue());
137 w.write("\r\n");
138 }
139
140 w.write("\r\n");
141 w.flush();
142
143 ourLog.debug("Writing {} bytes of actual data", getData().length);
144 theOutputStream.write(getData());
145
146 }
147
148
149
150
151 public String getActionLine() {
152 return myActionLine;
153 }
154
155
156
157
158
159 public void setActionLine(String theActionLine) {
160 myActionLine = theActionLine;
161 }
162
163
164
165
166
167 public void setDataProvider(ISendable<?> theSendable) {
168 if (getMessage() != null) {
169 throw new IllegalStateException("Message already provided");
170 }
171 mySendable = theSendable;
172 }
173
174
175
176
177
178 @Override
179 public void setMessage(String theData) {
180 if (mySendable != null) {
181 throw new IllegalStateException("Data provider already provided");
182 }
183 super.setMessage(theData);
184 }
185
186 protected abstract void addSpecificHeaders();
187
188 protected abstract void setActionLineAppropriately();
189
190 boolean isGzipData() {
191 return myGzipData;
192 }
193
194
195
196
197
198
199 void setGzipData(boolean theGzipData) {
200 myGzipData = theGzipData;
201 }
202
203 }