001 /* ************************************************************************ 002 * 003 * The Contents of this file are made available subject to the terms of 004 * the BSD license. 005 * 006 * Copyright (c) 2003 by Sun Microsystems, Inc. 007 * Modifications Copyright (c) 2005 by Marko Karppinen & Co. LLC 008 * All rights reserved. 009 * 010 * Redistribution and use in source and binary forms, with or without 011 * modification, are permitted provided that the following conditions 012 * are met: 013 * 1. Redistributions of source code must retain the above copyright 014 * notice, this list of conditions and the following disclaimer. 015 * 2. Redistributions in binary form must reproduce the above copyright 016 * notice, this list of conditions and the following disclaimer in the 017 * documentation and/or other materials provided with the distribution. 018 * 3. Neither the name of Sun Microsystems, Inc. nor the names of its 019 * contributors may be used to endorse or promote products derived 020 * from this software without specific prior written permission. 021 * 022 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 023 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 024 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 025 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 026 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 027 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 028 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 029 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 030 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 031 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 032 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 033 * 034 *************************************************************************/ 035 036 /* 037 * This file is derived by hsivonen from a file that came with the 038 * following note (dollar signs stripped): 039 * 040 * RCSfile: ConverterServlet.java,v 041 * 042 * Revision: 1.6 043 * 044 * last change: Author: hr Date: 2003/06/30 15:53:49 045 */ 046 047 package fi.karppinen.ooo; 048 049 import java.io.File; 050 051 import org.apache.log4j.Logger; 052 053 import com.sun.star.beans.PropertyValue; 054 import com.sun.star.beans.XPropertySet; 055 import com.sun.star.bridge.XUnoUrlResolver; 056 import com.sun.star.comp.helper.Bootstrap; 057 import com.sun.star.document.XDocumentInfo; 058 import com.sun.star.document.XDocumentInfoSupplier; 059 import com.sun.star.document.XDocumentInsertable; 060 import com.sun.star.frame.XComponentLoader; 061 import com.sun.star.frame.XStorable; 062 import com.sun.star.lang.Locale; 063 import com.sun.star.lang.XComponent; 064 import com.sun.star.lang.XMultiComponentFactory; 065 import com.sun.star.lang.XMultiServiceFactory; 066 import com.sun.star.text.XText; 067 import com.sun.star.text.XTextCursor; 068 import com.sun.star.text.XTextDocument; 069 import com.sun.star.uno.UnoRuntime; 070 import com.sun.star.uno.XComponentContext; 071 072 /** 073 * Converts an HTML file into PDF, OOo Writer, MS Word or RTF formats by inserting 074 * it into an OOo Writer template. 075 * 076 * @version $Id: Converter.java,v 1.1 2006/10/30 20:00:08 hsivonen Exp $ 077 * @author hr 078 * @author hsivonen 079 */ 080 public class Converter { 081 private static final Logger log4j = Logger.getLogger(Converter.class); 082 083 /** 084 * Specifies the host for the office server. 085 */ 086 private String stringHost = "localhost"; 087 088 /** 089 * Specifies the port for the office server. 090 */ 091 private String stringPort = "8100"; 092 093 public static void main(String[] args) throws Exception { 094 try { 095 new Converter().convertTextWithInsert(new File(args[0]), new File(args[1]), new File(args[2])); 096 } finally { 097 System.exit(0); 098 } 099 } 100 101 /** 102 * Performs the conversion. The target format is sniffed from the target file name. 103 * 104 * @param template The template 105 * @param htmlDoc The document to convert 106 * @param target The destination file 107 * @throws Exception 108 */ 109 public synchronized void convertTextWithInsert(File template, File htmlDoc, File target) throws Exception { 110 111 String templateUrl = template.toURL().toString(); 112 113 String htmlUrl = htmlDoc.toURL().toString(); 114 115 String stringConvertedFile = target.toURL().toString(); 116 117 String targetName = target.getName(); 118 119 int index = targetName.lastIndexOf('.'); 120 121 if(index < 0) { 122 throw new IllegalArgumentException("No filename extension"); 123 } 124 125 String extension = targetName.substring(index + 1); 126 127 String stringConvertType = null; 128 129 if("sxw".equals(extension)) { 130 stringConvertType = "StarOffice XML (Writer)"; 131 } else if("doc".equals(extension)) { 132 stringConvertType = "MS Word 97"; 133 } else if("rtf".equals(extension)) { 134 stringConvertType = "Rich Text Format"; 135 } else if("pdf".equals(extension)) { 136 stringConvertType = "writer_pdf_Export"; 137 } else { 138 throw new IllegalArgumentException("Unsupported filename extension: " + extension); 139 } 140 141 /* 142 * Bootstraps a component context with the jurt base components 143 * registered. Component context to be granted to a component for 144 * running. Arbitrary values can be retrieved from the context. 145 */ 146 XComponentContext xcomponentcontext = Bootstrap.createInitialComponentContext(null); 147 148 /* 149 * Gets the service manager instance to be used (or null). This 150 * method has been added for convenience, because the service 151 * manager is a often used object. 152 */ 153 XMultiComponentFactory xmulticomponentfactory = xcomponentcontext.getServiceManager(); 154 155 /* 156 * Creates an instance of the component UnoUrlResolver which 157 * supports the services specified by the factory. 158 */ 159 Object objectUrlResolver = xmulticomponentfactory.createInstanceWithContext( 160 "com.sun.star.bridge.UnoUrlResolver", xcomponentcontext); 161 162 // Create a new url resolver 163 XUnoUrlResolver xurlresolver = (XUnoUrlResolver) UnoRuntime.queryInterface( 164 XUnoUrlResolver.class, objectUrlResolver); 165 166 // Resolves an object that is specified as follow: 167 // uno:<connection description>;<protocol description>;<initial 168 // object name> 169 Object objectInitial = xurlresolver.resolve("uno:socket,host=" 170 + stringHost + ",port=" + stringPort 171 + ";urp;StarOffice.ServiceManager"); 172 173 // Create a service manager from the initial object 174 xmulticomponentfactory = (XMultiComponentFactory) UnoRuntime.queryInterface( 175 XMultiComponentFactory.class, objectInitial); 176 177 // Query for the XPropertySet interface. 178 XPropertySet xpropertysetMultiComponentFactory = (XPropertySet) UnoRuntime.queryInterface( 179 XPropertySet.class, xmulticomponentfactory); 180 181 // Get the default context from the office server. 182 Object objectDefaultContext = xpropertysetMultiComponentFactory.getPropertyValue("DefaultContext"); 183 184 // Query for the interface XComponentContext. 185 xcomponentcontext = (XComponentContext) UnoRuntime.queryInterface( 186 XComponentContext.class, objectDefaultContext); 187 188 /* 189 * A desktop environment contains tasks with one or more frames in 190 * which components can be loaded. Desktop is the environment for 191 * components which can instanciate within frames. 192 */ 193 XComponentLoader xcomponentloader = (XComponentLoader) UnoRuntime.queryInterface( 194 XComponentLoader.class, 195 xmulticomponentfactory.createInstanceWithContext( 196 "com.sun.star.frame.Desktop", xcomponentcontext)); 197 198 // Preparing properties for loading the document 199 PropertyValue[] propertyvalue = new PropertyValue[2]; 200 // Setting the flag for hidding the open document 201 propertyvalue[0] = new PropertyValue(); 202 propertyvalue[0].Name = "Hidden"; 203 propertyvalue[0].Value = new Boolean(true); 204 // will open as a Writer doc not as a Writer/Web doc 205 propertyvalue[1] = new PropertyValue(); 206 propertyvalue[1].Name = "FilterName"; 207 propertyvalue[1].Value = "HTML (StarWriter)"; 208 209 // open the HTML doc for getting the title 210 211 Object oHtmlDoc = xcomponentloader.loadComponentFromURL( 212 htmlUrl, "_blank", 0, propertyvalue); 213 214 // extract title 215 XDocumentInfoSupplier xDocumentInfoSupplier = (XDocumentInfoSupplier) UnoRuntime.queryInterface( 216 XDocumentInfoSupplier.class, oHtmlDoc); 217 218 XDocumentInfo xDocumentInfo = xDocumentInfoSupplier.getDocumentInfo(); 219 220 XPropertySet xPropertySet = (XPropertySet) UnoRuntime.queryInterface( 221 XPropertySet.class, xDocumentInfo); 222 223 Object title = xPropertySet.getPropertyValue("Title"); 224 225 // extract language 226 // Note! The body element has to declare the language. 227 // Declaring it on the root element is NOT enough! 228 229 XMultiServiceFactory xMultiServiceFactory = (XMultiServiceFactory) UnoRuntime.queryInterface( 230 XMultiServiceFactory.class, oHtmlDoc); 231 232 Object oCharStyle = xMultiServiceFactory.createInstance("com.sun.star.style.CharacterStyle"); 233 234 xPropertySet = (XPropertySet) UnoRuntime.queryInterface( 235 XPropertySet.class, oCharStyle); 236 237 Locale langWestern = (Locale) xPropertySet.getPropertyValue("CharLocale"); 238 239 Locale langCjk = (Locale) xPropertySet.getPropertyValue("CharLocaleAsian"); 240 241 Locale langCtl = (Locale) xPropertySet.getPropertyValue("CharLocaleComplex"); 242 243 if(log4j.isDebugEnabled()) { 244 log4j.debug("langWestern: " + langWestern.Language + "-" + langWestern.Country + "-" + langWestern.Variant); 245 log4j.debug("langCjk: " + langCjk.Language + "-" + langCjk.Country + "-" + langCjk.Variant); 246 log4j.debug("langCtl: " + langCtl.Language + "-" + langCtl.Country + "-" + langCtl.Variant); 247 } 248 249 // Getting the method dispose() for closing the document 250 XComponent xComponent = (XComponent) UnoRuntime.queryInterface( 251 XComponent.class, oHtmlDoc); 252 253 xComponent.dispose(); 254 255 256 // Loading the template 257 propertyvalue[0] = new PropertyValue(); 258 propertyvalue[0].Name = "Hidden"; 259 propertyvalue[0].Value = new Boolean(true); 260 261 Object objectDocumentToStore = xcomponentloader.loadComponentFromURL( 262 templateUrl, "_blank", 0, propertyvalue); 263 264 // set root language 265 // xMultiServiceFactory = (XMultiServiceFactory) UnoRuntime.queryInterface( 266 // XMultiServiceFactory.class, objectDocumentToStore); 267 // 268 // oCharStyle = xMultiServiceFactory.createInstance("com.sun.star.style.CharacterStyle"); 269 // 270 // xPropertySet = (XPropertySet) UnoRuntime.queryInterface( 271 // XPropertySet.class, oCharStyle); 272 273 xPropertySet = (XPropertySet) UnoRuntime.queryInterface( 274 XPropertySet.class, objectDocumentToStore); 275 276 Locale metaLang = null; 277 Locale noneLang = new Locale("", "", ""); 278 279 if (!"".equals(langCtl.Language)) { 280 log4j.debug("Using CTL lang."); 281 xPropertySet.setPropertyValue("CharLocale", noneLang); 282 // xPropertySet.setPropertyValue("CharLocale", noneLang); 283 // xPropertySet.setPropertyValue("CharLocaleAsian", noneLang); 284 // xPropertySet.setPropertyValue("CharLocaleComplex", langCtl); 285 metaLang = langCtl; 286 } else if (!"".equals(langCjk.Language)) { 287 log4j.debug("Using CJK lang."); 288 xPropertySet.setPropertyValue("CharLocale", noneLang); 289 // xPropertySet.setPropertyValue("CharLocale", noneLang); 290 // xPropertySet.setPropertyValue("CharLocaleAsian", langCjk); 291 // xPropertySet.setPropertyValue("CharLocaleComplex", noneLang); 292 metaLang = langCjk; 293 } else { 294 log4j.debug("Using Western lang."); 295 xPropertySet.setPropertyValue("CharLocale", langWestern); 296 // xPropertySet.setPropertyValue("CharLocaleAsian", noneLang); 297 // xPropertySet.setPropertyValue("CharLocaleComplex", noneLang); 298 metaLang = langWestern; 299 } 300 301 // set the title 302 xDocumentInfoSupplier = (XDocumentInfoSupplier) UnoRuntime.queryInterface( 303 XDocumentInfoSupplier.class, objectDocumentToStore); 304 305 xDocumentInfo = xDocumentInfoSupplier.getDocumentInfo(); 306 307 xPropertySet = (XPropertySet) UnoRuntime.queryInterface( 308 XPropertySet.class, xDocumentInfo); 309 310 xPropertySet.setPropertyValue("Title", title); 311 312 // set meta lang 313 xPropertySet.setPropertyValue("Language", metaLang); 314 315 // prepare for insertion 316 XTextDocument xTextDocument = (XTextDocument) UnoRuntime.queryInterface( 317 XTextDocument.class, objectDocumentToStore); 318 319 XText xText = xTextDocument.getText(); 320 XTextCursor xTextCursor = xText.createTextCursor(); 321 xTextCursor.gotoEnd(false); 322 323 XDocumentInsertable xDocumentInsertable = (XDocumentInsertable) UnoRuntime.queryInterface( 324 XDocumentInsertable.class, xTextCursor); 325 326 // insert the HTML doc into the template 327 xDocumentInsertable.insertDocumentFromURL(htmlUrl, new PropertyValue[0]); 328 329 // XXX should get rid of the empty paragraph left at the end of the document. 330 331 // Getting an object that will offer a simple way to store a 332 // document to a URL. 333 XStorable xstorable = (XStorable) UnoRuntime.queryInterface( 334 XStorable.class, objectDocumentToStore); 335 336 // Preparing properties for converting the document 337 propertyvalue = new PropertyValue[2]; 338 // Setting the flag for overwriting 339 propertyvalue[0] = new PropertyValue(); 340 propertyvalue[0].Name = "Overwrite"; 341 propertyvalue[0].Value = new Boolean(true); 342 // Setting the filter name 343 propertyvalue[1] = new PropertyValue(); 344 propertyvalue[1].Name = "FilterName"; 345 propertyvalue[1].Value = stringConvertType; 346 347 // Storing and converting the document 348 xstorable.storeToURL(stringConvertedFile, propertyvalue); 349 350 // Getting the method dispose() for closing the document 351 xComponent = (XComponent) UnoRuntime.queryInterface( 352 XComponent.class, xstorable); 353 354 // Closing the converted document 355 xComponent.dispose(); 356 } 357 }