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