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