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