LibreOffice Module odk (master) 1
InstallationFinder.java
Go to the documentation of this file.
1/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20package com.sun.star.lib.loader;
21
22import java.io.BufferedReader;
23import java.io.File;
24import java.io.FileInputStream;
25import java.io.InputStream;
26import java.io.InputStreamReader;
27import java.io.IOException;
28import java.io.UnsupportedEncodingException;
29import java.net.MalformedURLException;
30import java.net.URL;
31import java.util.StringTokenizer;
32import java.util.ArrayList;
33
61final class InstallationFinder {
62
63 private static final String SYSPROP_NAME =
64 "com.sun.star.lib.loader.unopath";
65 private static final String ENVVAR_NAME = "UNO_PATH";
66 private static final String SOFFICE = "libreoffice"; // Unix/Linux only
67
68 private InstallationFinder() {} // do not instantiate
69
76 public static String getPath() {
77
78 String path = null;
79
80 // get the installation path from the Java system property
81 // com.sun.star.lib.loader.unopath
82 // (all platforms)
83 path = getPathFromProperty( SYSPROP_NAME );
84 if ( path != null ) {
85 return path;
86 }
87 // get the installation path from the UNO_PATH environment variable
88 // (all platforms, not working for Java 1.3.1 and Java 1.4)
89 path = getPathFromEnvVar( ENVVAR_NAME );
90 if ( path != null ) {
91 return path;
92 }
93
94 String osname = null;
95 try {
96 osname = System.getProperty( "os.name" );
97 } catch ( SecurityException e ) {
98 // if a SecurityException was thrown,
99 // return <code>null</code>
100 return null;
101 }
102 if ( osname == null ) {
103 return null;
104 }
105
106 if ( osname.startsWith( "Windows" ) ) {
107 // get the installation path from the Windows Registry
108 // (Windows platform only)
109 path = getPathFromWindowsRegistry();
110 } else {
111 // get the installation path from the PATH environment
112 // variable (Unix/Linux platforms only, not working for
113 // Java 1.3.1 and Java 1.4)
114 path = getPathFromPathEnvVar();
115 if ( path == null ) {
116 // get the installation path from the 'which'
117 // command (Unix/Linux platforms only)
118 path = getPathFromWhich();
119 if ( path == null ) {
120 // get the installation path from the
121 // .sversionrc file (Unix/Linux platforms only,
122 // for older versions than OOo 2.0)
123 path = getPathFromSVersionFile();
124 }
125 }
126 }
127
128 return path;
129 }
130
142 private static String getPathFromProperty( String prop ) {
143
144 String path = null;
145
146 try {
147 path = System.getProperty( prop );
148 } catch ( SecurityException e ) {
149 // if a SecurityException was thrown, return <code>null</code>
150 }
151
152 return path;
153 }
154
166 private static String getPathFromEnvVar( String var ) {
167
168 String path = null;
169
170 try {
171 path = System.getenv( var );
172 } catch ( SecurityException e ) {
173 // if a SecurityException was thrown, return <code>null</code>
174 } catch ( java.lang.Error err ) {
175 // System.getenv() throws java.lang.Error in Java 1.3.1 and
176 // Java 1.4
177 }
178
179 return path;
180 }
181
190 private static String getPathFromWindowsRegistry() {
191
192 final String SUBKEYNAME = "\\Software\\LibreOffice\\UNO\\InstallPath";
193
194 String path = null;
195
196 try {
197 // read the key's default value from HKEY_CURRENT_USER
198 WinRegKey key = new WinRegKey( "HKEY_CURRENT_USER" + SUBKEYNAME );
199 path = key.getStringValue();
200 } catch ( WinRegKeyException e ) {
201 try {
202 // read the key's default value from HKEY_LOCAL_MACHINE
203 WinRegKey key = new WinRegKey( "HKEY_LOCAL_MACHINE" +
204 SUBKEYNAME );
205 path = key.getStringValue();
206 } catch ( WinRegKeyException we ) {
207 System.err.println( "com.sun.star.lib.loader." +
208 "InstallationFinder::getPathFromWindowsRegistry: " +
209 "reading key from Windows Registry failed: " + we );
210 }
211 }
212
213 return path;
214 }
215
229 private static String getPathFromPathEnvVar() {
230
231 final String PATH_ENVVAR_NAME = "PATH";
232
233 String path = null;
234 String str = null;
235
236 try {
237 str = System.getenv( PATH_ENVVAR_NAME );
238 } catch ( SecurityException e ) {
239 // if a SecurityException was thrown, return <code>null</code>
240 return null;
241 } catch ( java.lang.Error err ) {
242 // System.getenv() throws java.lang.Error in Java 1.3.1 and
243 // Java 1.4
244 return null;
245 }
246
247 if ( str != null ) {
248 StringTokenizer tokens = new StringTokenizer(
249 str, File.pathSeparator );
250 while ( tokens.hasMoreTokens() ) {
251 File file = new File( tokens.nextToken(), SOFFICE );
252 try {
253 if ( file.exists() ) {
254 try {
255 // resolve symlink
256 path = file.getCanonicalFile().getParent();
257 if ( path != null )
258 break;
259 } catch ( IOException e ) {
260 // if an I/O exception is thrown, ignore this
261 // path entry and try the next one
262 System.err.println( "com.sun.star.lib.loader." +
263 "InstallationFinder::getPathFromEnvVar: " +
264 "bad path: " + e );
265 }
266 }
267 } catch ( SecurityException e ) {
268 // if a SecurityException was thrown, ignore this path
269 // entry and try the next one
270 }
271 }
272 }
273
274 return path;
275 }
276
288 private static String getPathFromWhich() {
289
290 final String WHICH = "which";
291
292 String path = null;
293
294 // start the which process
295 String[] cmdArray = new String[] { WHICH, SOFFICE };
296 Process proc = null;
297 Runtime rt = Runtime.getRuntime();
298 try {
299 proc = rt.exec( cmdArray );
300 } catch ( SecurityException e ) {
301 return null;
302 } catch ( IOException e ) {
303 // if an I/O exception is thrown, return <code>null</null>
304 System.err.println( "com.sun.star.lib.loader." +
305 "InstallationFinder::getPathFromWhich: " +
306 "which command failed: " + e );
307 return null;
308 }
309
310 // empty standard error stream in a separate thread
311 StreamGobbler gobbler = new StreamGobbler( proc.getErrorStream() );
312 gobbler.start();
313
314 try {
315 // read the which output from standard input stream
316 BufferedReader br = new BufferedReader(
317 new InputStreamReader( proc.getInputStream(), "UTF-8" ) );
318 String line = null;
319 try {
320 while ( ( line = br.readLine() ) != null ) {
321 if ( path == null ) {
322 // get the path from the which output
323 int index = line.lastIndexOf( SOFFICE );
324 if ( index != -1 ) {
325 int end = index + SOFFICE.length();
326 for ( int i = 0; i <= index; i++ ) {
327 File file = new File( line.substring( i, end ) );
328 try {
329 if ( file.exists() ) {
330 // resolve symlink
331 path = file.getCanonicalFile().getParent();
332 if ( path != null )
333 break;
334 }
335 } catch ( SecurityException e ) {
336 return null;
337 }
338 }
339 }
340 }
341 }
342 } catch ( IOException e ) {
343 // if an I/O exception is thrown, return <code>null</null>
344 System.err.println( "com.sun.star.lib.loader." +
345 "InstallationFinder::getPathFromWhich: " +
346 "reading which command output failed: " + e );
347 return null;
348 } finally {
349 try {
350 br.close();
351 } catch ( IOException e ) {
352 // closing standard input stream failed, ignore
353 }
354 }
355 } catch ( UnsupportedEncodingException e ) {
356 // if an Encoding exception is thrown, return <code>null</null>
357 System.err.println( "com.sun.star.lib.loader." +
358 "InstallationFinder::getPathFromWhich: " +
359 "encoding failed: " + e );
360 return null;
361 }
362
363 try {
364 // wait until the which process has terminated
365 proc.waitFor();
366 } catch ( InterruptedException e ) {
367 // the current thread was interrupted by another thread,
368 // kill the which process
369 proc.destroy();
370 // set the interrupted status
371 Thread.currentThread().interrupt();
372 }
373
374 return path;
375 }
376
388 private static String getPathFromSVersionFile() {
389
390 final String SVERSION = ".sversionrc"; // Unix/Linux only
391 final String VERSIONS = "[Versions]";
392
393 String path = null;
394
395 try {
396 File fSVersion = new File(
397 System.getProperty( "user.home" ) ,SVERSION );
398 if ( fSVersion.exists() ) {
399 ArrayList<String> lines = new ArrayList<String>();
400 BufferedReader br = null;
401 try {
402 br = new BufferedReader( new InputStreamReader(
403 new FileInputStream( fSVersion ), "UTF-8" ) );
404 String line = null;
405 while ( ( line = br.readLine() ) != null &&
406 !line.equals( VERSIONS ) ) {
407 // read lines until [Versions] is found
408 }
409 while ( ( line = br.readLine() ) != null &&
410 line.length() != 0 ) {
411 if ( !line.startsWith( ";" ) )
412 lines.add( line );
413 }
414 } catch ( IOException e ) {
415 // if an I/O exception is thrown, try to analyze the lines
416 // read so far
417 System.err.println( "com.sun.star.lib.loader." +
418 "InstallationFinder::getPathFromSVersionFile: " +
419 "reading .sversionrc file failed: " + e );
420 } finally {
421 if ( br != null ) {
422 try {
423 br.close();
424 } catch ( IOException e ) {
425 // closing .sversionrc failed, ignore
426 }
427 }
428 }
429 for ( int i = lines.size() - 1; i >= 0; i-- ) {
430 StringTokenizer tokens = new StringTokenizer(
431 lines.get( i ), "=" );
432 if ( tokens.countTokens() != 2 )
433 continue;
434 tokens.nextToken(); // key
435 String url = tokens.nextToken();
436 path = getCanonicalPathFromFileURL( url );
437 if ( path != null )
438 break;
439 }
440 }
441 } catch ( SecurityException e ) {
442 return null;
443 }
444
445 return path;
446 }
447
459 private static String getCanonicalPathFromFileURL( String oooUrl ) {
460
461 String prefix = "file://";
462 if (oooUrl.length() < prefix.length()
463 || !oooUrl.substring(0, prefix.length()).equalsIgnoreCase(
464 prefix))
465 {
466 return null;
467 }
468 StringBuffer buf = new StringBuffer(prefix);
469 int n = oooUrl.indexOf('/', prefix.length());
470 if (n < 0) {
471 n = oooUrl.length();
472 }
473 String host = oooUrl.substring(prefix.length(), n);
474 if (host.length() != 0 && !host.equalsIgnoreCase("localhost")) {
475 return null;
476 }
477 buf.append(host);
478 if (n == oooUrl.length()) {
479 buf.append('/');
480 } else {
481 loop:
482 while (n < oooUrl.length()) {
483 buf.append('/');
484 ++n;
485 int n2 = oooUrl.indexOf('/', n);
486 if (n2 < 0) {
487 n2 = oooUrl.length();
488 }
489 while (n < n2) {
490 char c = oooUrl.charAt(n);
491 switch (c) {
492 case '%':
493 byte[] bytes = new byte[(n2 - n) / 3];
494 int len = 0;
495 while (oooUrl.length() - n > 2
496 && oooUrl.charAt(n) == '%')
497 {
498 int d1 = Character.digit(oooUrl.charAt(n + 1), 16);
499 int d2 = Character.digit(oooUrl.charAt(n + 2), 16);
500 if (d1 < 0 || d2 < 0) {
501 break;
502 }
503 int d = 16 * d1 + d2;
504 if (d == '/') {
505 return null;
506 }
507 bytes[len++] = (byte) d;
508 n += 3;
509 }
510 String s;
511 try {
512 s = new String(bytes, 0, len, "UTF-8");
513 } catch (UnsupportedEncodingException e) {
514 return null;
515 }
516 buf.append(s);
517 break;
518
519 case '#':
520 break loop;
521
522 default:
523 buf.append(c);
524 ++n;
525 break;
526 }
527 }
528 }
529 }
530 URL url;
531 try {
532 url = new URL(buf.toString());
533 } catch (MalformedURLException e) {
534 return null;
535 }
536 String path = url.getFile();
537 String fragment = url.getRef();
538 if (fragment != null) {
539 path += '#' + fragment;
540 }
541 String ret = null;
542 File file = new File( path, SOFFICE );
543 try {
544 if ( file.isAbsolute() && file.exists() ) {
545 try {
546 // resolve symlink
547 ret = file.getCanonicalFile().getParent();
548 } catch ( IOException e ) {
549 return null;
550 }
551 }
552 } catch ( SecurityException e ) {
553 return null;
554 }
555
556 return ret;
557 }
558
563 private static final class StreamGobbler extends Thread {
564
565 InputStream m_istream;
566
567 StreamGobbler( InputStream istream ) {
568 m_istream = istream;
569 }
570
571 @Override
572 public void run() {
573 try {
574 BufferedReader br = new BufferedReader(
575 new InputStreamReader( m_istream, "UTF-8" ) );
576 // read from input stream
577 while ( br.readLine() != null ) {
578 // don't handle line content
579 }
580 br.close();
581 } catch (UnsupportedEncodingException e) {
582 // cannot read from input stream
583 } catch ( IOException e ) {
584 // stop reading from input stream
585 }
586 }
587 }
588}
589
590/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
double d
This class is used for emptying any stream which is passed into it in a separate thread.
unsigned char byte
sal_Int64 n
int n2
err
int i
line
dictionary tokens
index
int fragment
end
std::vector< sal_uInt8 > bytes
static char * getPath(void)