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