Line data Source code
1 : /* -*- Mode: C++; 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 :
20 : #include <config_features.h>
21 : #include <config_folders.h>
22 :
23 : #include "util.hxx"
24 :
25 : #include "osl/process.h"
26 : #include "osl/security.hxx"
27 : #include "osl/file.hxx"
28 : #include "osl/module.hxx"
29 : #include "rtl/byteseq.hxx"
30 : #include "rtl/ustrbuf.hxx"
31 : #include "rtl/instance.hxx"
32 : #include "salhelper/linkhelper.hxx"
33 : #include "salhelper/thread.hxx"
34 : #include "boost/noncopyable.hpp"
35 : #include "boost/scoped_array.hpp"
36 : #include "com/sun/star/uno/Sequence.hxx"
37 : #include <utility>
38 : #include <algorithm>
39 : #include <map>
40 :
41 : #if defined WNT
42 : #if defined _MSC_VER
43 : #pragma warning(push, 1)
44 : #endif
45 : #include <windows.h>
46 : #if defined _MSC_VER
47 : #pragma warning(pop)
48 : #endif
49 : #endif
50 : #include <string.h>
51 :
52 : #include "sunjre.hxx"
53 : #include "vendorlist.hxx"
54 : #include "diagnostics.h"
55 :
56 : using namespace osl;
57 : using namespace std;
58 :
59 : using ::rtl::Reference;
60 :
61 : #ifdef WNT
62 : #define HKEY_SUN_JRE L"Software\\JavaSoft\\Java Runtime Environment"
63 : #define HKEY_SUN_SDK L"Software\\JavaSoft\\Java Development Kit"
64 : #endif
65 :
66 : #ifdef UNX
67 : #if !(defined MACOSX && defined X86_64)
68 : namespace {
69 : char const *g_arJavaNames[] = {
70 : "",
71 : "j2re",
72 : "j2se",
73 : "j2sdk",
74 : "jdk",
75 : "jre",
76 : "java",
77 : "Home",
78 : "IBMJava2-ppc-142"
79 : };
80 : /* These are directory names which could contain multiple java installations.
81 : */
82 : char const *g_arCollectDirs[] = {
83 : "",
84 : #ifndef JVM_ONE_PATH_CHECK
85 : "j2re/",
86 : "j2se/",
87 : "j2sdk/",
88 : "jdk/",
89 : "jre/",
90 : "java/",
91 : #endif
92 : "jvm/"
93 : };
94 :
95 : /* These are directories in which a java installation is
96 : looked for.
97 : */
98 : char const *g_arSearchPaths[] = {
99 : #ifdef MACOSX
100 : "",
101 : "Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/bin",
102 : "System/Library/Frameworks/JavaVM.framework/Versions/1.4.2/"
103 : #else
104 : #ifndef JVM_ONE_PATH_CHECK
105 : "",
106 : "usr/",
107 : "usr/local/",
108 : "usr/local/IBMJava2-ppc-142",
109 : "usr/local/j2sdk1.3.1",
110 : #ifdef X86_64
111 : "usr/lib64/",
112 : #endif
113 : "usr/lib/",
114 : "usr/bin/"
115 : #else
116 : JVM_ONE_PATH_CHECK
117 : #endif
118 : #endif
119 : };
120 : }
121 : #endif
122 : #endif // UNX
123 :
124 : namespace jfw_plugin
125 : {
126 : extern VendorSupportMapEntry gVendorMap[];
127 :
128 : #if defined WNT
129 : bool getSDKInfoFromRegistry(vector<OUString> & vecHome);
130 : bool getJREInfoFromRegistry(vector<OUString>& vecJavaHome);
131 : #endif
132 :
133 : bool decodeOutput(const OString& s, OUString* out);
134 :
135 :
136 :
137 : namespace
138 : {
139 1 : OUString getLibraryLocation()
140 : {
141 1 : OUString libraryFileUrl;
142 1 : OSL_VERIFY(osl::Module::getUrlFromAddress((void *)(sal_IntPtr)getLibraryLocation, libraryFileUrl));
143 1 : return getDirFromFile(libraryFileUrl);
144 : }
145 :
146 : struct InitBootstrap
147 : {
148 1 : rtl::Bootstrap * operator()(const OUString& sIni)
149 : {
150 1 : static rtl::Bootstrap aInstance(sIni);
151 1 : return & aInstance;
152 :
153 : }
154 : };
155 :
156 : struct InitBootstrapData
157 : {
158 1 : OUString const & operator()()
159 : {
160 1 : static OUString sIni;
161 1 : OUStringBuffer buf( 255);
162 1 : buf.append( getLibraryLocation());
163 : #if HAVE_FEATURE_MACOSX_MACLIKE_APP_STRUCTURE
164 : buf.appendAscii( "/../" LIBO_ETC_FOLDER );
165 : #endif
166 1 : buf.appendAscii( SAL_CONFIGFILE("/sunjavaplugin") );
167 1 : sIni = buf.makeStringAndClear();
168 : JFW_TRACE2("[Java framework] sunjavaplugin: "
169 : "Using configuration file \n" + sIni);
170 1 : return sIni;
171 : }
172 : };
173 : }
174 :
175 4 : rtl::Bootstrap * getBootstrap()
176 : {
177 : return rtl_Instance< rtl::Bootstrap, InitBootstrap,
178 : ::osl::MutexGuard, ::osl::GetGlobalMutex,
179 : OUString, InitBootstrapData >::create(
180 4 : InitBootstrap(), ::osl::GetGlobalMutex(), InitBootstrapData());
181 : }
182 :
183 :
184 :
185 :
186 : class FileHandleGuard: private boost::noncopyable
187 : {
188 : public:
189 4 : inline FileHandleGuard(oslFileHandle & rHandle) SAL_THROW(()):
190 4 : m_rHandle(rHandle) {}
191 :
192 : inline ~FileHandleGuard() SAL_THROW(());
193 :
194 7213 : inline oslFileHandle & getHandle() SAL_THROW(()) { return m_rHandle; }
195 :
196 : private:
197 : oslFileHandle & m_rHandle;
198 : };
199 :
200 4 : inline FileHandleGuard::~FileHandleGuard() SAL_THROW(())
201 : {
202 4 : if (m_rHandle != 0)
203 : {
204 4 : if (osl_closeFile(m_rHandle) != osl_File_E_None)
205 : {
206 : OSL_FAIL("unexpected situation");
207 : }
208 : }
209 4 : }
210 :
211 :
212 2 : class FileHandleReader
213 : {
214 : public:
215 : enum Result
216 : {
217 : RESULT_OK,
218 : RESULT_EOF,
219 : RESULT_ERROR
220 : };
221 :
222 2 : inline FileHandleReader(oslFileHandle & rHandle) SAL_THROW(()):
223 2 : m_aGuard(rHandle), m_nSize(0), m_nIndex(0), m_bLf(false) {}
224 :
225 : Result readLine(OString * pLine) SAL_THROW(());
226 :
227 : private:
228 : enum { BUFFER_SIZE = 1024 };
229 :
230 : sal_Char m_aBuffer[BUFFER_SIZE];
231 : FileHandleGuard m_aGuard;
232 : int m_nSize;
233 : int m_nIndex;
234 : bool m_bLf;
235 : };
236 :
237 : FileHandleReader::Result
238 104 : FileHandleReader::readLine(OString * pLine)
239 : SAL_THROW(())
240 : {
241 : OSL_ENSURE(pLine, "specification violation");
242 :
243 7246 : for (bool bEof = true;; bEof = false)
244 : {
245 7246 : if (m_nIndex == m_nSize)
246 : {
247 7211 : sal_uInt64 nRead = 0;
248 7211 : switch (osl_readFile(
249 7211 : m_aGuard.getHandle(), m_aBuffer, sizeof(m_aBuffer), &nRead))
250 : {
251 : case osl_File_E_PIPE: //HACK! for windows
252 0 : nRead = 0;
253 : case osl_File_E_None:
254 7211 : if (nRead == 0)
255 : {
256 2 : m_bLf = false;
257 4 : return bEof ? RESULT_EOF : RESULT_OK;
258 : }
259 7209 : m_nIndex = 0;
260 7209 : m_nSize = static_cast< int >(nRead);
261 7209 : break;
262 : case osl_File_E_INTR:
263 0 : continue;
264 :
265 : default:
266 0 : return RESULT_ERROR;
267 : }
268 : }
269 :
270 7244 : if (m_bLf && m_aBuffer[m_nIndex] == 0x0A)
271 0 : ++m_nIndex;
272 7244 : m_bLf = false;
273 :
274 7244 : int nStart = m_nIndex;
275 33370 : while (m_nIndex != m_nSize)
276 18984 : switch (m_aBuffer[m_nIndex++])
277 : {
278 : case 0x0D:
279 0 : m_bLf = true;
280 : case 0x0A:
281 204 : *pLine += OString(m_aBuffer + nStart,
282 204 : m_nIndex - 1 - nStart);
283 : //TODO! check for overflow, and not very efficient
284 102 : return RESULT_OK;
285 : }
286 :
287 7142 : *pLine += OString(m_aBuffer + nStart, m_nIndex - nStart);
288 : //TODO! check for overflow, and not very efficient
289 7142 : }
290 : }
291 :
292 : class AsynchReader: public salhelper::Thread
293 : {
294 : size_t m_nDataSize;
295 : boost::scoped_array<sal_Char> m_arData;
296 :
297 : bool m_bError;
298 : bool m_bDone;
299 : FileHandleGuard m_aGuard;
300 :
301 4 : virtual ~AsynchReader() {}
302 :
303 : void execute() SAL_OVERRIDE;
304 : public:
305 :
306 : AsynchReader(oslFileHandle & rHandle);
307 :
308 : /** only call this function after this thread has finished.
309 :
310 : That is, call join on this instance and then call getData.
311 :
312 : */
313 : OString getData();
314 : };
315 :
316 2 : AsynchReader::AsynchReader(oslFileHandle & rHandle):
317 : Thread("jvmfwkAsyncReader"), m_nDataSize(0), m_bError(false),
318 2 : m_bDone(false), m_aGuard(rHandle)
319 : {
320 2 : }
321 :
322 0 : OString AsynchReader::getData()
323 : {
324 0 : return OString(m_arData.get(), m_nDataSize);
325 : }
326 :
327 2 : void AsynchReader::execute()
328 : {
329 2 : const sal_uInt64 BUFFER_SIZE = 4096;
330 : sal_Char aBuffer[BUFFER_SIZE];
331 : while (true)
332 : {
333 : sal_uInt64 nRead;
334 : //the function blocks until something could be read or the pipe closed.
335 2 : switch (osl_readFile(
336 2 : m_aGuard.getHandle(), aBuffer, BUFFER_SIZE, &nRead))
337 : {
338 : case osl_File_E_PIPE: //HACK! for windows
339 0 : nRead = 0;
340 : case osl_File_E_None:
341 2 : break;
342 : default:
343 0 : m_bError = true;
344 2 : return;
345 : }
346 :
347 2 : if (nRead == 0)
348 : {
349 2 : m_bDone = true;
350 4 : break;
351 : }
352 0 : else if (nRead <= BUFFER_SIZE)
353 : {
354 : //Save the data we have in m_arData into a temporary array
355 0 : boost::scoped_array<sal_Char> arTmp( new sal_Char[m_nDataSize]);
356 0 : memcpy(arTmp.get(), m_arData.get(), m_nDataSize);
357 : //Enlarge m_arData to hold the newly read data
358 0 : m_arData.reset(new sal_Char[(size_t)(m_nDataSize + nRead)]);
359 : //Copy back the data that was already in m_arData
360 0 : memcpy(m_arData.get(), arTmp.get(), m_nDataSize);
361 : //Add the newly read data to m_arData
362 0 : memcpy(m_arData.get() + m_nDataSize, aBuffer, (size_t) nRead);
363 0 : m_nDataSize += (size_t) nRead;
364 : }
365 0 : }
366 : }
367 :
368 4 : static bool isEnvVarSetToOne(const OUString &aVar)
369 : {
370 4 : OUString aValue;
371 4 : getBootstrap()->getFrom(aVar, aValue);
372 4 : return aValue == "1";
373 : }
374 :
375 2 : bool getJavaProps(const OUString & exePath,
376 : #ifdef JVM_ONE_PATH_CHECK
377 : const OUString & homePath,
378 : #endif
379 : std::vector<std::pair<OUString, OUString> >& props,
380 : bool * bProcessRun)
381 : {
382 2 : bool ret = false;
383 :
384 : OSL_ASSERT(!exePath.isEmpty());
385 2 : OUString usStartDir;
386 : //We need to set the CLASSPATH in case the office is started from
387 : //a different directory. The JREProperties.class is expected to reside
388 : //next to the plugin.
389 4 : OUString sThisLib;
390 2 : if (osl_getModuleURLFromAddress((void *) (sal_IntPtr)& getJavaProps,
391 2 : & sThisLib.pData) == sal_False)
392 0 : return false;
393 2 : sThisLib = getDirFromFile(sThisLib);
394 4 : OUString sClassPath;
395 2 : if (osl_getSystemPathFromFileURL(sThisLib.pData, & sClassPath.pData)
396 : != osl_File_E_None)
397 0 : return false;
398 :
399 : //check if we shall examine a Java for accessibility support
400 : //If the bootstrap variable is "1" then we pass the argument
401 : //"noaccessibility" to JREProperties.class. This will prevent
402 : //that it calls java.awt.Toolkit.getDefaultToolkit();
403 2 : bool bNoAccessibility = isEnvVarSetToOne("JFW_PLUGIN_DO_NOT_CHECK_ACCESSIBILITY");
404 :
405 : //prepare the arguments
406 2 : sal_Int32 cArgs = 3;
407 4 : OUString arg1 = "-classpath";// + sClassPath;
408 4 : OUString arg2 = sClassPath;
409 4 : OUString arg3("JREProperties");
410 4 : OUString arg4 = "noaccessibility";
411 2 : rtl_uString *args[4] = {arg1.pData, arg2.pData, arg3.pData};
412 :
413 : #ifdef UNX
414 : // Java is no longer required for a11y - we use atk directly.
415 2 : bNoAccessibility = !isEnvVarSetToOne("JFW_PLUGIN_FORCE_ACCESSIBILITY");
416 : #endif
417 :
418 : // Only add the fourth param if the bootstrap parameter is set.
419 2 : if (bNoAccessibility)
420 : {
421 2 : args[3] = arg4.pData;
422 2 : cArgs = 4;
423 : }
424 :
425 2 : oslProcess javaProcess= 0;
426 2 : oslFileHandle fileOut= 0;
427 2 : oslFileHandle fileErr= 0;
428 :
429 4 : FileHandleReader stdoutReader(fileOut);
430 4 : rtl::Reference< AsynchReader > stderrReader(new AsynchReader(fileErr));
431 :
432 : JFW_TRACE2("\n[Java framework] Executing: " + exePath + ".\n");
433 : oslProcessError procErr =
434 : osl_executeProcess_WithRedirectedIO( exePath.pData,//usExe.pData,
435 : args,
436 : cArgs, //sal_uInt32 nArguments,
437 : osl_Process_HIDDEN, //oslProcessOption Options,
438 : NULL, //oslSecurity Security,
439 : usStartDir.pData,//usStartDir.pData,//usWorkDir.pData, //rtl_uString *strWorkDir,
440 : NULL, //rtl_uString *strEnvironment[],
441 : 0, // sal_uInt32 nEnvironmentVars,
442 : &javaProcess, //oslProcess *pProcess,
443 : NULL,//oslFileHandle *pChildInputWrite,
444 : &fileOut,//oslFileHandle *pChildOutputRead,
445 2 : &fileErr);//oslFileHandle *pChildErrorRead);
446 :
447 2 : if( procErr != osl_Process_E_None)
448 : {
449 : JFW_TRACE2("[Java framework] Execution failed. \n");
450 0 : *bProcessRun = false;
451 0 : return ret;
452 : }
453 : else
454 : {
455 : JFW_TRACE2("[Java framework] Java executed successfully.\n");
456 2 : *bProcessRun = true;
457 : }
458 :
459 : //Start asynchronous reading (different thread) of error stream
460 2 : stderrReader->launch();
461 :
462 : //Use this thread to read output stream
463 2 : FileHandleReader::Result rs = FileHandleReader::RESULT_OK;
464 : while (true)
465 : {
466 104 : OString aLine;
467 104 : rs = stdoutReader.readLine( & aLine);
468 104 : if (rs != FileHandleReader::RESULT_OK)
469 2 : break;
470 204 : OUString sLine;
471 102 : if (!decodeOutput(aLine, &sLine))
472 0 : continue;
473 : JFW_TRACE2("[Java framework]:\" " << sLine << " \".\n");
474 102 : sLine = sLine.trim();
475 102 : if (sLine.isEmpty())
476 0 : continue;
477 : //The JREProperties class writes key value pairs, separated by '='
478 102 : sal_Int32 index = sLine.indexOf('=', 0);
479 : OSL_ASSERT(index != -1);
480 204 : OUString sKey = sLine.copy(0, index);
481 204 : OUString sVal = sLine.copy(index + 1);
482 :
483 : #ifdef JVM_ONE_PATH_CHECK
484 : //replace absolute path by linux distro link
485 : OUString sHomeProperty("java.home");
486 : if(sHomeProperty.equals(sKey))
487 : {
488 : sVal = homePath + "/jre";
489 : }
490 : #endif
491 :
492 102 : props.push_back(std::make_pair(sKey, sVal));
493 102 : }
494 :
495 2 : if (rs != FileHandleReader::RESULT_ERROR && !props.empty())
496 2 : ret = true;
497 :
498 : //process error stream data
499 2 : stderrReader->join();
500 : JFW_TRACE2("[Java framework] Java wrote to stderr:\" "
501 : << stderrReader->getData().getStr() << " \".\n");
502 :
503 2 : TimeValue waitMax= {5 ,0};
504 2 : procErr = osl_joinProcessWithTimeout(javaProcess, &waitMax);
505 : OSL_ASSERT(procErr == osl_Process_E_None);
506 2 : osl_freeProcessHandle(javaProcess);
507 4 : return ret;
508 : }
509 :
510 : /* converts the properties printed by JREProperties.class into
511 : readable strings. The strings are encoded as integer values separated
512 : by spaces.
513 : */
514 102 : bool decodeOutput(const OString& s, OUString* out)
515 : {
516 : OSL_ASSERT(out != 0);
517 102 : OUStringBuffer buff(512);
518 102 : sal_Int32 nIndex = 0;
519 5456 : do
520 : {
521 5456 : OString aToken = s.getToken( 0, ' ', nIndex );
522 5456 : if (!aToken.isEmpty())
523 : {
524 18882 : for (sal_Int32 i = 0; i < aToken.getLength(); ++i)
525 : {
526 13528 : if (aToken[i] < '0' || aToken[i] > '9')
527 0 : return false;
528 : }
529 5354 : sal_Unicode value = (sal_Unicode)(aToken.toInt32());
530 5354 : buff.append(value);
531 5456 : }
532 5456 : } while (nIndex >= 0);
533 :
534 102 : *out = buff.makeStringAndClear();
535 102 : return true;
536 : }
537 :
538 :
539 : #if defined WNT
540 : void createJavaInfoFromWinReg(std::vector<rtl::Reference<VendorBase> > & vecInfos)
541 : {
542 : // Get Java s from registry
543 : std::vector<OUString> vecJavaHome;
544 : if(getSDKInfoFromRegistry(vecJavaHome))
545 : {
546 : // create impl objects
547 : typedef std::vector<OUString>::iterator ItHome;
548 : for(ItHome it_home= vecJavaHome.begin(); it_home != vecJavaHome.end();
549 : it_home++)
550 : {
551 : getJREInfoByPath(*it_home, vecInfos);
552 : }
553 : }
554 :
555 : vecJavaHome.clear();
556 : if(getJREInfoFromRegistry(vecJavaHome))
557 : {
558 : typedef std::vector<OUString>::iterator ItHome;
559 : for(ItHome it_home= vecJavaHome.begin(); it_home != vecJavaHome.end();
560 : it_home++)
561 : {
562 : getJREInfoByPath(*it_home, vecInfos);
563 : }
564 : }
565 : }
566 :
567 :
568 : bool getJavaInfoFromRegistry(const wchar_t* szRegKey,
569 : vector<OUString>& vecJavaHome)
570 : {
571 : HKEY hRoot;
572 : if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, szRegKey, 0, KEY_ENUMERATE_SUB_KEYS, &hRoot)
573 : == ERROR_SUCCESS)
574 : {
575 : DWORD dwIndex = 0;
576 : const DWORD BUFFSIZE = 1024;
577 : wchar_t bufVersion[BUFFSIZE];
578 : DWORD nNameLen = BUFFSIZE;
579 : FILETIME fileTime;
580 : nNameLen = sizeof(bufVersion);
581 :
582 : // Iterate over all subkeys of HKEY_LOCAL_MACHINE\Software\JavaSoft\Java Runtime Environment
583 : while (RegEnumKeyExW(hRoot, dwIndex, bufVersion, &nNameLen, NULL, NULL, NULL, &fileTime) != ERROR_NO_MORE_ITEMS)
584 : {
585 : HKEY hKey;
586 : // Open a Java Runtime Environment sub key, e.g. "1.4.0"
587 : if (RegOpenKeyExW(hRoot, bufVersion, 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
588 : {
589 : DWORD dwType;
590 : DWORD dwTmpPathLen= 0;
591 : // Get the path to the JavaHome every JRE entry
592 : // Find out how long the string for JavaHome is and allocate memory to hold the path
593 : if( RegQueryValueExW(hKey, L"JavaHome", 0, &dwType, NULL, &dwTmpPathLen)== ERROR_SUCCESS)
594 : {
595 : char* szTmpPath= (char *) malloc( dwTmpPathLen);
596 : // Get the path for the runtime lib
597 : if(RegQueryValueExW(hKey, L"JavaHome", 0, &dwType, (unsigned char*) szTmpPath, &dwTmpPathLen) == ERROR_SUCCESS)
598 : {
599 : // There can be several version entries refering with the same JavaHome,e.g 1.4 and 1.4.1
600 : OUString usHome((sal_Unicode*) szTmpPath);
601 : // check if there is already an entry with the same JavaHomeruntime lib
602 : // if so, we use the one with the more accurate version
603 : bool bAppend= true;
604 : OUString usHomeUrl;
605 : if (osl_getFileURLFromSystemPath(usHome.pData, & usHomeUrl.pData) ==
606 : osl_File_E_None)
607 : {
608 : //iterate over the vector with java home strings
609 : typedef vector<OUString>::iterator ItHome;
610 : for(ItHome itHome= vecJavaHome.begin();
611 : itHome != vecJavaHome.end(); itHome++)
612 : {
613 : if(usHomeUrl.equals(*itHome))
614 : {
615 : bAppend= false;
616 : break;
617 : }
618 : }
619 : // Save the home dir
620 : if(bAppend)
621 : {
622 : vecJavaHome.push_back(usHomeUrl);
623 : }
624 : }
625 : }
626 : free( szTmpPath);
627 : RegCloseKey(hKey);
628 : }
629 : }
630 : dwIndex ++;
631 : nNameLen = BUFFSIZE;
632 : }
633 : RegCloseKey(hRoot);
634 : }
635 : return true;
636 : }
637 :
638 :
639 :
640 : bool getSDKInfoFromRegistry(vector<OUString> & vecHome)
641 : {
642 : return getJavaInfoFromRegistry(HKEY_SUN_SDK, vecHome);
643 : }
644 :
645 : bool getJREInfoFromRegistry(vector<OUString>& vecJavaHome)
646 : {
647 : return getJavaInfoFromRegistry(HKEY_SUN_JRE, vecJavaHome);
648 : }
649 :
650 : #endif // WNT
651 :
652 2 : void bubbleSortVersion(vector<rtl::Reference<VendorBase> >& vec)
653 : {
654 2 : if(vec.empty())
655 2 : return;
656 2 : int size= vec.size() - 1;
657 2 : int cIter= 0;
658 : // sort for version
659 2 : for(int i= 0; i < size; i++)
660 : {
661 0 : for(int j= size; j > 0 + cIter; j--)
662 : {
663 0 : rtl::Reference<VendorBase>& cur= vec.at(j);
664 0 : rtl::Reference<VendorBase>& next= vec.at(j-1);
665 :
666 0 : int nCmp = 0;
667 : // comparing invalid SunVersion s is possible, they will be less than a
668 : // valid version
669 :
670 : //check if version of current is recognized, by comparing it with itself
671 : try
672 : {
673 0 : cur->compareVersions(cur->getVersion());
674 : }
675 0 : catch (MalformedVersionException &)
676 : {
677 0 : nCmp = -1; // current < next
678 : }
679 : //The version of cur is valid, now compare with the second version
680 0 : if (nCmp == 0)
681 : {
682 : try
683 : {
684 0 : nCmp = cur->compareVersions(next->getVersion());
685 : }
686 0 : catch (MalformedVersionException & )
687 : {
688 : //The second version is invalid, therefor it is regardes less.
689 0 : nCmp = 1;
690 : }
691 : }
692 0 : if(nCmp == 1) // cur > next
693 : {
694 0 : rtl::Reference<VendorBase> less = next;
695 0 : vec.at(j-1)= cur;
696 0 : vec.at(j)= less;
697 : }
698 : }
699 0 : ++cIter;
700 : }
701 : }
702 :
703 :
704 12 : bool getJREInfoFromBinPath(
705 : const OUString& path, vector<rtl::Reference<VendorBase> > & vecInfos)
706 : {
707 : // file:///c:/jre/bin
708 : //map: jre/bin/java.exe
709 12 : bool ret = false;
710 :
711 204 : for ( sal_Int32 pos = 0;
712 102 : gVendorMap[pos].sVendorName != NULL; ++pos )
713 : {
714 92 : vector<OUString> vecPaths;
715 92 : getJavaExePaths_func pFunc = gVendorMap[pos].getJavaFunc;
716 :
717 92 : int size = 0;
718 92 : char const* const* arExePaths = (*pFunc)(&size);
719 92 : vecPaths = getVectorFromCharArray(arExePaths, size);
720 :
721 : //make sure argument path does not end with '/'
722 182 : OUString sBinPath = path;
723 92 : if (path.endsWith("/"))
724 0 : sBinPath = path.copy(0, path.getLength() - 1);
725 :
726 : typedef vector<OUString>::const_iterator c_it;
727 352 : for (c_it i = vecPaths.begin(); i != vecPaths.end(); ++i)
728 : {
729 : //the map contains e.g. jre/bin/java.exe
730 : //get the directory where the executable is contained
731 262 : OUString sHome;
732 262 : sal_Int32 index = i->lastIndexOf('/');
733 262 : if (index == -1)
734 : {
735 : //map contained only : "java.exe, then the argument
736 : //path is already the home directory
737 62 : sHome = sBinPath;
738 : }
739 : else
740 : {
741 : // jre/bin/jre -> jre/bin
742 200 : OUString sMapPath(i->getStr(), index);
743 200 : index = sBinPath.lastIndexOf(sMapPath);
744 200 : if (index != -1
745 120 : && (index + sMapPath.getLength() == sBinPath.getLength())
746 320 : && sBinPath[index - 1] == '/')
747 : {
748 72 : sHome = sBinPath.copy(index - 1);
749 200 : }
750 : }
751 262 : if (!sHome.isEmpty())
752 : {
753 134 : ret = getJREInfoByPath(sHome, vecInfos);
754 134 : if (ret)
755 2 : break;
756 : }
757 260 : }
758 92 : if (ret)
759 2 : break;
760 90 : }
761 12 : return ret;
762 : }
763 :
764 2 : vector<Reference<VendorBase> > getAllJREInfos()
765 : {
766 2 : vector<Reference<VendorBase> > vecInfos;
767 :
768 : #if defined WNT
769 : // Get Javas from the registry
770 : createJavaInfoFromWinReg(vecInfos);
771 : #endif // WNT
772 :
773 : #ifndef JVM_ONE_PATH_CHECK
774 2 : createJavaInfoFromJavaHome(vecInfos);
775 : //this function should be called after createJavaInfoDirScan.
776 : //Otherwise in SDKs Java may be started twice
777 2 : createJavaInfoFromPath(vecInfos);
778 : #endif
779 :
780 : #ifdef UNX
781 2 : createJavaInfoDirScan(vecInfos);
782 : #endif
783 :
784 2 : bubbleSortVersion(vecInfos);
785 2 : return vecInfos;
786 : }
787 :
788 :
789 608 : vector<OUString> getVectorFromCharArray(char const * const * ar, int size)
790 : {
791 608 : vector<OUString> vec;
792 2370 : for( int i = 0; i < size; i++)
793 : {
794 1762 : OUString s(ar[i], strlen(ar[i]), RTL_TEXTENCODING_UTF8);
795 1762 : vec.push_back(s);
796 1762 : }
797 608 : return vec;
798 : }
799 170 : bool getJREInfoByPath(const OUString& path,
800 : std::vector<rtl::Reference<VendorBase> > & vecInfos)
801 : {
802 170 : bool ret = false;
803 :
804 170 : rtl::Reference<VendorBase> aInfo = getJREInfoByPath(path);
805 170 : if (aInfo.is())
806 : {
807 28 : ret = true;
808 : vector<rtl::Reference<VendorBase> >::const_iterator it_impl= std::find_if(
809 28 : vecInfos.begin(),vecInfos.end(), InfoFindSame(aInfo->getHome()));
810 28 : if(it_impl == vecInfos.end())
811 : {
812 2 : vecInfos.push_back(aInfo);
813 : }
814 : }
815 170 : return ret;
816 : }
817 :
818 : /** Checks if the path is a directory. Links are resolved.
819 : In case of an error the returned string has the length 0.
820 : Otherwise the returned string is the "resolved" file URL.
821 : */
822 170 : OUString resolveDirPath(const OUString & path)
823 : {
824 170 : OUString ret;
825 : salhelper::LinkResolver aResolver(osl_FileStatus_Mask_Type |
826 340 : osl_FileStatus_Mask_FileURL);
827 170 : if (aResolver.fetchFileStatus(path) == osl::FileBase::E_None)
828 : {
829 : //check if this is a directory
830 86 : if (aResolver.m_aStatus.getFileType() == FileStatus::Directory)
831 : {
832 : #ifndef JVM_ONE_PATH_CHECK
833 84 : ret = aResolver.m_aStatus.getFileURL();
834 : #else
835 : ret = path;
836 : #endif
837 : }
838 : }
839 340 : return ret;
840 : }
841 : /** Checks if the path is a file. If it is a link to a file than
842 : it is resolved.
843 : */
844 1471 : OUString resolveFilePath(const OUString & path)
845 : {
846 1471 : OUString ret;
847 : salhelper::LinkResolver aResolver(osl_FileStatus_Mask_Type |
848 2942 : osl_FileStatus_Mask_FileURL);
849 1471 : if (aResolver.fetchFileStatus(path) == osl::FileBase::E_None)
850 : {
851 : //check if this is a file
852 12 : if (aResolver.m_aStatus.getFileType() == FileStatus::Regular)
853 : {
854 : #ifndef JVM_ONE_PATH_CHECK
855 8 : ret = aResolver.m_aStatus.getFileURL();
856 : #else
857 : ret = path;
858 : #endif
859 : }
860 : }
861 2942 : return ret;
862 : }
863 :
864 170 : rtl::Reference<VendorBase> getJREInfoByPath(
865 : const OUString& path)
866 : {
867 170 : rtl::Reference<VendorBase> ret;
868 170 : static vector<OUString> vecBadPaths;
869 :
870 170 : static map<OUString, rtl::Reference<VendorBase> > mapJREs;
871 : typedef map<OUString, rtl::Reference<VendorBase> >::const_iterator MapIt;
872 : typedef map<OUString, rtl::Reference<VendorBase> > MAPJRE;
873 340 : OUString sFilePath;
874 : typedef vector<OUString>::const_iterator cit_path;
875 340 : vector<pair<OUString, OUString> > props;
876 :
877 340 : OUString sResolvedDir = resolveDirPath(path);
878 : // If this path is invalid then there is no chance to find a JRE here
879 170 : if (sResolvedDir.isEmpty())
880 86 : return 0;
881 :
882 : //check if the directory path is good, that is a JRE was already recognized.
883 : //Then we need not detect it again
884 : //For example, a sun JKD contains <jdk>/bin/java and <jdk>/jre/bin/java.
885 : //When <jdk>/bin/java has been found then we need not find <jdk>/jre/bin/java.
886 : //Otherwise we would execute java two times for evers JDK found.
887 : MapIt entry2 = find_if(mapJREs.begin(), mapJREs.end(),
888 84 : SameOrSubDirJREMap(sResolvedDir));
889 84 : if (entry2 != mapJREs.end())
890 : {
891 : JFW_TRACE2(OUString("[Java framework] sunjavaplugin")
892 : + SAL_DLLEXTENSION + ": "
893 : + "JRE found again (detected before): " + sResolvedDir
894 : + ".\n");
895 20 : return entry2->second;
896 : }
897 :
898 1136 : for ( sal_Int32 pos = 0;
899 568 : gVendorMap[pos].sVendorName != NULL; ++pos )
900 : {
901 512 : vector<OUString> vecPaths;
902 512 : getJavaExePaths_func pFunc = gVendorMap[pos].getJavaFunc;
903 :
904 512 : int size = 0;
905 512 : char const* const* arExePaths = (*pFunc)(&size);
906 512 : vecPaths = getVectorFromCharArray(arExePaths, size);
907 :
908 512 : bool bBreak = false;
909 : typedef vector<OUString>::const_iterator c_it;
910 1975 : for (c_it i = vecPaths.begin(); i != vecPaths.end(); ++i)
911 : {
912 : //if the path is a link, then resolve it
913 : //check if the executable exists at all
914 :
915 : //path can be only "file:///". Then do not append a '/'
916 : //sizeof counts the terminating 0
917 1471 : OUString sFullPath;
918 1471 : if (path.getLength() == sizeof("file:///") - 1)
919 4 : sFullPath = sResolvedDir + (*i);
920 : else
921 5868 : sFullPath = sResolvedDir +
922 7335 : OUString("/") + (*i);
923 :
924 :
925 1471 : sFilePath = resolveFilePath(sFullPath);
926 :
927 1471 : if (sFilePath.isEmpty())
928 : {
929 : //The file path (to java exe) is not valid
930 1463 : cit_path ifull = find(vecBadPaths.begin(), vecBadPaths.end(), sFullPath);
931 1463 : if (ifull == vecBadPaths.end())
932 87 : vecBadPaths.push_back(sFullPath);
933 1463 : continue;
934 : }
935 :
936 8 : cit_path ifile = find(vecBadPaths.begin(), vecBadPaths.end(), sFilePath);
937 8 : if (ifile != vecBadPaths.end())
938 0 : continue;
939 :
940 8 : MapIt entry = mapJREs.find(sFilePath);
941 8 : if (entry != mapJREs.end())
942 : {
943 : JFW_TRACE2(OUString("[Java framework] sunjavaplugin")
944 : + SAL_DLLEXTENSION + ": "
945 : + "JRE found again (detected before): " + sFilePath
946 : + ".\n");
947 :
948 6 : return entry->second;
949 : }
950 :
951 2 : bool bProcessRun= false;
952 2 : if (getJavaProps(sFilePath,
953 : #ifdef JVM_ONE_PATH_CHECK
954 : sResolvedDir,
955 : #endif
956 2 : props, & bProcessRun) == false)
957 : {
958 : //The java executable could not be run or the system properties
959 : //could not be retrieved. We can assume that this java is corrupt.
960 0 : vecBadPaths.push_back(sFilePath);
961 : //If there was a java executable, that could be run but we did not get
962 : //the system properties, then we also assume that the whole Java installation
963 : //does not work. In a jdk there are two executables. One in jdk/bin and the other
964 : //in jdk/jre/bin. We do not search any further, because we assume that if one java
965 : //does not work then the other does not work as well. This saves us to run java
966 : //again which is quite costly.
967 0 : if (bProcessRun == true)
968 : {
969 : // 1.3.1 special treatment: jdk/bin/java and /jdk/jre/bin/java are links to
970 : //a script, named .java_wrapper. The script starts jdk/bin/sparc/native_threads/java
971 : //or jdk/jre/bin/sparc/native_threads/java. The script uses the name with which it was
972 : //invoked to build the path to the executable. It we start the script directy as .java_wrapper
973 : //then it tries to start a jdk/.../native_threads/.java_wrapper. Therefore the link, which
974 : //is named java, must be used to start the script.
975 : getJavaProps(sFullPath,
976 : #ifdef JVM_ONE_PATH_CHECK
977 : sResolvedDir,
978 : #endif
979 0 : props, & bProcessRun);
980 : // Either we found a working 1.3.1
981 : //Or the java is broken. In both cases we stop searchin under this "root" directory
982 0 : bBreak = true;
983 0 : break;
984 : }
985 : //sFilePath is no working java executable. We continue with another possible
986 : //path.
987 : else
988 : {
989 0 : continue;
990 : }
991 : }
992 : //sFilePath is a java and we could get the system properties. We proceed with this
993 : //java.
994 : else
995 : {
996 2 : bBreak = true;
997 2 : break;
998 : }
999 0 : }
1000 506 : if (bBreak)
1001 2 : break;
1002 504 : }
1003 :
1004 58 : if (props.empty())
1005 56 : return rtl::Reference<VendorBase>();
1006 :
1007 : //find java.vendor property
1008 : typedef vector<pair<OUString, OUString> >::const_iterator c_ip;
1009 4 : OUString sVendor("java.vendor");
1010 4 : OUString sVendorName;
1011 :
1012 92 : for (c_ip i = props.begin(); i != props.end(); ++i)
1013 : {
1014 92 : if (sVendor.equals(i->first))
1015 : {
1016 2 : sVendorName = i->second;
1017 2 : break;
1018 : }
1019 : }
1020 :
1021 2 : if (!sVendorName.isEmpty())
1022 : {
1023 : //find the creator func for the respective vendor name
1024 8 : for ( sal_Int32 c = 0;
1025 4 : gVendorMap[c].sVendorName != NULL; ++c )
1026 : {
1027 4 : OUString sNameMap(gVendorMap[c].sVendorName, strlen(gVendorMap[c].sVendorName),
1028 4 : RTL_TEXTENCODING_ASCII_US);
1029 4 : if (sNameMap.equals(sVendorName))
1030 : {
1031 2 : ret = createInstance(gVendorMap[c].createFunc, props);
1032 2 : break;
1033 : }
1034 2 : }
1035 : }
1036 2 : if (!ret.is())
1037 0 : vecBadPaths.push_back(sFilePath);
1038 : else
1039 : {
1040 : JFW_TRACE2(OUString("[Java framework] sunjavaplugin")
1041 : + SAL_DLLEXTENSION + ": "
1042 : + "Found JRE: " + sResolvedDir
1043 : + " \n at: " + path + ".\n");
1044 :
1045 2 : mapJREs.insert(MAPJRE::value_type(sResolvedDir, ret));
1046 2 : mapJREs.insert(MAPJRE::value_type(sFilePath, ret));
1047 : }
1048 :
1049 172 : return ret;
1050 : }
1051 :
1052 2 : Reference<VendorBase> createInstance(createInstance_func pFunc,
1053 : vector<pair<OUString, OUString> > properties)
1054 : {
1055 :
1056 2 : Reference<VendorBase> aBase = (*pFunc)();
1057 2 : if (aBase.is())
1058 : {
1059 2 : if (aBase->initialize(properties) == false)
1060 0 : aBase = 0;
1061 : }
1062 2 : return aBase;
1063 : }
1064 :
1065 3 : inline OUString getDirFromFile(const OUString& usFilePath)
1066 : {
1067 3 : sal_Int32 index = usFilePath.lastIndexOf('/');
1068 3 : return usFilePath.copy(0, index);
1069 : }
1070 :
1071 2 : void createJavaInfoFromPath(vector<rtl::Reference<VendorBase> >& vecInfos)
1072 : {
1073 : // Get Java from PATH environment variable
1074 2 : static OUString sCurDir(".");
1075 2 : static OUString sParentDir("..");
1076 2 : char *szPath= getenv("PATH");
1077 2 : if(szPath)
1078 : {
1079 2 : OUString usAllPath(szPath, strlen(szPath), osl_getThreadTextEncoding());
1080 2 : sal_Int32 nIndex = 0;
1081 12 : do
1082 : {
1083 12 : OUString usToken = usAllPath.getToken( 0, SAL_PATHSEPARATOR, nIndex );
1084 24 : OUString usTokenUrl;
1085 12 : if(File::getFileURLFromSystemPath(usToken, usTokenUrl) == File::E_None)
1086 : {
1087 12 : if(!usTokenUrl.isEmpty())
1088 : {
1089 12 : OUString usBin;
1090 : // "."
1091 12 : if(usTokenUrl.equals(sCurDir))
1092 : {
1093 0 : OUString usWorkDirUrl;
1094 0 : if(osl_Process_E_None == osl_getProcessWorkingDir(&usWorkDirUrl.pData))
1095 0 : usBin= usWorkDirUrl;
1096 : }
1097 : // ".."
1098 12 : else if(usTokenUrl.equals(sParentDir))
1099 : {
1100 0 : OUString usWorkDir;
1101 0 : if(osl_Process_E_None == osl_getProcessWorkingDir(&usWorkDir.pData))
1102 0 : usBin= getDirFromFile(usWorkDir);
1103 : }
1104 : else
1105 : {
1106 12 : usBin = usTokenUrl;
1107 : }
1108 12 : if(!usBin.isEmpty())
1109 : {
1110 12 : getJREInfoFromBinPath(usBin, vecInfos);
1111 12 : }
1112 : }
1113 12 : }
1114 : }
1115 14 : while ( nIndex >= 0 );
1116 : }
1117 2 : }
1118 :
1119 2 : void createJavaInfoFromJavaHome(vector<rtl::Reference<VendorBase> >& vecInfos)
1120 : {
1121 : // Get Java from JAVA_HOME environment
1122 2 : char *szJavaHome= getenv("JAVA_HOME");
1123 2 : if(szJavaHome)
1124 : {
1125 0 : OUString sHome(szJavaHome,strlen(szJavaHome),osl_getThreadTextEncoding());
1126 0 : OUString sHomeUrl;
1127 0 : if(File::getFileURLFromSystemPath(sHome, sHomeUrl) == File::E_None)
1128 : {
1129 0 : getJREInfoByPath(sHomeUrl, vecInfos);
1130 0 : }
1131 : }
1132 2 : }
1133 :
1134 2 : bool makeDriveLetterSame(OUString * fileURL)
1135 : {
1136 2 : bool ret = false;
1137 2 : DirectoryItem item;
1138 2 : if (DirectoryItem::get(*fileURL, item) == File::E_None)
1139 : {
1140 2 : FileStatus status(osl_FileStatus_Mask_FileURL);
1141 2 : if (item.getFileStatus(status) == File::E_None)
1142 : {
1143 2 : *fileURL = status.getFileURL();
1144 2 : ret = true;
1145 2 : }
1146 : }
1147 2 : return ret;
1148 : }
1149 :
1150 : #ifdef UNX
1151 : #ifdef SOLARIS
1152 :
1153 : void createJavaInfoDirScan(vector<rtl::Reference<VendorBase> >& vecInfos)
1154 : {
1155 : JFW_TRACE2("\n[Java framework] Checking \"/usr/jdk/latest\"\n");
1156 : getJREInfoByPath("file:////usr/jdk/latest", vecInfos);
1157 : }
1158 :
1159 : #elif defined MACOSX && defined X86_64
1160 :
1161 : void createJavaInfoDirScan(vector<rtl::Reference<VendorBase> >& vecInfos)
1162 : {
1163 : // Oracle Java 7
1164 : getJREInfoByPath("file:///Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home", vecInfos);
1165 : }
1166 :
1167 : #else
1168 2 : void createJavaInfoDirScan(vector<rtl::Reference<VendorBase> >& vecInfos)
1169 : {
1170 : OUString excMessage = "[Java framework] sunjavaplugin: "
1171 2 : "Error in function createJavaInfoDirScan in util.cxx.";
1172 2 : int cJavaNames= sizeof(g_arJavaNames) / sizeof(char*);
1173 4 : boost::scoped_array<OUString> sarJavaNames(new OUString[cJavaNames]);
1174 2 : OUString *arNames = sarJavaNames.get();
1175 20 : for(int i= 0; i < cJavaNames; i++)
1176 36 : arNames[i] = OUString(g_arJavaNames[i], strlen(g_arJavaNames[i]),
1177 18 : RTL_TEXTENCODING_UTF8);
1178 :
1179 2 : int cSearchPaths= sizeof(g_arSearchPaths) / sizeof(char*);
1180 4 : boost::scoped_array<OUString> sarPathNames(new OUString[cSearchPaths]);
1181 2 : OUString *arPaths = sarPathNames.get();
1182 16 : for(int c = 0; c < cSearchPaths; c++)
1183 28 : arPaths[c] = OUString(g_arSearchPaths[c], strlen(g_arSearchPaths[c]),
1184 14 : RTL_TEXTENCODING_UTF8);
1185 :
1186 2 : int cCollectDirs = sizeof(g_arCollectDirs) / sizeof(char*);
1187 4 : boost::scoped_array<OUString> sarCollectDirs(new OUString[cCollectDirs]);
1188 2 : OUString *arCollectDirs = sarCollectDirs.get();
1189 18 : for(int d = 0; d < cCollectDirs; d++)
1190 32 : arCollectDirs[d] = OUString(g_arCollectDirs[d], strlen(g_arCollectDirs[d]),
1191 16 : RTL_TEXTENCODING_UTF8);
1192 :
1193 :
1194 :
1195 4 : OUString usFile("file:///");
1196 16 : for( int ii = 0; ii < cSearchPaths; ii ++)
1197 : {
1198 14 : OUString usDir1(usFile + arPaths[ii]);
1199 28 : DirectoryItem item;
1200 14 : if(DirectoryItem::get(usDir1, item) == File::E_None)
1201 : {
1202 90 : for(int j= 0; j < cCollectDirs; j++)
1203 : {
1204 80 : OUString usDir2(usDir1 + arCollectDirs[j]);
1205 : // prevent that we scan the whole /usr, /usr/lib, etc directories
1206 80 : if (!arCollectDirs[j].isEmpty())
1207 : {
1208 : //usr/java/xxx
1209 : //Examin every subdirectory
1210 70 : Directory aCollectionDir(usDir2);
1211 :
1212 70 : Directory::RC openErr = aCollectionDir.open();
1213 70 : switch (openErr)
1214 : {
1215 : case File::E_None:
1216 4 : break;
1217 : case File::E_NOENT:
1218 : case File::E_NOTDIR:
1219 66 : continue;
1220 : case File::E_ACCES:
1221 : JFW_TRACE2(OUString("[Java framework] sunjavaplugin: ")
1222 : + "Could not read directory " + usDir2
1223 : + " because of missing access rights.");
1224 0 : continue;
1225 : default:
1226 : JFW_TRACE2(OUString("[Java framework] sunjavaplugin: ")
1227 : + "Could not read directory "
1228 : + usDir2 + ". Osl file error: "
1229 : + OUString::number(openErr));
1230 0 : continue;
1231 : }
1232 :
1233 4 : DirectoryItem curIt;
1234 4 : File::RC errNext = File::E_None;
1235 30 : while( (errNext = aCollectionDir.getNextItem(curIt)) == File::E_None)
1236 : {
1237 22 : FileStatus aStatus(osl_FileStatus_Mask_FileURL);
1238 22 : File::RC errStatus = File::E_None;
1239 22 : if ((errStatus = curIt.getFileStatus(aStatus)) != File::E_None)
1240 : {
1241 : JFW_TRACE2(excMessage + "getFileStatus failed with error "
1242 : + OUString::number(errStatus));
1243 0 : continue;
1244 : }
1245 : JFW_TRACE2(OUString("[Java framework] sunjavaplugin: ") +
1246 : "Checking if directory: " + aStatus.getFileURL() +
1247 : " is a Java. \n");
1248 :
1249 22 : getJREInfoByPath(aStatus.getFileURL(),vecInfos);
1250 22 : }
1251 :
1252 : JFW_ENSURE(errNext == File::E_None || errNext == File::E_NOENT,
1253 : OUString("[Java framework] sunjavaplugin: ")
1254 : + "Error while iterating over contens of "
1255 : + usDir2 + ". Osl file error: "
1256 4 : + OUString::number(openErr));
1257 : }
1258 : else
1259 : {
1260 : //usr/java
1261 : //When we look directly into a dir like /usr, /usr/lib, etc. then we only
1262 : //look for certain java directories, such as jre, jdk, etc. Whe do not want
1263 : //to examine the whole directory because of performance reasons.
1264 10 : DirectoryItem item2;
1265 10 : if(DirectoryItem::get(usDir2, item2) == File::E_None)
1266 : {
1267 100 : for( int k= 0; k < cJavaNames; k++)
1268 : {
1269 : // /usr/java/j2re1.4.0
1270 90 : OUString usDir3(usDir2 + arNames[k]);
1271 :
1272 180 : DirectoryItem item3;
1273 90 : if(DirectoryItem::get(usDir3, item) == File::E_None)
1274 : {
1275 : //remove trailing '/'
1276 14 : sal_Int32 islash = usDir3.lastIndexOf('/');
1277 28 : if (islash == usDir3.getLength() - 1
1278 24 : && (islash
1279 10 : > RTL_CONSTASCII_LENGTH("file://")))
1280 8 : usDir3 = usDir3.copy(0, islash);
1281 14 : getJREInfoByPath(usDir3,vecInfos);
1282 : }
1283 90 : }
1284 10 : }
1285 : }
1286 14 : }
1287 : }
1288 16 : }
1289 2 : }
1290 : #endif // ifdef SOLARIS
1291 : #endif // ifdef UNX
1292 : }
1293 :
1294 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|