/*******************************************************************************
* Copyright (c) 2009, Adobe Systems Incorporated
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Adobe Systems Incorporated nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************/
package com.adobe.dp.epub.web.servlet;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Writer;
import java.net.InetAddress;
import java.net.URL;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import com.adobe.dp.epub.io.OCFContainerWriter;
import com.adobe.dp.epub.io.ZipContainerSource;
import com.adobe.dp.epub.opf.Publication;
import com.adobe.dp.epub.otf.FontEmbeddingReport;
import com.adobe.dp.epub.util.Translit;
import com.adobe.dp.epub.web.font.FontCookieSet;
import com.adobe.dp.epub.web.font.SharedFontSet;
import com.adobe.dp.epub.web.util.Initializer;
import com.adobe.dp.office.conv.DOCXConverter;
import com.adobe.dp.office.word.WordDocument;
import com.adobe.dp.otf.FontLocator;
public class DOCXConverterServlet extends HttpServlet {
public static final long serialVersionUID = 0;
static Logger logger;
static HashSet activeStreams = new HashSet();
static {
Initializer.init();
logger = Logger.getLogger(DOCXConverterServlet.class);
logger.setLevel(Level.ALL);
logger.trace("servlet loaded");
}
void reportError(HttpServletResponse resp, String err) throws IOException {
logger.error(err);
resp.setContentType("text/plain; charset=utf8");
Writer out = resp.getWriter();
out.write(err);
}
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doRequest(false, req, resp);
}
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doRequest(true, req, resp);
}
private void doRequest(boolean post, HttpServletRequest req, HttpServletResponse resp) throws ServletException,
IOException {
String streamIP = null;
ZipContainerSource resources = null;
try {
logger.trace("start " + req.getRemoteAddr());
InputStream docxin = null;
InputStream templatein = null;
FileItem book = null;
FileItem template = null;
boolean translit = false;
boolean useurl = false;
boolean fontReport = false;
String docxurl = null;
File workPath = Initializer.getWorkDir();
String ref = null;
String lang = "en";
workPath.mkdir();
String docxpath = null;
if (post && ServletFileUpload.isMultipartContent(req)) {
DiskFileItemFactory itemFac = new DiskFileItemFactory();
File repositoryPath = Initializer.getUploadDir();
repositoryPath.mkdir();
itemFac.setRepository(repositoryPath);
ServletFileUpload servletFileUpload = new ServletFileUpload(itemFac);
List fileItemList = servletFileUpload.parseRequest(req);
Iterator list = fileItemList.iterator();
while (list.hasNext()) {
FileItem item = (FileItem) list.next();
String t = item.getString();
String paramName = item.getFieldName();
if (paramName.equals("file")) {
if (t.startsWith("http://"))
docxurl = t;
else if (t.length() > 0)
book = item;
} else if (paramName.equals("template")) {
if (t.length() > 0)
template = item;
} else if (paramName.equals("translit"))
translit = t.equals("on") || t.equals("yes");
else if (paramName.equals("fontReport"))
fontReport = t.equals("on") || t.equals("yes");
else if (paramName.equals("useurl"))
useurl = t.equals("on") || t.equals("yes");
else if (paramName.equals("url")) {
if (t.length() > 0)
docxurl = t;
} else if (paramName.equals("ref")) {
ref = item.getString();
} else if (paramName.equals("lang")) {
lang = item.getString();
}
}
if (!useurl && book != null) {
docxin = book.getInputStream();
docxpath = book.getName();
}
if (template != null)
templatein = template.getInputStream();
} else {
docxurl = req.getParameter("url");
String t = req.getParameter("translit");
translit = t != null && (t.equals("on") || t.equals("yes"));
t = req.getParameter("fontReport");
fontReport = t != null && (t.equals("on") || t.equals("yes"));
ref = req.getParameter("ref");
lang = req.getParameter("lang");
}
if (docxin == null) {
if (docxurl == null) {
reportError(resp, "Invalid request: neither docx file nor URL is provided");
return;
}
URL url = new URL(docxurl);
if (!url.getProtocol().equals("http")) {
reportError(resp, "Invalid request: docx URL protocol is not http");
return;
}
docxpath = url.getPath();
String host = url.getHost();
InetAddress ipaddr = InetAddress.getByName(host);
String ipstr = ipaddr.toString();
synchronized (activeStreams) {
if (!activeStreams.contains(ipstr)) {
activeStreams.add(ipstr);
streamIP = ipstr;
}
}
if (streamIP == null) {
reportError(resp, "Only a single connection to the server " + host + " is allowed");
return;
}
logger.info("downloading from " + docxurl);
docxin = url.openStream();
}
File docxtmp = File.createTempFile("docx2epub", "docx", workPath);
FileOutputStream docxout = new FileOutputStream(docxtmp);
byte[] buffer = new byte[8 * 1024];
int len;
while ((len = docxin.read(buffer)) > 0) {
docxout.write(buffer, 0, len);
}
docxout.close();
docxin.close();
if (book != null)
book.delete();
if (docxpath != null) {
if (docxpath.endsWith("/"))
docxpath = docxpath.substring(0, docxpath.length() - 1);
int index = docxpath.lastIndexOf('/');
if (index >= 0)
docxpath = docxpath.substring(index + 1);
index = docxpath.lastIndexOf('\\');
if (index >= 0)
docxpath = docxpath.substring(index + 1);
}
WordDocument doc = new WordDocument(docxtmp);
Publication epub = new Publication();
epub.setTranslit(translit);
epub.useAdobeFontMangling();
DOCXConverter conv = new DOCXConverter(doc, epub);
if (templatein != null) {
if (template != null)
template.delete();
}
FontLocator fontLocator = Initializer.getDefaultFontLocator();
FontCookieSet customFontCookies = new FontCookieSet(req);
SharedFontSet sharedFontSet = SharedFontSet.getInstance();
fontLocator = sharedFontSet.getFontLocator(customFontCookies, fontLocator);
conv.setFontLocator(fontLocator);
resources = new ZipContainerSource(docxtmp);
conv.setWordResources(resources);
conv.convert();
FontEmbeddingReport report = conv.embedFonts();
if (fontReport) {
FontsServlet.reportFonts(resp, report, ref, lang);
} else {
String title = epub.getDCMetadata("title");
String fname;
if (title == null) {
if (docxpath != null) {
fname = docxpath;
if (fname.endsWith(".docx"))
fname = fname.substring(0, fname.length() - 5);
epub.addDCMetadata("title", docxpath);
} else
fname = "book";
} else {
fname = Translit.translit(title).replace(' ', '_').replace('\t', '_').replace('\n', '_').replace(
'\r', '_');
}
resp.setContentType("application/epub+zip");
resp.setHeader("Content-Disposition", "attachment; filename=" + fname + ".epub");
OutputStream out = resp.getOutputStream();
OCFContainerWriter container = new OCFContainerWriter(out);
epub.serialize(container);
}
resources.close();
docxtmp.delete();
} catch (Exception e) {
logger.error("error", e);
reportError(resp, "Internal server error: " + e.toString());
e.printStackTrace();
} catch (Throwable e) {
logger.fatal("error", e);
} finally {
if( resources != null ) {
resources.close();
}
if (streamIP != null) {
synchronized (activeStreams) {
activeStreams.remove(streamIP);
}
}
logger.trace("end");
}
}
}