package lb.signbook.service.application.libreoffice; import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; import java.net.URI; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; 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.io.FileUtils; import org.apache.commons.io.IOUtils; import org.coin.util.HttpUtil; import org.json.JSONArray; import org.json.JSONObject; import com.sun.star.beans.PropertyValue; import com.sun.star.beans.XPropertySet; import com.sun.star.bridge.UnoUrlResolver; import com.sun.star.bridge.XUnoUrlResolver; import com.sun.star.comp.helper.Bootstrap; import com.sun.star.frame.XComponentLoader; import com.sun.star.frame.XStorable; import com.sun.star.lang.XComponent; import com.sun.star.lang.XMultiComponentFactory; import com.sun.star.uno.UnoRuntime; import com.sun.star.uno.XComponentContext; import com.sun.star.util.XReplaceDescriptor; import com.sun.star.util.XReplaceable; @WebServlet(value="/restful/libreoffice/transformation", loadOnStartup=0) public class LibreOfficeTransformationServlet extends HttpServlet { private static final long serialVersionUID = 1L; public static DiskFileItemFactory factory = new DiskFileItemFactory(); public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException { try { HashMap hashMap = new HashMap(); JSONObject parameters = null; InputStream inputStream = null; String fileName = ""; FileItem fileItem = null; Iterator iter = HttpUtil.getItemList(request); while (iter.hasNext()) { FileItem itemField = (FileItem) iter.next(); if (itemField.isFormField() ) { hashMap.put(itemField.getFieldName(), itemField.getString()) ; System.out.println(itemField.getFieldName() + " : " + itemField.getString()); if ("parameters".equals(itemField.getFieldName())) { parameters = new JSONObject(itemField.getString()); } if ("fileName".equals(itemField.getFieldName())) { fileName = itemField.getString(); } } else { fileItem = itemField; inputStream = itemField.getInputStream(); } } switch (parameters.getString("action")) { case "replace": replaceAction(parameters, response, inputStream, fileName); break; case "convert": saveAsAction(parameters, response, inputStream, fileName); break; default: break; } inputStream.close(); fileItem.delete(); } catch (Exception e) { e.printStackTrace(); } } public synchronized void replaceAction( JSONObject parameters, HttpServletResponse response, InputStream inputStream, String fileName) throws Exception { OutputStream out; String fileExtension = com.google.common.io.Files.getFileExtension(fileName); Path inPath = Files.createTempFile("lo_in_", "docToBeTransformed." + fileExtension); try (FileOutputStream fos = new FileOutputStream(inPath.toFile())) { IOUtils.copy(inputStream, fos); } String[] findText = {}, replaceText = {}; ArrayList findTextArrayList = new ArrayList(); ArrayList replaceTextArrayList = new ArrayList(); JSONArray parametersArray = parameters.getJSONArray("parameters"); for (int i = 0; i < parametersArray.length(); i++) { findTextArrayList.add(i, parametersArray.getJSONObject(i).getString("findText")); replaceTextArrayList.add(i, parametersArray.getJSONObject(i).getString("replaceText")); } findText = findTextArrayList.toArray(new String[]{}); replaceText = replaceTextArrayList.toArray(new String[]{}); // example remplacer #date# /* * { * action : 'replace', * parameters : [{ * findText : '#date#', * replaceText : '12/03/2014' * }, { * ... * }] * } */ XComponent document = initializeLibreOfficeService(inPath.toUri()); replaceText(document, findText, replaceText); try (InputStream is = FileUtils.openInputStream(inPath.toFile())) { out = response.getOutputStream(); response.setContentType("application/octet-stream"); response.setHeader("Cache-Control", ""); response.setHeader("Pragma", ""); response.setHeader("Expires", ""); response.setHeader("Content-Disposition", "attachment; filename=\"" + inPath.toFile().getName() + "\""); IOUtils.copy(is, out); out.flush(); } inPath.toFile().delete(); } public synchronized void saveAsAction( JSONObject parameters, HttpServletResponse response, InputStream inputStream, String fileName) throws Exception { OutputStream out; JSONArray parametersArray = parameters.getJSONArray("parameters"); String filterName = parametersArray.getJSONObject(0).getString("filterName"); JSONObject filterData = null; try { filterData = parametersArray.getJSONObject(0).getJSONObject("filterData"); } catch (Exception e) {} String fileExtension = com.google.common.io.Files.getFileExtension(fileName); Path inPath = Files.createTempFile("lo_in_", "docToBeTransformed." + fileExtension); Path outPath = Files.createTempFile("lo_out_", "docTransformed." + getFileExtension(filterName)); try (FileOutputStream fos = new FileOutputStream(inPath.toFile())) { IOUtils.copy(inputStream, fos); } XComponent document = initializeLibreOfficeService(inPath.toUri()); saveAs(document, outPath.toUri(), filterName, filterData); try (InputStream is = FileUtils.openInputStream(outPath.toFile())) { out = response.getOutputStream(); response.setContentType("application/octet-stream"); response.setHeader("Cache-Control", ""); response.setHeader("Pragma", ""); response.setHeader("Expires", ""); response.setHeader("Content-Disposition", "attachment; filename=\"" + outPath.toFile().getName() + "\""); IOUtils.copy(is, out); out.flush(); } inPath.toFile().delete(); outPath.toFile().delete(); } public XComponent initializeLibreOfficeService(URI path) throws Exception { System.out.println("xcomponentcontext"); XComponentContext xcomponentcontext = Bootstrap .createInitialComponentContext(null); // create a connector, so that it can contact the office System.out.println("urlResolver"); XUnoUrlResolver urlResolver = UnoUrlResolver.create(xcomponentcontext); System.out.println("initialObject"); Object initialObject = urlResolver .resolve("uno:socket,host=localhost,port=8100;urp;StarOffice.ServiceManager"); System.out.println("xOfficeFactory"); XMultiComponentFactory xOfficeFactory = (XMultiComponentFactory) UnoRuntime .queryInterface(XMultiComponentFactory.class, initialObject); // retrieve the component context as property (it is not yet exported // from the office) // Query for the XPropertySet interface. XPropertySet xProperySet = (XPropertySet) UnoRuntime.queryInterface( XPropertySet.class, xOfficeFactory); // Get the default context from the office server. Object oDefaultContext = xProperySet.getPropertyValue("DefaultContext"); // Query for the interface XComponentContext. XComponentContext xOfficeComponentContext = (XComponentContext) UnoRuntime .queryInterface(XComponentContext.class, oDefaultContext); XMultiComponentFactory xServiceManager = xOfficeComponentContext .getServiceManager(); String available = (xServiceManager != null ? "available" : "not available"); System.out.println("remote ServiceManager is " + available); // get an instance of the remote office desktop UNO service Object desktop = xServiceManager.createInstanceWithContext( "com.sun.star.frame.Desktop", xOfficeComponentContext); // query the XComponentLoader interface from the desktop XComponentLoader xComponentLoader = (XComponentLoader) UnoRuntime.queryInterface( XComponentLoader.class, desktop ); // load a spreadsheet document //String loadURL = "private:factory/scalc"; // String loadURL = "file:///" + path.replace("\\", "/"); // "D:/test/CS-Convocation%20entretien%20-%20%23date%23.docx"; PropertyValue propertyValue[]=new PropertyValue[2]; propertyValue[0]=new PropertyValue(); propertyValue[0].Name="Hidden"; propertyValue[0].Value=Boolean.valueOf(true); propertyValue[1]=new PropertyValue(); propertyValue[1].Name="UpdateDocMode"; propertyValue[1].Value="1"; XComponent document = xComponentLoader.loadComponentFromURL(path.toString(), "_blank", 0, propertyValue); return document; } /** * @see http://www.oooforum.org/forum/viewtopic.phtml?t=3549 * @see https://gist.github.com/six519/28802627584b21ba1f6a * @see https://wiki.openoffice.org/wiki/API/Tutorials/PDF_export */ public static String getFileExtension(String filterName) { String extension = ""; switch (filterName) { case "MS Excel 97": extension = "xls"; break; case "MS Word 97": extension = "doc"; break; case "MS Word 2007 XML": extension = "docx"; break; case "Rich Text Format": extension = "rtc"; break; case "Text": extension = "txt"; break; case "XHTML File": extension = "xhtml"; break; case "writer_pdf_Export": extension = "pdf"; break; case "impress8": extension = "odt"; break; } return extension; } public static void replaceText( XComponent xTextDocument, String findText[], String replaceText[]) throws Exception { XReplaceDescriptor xReplaceDescr = null; //XSearchDescriptor xSearchDescriptor = null; XReplaceable xReplaceable = null; xReplaceable = (XReplaceable) UnoRuntime.queryInterface( com.sun.star.util.XReplaceable.class, xTextDocument); // You need a descriptor to set properies for Replace xReplaceDescr = xReplaceable.createReplaceDescriptor(); System.out.println("Change all occurrences of ..."); for( int iArrayCounter = 0; iArrayCounter < findText.length; iArrayCounter++ ) { System.out.println(findText[iArrayCounter] + " -> " + replaceText[iArrayCounter]); // Set the properties the replace method need xReplaceDescr.setSearchString(findText[iArrayCounter]); xReplaceDescr.setReplaceString(replaceText[iArrayCounter]); // Replace all words xReplaceable.replaceAll( xReplaceDescr ); } XStorable xStorable=(XStorable)UnoRuntime.queryInterface(XStorable.class,xTextDocument); xStorable.store(); XComponent xcomponent=(XComponent)UnoRuntime.queryInterface(XComponent.class,xStorable); xcomponent.dispose(); } public static void saveAs( XComponent xTextDocument, URI fileOut, String filterName, JSONObject filterData) throws Exception { XStorable xStorable=(XStorable)UnoRuntime.queryInterface(XStorable.class,xTextDocument); int parameterCount = 2; PropertyValue[] outputOpts = null; if (filterName.equals("writer_pdf_Export")) { int SelectPdfVersion = 0; if (filterData != null) { SelectPdfVersion = filterData.getInt("SelectPdfVersion"); } outputOpts = new PropertyValue[1]; outputOpts[0] = new PropertyValue(); outputOpts[0].Name = "SelectPdfVersion"; outputOpts[0].Value = SelectPdfVersion; parameterCount = 3; } PropertyValue[] propertyvalue = new PropertyValue[parameterCount]; propertyvalue[0] = new PropertyValue(); propertyvalue[0].Name = "Overwrite"; propertyvalue[0].Value = new Boolean(true); propertyvalue[1] = new PropertyValue(); propertyvalue[1].Name = "FilterName"; propertyvalue[1].Value = filterName != null ? filterName : "writer_pdf_Export"; if (outputOpts != null) { propertyvalue[2] = new PropertyValue(); propertyvalue[2].Name = "FilterData"; propertyvalue[2].Value = outputOpts; } xStorable.storeToURL(fileOut.toString(), propertyvalue); XComponent xcomponent=(XComponent)UnoRuntime.queryInterface(XComponent.class,xStorable); xcomponent.dispose(); } }