001package ca.uhn.hl7v2.hoh.raw.client;
002
003import java.io.IOException;
004import java.net.Socket;
005import java.net.URL;
006
007import ca.uhn.hl7v2.hoh.api.DecodeException;
008import ca.uhn.hl7v2.hoh.api.EncodeException;
009import ca.uhn.hl7v2.hoh.api.IAuthorizationClientCallback;
010import ca.uhn.hl7v2.hoh.api.IClientSimple;
011import ca.uhn.hl7v2.hoh.api.IReceivable;
012import ca.uhn.hl7v2.hoh.api.ISendable;
013import ca.uhn.hl7v2.hoh.api.MessageMetadataKeys;
014import ca.uhn.hl7v2.hoh.auth.SingleCredentialClientCallback;
015import ca.uhn.hl7v2.hoh.raw.api.RawSendable;
016import ca.uhn.hl7v2.hoh.sockets.TlsSocketFactory;
017
018/**
019 * <p>
020 * Simple raw message sender using the HL7 over HTTP specification. This implementation 
021 * makes use of a single connection so it is simple, but may only be used to send
022 * one message at time (per instance).
023 * </p>
024 * <p>
025 * This client uses no external threads, so it is suitable for use within
026 * J2EE containers.
027 * </p>
028 */
029public class HohRawClientSimple extends AbstractRawClient implements IClientSimple {
030
031        private boolean myAutoClose = true;
032        private Socket mySocket;
033
034        /**
035         * Constructor
036         * 
037         * @param theHost
038         *            The HOST (name/address). E.g. "192.168.1.1"
039         * @param thePort
040         *            The PORT. E.g. "8080"
041         * @param theUriPath
042         *            The URI path being requested (must either be blank or start with
043         *            '/' and contain a path). E.g. "/Apps/Receiver.jsp"
044         */
045        public HohRawClientSimple(String theHost, int thePort, String theUriPath) {
046                super(theHost, thePort, theUriPath);
047        }
048
049        /**
050         * {@inheritDoc}
051         */
052        @Override
053        public synchronized IReceivable<String> sendAndReceive(ISendable<?> theMessageToSend) throws DecodeException, IOException, EncodeException {
054                // **** Overridden to add synchronization
055                return super.sendAndReceive(theMessageToSend);
056        }
057
058        /**
059         * Constructor
060         * 
061         * @param theUrl
062         *            The URL to connect to
063         */
064        public HohRawClientSimple(URL theUrl) {
065                super(theUrl);
066        }
067
068        /**
069         * {@inheritDoc}
070         */
071        public void close() {
072                if (mySocket != null) {
073                        closeSocket(mySocket);
074                }
075        }
076
077        /**
078         * {@inheritDoc}
079         */
080        public boolean isAutoClose() {
081                return myAutoClose;
082        }
083
084        /* (non-Javadoc)
085         * @see ca.uhn.hl7v2.hoh.raw.client.IClientSimple#isConnected()
086         */
087        public boolean isConnected() {
088                return isSocketConnected(mySocket);
089        }
090
091
092        /**
093         * {@inheritDoc}
094         */
095        @Override
096        protected Socket provideSocket() throws IOException {
097                if (mySocket == null || mySocket.isClosed() || mySocket.isInputShutdown() || mySocket.isOutputShutdown()) {
098                        mySocket = connect();
099                }
100                return mySocket;
101        }
102
103        /**
104         * {@inheritDoc}
105         */
106        @Override
107        protected void returnSocket(Socket theSocket) {
108                if (isAutoClose()) {
109                        close();
110                }
111        }
112
113        /**
114         * {@inheritDoc}
115         */
116        public void setAutoClose(boolean theAutoClose) {
117                myAutoClose = theAutoClose;
118        }
119
120        public static void main(String[] args) {
121
122                /*
123                 * http://localhost:8080/AppContext
124                 */
125                String host = "localhost";
126                int port = 8080;
127                String uri = "/AppContext";
128
129                // Create a client
130                HohRawClientSimple client = new HohRawClientSimple(host, port, uri);
131
132                // Set the socket factory to use TLS
133                client.setSocketFactory(new TlsSocketFactory());
134
135                // Optionally, if credentials should be sent, they
136                // can be provided using a credential callback
137                IAuthorizationClientCallback authCalback = new SingleCredentialClientCallback("ausername", "somepassword");
138                client.setAuthorizationCallback(authCalback);
139
140                // The ISendable defines the object that provides the actual
141                // message to send
142                String message = "MSH|^~\\&|||||200803051508||ADT^A31|2|P|2.5\r" + "EVN||200803051509\r" + "PID|||ZZZZZZ83M64Z148R^^^SSN^SSN^^20070103\r";
143                ISendable<?> sendable = new RawSendable(message);
144
145                try {
146                        // sendAndReceive actually sends the message
147                        IReceivable<String> receivable = client.sendAndReceive(sendable);
148
149                        // receivavle.getRawMessage() provides the response
150                        System.out.println("Response was:\n" + receivable.getMessage());
151
152                        // IReceivable also stores metadata about the message
153                        String remoteHostIp = (String) receivable.getMetadata().get(MessageMetadataKeys.REMOTE_HOST_ADDRESS);
154                        System.out.println("From:\n" + remoteHostIp);
155
156                } catch (DecodeException e) {
157                        // Thrown if the response can't be read
158                        e.printStackTrace();
159                } catch (IOException e) {
160                        // Thrown if communication fails
161                        e.printStackTrace();
162                } catch (EncodeException e) {
163                        // Thrown if the message can't be encoded (generally a programming
164                        // bug)
165                        e.printStackTrace();
166                }
167
168        }
169
170}