merge the formfield patch from ooo-build
[ooovba.git] / bean / com / sun / star / beans / LocalOfficeConnection.java
blobc974a9108b4e28f025972bccf6a59f9314ab2849
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: LocalOfficeConnection.java,v $
10 * $Revision: 1.5 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 package com.sun.star.beans;
33 import java.awt.Container;
34 import java.io.File;
35 import java.util.Iterator;
36 import java.util.List;
37 import java.util.Vector;
39 import com.sun.star.lang.XMultiComponentFactory;
40 import com.sun.star.lang.XEventListener;
41 import com.sun.star.bridge.XUnoUrlResolver;
42 import com.sun.star.uno.XComponentContext;
43 import com.sun.star.uno.UnoRuntime;
44 import com.sun.star.lib.uno.helper.UnoUrl;
45 import com.sun.star.lib.util.NativeLibraryLoader;
47 /**
48 * This class reprecents a connection to the local office application.
49 * @deprecated
51 public class LocalOfficeConnection
52 implements OfficeConnection
54 public static final String OFFICE_APP_NAME = "soffice";
55 public static final String OFFICE_LIB_NAME = "officebean";
56 public static final String OFFICE_ID_SUFFIX = "_Office";
58 private Process mProcess;
59 private ContainerFactory mContainerFactory;
60 private XComponentContext mContext;
62 private String mURL;
63 private String mProgramPath;
64 private String mConnType;
65 private String mPipe;
66 private String mPort;
67 private String mProtocol;
68 private String mInitialObject;
70 private List mComponents = new Vector();
72 /**
73 * Constructor.
74 * Sets up paths to the office application and native libraries if
75 * values are available in <code>OFFICE_PROP_FILE</code> in the user
76 * home directory.<br />
77 * "com.sun.star.beans.path" - the office application directory;<br/>
78 * "com.sun.star.beans.libpath" - native libraries directory.
80 public LocalOfficeConnection()
82 // init member vars
83 try
85 setUnoUrl( "uno:pipe,name=" + getPipeName() + ";urp;StarOffice.ServiceManager" );
87 catch ( java.net.MalformedURLException e )
90 // load libofficebean.so/officebean.dll
91 String aSharedLibName = getProgramPath() + java.io.File.separator +
92 System.mapLibraryName(OFFICE_LIB_NAME);
93 System.load( aSharedLibName );
96 /**
97 * Sets a connection URL.
98 * This implementation accepts a UNO URL with following format:<br />
99 * <pre>
100 * url := uno:localoffice[,&lt;params&gt;];urp;StarOffice.ServiceManager
101 * params := &lt;path&gt;[,&lt;pipe&gt;]
102 * path := path=&lt;pathv&gt;
103 * pipe := pipe=&lt;pipev&gt;
104 * pathv := platform_specific_path_to_the_local_office_distribution
105 * pipev := local_office_connection_pipe_name
106 * </pre>
108 * @param url This is UNO URL which discribes the type of a connection.
110 public void setUnoUrl(String url)
111 throws java.net.MalformedURLException
113 mURL = null;
115 String prefix = "uno:localoffice";
116 if ( url.startsWith(prefix) )
117 parseUnoUrlWithOfficePath( url, prefix );
118 else
122 UnoUrl aURL = UnoUrl.parseUnoUrl( url );
123 mProgramPath = null;
124 mConnType = aURL.getConnection();
125 mPipe = (String) aURL.getConnectionParameters().get( "pipe" );
126 mPort = (String) aURL.getConnectionParameters().get( "port" );
127 mProtocol = aURL.getProtocol();
128 mInitialObject = aURL.getRootOid();
130 catch ( com.sun.star.lang.IllegalArgumentException eIll )
132 throw new java.net.MalformedURLException(
133 "Invalid UNO connection URL.");
136 mURL = url;
140 * Sets an AWT container catory.
142 * @param containerFactory This is a application provided AWT container
143 * factory.
145 public void setContainerFactory(ContainerFactory containerFactory)
147 mContainerFactory = containerFactory;
151 * Retrives the UNO component context.
152 * Establishes a connection if necessary and initialises the
153 * UNO service manager if it has not already been initialised.
154 * This method can return <code>null</code> if it fails to connect
155 * to the office application.
157 * @return The office UNO component context.
159 public XComponentContext getComponentContext()
161 if ( mContext == null )
162 mContext = connect();
163 return mContext;
167 * Creates an office window.
168 * The window is either a sub-class of java.awt.Canvas (local) or
169 * java.awt.Container (RVP).
171 * @param container This is an AWT container.
172 * @return The office window instance.
174 public OfficeWindow createOfficeWindow(Container container)
176 return new LocalOfficeWindow(this);
180 * Closes the connection.
182 public void dispose()
184 Iterator itr = mComponents.iterator();
185 while (itr.hasNext() == true) {
186 // ignore runtime exceptions in dispose
187 try { ((XEventListener)itr.next()).disposing(null); }
188 catch ( RuntimeException aExc ) {}
190 mComponents.clear();
192 mContainerFactory = null;
193 mContext = null;
197 * Adds an event listener to the object.
199 * @param listener is a listener object.
201 public void addEventListener(XEventListener listener)
203 mComponents.add(listener);
207 * Removes an event listener from the listener list.
209 * @param listener is a listener object.
211 public void removeEventListener(XEventListener listener)
213 mComponents.remove(listener);
217 * Establishes the connection to the office.
219 private XComponentContext connect()
221 try
223 // create default local component context
224 XComponentContext xLocalContext =
225 com.sun.star.comp.helper.Bootstrap.createInitialComponentContext(null);
227 // initial serviceManager
228 XMultiComponentFactory xLocalServiceManager = xLocalContext.getServiceManager();
230 // create a urlresolver
231 Object urlResolver = xLocalServiceManager.createInstanceWithContext(
232 "com.sun.star.bridge.UnoUrlResolver", xLocalContext );
234 // query for the XUnoUrlResolver interface
235 XUnoUrlResolver xUrlResolver =
236 (XUnoUrlResolver) UnoRuntime.queryInterface( XUnoUrlResolver.class, urlResolver );
238 // try to connect to soffice
239 Object aInitialObject = null;
240 try
242 aInitialObject = xUrlResolver.resolve( mURL );
244 catch( com.sun.star.connection.NoConnectException e )
246 // launch soffice
247 OfficeService aSOffice = new OfficeService();
248 aSOffice.startupService();
250 // wait until soffice is started
251 long nMaxMillis = System.currentTimeMillis() + 1000*aSOffice.getStartupTime();
252 while ( aInitialObject == null )
254 try
256 // try to connect to soffice
257 Thread.currentThread().sleep( 500 );
258 aInitialObject = xUrlResolver.resolve( mURL );
260 catch( com.sun.star.connection.NoConnectException aEx )
262 // soffice did not start in time
263 if ( System.currentTimeMillis() > nMaxMillis )
264 throw aEx;
269 finally
273 // XComponentContext
274 if( null != aInitialObject )
276 XPropertySet xPropertySet = (XPropertySet)
277 UnoRuntime.queryInterface( XPropertySet.class, aInitialObject);
278 Object xContext = xPropertySet.getPropertyValue("DefaultContext");
279 XComponentContext xComponentContext = (XComponentContext) UnoRuntime.queryInterface(
280 XComponentContext.class, xContext);
281 return xComponentContext;
284 catch( com.sun.star.connection.NoConnectException e )
286 System.out.println( "Couldn't connect to remote server" );
287 System.out.println( e.getMessage() );
289 catch( com.sun.star.connection.ConnectionSetupException e )
291 System.out.println( "Couldn't access necessary local resource to establish the interprocess connection" );
292 System.out.println( e.getMessage() );
294 catch( com.sun.star.lang.IllegalArgumentException e )
296 System.out.println( "uno-url is syntactical illegal ( " + mURL + " )" );
297 System.out.println( e.getMessage() );
299 catch( com.sun.star.uno.RuntimeException e )
301 System.out.println( "--- RuntimeException:" );
302 System.out.println( e.getMessage() );
303 e.printStackTrace();
304 System.out.println( "--- end." );
305 throw e;
307 catch( java.lang.Exception e )
309 System.out.println( "java.lang.Exception: " );
310 System.out.println( e );
311 e.printStackTrace();
312 System.out.println( "--- end." );
313 throw new com.sun.star.uno.RuntimeException( e.toString() );
316 return null;
320 * Retrives a path to the office program folder.
322 * @return The path to the office program folder.
324 private String getProgramPath()
326 if (mProgramPath == null)
328 // determine name of executable soffice
329 String aExec = OFFICE_APP_NAME; // default for UNIX
330 String aOS = System.getProperty("os.name");
332 // running on Windows?
333 if (aOS.startsWith("Windows"))
334 aExec = OFFICE_APP_NAME + ".exe";
336 // add other non-UNIX operating systems here
337 // ...
339 // find soffice executable relative to this class's class loader:
340 File path = NativeLibraryLoader.getResource(
341 this.getClass().getClassLoader(), aExec);
342 if (path != null) {
343 mProgramPath = path.getParent();
346 // default is ""
347 if ( mProgramPath == null )
348 mProgramPath = "";
350 return mProgramPath;
354 * Parses a connection URL.
355 * This method accepts a UNO URL with following format:<br />
356 * <pre>
357 * url := uno:localoffice[,&lt;params&gt;];urp;StarOffice.NamingService
358 * params := &lt;path&gt;[,&lt;pipe&gt;]
359 * path := path=&lt;pathv&gt;
360 * pipe := pipe=&lt;pipev&gt;
361 * pathv := platform_specific_path_to_the_local_office_distribution
362 * pipev := local_office_connection_pipe_name
363 * </pre>
365 * <h4>Examples</h4>
366 * <ul>
367 * <li>"uno:localoffice,pipe=xyz_Office,path=/opt/openoffice11/program;urp;StarOffice.ServiceManager";
368 * <li>"uno:socket,host=localhost,port=8100;urp;StarOffice.ServiceManager";
369 * </ul>
371 * @param url This is UNO URL which describes the type of a connection.
372 * @exception java.net.MalformedURLException when inappropreate URL was
373 * provided.
375 private void parseUnoUrlWithOfficePath(String url, String prefix)
376 throws java.net.MalformedURLException
378 // Extruct parameters.
379 int idx = url.indexOf(";urp;StarOffice.NamingService");
380 if (idx < 0)
381 throw new java.net.MalformedURLException(
382 "Invalid UNO connection URL.");
383 String params = url.substring(prefix.length(), idx + 1);
385 // Parse parameters.
386 String name = null;
387 String path = null;
388 String pipe = null;
389 char ch;
390 int state = 0;
391 StringBuffer buffer = new StringBuffer();
392 for(idx = 0; idx < params.length(); idx += 1) {
393 ch = params.charAt(idx);
394 switch (state) {
395 case 0: // initial state
396 switch(ch) {
397 case ',':
398 buffer.delete(0, buffer.length());
399 state = 1;
400 break;
402 case ';':
403 state = 7;
404 break;
406 default:
407 buffer.delete(0, buffer.length());
408 buffer.append(ch);
409 state = 1;
410 break;
412 break;
414 case 1: // parameter name
415 switch(ch) {
416 case ' ':
417 case '=':
418 name = buffer.toString();
419 state = (ch == ' ')? 2: 3;
420 break;
422 case ',':
423 case ';':
424 state = -6; // error: invalid name
425 break;
427 default:
428 buffer.append(ch);
429 break;
431 break;
433 case 2: // equal between the name and the value
434 switch(ch) {
435 case '=':
436 state = 3;
437 break;
439 case ' ':
440 break;
442 default:
443 state = -1; // error: missing '='
444 break;
446 break;
448 case 3: // value leading spaces
449 switch(ch) {
450 case ' ':
451 break;
453 default:
454 buffer.delete(0, buffer.length());
455 buffer.append(ch);
456 state = 4;
457 break;
459 break;
461 case 4: // value
462 switch(ch) {
463 case ' ':
464 case ',':
465 case ';':
466 idx -= 1; // put back the last read character
467 state = 5;
468 if (name.equals("path")) {
469 if (path == null)
470 path = buffer.toString();
471 else
472 state = -3; // error: more then one 'path'
473 } else if (name.equals("pipe")) {
474 if (pipe == null)
475 pipe = buffer.toString();
476 else
477 state = -4; // error: more then one 'pipe'
478 } else
479 state = -2; // error: unknown parameter
480 buffer.delete(0, buffer.length());
481 break;
483 default:
484 buffer.append(ch);
485 break;
487 break;
489 case 5: // a delimeter after the value
490 switch(ch) {
491 case ' ':
492 break;
494 case ',':
495 state = 6;
496 break;
498 case ';':
499 state = 7;
500 break;
502 default:
503 state = -5; // error: ' ' inside the value
504 break;
506 break;
508 case 6: // leading spaces before next parameter name
509 switch(ch) {
510 case ' ':
511 break;
513 default:
514 buffer.delete(0, buffer.length());
515 buffer.append(ch);
516 state = 1;
517 break;
519 break;
521 default:
522 throw new java.net.MalformedURLException(
523 "Invalid UNO connection URL.");
526 if (state != 7)
527 throw new java.net.MalformedURLException(
528 "Invalid UNO connection URL.");
530 // Set up the connection parameters.
531 if (path != null)
532 mProgramPath = path;
533 if (pipe != null)
534 mPipe = pipe;
537 /* replaces each substring aSearch in aString by aReplace.
539 StringBuffer.replaceAll() is not avaialable in Java 1.3.x.
541 private static String replaceAll(String aString, String aSearch, String aReplace )
543 StringBuffer aBuffer = new StringBuffer(aString);
545 int nPos = aString.length();
546 int nOfs = aSearch.length();
548 while ( ( nPos = aString.lastIndexOf( aSearch, nPos - 1 ) ) > -1 )
549 aBuffer.replace( nPos, nPos+nOfs, aReplace );
551 return aBuffer.toString();
555 /** creates a unique pipe name.
557 static String getPipeName()
559 // turn user name into a URL and file system safe name (% chars will not work)
560 String aPipeName = System.getProperty("user.name") + OFFICE_ID_SUFFIX;
561 aPipeName = replaceAll( aPipeName, "_", "%B7" );
562 return replaceAll( replaceAll( java.net.URLEncoder.encode(aPipeName), "\\+", "%20" ), "%", "_" );
565 /**
566 * @para This is an implementation of the native office service.
567 * @deprecated
569 private class OfficeService
570 implements NativeService
573 * Retrive the office service identifier.
575 * @return The identifier of the office service.
577 public String getIdentifier()
579 if ( mPipe == null)
580 return getPipeName();
581 else
582 return mPipe;
586 * Starts the office process.
588 public void startupService()
589 throws java.io.IOException
591 // create call with arguments
592 String[] cmdArray = new String[4];
593 cmdArray[0] = (new File(getProgramPath(), OFFICE_APP_NAME)).getPath();
594 cmdArray[1] = "-nologo";
595 cmdArray[2] = "-nodefault";
596 if ( mConnType.equals( "pipe" ) )
597 cmdArray[3] = "-accept=pipe,name=" + getIdentifier() + ";" +
598 mProtocol + ";" + mInitialObject;
599 else if ( mConnType.equals( "socket" ) )
600 cmdArray[3] = "-accept=socket,port=" + mPort + ";urp";
601 else
602 throw new java.io.IOException( "not connection specified" );
604 // start process
605 mProcess = Runtime.getRuntime().exec(cmdArray);
606 if ( mProcess == null )
607 throw new RuntimeException( "cannot start soffice: " + cmdArray );
611 * Retrives the ammount of time to wait for the startup.
613 * @return The ammount of time to wait in seconds(?).
615 public int getStartupTime()
617 return 60;