/**
* Copyright (C) 2015 Orion Health (Orchestral Development Ltd)
*
* 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 xbdd.webapp.resource.feature;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Random;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.BeanParam;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.QueryParam;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;
import javax.ws.rs.core.StreamingOutput;
import org.apache.commons.io.IOUtils;
import xbdd.webapp.util.Coordinates;
@Path("/rest/pdfreports")
public class PrintPDF {
private static final String XBDD_PHANTOMJS_HOME_INIT_PARAMETER = "xbdd.phantomjs.home";
private static final String XBDD_PHANTOMJS_USERNAME_INIT_PARAMETER = "xbdd.phantomjs.username";
private static final String XBDD_PHANTOMJS_PASSWORD_INIT_PARAMETER = "xbdd.phantomjs.password";
@GET
@Path("/{product}/{major}.{minor}.{servicePack}/{build}/")
public Response viewPDF(@BeanParam final Coordinates coord, @Context final HttpServletRequest request,
@Context final ServletContext context, @QueryParam("view") final String view) throws URISyntaxException {
final String urlcontext = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort()
+ request.getContextPath();
final String previousPage = request.getHeader("Referer");
final String productString = "/" + coord.getProduct() + "/" + coord.getVersionString() + "/" + coord.getBuild();
final String urlstring = urlcontext + "/print/" + productString;
// Getting the location of PHANTOMJS_HOME environment variable
final String phantomjsloc = Objects.toString(context.getInitParameter(XBDD_PHANTOMJS_HOME_INIT_PARAMETER),
System.getProperty("PHANTOMJS_HOME"));
if (phantomjsloc == null) {
final URI location = new URI(previousPage + "&phantom=no");
return Response.temporaryRedirect(location).build();
} else {
final String username = Objects.toString(context.getInitParameter(XBDD_PHANTOMJS_USERNAME_INIT_PARAMETER),
System.getProperty("PHANTOMJS_USER"));
final String password = Objects.toString(context.getInitParameter(XBDD_PHANTOMJS_PASSWORD_INIT_PARAMETER),
System.getProperty("PHANTOMJS_PASSWORD"));
final StreamingOutput stream = createPDFStream(urlstring, phantomjsloc, context.getRealPath("/WEB-INF/rasterize.js"), username,
password);
String viewType = "inline";
// View in browser or download as attachment
if (view != null) {
viewType = view;
}
final ResponseBuilder response = Response.ok(stream);
response.type("application/pdf");
response.status(200);
response.header("Content-Disposition", viewType + "; filename=\"" + coord.getProduct() + " Version=" +
coord.getVersionString() + ", Build=" + coord.getBuild() + ".pdf\"");
return response.build();
}
}
public StreamingOutput createPDFStream(final String urlstring, final String phantomjsloc, final String rasterJsPath,
final String username, final String password) {
final StreamingOutput stream = new StreamingOutput() {
@Override
public void write(final OutputStream os) throws IOException, WebApplicationException {
final File tmpFile = File.createTempFile("report", ".pdf");
final List<String> commands = new ArrayList<String>();
final String osName = System.getProperty("os.name").toLowerCase();
if (osName.indexOf("win") >= 0) {// It's windows
commands.add("CMD");
commands.add("/c");
commands.add(phantomjsloc + "\\phantomjs");
commands.add("--ignore-ssl-errors=yes");
commands.add(rasterJsPath);
commands.add("\"" + urlstring + "\"");
} else {// Assume it's linux
commands.add(phantomjsloc + "/phantomjs");
commands.add("--ignore-ssl-errors=yes");
commands.add(rasterJsPath);
commands.add(urlstring);
}
commands.add(tmpFile.getAbsolutePath());
commands.add(username);
commands.add(password);
generatePDF(commands);
makeStream(tmpFile, os);
tmpFile.delete();
}
};
return stream;
}
public static int randInt(final int min, final int max) {
final Random rand = new Random();
// nextInt is normally exclusive of the top value,
// so add 1 to make it inclusive
final int randomNum = rand.nextInt((max - min) + 1) + min;
return randomNum;
}
public void generatePDF(final List<String> commands) throws IOException {
final ProcessBuilder probuilder = new ProcessBuilder(commands);
probuilder.redirectError();
probuilder.redirectOutput();
probuilder.redirectInput();
final Process process = probuilder.start();
try {
process.waitFor();
} catch (final InterruptedException e) {
e.printStackTrace();
}
process.destroy();
}
public void makeStream(final File tmpFile, final OutputStream os) throws IOException {
try (InputStream inputStream = new FileInputStream(tmpFile);
BufferedOutputStream fos1 = new BufferedOutputStream(os)) {
final byte[] bytes = IOUtils.toByteArray(inputStream);
fos1.write(bytes);
fos1.flush();
}
}
}