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 }