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