/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with this
* work for additional information regarding copyright ownership. The ASF
* licenses this file to You 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.apache.sling.testing.tools.http;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import org.apache.http.Header;
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
/** Generate RESTful API documentation based on actual requests
* executed during integration tests, enhanced with user-supplied
* bits of documentation.
*/
public class RequestDocumentor {
public static final String OUTPUT_BASE = "./target/" + RequestDocumentor.class.getSimpleName();
private final String name;
public RequestDocumentor(String name) {
this.name = name;
}
public String toString() {
return getClass().getSimpleName() + " (" + name + ")";
}
void generateDocumentation(RequestExecutor executor, String [] metadata) throws IOException {
final File f = getOutputFile();
final File dir = f.getParentFile();
dir.mkdirs();
if(!dir.isDirectory()) {
throw new IOException("Failed to create output folder " + dir.getAbsolutePath());
}
final PrintWriter pw = new PrintWriter(new FileWriter(f, true));
try {
System.out.println("Appending documentation of " + executor + " to " + f.getAbsolutePath());
documentRequest(pw, executor, metadata);
} finally {
pw.flush();
pw.close();
}
}
protected File getOutputFile() {
return new File(OUTPUT_BASE + "/" + name + ".txt");
}
protected void documentRequest(PrintWriter pw, RequestExecutor executor, String [] metadataArray) throws IOException {
// Convert metadata to more convenient Map
final Map<String, String> m = new HashMap<String, String>();
if(metadataArray.length % 2 != 0) {
throw new IllegalArgumentException("Metadata array must be of even size, got " + metadataArray.length);
}
for(int i=0 ; i < metadataArray.length; i += 2) {
m.put(metadataArray[i], metadataArray[i+1]);
}
// TODO use velocity or other templates? Just a rough prototype for now
// Also need to filter overly long input/output, binary etc.
pw.println();
pw.println("====================================================================================");
pw.print("=== ");
pw.print(m.get("title"));
pw.println(" ===");
pw.println(m.get("description"));
pw.print("\n=== ");
pw.print("REQUEST");
pw.println(" ===");
pw.print("Method: ");
pw.println(executor.getRequest().getMethod());
pw.print("URI: ");
pw.println(executor.getRequest().getURI());
final Header [] allHeaders = executor.getRequest().getAllHeaders();
if(allHeaders != null && allHeaders.length > 0) {
pw.println("Headers:");
for(Header h : allHeaders) {
pw.print(h.getName());
pw.print(":");
pw.println(h.getValue());
}
}
if(executor.getRequest() instanceof HttpEntityEnclosingRequestBase) {
final HttpEntityEnclosingRequestBase heb = (HttpEntityEnclosingRequestBase)executor.getRequest();
if(heb.getEntity() != null) {
pw.print("Content-Type:");
pw.println(heb.getEntity().getContentType().getValue());
pw.println("Content:");
final InputStream is = heb.getEntity().getContent();
final byte[] buffer = new byte[16384];
int count = 0;
while( (count = is.read(buffer, 0, buffer.length)) > 0) {
// TODO encoding??
pw.write(new String(buffer, 0, count));
}
pw.println();
}
}
pw.print("\n=== ");
pw.print("RESPONSE");
pw.println(" ===");
pw.print("Content-Type:");
pw.println(executor.getResponse().getEntity().getContentType().getValue());
pw.println("Content:");
pw.println(executor.getContent());
pw.println("====================================================================================");
}
}