Initial commit
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 2014 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.restdocs.core;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.PrintStream;
|
||||
|
||||
import org.springframework.restdocs.core.DocumentationWriter.DocumentationAction;
|
||||
|
||||
public abstract class Documentation {
|
||||
|
||||
public static void document(String path, DocumentationAction action) throws Exception {
|
||||
PrintStream printStream = createPrintStream(path);
|
||||
try {
|
||||
DocumentationContext.set(new DocumentationContext(printStream));
|
||||
action.perform();
|
||||
}
|
||||
finally {
|
||||
DocumentationContext.set(null);
|
||||
printStream.close();
|
||||
}
|
||||
}
|
||||
|
||||
private static PrintStream createPrintStream(String name)
|
||||
throws FileNotFoundException {
|
||||
File outputFile = new File(name);
|
||||
if (!outputFile.isAbsolute()) {
|
||||
outputFile = makeAbsolute(outputFile);
|
||||
}
|
||||
outputFile.getParentFile().mkdirs();
|
||||
|
||||
return new PrintStream(new FileOutputStream(outputFile));
|
||||
}
|
||||
|
||||
private static File makeAbsolute(File outputFile) {
|
||||
return new File(new DocumentationProperties().getOutputDir(),
|
||||
outputFile.getPath());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2014 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.restdocs.core;
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
class DocumentationContext {
|
||||
|
||||
private static final InheritableThreadLocal<DocumentationContext> CONTEXTS = new InheritableThreadLocal<DocumentationContext>();
|
||||
|
||||
private final DocumentationWriter writer;
|
||||
|
||||
public DocumentationContext(PrintStream printStream) {
|
||||
this.writer = new DocumentationWriter(printStream);
|
||||
}
|
||||
|
||||
public DocumentationWriter getWriter() {
|
||||
return this.writer;
|
||||
}
|
||||
|
||||
public static DocumentationContext current() {
|
||||
return CONTEXTS.get();
|
||||
}
|
||||
|
||||
static void set(DocumentationContext context) {
|
||||
CONTEXTS.set(context);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 2014 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.restdocs.core;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Properties;
|
||||
|
||||
class DocumentationProperties {
|
||||
|
||||
private final Properties properties = new Properties();
|
||||
|
||||
DocumentationProperties() {
|
||||
this.properties.putAll(System.getProperties());
|
||||
|
||||
InputStream stream = getClass().getClassLoader().getResourceAsStream(
|
||||
"documentation.properties");
|
||||
if (stream != null) {
|
||||
try {
|
||||
this.properties.load(stream);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new IllegalStateException(
|
||||
"Failed to read documentation.properties", ex);
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
stream.close();
|
||||
}
|
||||
catch (IOException e) {
|
||||
// Continue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File getOutputDir() {
|
||||
return new File(this.properties.getProperty(
|
||||
"org.springframework.restdocs.outputDir", "generated-documentation"))
|
||||
.getAbsoluteFile();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright 2014 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.restdocs.core;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
public class DocumentationWriter extends PrintWriter {
|
||||
|
||||
private boolean escapeNewline = false;
|
||||
|
||||
public DocumentationWriter(OutputStream stream) {
|
||||
super(stream, true);
|
||||
}
|
||||
|
||||
public void shellCommand(final DocumentationAction... actions) throws Exception {
|
||||
codeBlock(new DocumentationAction() {
|
||||
|
||||
@Override
|
||||
public void perform() throws Exception {
|
||||
DocumentationWriter.this.print("$ ");
|
||||
DocumentationWriter.this.escapeNewline = true;
|
||||
try {
|
||||
for (DocumentationAction action : actions) {
|
||||
action.perform();
|
||||
}
|
||||
}
|
||||
finally {
|
||||
DocumentationWriter.this.escapeNewline = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(String s) {
|
||||
if (this.escapeNewline) {
|
||||
s = s.replace("\n", "\\\n");
|
||||
}
|
||||
super.write(s);
|
||||
}
|
||||
|
||||
public void codeBlock(DocumentationAction... actions) throws Exception {
|
||||
println();
|
||||
println("----");
|
||||
for (DocumentationAction action : actions) {
|
||||
action.perform();
|
||||
}
|
||||
println("----");
|
||||
println();
|
||||
}
|
||||
|
||||
public interface DocumentationAction {
|
||||
void perform() throws Exception;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2014 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.restdocs.core;
|
||||
|
||||
import java.util.Enumeration;
|
||||
import java.util.Iterator;
|
||||
|
||||
public final class IterableEnumeration<T> implements Iterable<T> {
|
||||
|
||||
private final Enumeration<T> enumeration;
|
||||
|
||||
public IterableEnumeration(Enumeration<T> enumeration) {
|
||||
this.enumeration = enumeration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<T> iterator() {
|
||||
return new Iterator<T>() {
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return IterableEnumeration.this.enumeration.hasMoreElements();
|
||||
}
|
||||
|
||||
@Override
|
||||
public T next() {
|
||||
return IterableEnumeration.this.enumeration.nextElement();
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
public static <T> Iterable<T> iterable(Enumeration<T> enumeration) {
|
||||
return new IterableEnumeration<T>(enumeration);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2014 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.restdocs.core;
|
||||
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.test.web.servlet.request.RequestPostProcessor;
|
||||
|
||||
public abstract class RestDocumentationRequestPostProcessors {
|
||||
|
||||
public static RequestPostProcessor port(final int port) {
|
||||
return new RequestPostProcessor() {
|
||||
|
||||
@Override
|
||||
public MockHttpServletRequest postProcessRequest(
|
||||
MockHttpServletRequest request) {
|
||||
request.setRemotePort(port);
|
||||
request.setServerPort(port);
|
||||
return request;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
public static RequestPostProcessor host(final String host) {
|
||||
return new RequestPostProcessor() {
|
||||
|
||||
@Override
|
||||
public MockHttpServletRequest postProcessRequest(
|
||||
MockHttpServletRequest request) {
|
||||
request.setRemoteHost(host);
|
||||
return request;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,216 @@
|
||||
/*
|
||||
* Copyright 2014 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.restdocs.core;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.io.StringWriter;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.restdocs.core.DocumentationWriter.DocumentationAction;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
import org.springframework.test.web.servlet.ResultHandler;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
|
||||
import static org.springframework.restdocs.core.IterableEnumeration.iterable;
|
||||
|
||||
public abstract class RestDocumentationResultHandlers {
|
||||
|
||||
public static CurlResultHandler documentCurlRequest(String path) {
|
||||
return new CurlResultHandler(path) {
|
||||
@Override
|
||||
public void handle(MvcResult result, DocumentationWriter writer)
|
||||
throws Exception {
|
||||
writer.shellCommand(new CurlRequestDocumentationAction(writer, result,
|
||||
getCurlConfiguration()));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static CurlResultHandler documentCurlResponse(String path) {
|
||||
return new CurlResultHandler(path) {
|
||||
@Override
|
||||
public void handle(MvcResult result, DocumentationWriter writer)
|
||||
throws Exception {
|
||||
writer.codeBlock(new CurlResponseDocumentationAction(writer, result,
|
||||
getCurlConfiguration()));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static CurlResultHandler documentCurlRequestAndResponse(String path) {
|
||||
return new CurlResultHandler(path) {
|
||||
@Override
|
||||
public void handle(MvcResult result, DocumentationWriter writer)
|
||||
throws Exception {
|
||||
writer.shellCommand(new CurlRequestDocumentationAction(writer, result,
|
||||
getCurlConfiguration()));
|
||||
writer.codeBlock(new CurlResponseDocumentationAction(writer, result,
|
||||
getCurlConfiguration()));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static PrintStream createPrintStream(String path)
|
||||
throws FileNotFoundException {
|
||||
File outputFile = new File(path);
|
||||
if (!outputFile.isAbsolute()) {
|
||||
outputFile = makeAbsolute(outputFile);
|
||||
}
|
||||
outputFile.getParentFile().mkdirs();
|
||||
|
||||
return new PrintStream(new FileOutputStream(outputFile));
|
||||
}
|
||||
|
||||
private static File makeAbsolute(File outputFile) {
|
||||
return new File(new DocumentationProperties().getOutputDir(),
|
||||
outputFile.getPath());
|
||||
}
|
||||
|
||||
private static final class CurlRequestDocumentationAction implements
|
||||
DocumentationAction {
|
||||
|
||||
private final DocumentationWriter writer;
|
||||
|
||||
private final MvcResult result;
|
||||
|
||||
private final CurlConfiguration curlConfiguration;
|
||||
|
||||
CurlRequestDocumentationAction(DocumentationWriter writer, MvcResult result,
|
||||
CurlConfiguration curlConfiguration) {
|
||||
this.writer = writer;
|
||||
this.result = result;
|
||||
this.curlConfiguration = curlConfiguration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void perform() throws Exception {
|
||||
MockHttpServletRequest request = this.result.getRequest();
|
||||
this.writer.print(String.format("curl %s://%s:%d%s", request.getScheme(),
|
||||
request.getRemoteHost(), request.getRemotePort(),
|
||||
request.getRequestURI()));
|
||||
|
||||
if (this.curlConfiguration.includeResponseHeaders) {
|
||||
this.writer.print(" -i");
|
||||
}
|
||||
|
||||
RequestMethod requestMethod = RequestMethod.valueOf(request.getMethod());
|
||||
if (requestMethod != RequestMethod.GET) {
|
||||
this.writer.print(String.format(" -X %s", requestMethod.toString()));
|
||||
}
|
||||
|
||||
for (String headerName : iterable(request.getHeaderNames())) {
|
||||
for (String header : iterable(request.getHeaders(headerName))) {
|
||||
this.writer
|
||||
.print(String.format(" -H \"%s: %s\"", headerName, header));
|
||||
}
|
||||
}
|
||||
|
||||
if (request.getContentLengthLong() > 0) {
|
||||
this.writer.print(String.format(" -d '%s'", getContent(request)));
|
||||
}
|
||||
|
||||
this.writer.println();
|
||||
}
|
||||
|
||||
private String getContent(MockHttpServletRequest request) throws IOException {
|
||||
StringWriter writer = new StringWriter();
|
||||
FileCopyUtils.copy(request.getReader(), writer);
|
||||
return writer.toString();
|
||||
}
|
||||
}
|
||||
|
||||
private static final class CurlResponseDocumentationAction implements
|
||||
DocumentationAction {
|
||||
|
||||
private final DocumentationWriter writer;
|
||||
|
||||
private final MvcResult result;
|
||||
|
||||
private final CurlConfiguration curlConfiguration;
|
||||
|
||||
CurlResponseDocumentationAction(DocumentationWriter writer, MvcResult result,
|
||||
CurlConfiguration curlConfiguration) {
|
||||
this.writer = writer;
|
||||
this.result = result;
|
||||
this.curlConfiguration = curlConfiguration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void perform() throws Exception {
|
||||
if (this.curlConfiguration.includeResponseHeaders) {
|
||||
HttpStatus status = HttpStatus.valueOf(this.result.getResponse()
|
||||
.getStatus());
|
||||
this.writer.println(String.format("HTTP/1.1 %d %s", status.value(),
|
||||
status.getReasonPhrase()));
|
||||
for (String headerName : this.result.getResponse().getHeaderNames()) {
|
||||
for (String header : this.result.getResponse().getHeaders(headerName)) {
|
||||
this.writer.println(String.format("%s: %s", headerName, header));
|
||||
}
|
||||
}
|
||||
this.writer.println();
|
||||
}
|
||||
this.writer.println(this.result.getResponse().getContentAsString());
|
||||
}
|
||||
}
|
||||
|
||||
private static class CurlConfiguration {
|
||||
|
||||
private boolean includeResponseHeaders = false;
|
||||
|
||||
}
|
||||
|
||||
public static abstract class CurlResultHandler implements ResultHandler {
|
||||
|
||||
private final CurlConfiguration curlConfiguration = new CurlConfiguration();
|
||||
|
||||
private final String path;
|
||||
|
||||
private CurlResultHandler(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
CurlConfiguration getCurlConfiguration() {
|
||||
return this.curlConfiguration;
|
||||
}
|
||||
|
||||
public CurlResultHandler includeResponseHeaders() {
|
||||
this.curlConfiguration.includeResponseHeaders = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(MvcResult result) throws Exception {
|
||||
PrintStream printStream = createPrintStream(this.path);
|
||||
try {
|
||||
handle(result, new DocumentationWriter(printStream));
|
||||
}
|
||||
finally {
|
||||
printStream.close();
|
||||
}
|
||||
}
|
||||
|
||||
abstract void handle(MvcResult result, DocumentationWriter writer)
|
||||
throws Exception;
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user