1 /*
2 * Copyright 2007 the original author or authors.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package org.springframework.ws.transport;
18
19 import java.io.IOException;
20
21 import org.springframework.ws.WebServiceMessage;
22 import org.springframework.ws.WebServiceMessageFactory;
23
24 /**
25 * Abstract base class for {@link WebServiceConnection} implementations.
26 *
27 * @author Arjen Poutsma
28 * @since 1.0.0
29 */
30 public abstract class AbstractWebServiceConnection implements WebServiceConnection {
31
32 private TransportInputStream tis;
33
34 private TransportOutputStream tos;
35
36 private boolean closed = false;
37
38 public final void send(WebServiceMessage message) throws IOException {
39 checkClosed();
40 onSendBeforeWrite(message);
41 tos = createTransportOutputStream();
42 if (tos == null) {
43 return;
44 }
45 message.writeTo(tos);
46 tos.flush();
47 onSendAfterWrite(message);
48 }
49
50 /**
51 * Called before the given message has been written to the <code>TransportOutputStream</code>. Called from {@link
52 * #send(WebServiceMessage)}.
53 * <p/>
54 * Default implementation does nothing.
55 *
56 * @param message the message
57 * @throws IOException when an I/O exception occurs
58 */
59 protected void onSendBeforeWrite(WebServiceMessage message) throws IOException {
60 }
61
62 /**
63 * Returns a <code>TransportOutputStream</code> for the given message. Called from {@link
64 * #send(WebServiceMessage)}.
65 *
66 * @return the output stream
67 * @throws IOException when an I/O exception occurs
68 */
69 protected abstract TransportOutputStream createTransportOutputStream() throws IOException;
70
71 /**
72 * Called after the given message has been written to the <code>TransportOutputStream</code>. Called from {@link
73 * #send(WebServiceMessage)}.
74 * <p/>
75 * Default implementation does nothing.
76 *
77 * @param message the message
78 * @throws IOException when an I/O exception occurs
79 */
80 protected void onSendAfterWrite(WebServiceMessage message) throws IOException {
81 }
82
83 public final WebServiceMessage receive(WebServiceMessageFactory messageFactory) throws IOException {
84 checkClosed();
85 onReceiveBeforeRead();
86 tis = createTransportInputStream();
87 if (tis == null) {
88 return null;
89 }
90 WebServiceMessage message = messageFactory.createWebServiceMessage(tis);
91 onReceiveAfterRead(message);
92 return message;
93 }
94
95 /**
96 * Called before a message has been read from the <code>TransportInputStream</code>. Called from {@link
97 * #receive(WebServiceMessageFactory)}.
98 * <p/>
99 * Default implementation does nothing.
100 *
101 * @throws IOException when an I/O exception occurs
102 */
103 protected void onReceiveBeforeRead() throws IOException {
104 }
105
106 /**
107 * Returns a <code>TransportInputStream</code>. Called from {@link #receive(WebServiceMessageFactory)}.
108 *
109 * @return the input stream, or <code>null</code> if no response can be read
110 * @throws IOException when an I/O exception occurs
111 */
112 protected abstract TransportInputStream createTransportInputStream() throws IOException;
113
114 /**
115 * Called when the given message has been read from the <code>TransportInputStream</code>. Called from {@link
116 * #receive(WebServiceMessageFactory)}.
117 * <p/>
118 * Default implementation does nothing.
119 *
120 * @param message the message
121 * @throws IOException when an I/O exception occurs
122 */
123 protected void onReceiveAfterRead(WebServiceMessage message) throws IOException {
124 }
125
126 public final void close() throws IOException {
127 IOException ioex = null;
128 if (tis != null) {
129 try {
130 tis.close();
131 }
132 catch (IOException ex) {
133 ioex = ex;
134 }
135 }
136 if (tos != null) {
137 try {
138 tos.close();
139 }
140 catch (IOException ex) {
141 ioex = ex;
142 }
143 }
144 onClose();
145 closed = true;
146 if (ioex != null) {
147 throw ioex;
148 }
149 }
150
151 private void checkClosed() {
152 if (closed) {
153 throw new IllegalStateException("Connection has been closed and cannot be reused.");
154 }
155 }
156
157 /**
158 * Template method invoked from {@link #close()}. Default implementation is empty.
159 *
160 * @throws IOException if an I/O error occurs when closing this connection
161 */
162 protected void onClose() throws IOException {
163 }
164
165 }