package com.appirio.workers.pdf;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import org.apache.commons.lang3.SerializationUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.codehaus.jackson.map.ObjectMapper;
import com.appirio.PDFCombiner;
import com.appirio.PDFCombinerArguments;
import com.appirio.PDFCombinerFile;
import com.appirio.report.Reporter;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.QueueingConsumer;
/**
* @author jesus
*
* This class is calls the pdf combiner and reporter and can be used as a Worker process
* that listens for messages coming from CLOUDAMQP.
*/
public class WorkerProcess {
private final static String QUEUE_NAME = "pdfcombiner";
public static void main(String[] argv) throws Exception {
String uri = System.getenv("CLOUDAMQP_URL");
if (uri == null) uri = "amqp://guest:guest@localhost";
ConnectionFactory factory = new ConnectionFactory();
factory.setUri(uri);
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
System.out.println(" [*] Waiting for messages");
//Logger.debug(" [*] Waiting for messages");
QueueingConsumer consumer = new QueueingConsumer(channel);
channel.basicConsume(QUEUE_NAME, true, consumer);
// main loop waits for queue messages
while (true) {
PDFCombinerArguments pdfCombinerArguments = null;
try {
// get a unique id
String uniqueId = String.valueOf(Calendar.getInstance().getTimeInMillis());
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
byte[] data = delivery.getBody();
pdfCombinerArguments = (PDFCombinerArguments) SerializationUtils.deserialize(data);
System.out.println(" [x] Message received");
// download disclaimer
String disclaimerXmlFilename = "/tmp/disclaimers.xml";
downloadFile(pdfCombinerArguments.getDisclaimerUrl(), pdfCombinerArguments.getSessionId(), disclaimerXmlFilename);
// download shipping instructions
String shippingInstructionsXmlFilename = null;
if(pdfCombinerArguments.isExportToPdf()) {
shippingInstructionsXmlFilename = "/tmp/shippingInstructions" + uniqueId + ".xml";
downloadFile(pdfCombinerArguments.getShippingInstructionsUrl(), pdfCombinerArguments.getSessionId(), shippingInstructionsXmlFilename);
}
//download package summary file
String packageSummaryXmlFilename = "/tmp/packageSummary" + uniqueId + ".xml";
downloadFile(pdfCombinerArguments.getPackageSummaryUrl(), pdfCombinerArguments.getSessionId(), packageSummaryXmlFilename);
// download map panel order preferences
String mapPanelOrderPrefXmlFilename = "/tmp/mapPanelOrderPref" + uniqueId + ".xml";
downloadFile(pdfCombinerArguments.getMapPanelOrderPrefUrl(), pdfCombinerArguments.getSessionId(), mapPanelOrderPrefXmlFilename);
boolean hasLocationMap = hasLocationMapAttachments(pdfCombinerArguments);
// if has contents...
if(pdfCombinerArguments.getContents() != null) {
// iterate over contents
Iterator<PDFCombinerFile> it = pdfCombinerArguments.getContents().iterator();
// while iterator has elements
while (it.hasNext()) {
// get next file
PDFCombinerFile file = it.next();
// format file name
String fileName = "/tmp/" + file.getPathOnClient();
downloadFile(file.getSalesforceUrl(), pdfCombinerArguments.getSessionId(), fileName);
if(fileName.endsWith(".xml")) {
Reporter reporter = new Reporter(fileName, disclaimerXmlFilename, mapPanelOrderPrefXmlFilename, shippingInstructionsXmlFilename, packageSummaryXmlFilename, pdfCombinerArguments.isShowTotalProgramSummary(), pdfCombinerArguments.isShowIndividualMarketSummary(), pdfCombinerArguments.isShowIndividualFlightSummary(), file, pdfCombinerArguments.isExportToPdf(), pdfCombinerArguments.isExportToXls(),pdfCombinerArguments.getAppendixes());
if(pdfCombinerArguments.isExportToXls()) {
// upload file to s3
// TODO: remove when is enabled
//String downloadXlsFileUrl = uploadFileToAmazonS3(reporter.getGeneratedReport("xls"), "xls", pdfCombinerArguments);
// upload to salesforce
String result = uploadFileToSalesforce(reporter.getGeneratedReport("xls"), "xls", pdfCombinerArguments);
// get the id
ObjectMapper mapper = new ObjectMapper(); // can reuse, share globally
Map<String, String> resultJson = mapper.readValue(result, Map.class);
String xlsDocumentId = resultJson.get("id");
System.out.println(" contentId: " + xlsDocumentId);
// open callback url
//openCallbackUrl(pdfCombinerArguments, xlsDocumentId, null);
openCallbackUrl(pdfCombinerArguments, null, xlsDocumentId , "Completed" , "" );
// open callback url
//openCallbackUrl(pdfCombinerArguments, "Ok", "%urlXls%", downloadXlsFileUrl);
// as this xls file is not to be combined using pdf combiner,
// remove from the collection
it.remove();
} else {
file.setFileName(reporter.getGeneratedReport("pdf"));
// set custom toc frm report to combiner arguments
pdfCombinerArguments.setPdfCombinerContentEntryList(reporter.getPDFCombinerContentEntryList());
}
} else {
file.setFileName(fileName);
}
}
}
// if it has appendixes
if(pdfCombinerArguments.getAppendixes() != null) {
List<PDFCombinerFile> appendixes = new ArrayList<PDFCombinerFile>();
for(PDFCombinerFile file : pdfCombinerArguments.getAppendixes()) {
String fileName = "/tmp/" + file.getPathOnClient();
//downloadFile(file.getSalesforceUrl(), pdfCombinerArguments.getSessionId(), fileName);
if(downloadFile(file.getSalesforceUrl(), pdfCombinerArguments.getSessionId(), fileName)){
appendixes.add(file);
}
file.setFileName(fileName);
}
System.out.println(" appendix list size" + pdfCombinerArguments.getAppendixes().size());
System.out.println(" resultant appendix list size" + appendixes.size());
pdfCombinerArguments.setAppendixes(appendixes);
}
// TODO: it will be necessary to export pdf and xls at the same time
if(pdfCombinerArguments.isExportToPdf()) {
// instantiate pdfcombiner and get pdf filename (ephimeral filesystem path)
System.out.println(" combining content");
PDFCombiner combiner = new PDFCombiner();
String pdfFile = combiner.combine(pdfCombinerArguments);
// upload file to s3
// TODO: remove when is enabled
//String downloadFileUrl = uploadFileToAmazonS3(pdfFile, "pdf", pdfCombinerArguments);
// upload pdf to storage service (to avoid ephimeral file being removed)
// TODO: disabled because it is giving error number 500
String result = uploadFileToSalesforce(pdfFile, "pdf", pdfCombinerArguments);
// get the id
ObjectMapper mapper = new ObjectMapper(); // can reuse, share globally
Map readValue = mapper.readValue(result, Map.class);
Map<String, String> resultJson = readValue;
String pdfDocumentId = resultJson.get("id");
System.out.println(" contentId: " + pdfDocumentId);
// open callback url
openCallbackUrl(pdfCombinerArguments, pdfDocumentId, null, "Completed" , "");
}
// send file link by email
//Logger.debug(" sending email message");
//sendMail(pdfFile, "Test message", "apps2biz@gmail.com", pdfCombinerArguments.getRequesterUserEmailAddress());
// debug info
//Logger.debug("Finishing");
//System.out.println(" pdfFile '" + pdfFile + "'");
} catch (Exception ex) {
System.out.println("Exception in WorkerProcess");
ex.printStackTrace();
openCallbackUrl(pdfCombinerArguments, null, null, "Failed", ex.getMessage());
}
}
}
private static boolean hasLocationMapAttachments(PDFCombinerArguments pdfCombinerArguments) {
boolean locationMapExists = false;
// if it has appendixes
if(pdfCombinerArguments.getAppendixes() != null) {
for(PDFCombinerFile file : pdfCombinerArguments.getAppendixes()) {
System.out.println(" appendix attachment url " + file.getSalesforceUrl() );
if(file.getSalesforceUrl() != null) {
if(file.getSalesforceUrl().toLowerCase().contains("sobjects/attachment")) {
locationMapExists = true;
break;
}
}
}
}
return locationMapExists;
}
private static void openCallbackUrl(PDFCombinerArguments pdfCombinerArguments, String pdfOutputUrl, String excelOutputUrl,
String status, String message) throws ClientProtocolException, IOException {
String url = pdfCombinerArguments.getPdfCombinerCallback().getCallbackUrl();
System.out.println("openCallbackUrl(): begin");
HttpClient httpclient = new DefaultHttpClient();
HttpPost httpreq = new HttpPost(url);
httpreq.setHeader("Authorization", "Bearer " + pdfCombinerArguments.getSessionId());
httpreq.setHeader("Content-Type", "application/json");
String jsonSend = pdfCombinerArguments.getPdfCombinerCallback().getCallbackContents();
if(StringUtils.isNotEmpty(pdfOutputUrl)) {
jsonSend = jsonSend.replace("%PDFOutput%", pdfOutputUrl);
}
if(StringUtils.isNotEmpty(excelOutputUrl)) {
jsonSend = jsonSend.replace("%ExcelOutput%", excelOutputUrl);
}
jsonSend = jsonSend.replace("%Status%", status);
jsonSend = jsonSend.replace("%Message%", message);
StringEntity myEntity = new StringEntity(jsonSend);
httpreq.setEntity(myEntity);
HttpResponse response = httpclient.execute(httpreq);
// consume response
//HttpEntity resEntity = response.getEntity();
if(response.getStatusLine().getStatusCode() > 204) {
// could not notify callback url
// TODO: Send email message using an alternate system to salesforce?
}
System.out.println("openCallbackUrl(): end");
}
public static String uploadFileToSalesforce(String sourceFileName,
String fileExtension, PDFCombinerArguments pdfCombinerArguments)
throws MalformedURLException, IOException {
System.out.println("uploadFileToSalesforce(): begin");
FileUploader fileUpload = new FileUploader();
File file = new File(sourceFileName);
String resultingFileName = pdfCombinerArguments.getOutputFileName() + "." + fileExtension;
HashMap<String, String> headerHashMap = new HashMap<String, String>();
headerHashMap.put("Authorization", "Bearer " + pdfCombinerArguments.getSessionId());
headerHashMap.put("Accept", "application/json");
//creeate jsonContent
String jsonContent =
"{" +
" \"Title\" : \"" + pdfCombinerArguments.getTitle() + "\"," +
" \"Description\" : \"" + pdfCombinerArguments.getSubTitle() + "\"," +
" \"FirstPublishLocationId\" : \"" + pdfCombinerArguments.getContentDocumentId() + "\"," +
" \"ReasonForChange\" : \"" + pdfCombinerArguments.getTitle() + "\"," +
" \"PathOnClient\" : \"" + resultingFileName + "\"" +
"}";
String response = fileUpload.executeMultiPartRequest(
pdfCombinerArguments.getInsertContentVersionUrl(),
file,
jsonContent,
headerHashMap);
System.out.println(" response: " + response);
return response;
}
private static boolean downloadFile(String url, String sessionId, String outputFileName) {
System.out.println("downloadFile(): begin");
System.out.println(" url : " + url);
System.out.println(" sessionId : " + sessionId);
System.out.println(" outputFileName: " + outputFileName);
System.out.println(" curl command : curl -H \"Authorization: Bearer " + sessionId + "\" -H \"Accept: application/xml\"" + url);
boolean isSuccess = false;
int size=1024;
InputStream is = null;
OutputStream outStream = null;
URLConnection uCon = null;
try {
URL Url;
byte[] buf;
int ByteRead,ByteWritten=0;
Url= new URL(url);
outStream = new BufferedOutputStream(new FileOutputStream(outputFileName));
uCon = Url.openConnection();
uCon.setRequestProperty("Authorization", "Bearer " + sessionId);
uCon.setRequestProperty("Accept", "application/xml, application/pdf");
is = uCon.getInputStream();
buf = new byte[size];
while ((ByteRead = is.read(buf)) != -1) {
outStream.write(buf, 0, ByteRead);
ByteWritten += ByteRead;
}
System.out.println(" Downloaded Successfully.");
System.out.println(" File name:\""+outputFileName+ "\"\nNo ofbytes :" + ByteWritten);
isSuccess = true;
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
is.close();
outStream.close();
}
catch (Exception e) {
e.printStackTrace();
}
}
return isSuccess;
}
}