diff --git a/org.springframework.web/src/main/java/org/springframework/web/http/server/ServerHttpRequest.java b/org.springframework.web/src/main/java/org/springframework/web/http/server/ServerHttpRequest.java
new file mode 100644
index 0000000000..a47735bc0c
--- /dev/null
+++ b/org.springframework.web/src/main/java/org/springframework/web/http/server/ServerHttpRequest.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2002-2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.web.http.server;
+
+import org.springframework.web.http.HttpInputMessage;
+import org.springframework.web.http.HttpMethod;
+
+/**
+ * Represents a server-side HTTP request.
+ *
+ * @author Arjen Poutsma
+ * @since 3.0
+ */
+public interface ServerHttpRequest extends HttpInputMessage {
+
+ /**
+ * Returns the HTTP method of the request.
+ *
+ * @return the http method
+ */
+ HttpMethod getMethod();
+
+}
diff --git a/org.springframework.web/src/main/java/org/springframework/web/http/server/ServerHttpResponse.java b/org.springframework.web/src/main/java/org/springframework/web/http/server/ServerHttpResponse.java
new file mode 100644
index 0000000000..b3cb770c19
--- /dev/null
+++ b/org.springframework.web/src/main/java/org/springframework/web/http/server/ServerHttpResponse.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2002-2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.web.http.server;
+
+import org.springframework.web.http.HttpOutputMessage;
+import org.springframework.web.http.HttpStatus;
+
+/**
+ * Represents a server-side HTTP response.
+ *
+ * @author Arjen Poutsma
+ * @since 3.0
+ */
+public interface ServerHttpResponse extends HttpOutputMessage {
+
+ /**
+ * Sets the HTTP status code of the response.
+ *
+ * @param status the HTTP status
+ */
+ void setStatusCode(HttpStatus status);
+
+ /**
+ * Closes this response, freeing any resources created.
+ */
+ void close();
+
+}
diff --git a/org.springframework.web/src/main/java/org/springframework/web/http/server/ServletServerHttpRequest.java b/org.springframework.web/src/main/java/org/springframework/web/http/server/ServletServerHttpRequest.java
new file mode 100644
index 0000000000..640d402915
--- /dev/null
+++ b/org.springframework.web/src/main/java/org/springframework/web/http/server/ServletServerHttpRequest.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2002-2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.web.http.server;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Enumeration;
+import javax.servlet.http.HttpServletRequest;
+
+import org.springframework.util.Assert;
+import org.springframework.web.http.HttpHeaders;
+import org.springframework.web.http.HttpMethod;
+
+/**
+ * {@link ServerHttpRequest} implementation that is based on a {@link HttpServletRequest}.
+ *
+ * @author Arjen Poutsma
+ * @since 3.0
+ */
+public class ServletServerHttpRequest implements ServerHttpRequest {
+
+ private final HttpServletRequest servletRequest;
+
+ private HttpHeaders headers;
+
+ /**
+ * Constructs a new instance of the ServletHttpRequest
based on the given {@link HttpServletRequest}
+ *
+ * @param servletRequest the HTTP Servlet request
+ */
+ public ServletServerHttpRequest(HttpServletRequest servletRequest) {
+ Assert.notNull(servletRequest, "'servletRequest' must not be null");
+ this.servletRequest = servletRequest;
+ }
+
+ public HttpMethod getMethod() {
+ return HttpMethod.valueOf(servletRequest.getMethod());
+ }
+
+ public HttpHeaders getHeaders() {
+ if (headers == null) {
+ headers = new HttpHeaders();
+ for (Enumeration headerNames = servletRequest.getHeaderNames(); headerNames.hasMoreElements();) {
+ String headerName = (String) headerNames.nextElement();
+ for (Enumeration headerValues = servletRequest.getHeaders(headerName);
+ headerValues.hasMoreElements();) {
+ String headerValue = (String) headerValues.nextElement();
+ headers.add(headerName, headerValue);
+ }
+ }
+ }
+ return headers;
+ }
+
+ public InputStream getBody() throws IOException {
+ return servletRequest.getInputStream();
+ }
+}
diff --git a/org.springframework.web/src/main/java/org/springframework/web/http/server/ServletServerHttpResponse.java b/org.springframework.web/src/main/java/org/springframework/web/http/server/ServletServerHttpResponse.java
new file mode 100644
index 0000000000..940f12c8dd
--- /dev/null
+++ b/org.springframework.web/src/main/java/org/springframework/web/http/server/ServletServerHttpResponse.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2002-2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.web.http.server;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.List;
+import java.util.Map;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.util.Assert;
+import org.springframework.web.http.HttpHeaders;
+import org.springframework.web.http.HttpStatus;
+
+/**
+ * {@link ServerHttpResponse} implementation that is based on a {@link HttpServletResponse}.
+ *
+ * @author Arjen Poutsma
+ * @since 3.0
+ */
+public class ServletServerHttpResponse implements ServerHttpResponse {
+
+ private final HttpServletResponse servletResponse;
+
+ private final HttpHeaders headers = new HttpHeaders();
+
+ private boolean headersWritten = false;
+
+ /**
+ * Constructs a new instance of the ServletHttpResponse
based on the given {@link HttpServletResponse}
+ *
+ * @param servletResponse the HTTP Servlet response
+ */
+ public ServletServerHttpResponse(HttpServletResponse servletResponse) {
+ Assert.notNull(servletResponse, "'servletResponse' must not be null");
+ this.servletResponse = servletResponse;
+ }
+
+ public void setStatusCode(HttpStatus status) {
+ servletResponse.setStatus(status.value());
+ }
+
+ public HttpHeaders getHeaders() {
+ return headers;
+ }
+
+ public OutputStream getBody() throws IOException {
+ writeHeaders();
+ return servletResponse.getOutputStream();
+ }
+
+ private void writeHeaders() {
+ if (!headersWritten) {
+ for (Map.Entry> entry : headers.entrySet()) {
+ String headerName = entry.getKey();
+ for (String headerValue : entry.getValue()) {
+ servletResponse.addHeader(headerName, headerValue);
+ }
+ }
+ headersWritten = true;
+ }
+ }
+
+ public void close() {
+ writeHeaders();
+ }
+}
diff --git a/org.springframework.web/src/main/java/org/springframework/web/http/server/package.html b/org.springframework.web/src/main/java/org/springframework/web/http/server/package.html
new file mode 100644
index 0000000000..6dd025201f
--- /dev/null
+++ b/org.springframework.web/src/main/java/org/springframework/web/http/server/package.html
@@ -0,0 +1,10 @@
+
+
+
+Contains an abstraction over server-side HTTP. This package
+contains the ServerHttpRequest
and
+ServerHttpResponse
, as well as a Servlet-based implementation of these
+interfaces.
+
+
+
diff --git a/org.springframework.web/src/test/java/org/springframework/web/http/server/ServletHttpRequestTests.java b/org.springframework.web/src/test/java/org/springframework/web/http/server/ServletHttpRequestTests.java
new file mode 100644
index 0000000000..3921338ac8
--- /dev/null
+++ b/org.springframework.web/src/test/java/org/springframework/web/http/server/ServletHttpRequestTests.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2002-2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.web.http.server;
+
+import java.util.List;
+
+import static org.junit.Assert.*;
+import org.junit.Before;
+import org.junit.Test;
+
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.util.FileCopyUtils;
+import org.springframework.web.http.HttpHeaders;
+import org.springframework.web.http.HttpMethod;
+
+/**
+ * @author Arjen Poutsma
+ */
+public class ServletHttpRequestTests {
+
+ private ServletServerHttpRequest request;
+
+ private MockHttpServletRequest mockRequest;
+
+ @Before
+ public void create() throws Exception {
+ mockRequest = new MockHttpServletRequest();
+ request = new ServletServerHttpRequest(mockRequest);
+ }
+
+ @Test
+ public void getMethod() throws Exception {
+ mockRequest.setMethod("POST");
+ assertEquals("Invalid method", HttpMethod.POST, request.getMethod());
+ }
+
+ @Test
+ public void getHeaders() throws Exception {
+ String headerName = "MyHeader";
+ String headerValue1 = "value1";
+ mockRequest.addHeader(headerName, headerValue1);
+ String headerValue2 = "value2";
+ mockRequest.addHeader(headerName, headerValue2);
+
+ HttpHeaders headers = request.getHeaders();
+ assertNotNull("No HttpHeaders returned", headers);
+ assertTrue("Invalid headers returned", headers.containsKey(headerName));
+ List headerValues = headers.get(headerName);
+ assertEquals("Invalid header values returned", 2, headerValues.size());
+ assertTrue("Invalid header values returned", headerValues.contains(headerValue1));
+ assertTrue("Invalid header values returned", headerValues.contains(headerValue2));
+ }
+
+ @Test
+ public void getBody() throws Exception {
+ byte[] content = "Hello World".getBytes("UTF-8");
+ mockRequest.setContent(content);
+
+ byte[] result = FileCopyUtils.copyToByteArray(request.getBody());
+ assertArrayEquals("Invalid content returned", content, result);
+ }
+}
\ No newline at end of file
diff --git a/org.springframework.web/src/test/java/org/springframework/web/http/server/ServletHttpResponseTest.java b/org.springframework.web/src/test/java/org/springframework/web/http/server/ServletHttpResponseTest.java
new file mode 100644
index 0000000000..c4bbbcc49e
--- /dev/null
+++ b/org.springframework.web/src/test/java/org/springframework/web/http/server/ServletHttpResponseTest.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2002-2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.web.http.server;
+
+import java.util.List;
+
+import static org.junit.Assert.*;
+import org.junit.Before;
+import org.junit.Test;
+
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.util.FileCopyUtils;
+import org.springframework.web.http.HttpHeaders;
+import org.springframework.web.http.HttpStatus;
+
+/**
+ * @author Arjen Poutsma
+ */
+public class ServletHttpResponseTest {
+
+ private ServletServerHttpResponse response;
+
+ private MockHttpServletResponse mockResponse;
+
+ @Before
+ public void create() throws Exception {
+ mockResponse = new MockHttpServletResponse();
+ response = new ServletServerHttpResponse(mockResponse);
+ }
+
+ @Test
+ public void setStatusCode() throws Exception {
+ response.setStatusCode(HttpStatus.NOT_FOUND);
+ assertEquals("Invalid status code", 404, mockResponse.getStatus());
+ }
+
+ @Test
+ public void getHeaders() throws Exception {
+ HttpHeaders headers = response.getHeaders();
+ String headerName = "MyHeader";
+ String headerValue1 = "value1";
+ headers.add(headerName, headerValue1);
+ String headerValue2 = "value2";
+ headers.add(headerName, headerValue2);
+
+ response.close();
+ assertTrue("Header not set", mockResponse.getHeaderNames().contains(headerName));
+ List headerValues = mockResponse.getHeaders(headerName);
+ assertTrue("Header not set", headerValues.contains(headerValue1));
+ assertTrue("Header not set", headerValues.contains(headerValue2));
+ }
+
+ @Test
+ public void getBody() throws Exception {
+ byte[] content = "Hello World".getBytes("UTF-8");
+ FileCopyUtils.copy(content, response.getBody());
+
+ assertArrayEquals("Invalid content written", content, mockResponse.getContentAsByteArray());
+ }
+}
\ No newline at end of file