1 /************************************************************************* 2 * 3 * The Contents of this file are made available subject to the terms of 4 * the BSD license. 5 * 6 * Copyright 2000, 2010 Oracle and/or its affiliates. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. Neither the name of Sun Microsystems, Inc. nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 28 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 29 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 30 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 31 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 * 33 *************************************************************************/ 34 35 // JDK API 36 import java.io.IOException; 37 import java.io.PrintWriter; 38 import java.io.File; 39 import java.io.FileInputStream; 40 import java.io.BufferedInputStream; 41 import java.util.Enumeration; 42 43 // Servlet API 44 import javax.servlet.ServletException; 45 import javax.servlet.http.HttpServlet; 46 import javax.servlet.http.HttpServletRequest; 47 import javax.servlet.http.HttpServletResponse; 48 import javax.servlet.ServletOutputStream; 49 50 // Helper API 51 import com.oreilly.servlet.MultipartRequest; 52 import com.oreilly.servlet.MultipartResponse; 53 import com.oreilly.servlet.ServletUtils; 54 55 // UNO API 56 import com.sun.star.bridge.XUnoUrlResolver; 57 import com.sun.star.uno.XComponentContext; 58 import com.sun.star.uno.UnoRuntime; 59 import com.sun.star.frame.XComponentLoader; 60 import com.sun.star.frame.XStorable; 61 import com.sun.star.util.XCloseable; 62 import com.sun.star.beans.PropertyValue; 63 import com.sun.star.beans.XPropertySet; 64 import com.sun.star.lang.XComponent; 65 import com.sun.star.lang.XMultiComponentFactory; 66 67 68 /** This class implements a http servlet in order to convert an incoming document 69 * with help of a running OpenOffice.org and to push the converted file back 70 * to the client. 71 */ 72 public class ConverterServlet extends HttpServlet { 73 /** Specifies the temporary directory on the web server. 74 */ 75 private String stringWorkingDirectory = 76 System.getProperty( "java.io.tmpdir" ).replace( '\\', '/' ); 77 78 /** Specifies the host for the office server. 79 */ 80 private String stringHost = "localhost"; 81 82 /** Specifies the port for the office server. 83 */ 84 private String stringPort = "2083"; 85 86 /** Called by the server (via the service method) to allow a servlet to handle 87 * a POST request. The file from the client will be uploaded to the web server 88 * and converted on the web server and after all pushed to the client. 89 * @param request Object that contains the request the client has made of the servlet. 90 * @param response Object that contains the response the servlet sends to the client. 91 * @throws ServletException If the request for the POST could not be handled. 92 * @throws IOException If an input or output error is detected when the servlet handles the request. 93 */ 94 protected void doPost( HttpServletRequest request, 95 HttpServletResponse response) throws ServletException, java.io.IOException { 96 try { 97 // If necessary, add a slash to the end of the string. 98 if ( !stringWorkingDirectory.endsWith( "/" ) ) { 99 stringWorkingDirectory += "/"; 100 } 101 102 // Construct a MultipartRequest to help read the information. 103 // Pass in the request, a directory to save files to, and the 104 // maximum POST size we should attempt to handle. 105 MultipartRequest multipartrequest = 106 new MultipartRequest( request, stringWorkingDirectory, 5 * 1024 * 1024 ); 107 108 // Getting all file names from the request 109 Enumeration files = multipartrequest.getFileNames(); 110 111 // Every received file will be converted to the specified type 112 while (files.hasMoreElements()) { 113 // Getting the name from the element 114 String stringName = (String)files.nextElement(); 115 116 // Getting the filename from the request 117 String stringFilename = 118 multipartrequest.getFilesystemName( stringName ); 119 120 // Converting the given file on the server to the specified type and 121 // append a special extension 122 File cleanupFile = null; 123 String stringSourceFile = stringWorkingDirectory + stringFilename; 124 125 try { 126 String stringConvertedFile = convertDocument(stringSourceFile, 127 multipartrequest.getParameter( "converttype" ), 128 multipartrequest.getParameter( "extension" )); 129 130 String shortFileName = stringConvertedFile.substring( 131 stringConvertedFile.lastIndexOf('/') + 1); 132 133 // Set the response header 134 // Set the filename, is used when the file will be saved (problem with mozilla) 135 response.addHeader( "Content-Disposition", 136 "attachment; filename=" + shortFileName); 137 138 // Constructing the multi part response to the client 139 MultipartResponse multipartresponse = new MultipartResponse(response); 140 141 // Is the convert type HTML? 142 if ( ( multipartrequest.getParameter( "converttype" ).equals( 143 "swriter: HTML (StarWriter)" ) ) 144 || ( multipartrequest.getParameter( "converttype" ).equals( 145 "scalc: HTML (StarCalc)" ) ) ) { 146 // Setting the content type of the response being sent to the client 147 // to text 148 multipartresponse.startResponse( "text/html" ); 149 } else { 150 // Setting the content type of the response being sent to the client 151 // to application/octet-stream so that file will open a dialog box 152 // at the client in order to save the converted file 153 multipartresponse.startResponse( "application/octet-stream" ); 154 } 155 156 // Pushing the converted file to the client 157 ServletUtils.returnFile( stringConvertedFile, 158 response.getOutputStream() ); 159 160 // Finishing the multi part response 161 multipartresponse.finish(); 162 163 // clean up the working directory 164 cleanupFile = new File(stringConvertedFile); 165 if ( cleanupFile.exists() ) 166 cleanupFile.delete(); 167 168 } catch (Exception exc) { 169 response.setContentType( "text/html;charset=8859-1" ); 170 PrintWriter out = response.getWriter(); 171 172 exc.printStackTrace(); 173 174 out.println( "<html><head>" ); 175 out.println( " <title>" + "SDK Converter Servlet" + "</title>" ); 176 out.println( "</head>" ); 177 out.println( "<body><br><p>"); 178 out.println( "<b>Sorry, the conversion failed!</b></p>"); 179 out.println( "<p><b>Error Mesage:</b><br>" + exc.getMessage() + "<br>"); 180 exc.printStackTrace(out); 181 out.println( "</p></body><html>"); 182 } 183 184 // clean up the working directory 185 cleanupFile = new File(stringSourceFile); 186 if ( cleanupFile.exists() ) 187 cleanupFile.delete(); 188 } 189 } 190 catch (Exception exception) { 191 System.err.println( exception.toString() ); 192 } 193 } 194 195 /** This method converts a document to a given type by using a running 196 * OpenOffice.org and saves the converted document to the specified 197 * working directory. 198 * @param stringDocumentName The full path name of the file on the server to be converted. 199 * @param stringConvertType Type to convert to. 200 * @param stringExtension This string will be appended to the file name of the converted file. 201 * @return The full path name of the converted file will be returned. 202 * @see stringWorkingDirectory 203 */ 204 private String convertDocument( String stringDocumentName, 205 String stringConvertType, 206 String stringExtension) 207 throws Exception 208 { 209 String stringConvertedFile = ""; 210 211 // Converting the document to the favoured type 212 // try { 213 // Composing the URL 214 String stringUrl = "file:///" + stringDocumentName; 215 216 /* Bootstraps a component context with the jurt base components 217 registered. Component context to be granted to a component for running. 218 Arbitrary values can be retrieved from the context. */ 219 XComponentContext xcomponentcontext = 220 com.sun.star.comp.helper.Bootstrap.createInitialComponentContext( null ); 221 222 /* Gets the service manager instance to be used (or null). This method has 223 been added for convenience, because the service manager is a often used 224 object. */ 225 XMultiComponentFactory xmulticomponentfactory = 226 xcomponentcontext.getServiceManager(); 227 228 /* Creates an instance of the component UnoUrlResolver which 229 supports the services specified by the factory. */ 230 Object objectUrlResolver = 231 xmulticomponentfactory.createInstanceWithContext( 232 "com.sun.star.bridge.UnoUrlResolver", xcomponentcontext ); 233 234 // Create a new url resolver 235 XUnoUrlResolver xurlresolver = ( XUnoUrlResolver ) 236 UnoRuntime.queryInterface( XUnoUrlResolver.class, 237 objectUrlResolver ); 238 239 // Resolves an object that is specified as follow: 240 // uno:<connection description>;<protocol description>;<initial object name> 241 Object objectInitial = xurlresolver.resolve( 242 "uno:socket,host=" + stringHost + ",port=" + stringPort + 243 ";urp;StarOffice.ServiceManager" ); 244 245 // Create a service manager from the initial object 246 xmulticomponentfactory = ( XMultiComponentFactory ) 247 UnoRuntime.queryInterface( XMultiComponentFactory.class, objectInitial ); 248 249 // Query for the XPropertySet interface. 250 XPropertySet xpropertysetMultiComponentFactory = ( XPropertySet ) 251 UnoRuntime.queryInterface( XPropertySet.class, xmulticomponentfactory ); 252 253 // Get the default context from the office server. 254 Object objectDefaultContext = 255 xpropertysetMultiComponentFactory.getPropertyValue( "DefaultContext" ); 256 257 // Query for the interface XComponentContext. 258 xcomponentcontext = ( XComponentContext ) UnoRuntime.queryInterface( 259 XComponentContext.class, objectDefaultContext ); 260 261 /* A desktop environment contains tasks with one or more 262 frames in which components can be loaded. Desktop is the 263 environment for components which can instanciate within 264 frames. */ 265 XComponentLoader xcomponentloader = ( XComponentLoader ) 266 UnoRuntime.queryInterface( XComponentLoader.class, 267 xmulticomponentfactory.createInstanceWithContext( 268 "com.sun.star.frame.Desktop", xcomponentcontext ) ); 269 270 // Preparing properties for loading the document 271 PropertyValue propertyvalue[] = new PropertyValue[ 1 ]; 272 // Setting the flag for hidding the open document 273 propertyvalue[ 0 ] = new PropertyValue(); 274 propertyvalue[ 0 ].Name = "Hidden"; 275 propertyvalue[ 0 ].Value = new Boolean(true); 276 277 // Loading the wanted document 278 Object objectDocumentToStore = 279 xcomponentloader.loadComponentFromURL( 280 stringUrl, "_blank", 0, propertyvalue ); 281 282 // Getting an object that will offer a simple way to store a document to a URL. 283 XStorable xstorable = 284 ( XStorable ) UnoRuntime.queryInterface( XStorable.class, 285 objectDocumentToStore ); 286 287 // Preparing properties for converting the document 288 propertyvalue = new PropertyValue[ 2 ]; 289 // Setting the flag for overwriting 290 propertyvalue[ 0 ] = new PropertyValue(); 291 propertyvalue[ 0 ].Name = "Overwrite"; 292 propertyvalue[ 0 ].Value = new Boolean(true); 293 // Setting the filter name 294 propertyvalue[ 1 ] = new PropertyValue(); 295 propertyvalue[ 1 ].Name = "FilterName"; 296 propertyvalue[ 1 ].Value = stringConvertType; 297 298 // Appending the favoured extension to the origin document name 299 int index = stringUrl.lastIndexOf('.'); 300 if ( index >= 0 ) { 301 stringConvertedFile = stringUrl.substring(0, index) + "." + stringExtension; 302 } else { 303 stringConvertedFile = stringUrl + "." + stringExtension; 304 } 305 306 // Storing and converting the document 307 xstorable.storeAsURL( stringConvertedFile, propertyvalue ); 308 309 XCloseable xcloseable = (XCloseable)UnoRuntime.queryInterface( XCloseable.class,xstorable ); 310 311 // Closing the converted document 312 if ( xcloseable != null ) 313 xcloseable.close(false); 314 else { 315 // If Xcloseable is not supported (older versions, 316 // use dispose() for closing the document 317 XComponent xComponent = ( XComponent ) UnoRuntime.queryInterface( 318 XComponent.class, xstorable ); 319 xComponent.dispose(); 320 } 321 322 // } 323 // catch( Exception exception ) { 324 // exception.printStackTrace(); 325 // return( "" ); 326 // } 327 328 if ( stringConvertedFile.startsWith( "file:///" ) ) { 329 // Truncating the beginning of the file name 330 stringConvertedFile = stringConvertedFile.substring( 8 ); 331 } 332 333 // Returning the name of the converted file 334 return stringConvertedFile; 335 } 336 } 337