1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: util.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_jvmfwk.hxx"
36 #include "osl/process.h"
37 #include "osl/security.hxx"
38 #include "osl/thread.hxx"
39 #include "osl/file.hxx"
40 #include "osl/module.hxx"
41 #include "rtl/byteseq.hxx"
42 #include "rtl/ustrbuf.hxx"
43 #include "rtl/instance.hxx"
44 #include "boost/scoped_array.hpp"
45 #include "com/sun/star/uno/Sequence.hxx"
52 #pragma warning(push, 1)
62 #include "vendorlist.hxx"
63 #include "diagnostics.h"
68 #define CHAR_POINTER(oustr) ::rtl::OUStringToOString(oustr,RTL_TEXTENCODING_UTF8).pData->buffer
69 #define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) )
71 #define HKEY_SUN_JRE L"Software\\JavaSoft\\Java Runtime Environment"
72 #define HKEY_SUN_SDK L"Software\\JavaSoft\\Java Development Kit"
77 char const *g_arJavaNames
[] = {
88 /* These are directory names which could contain multiple java installations.
90 char const *g_arCollectDirs
[] = {
101 /* These are directories in which a java installation is
104 char const *g_arSearchPaths
[] = {
107 "System/Library/Frameworks/JavaVM.framework/Versions/1.4.2/"
112 "usr/local/IBMJava2-ppc-142",
113 "usr/local/j2sdk1.3.1",
126 extern VendorSupportMapEntry gVendorMap
[];
128 bool getSDKInfoFromRegistry(vector
<OUString
> & vecHome
);
129 bool getJREInfoFromRegistry(vector
<OUString
>& vecJavaHome
);
130 rtl::OUString
decodeOutput(const rtl::OString
& s
);
136 rtl::OUString
getLibraryLocation()
138 rtl::OUString libraryFileUrl
;
139 OSL_VERIFY(osl::Module::getUrlFromAddress((void *)(sal_IntPtr
)getLibraryLocation
, libraryFileUrl
));
140 return getDirFromFile(libraryFileUrl
);
145 rtl::Bootstrap
* operator()(const OUString
& sIni
)
147 static rtl::Bootstrap
aInstance(sIni
);
153 struct InitBootstrapData
155 OUString
const & operator()()
157 // osl::Guard<osl::Mutex> g(osl::GetGlobalMutex());
158 static OUString sIni
;
159 rtl::OUStringBuffer
buf( 255);
160 buf
.append( getLibraryLocation());
161 buf
.appendAscii( SAL_CONFIGFILE("/sunjavaplugin") );
162 sIni
= buf
.makeStringAndClear();
163 JFW_TRACE2(OUSTR("[Java framework] sunjavaplugin: "
164 "Using configuration file \n") + sIni
);
170 rtl::Bootstrap
* getBootstrap()
172 return rtl_Instance
< rtl::Bootstrap
, InitBootstrap
,
173 ::osl::MutexGuard
, ::osl::GetGlobalMutex
,
174 OUString
, InitBootstrapData
>::create(
175 InitBootstrap(), ::osl::GetGlobalMutex(), InitBootstrapData());
181 class FileHandleGuard
184 inline FileHandleGuard(oslFileHandle
& rHandle
) SAL_THROW(()):
185 m_rHandle(rHandle
) {}
187 inline ~FileHandleGuard() SAL_THROW(());
189 inline oslFileHandle
& getHandle() SAL_THROW(()) { return m_rHandle
; }
192 oslFileHandle
& m_rHandle
;
194 FileHandleGuard(FileHandleGuard
&); // not implemented
195 void operator =(FileHandleGuard
); // not implemented
198 inline FileHandleGuard::~FileHandleGuard() SAL_THROW(())
202 if (osl_closeFile(m_rHandle
) != osl_File_E_None
)
204 OSL_ENSURE(false, "unexpected situation");
210 class FileHandleReader
220 inline FileHandleReader(oslFileHandle
& rHandle
) SAL_THROW(()):
221 m_aGuard(rHandle
), m_nSize(0), m_nIndex(0), m_bLf(false) {}
223 Result
readLine(rtl::OString
* pLine
) SAL_THROW(());
226 enum { BUFFER_SIZE
= 1024 };
228 sal_Char m_aBuffer
[BUFFER_SIZE
];
229 FileHandleGuard m_aGuard
;
235 FileHandleReader::Result
236 FileHandleReader::readLine(rtl::OString
* pLine
)
239 OSL_ENSURE(pLine
, "specification violation");
241 for (bool bEof
= true;; bEof
= false)
243 if (m_nIndex
== m_nSize
)
245 sal_uInt64 nRead
= 0;
246 switch (osl_readFile(
247 m_aGuard
.getHandle(), m_aBuffer
, sizeof(m_aBuffer
), &nRead
))
249 case osl_File_E_PIPE
: //HACK! for windows
251 case osl_File_E_None
:
255 return bEof
? RESULT_EOF
: RESULT_OK
;
258 m_nSize
= static_cast< int >(nRead
);
260 case osl_File_E_INTR
:
268 if (m_bLf
&& m_aBuffer
[m_nIndex
] == 0x0A)
272 int nStart
= m_nIndex
;
273 while (m_nIndex
!= m_nSize
)
274 switch (m_aBuffer
[m_nIndex
++])
279 *pLine
+= rtl::OString(m_aBuffer
+ nStart
,
280 m_nIndex
- 1 - nStart
);
281 //TODO! check for overflow, and not very efficient
285 *pLine
+= rtl::OString(m_aBuffer
+ nStart
, m_nIndex
- nStart
);
286 //TODO! check for overflow, and not very efficient
290 class AsynchReader
: public Thread
293 boost::scoped_array
<sal_Char
> m_arData
;
297 FileHandleGuard m_aGuard
;
302 AsynchReader(oslFileHandle
& rHandle
);
304 /** only call this function after this thread has finished.
306 That is, call join on this instance and then call getData.
312 AsynchReader::AsynchReader(oslFileHandle
& rHandle
):
313 m_nDataSize(0), m_bError(false), m_bDone(false), m_aGuard(rHandle
)
317 OString
AsynchReader::getData()
319 OSL_ASSERT(isRunning() == sal_False
);
320 return OString(m_arData
.get(), m_nDataSize
);
323 void AsynchReader::run()
325 const sal_uInt64 BUFFER_SIZE
= 4096;
326 sal_Char aBuffer
[BUFFER_SIZE
];
330 //the function blocks until something could be read or the pipe closed.
331 switch (osl_readFile(
332 m_aGuard
.getHandle(), aBuffer
, BUFFER_SIZE
, &nRead
))
334 case osl_File_E_PIPE
: //HACK! for windows
336 case osl_File_E_None
:
348 else if (nRead
<= BUFFER_SIZE
)
350 //Save the data we have in m_arData into a temporary array
351 boost::scoped_array
<sal_Char
> arTmp( new sal_Char
[m_nDataSize
]);
352 memcpy(arTmp
.get(), m_arData
.get(), m_nDataSize
);
353 //Enlarge m_arData to hold the newly read data
354 m_arData
.reset(new sal_Char
[(size_t)(m_nDataSize
+ nRead
)]);
355 //Copy back the data that was already in m_arData
356 memcpy(m_arData
.get(), arTmp
.get(), m_nDataSize
);
357 //Add the newly read data to m_arData
358 memcpy(m_arData
.get() + m_nDataSize
, aBuffer
, (size_t) nRead
);
359 m_nDataSize
+= (size_t) nRead
;
365 bool getJavaProps(const OUString
& exePath
,
366 std::vector
<std::pair
<rtl::OUString
, rtl::OUString
> >& props
,
371 OSL_ASSERT( exePath
.getLength() > 0);
373 //We need to set the CLASSPATH in case the office is started from
374 //a different directory. The JREProperties.class is expected to reside
375 //next to the plugin.
376 rtl::OUString sThisLib
;
377 if (osl_getModuleURLFromAddress((void *) (sal_IntPtr
)& getJavaProps
,
378 & sThisLib
.pData
) == sal_False
)
380 sThisLib
= getDirFromFile(sThisLib
);
382 if (osl_getSystemPathFromFileURL(sThisLib
.pData
, & sClassPath
.pData
)
386 //check if we shall examine a Java for accessibility support
387 //If the bootstrap variable is "1" then we pass the argument
388 //"noaccessibility" to JREProperties.class. This will prevent
389 //that it calls java.awt.Toolkit.getDefaultToolkit();
391 getBootstrap()->getFrom(OUSTR("JFW_PLUGIN_DO_NOT_CHECK_ACCESSIBILITY"), sValue
);
393 //prepare the arguments
395 OUString arg1
= OUString(RTL_CONSTASCII_USTRINGPARAM("-classpath"));// + sClassPath;
396 OUString arg2
= sClassPath
;
397 OUString
arg3(RTL_CONSTASCII_USTRINGPARAM("JREProperties"));
398 OUString arg4
= OUSTR("noaccessibility");
399 rtl_uString
*args
[4] = {arg1
.pData
, arg2
.pData
, arg3
.pData
};
401 // Only add the fourth param if the bootstrap parameter is set.
402 if (sValue
.equals(OUString::valueOf((sal_Int32
) 1)))
404 args
[3] = arg4
.pData
;
408 oslProcess javaProcess
= 0;
409 oslFileHandle fileOut
= 0;
410 oslFileHandle fileErr
= 0;
412 FileHandleReader
stdoutReader(fileOut
);
413 AsynchReader
stderrReader(fileErr
);
415 JFW_TRACE2(OUSTR("\n[Java framework] Executing: ") + exePath
+ OUSTR(".\n"));
416 oslProcessError procErr
=
417 osl_executeProcess_WithRedirectedIO( exePath
.pData
,//usExe.pData,
419 cArgs
, //sal_uInt32 nArguments,
420 osl_Process_HIDDEN
, //oslProcessOption Options,
421 NULL
, //oslSecurity Security,
422 usStartDir
.pData
,//usStartDir.pData,//usWorkDir.pData, //rtl_uString *strWorkDir,
423 NULL
, //rtl_uString *strEnvironment[],
424 0, // sal_uInt32 nEnvironmentVars,
425 &javaProcess
, //oslProcess *pProcess,
426 NULL
,//oslFileHandle *pChildInputWrite,
427 &fileOut
,//oslFileHandle *pChildOutputRead,
428 &fileErr
);//oslFileHandle *pChildErrorRead);
430 if( procErr
!= osl_Process_E_None
)
432 JFW_TRACE2("[Java framework] Execution failed. \n");
433 *bProcessRun
= false;
438 JFW_TRACE2("[Java framework] Java executed successfully.\n");
442 //Start asynchronous reading (different thread) of error stream
443 stderrReader
.create();
445 //Use this thread to read output stream
446 FileHandleReader::Result rs
= FileHandleReader::RESULT_OK
;
450 rs
= stdoutReader
.readLine( & aLine
);
451 if (rs
!= FileHandleReader::RESULT_OK
)
453 JFW_TRACE2(OString("[Java framework] line:\" ")
454 + aLine
+ OString(" \".\n"));
455 OUString sLine
= decodeOutput(aLine
);
456 JFW_TRACE2(OString("[Java framework] line:\" ")
457 + OString( CHAR_POINTER(sLine
)) + OString(" \".\n"));
458 sLine
= sLine
.trim();
459 if (sLine
.getLength() == 0)
461 //The JREProperties class writes key value pairs, separated by '='
462 sal_Int32 index
= sLine
.indexOf('=', 0);
463 OSL_ASSERT(index
!= -1);
464 OUString sKey
= sLine
.copy(0, index
);
465 OUString sVal
= sLine
.copy(index
+ 1);
467 props
.push_back(std::make_pair(sKey
, sVal
));
470 if (rs
!= FileHandleReader::RESULT_ERROR
&& props
.size()>0)
473 //process error stream data
475 JFW_TRACE2(OString("[Java framework] Java wrote to stderr:\" ")
476 + stderrReader
.getData() + OString(" \".\n"));
478 TimeValue waitMax
= {5 ,0};
479 procErr
= osl_joinProcessWithTimeout(javaProcess
, &waitMax
);
480 OSL_ASSERT(procErr
== osl_Process_E_None
);
481 osl_freeProcessHandle(javaProcess
);
485 /* converts the properties printed by JREProperties.class into
486 readable strings. The strings are encoded as integer values separated
489 rtl::OUString
decodeOutput(const rtl::OString
& s
)
491 OUStringBuffer
buff(512);
492 sal_Int32 nIndex
= 0;
495 OString aToken
= s
.getToken( 0, ' ', nIndex
);
496 if (aToken
.getLength())
498 sal_Unicode value
= (sal_Unicode
)(aToken
.toInt32());
501 } while (nIndex
>= 0);
503 OUString
sDecoded(buff
.makeStringAndClear());
504 JFW_TRACE2(sDecoded
);
510 void createJavaInfoFromWinReg(std::vector
<rtl::Reference
<VendorBase
> > & vecInfos
)
512 // Get Java s from registry
513 std::vector
<OUString
> vecJavaHome
;
514 if(getSDKInfoFromRegistry(vecJavaHome
))
516 // create impl objects
517 typedef std::vector
<OUString
>::iterator ItHome
;
518 for(ItHome it_home
= vecJavaHome
.begin(); it_home
!= vecJavaHome
.end();
521 getJREInfoByPath(*it_home
, vecInfos
);
526 if(getJREInfoFromRegistry(vecJavaHome
))
528 typedef std::vector
<OUString
>::iterator ItHome
;
529 for(ItHome it_home
= vecJavaHome
.begin(); it_home
!= vecJavaHome
.end();
532 getJREInfoByPath(*it_home
, vecInfos
);
538 bool getJavaInfoFromRegistry(const wchar_t* szRegKey
,
539 vector
<OUString
>& vecJavaHome
)
542 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, szRegKey
, 0, KEY_ENUMERATE_SUB_KEYS
, &hRoot
)
546 const DWORD BUFFSIZE
= 1024;
547 wchar_t bufVersion
[BUFFSIZE
];
548 // char bufVersion[BUFFSIZE];
549 DWORD nNameLen
= BUFFSIZE
;
551 nNameLen
= sizeof(bufVersion
);
553 // Iterate over all subkeys of HKEY_LOCAL_MACHINE\Software\JavaSoft\Java Runtime Environment
554 while (RegEnumKeyExW(hRoot
, dwIndex
, bufVersion
, &nNameLen
, NULL
, NULL
, NULL
, &fileTime
) != ERROR_NO_MORE_ITEMS
)
557 // Open a Java Runtime Environment sub key, e.g. "1.4.0"
558 if (RegOpenKeyExW(hRoot
, bufVersion
, 0, KEY_QUERY_VALUE
, &hKey
) == ERROR_SUCCESS
)
561 DWORD dwTmpPathLen
= 0;
562 // Get the path to the JavaHome every JRE entry
563 // Find out how long the string for JavaHome is and allocate memory to hold the path
564 if( RegQueryValueExW(hKey
, L
"JavaHome", 0, &dwType
, NULL
, &dwTmpPathLen
)== ERROR_SUCCESS
)
566 char* szTmpPath
= (char *) malloc( dwTmpPathLen
);
567 // Get the path for the runtime lib
568 if(RegQueryValueExW(hKey
, L
"JavaHome", 0, &dwType
, (unsigned char*) szTmpPath
, &dwTmpPathLen
) == ERROR_SUCCESS
)
570 // There can be several version entries refering with the same JavaHome,e.g 1.4 and 1.4.1
571 OUString
usHome((sal_Unicode
*) szTmpPath
);
572 // check if there is already an entry with the same JavaHomeruntime lib
573 // if so, we use the one with the more accurate version
576 if (osl_getFileURLFromSystemPath(usHome
.pData
, & usHomeUrl
.pData
) ==
579 //iterate over the vector with java home strings
580 typedef vector
<OUString
>::iterator ItHome
;
581 for(ItHome itHome
= vecJavaHome
.begin();
582 itHome
!= vecJavaHome
.end(); itHome
++)
584 if(usHomeUrl
.equals(*itHome
))
593 vecJavaHome
.push_back(usHomeUrl
);
611 bool getSDKInfoFromRegistry(vector
<OUString
> & vecHome
)
613 return getJavaInfoFromRegistry(HKEY_SUN_SDK
, vecHome
);
616 bool getJREInfoFromRegistry(vector
<OUString
>& vecJavaHome
)
618 return getJavaInfoFromRegistry(HKEY_SUN_JRE
, vecJavaHome
);
623 void bubbleSortVersion(vector
<rtl::Reference
<VendorBase
> >& vec
)
627 int size
= vec
.size() - 1;
630 for(int i
= 0; i
< size
; i
++)
632 for(int j
= size
; j
> 0 + cIter
; j
--)
634 rtl::Reference
<VendorBase
>& cur
= vec
.at(j
);
635 rtl::Reference
<VendorBase
>& next
= vec
.at(j
-1);
638 // comparing invalid SunVersion s is possible, they will be less than a
641 //check if version of current is recognized, by comparing it with itself
644 cur
->compareVersions(cur
->getVersion());
646 catch (MalformedVersionException
&)
648 nCmp
= -1; // current < next
650 //The version of cur is valid, now compare with the second version
655 nCmp
= cur
->compareVersions(next
->getVersion());
657 catch (MalformedVersionException
& )
659 //The second version is invalid, therefor it is regardes less.
663 if(nCmp
== 1) // cur > next
665 rtl::Reference
<VendorBase
> less
= next
;
675 bool getJREInfoFromBinPath(
676 const rtl::OUString
& path
, vector
<rtl::Reference
<VendorBase
> > & vecInfos
)
678 // file:///c:/jre/bin
679 //map: jre/bin/java.exe
681 vector
<pair
<OUString
, OUString
> > props
;
683 for ( sal_Int32 pos
= 0;
684 gVendorMap
[pos
].sVendorName
!= NULL
; ++pos
)
686 vector
<OUString
> vecPaths
;
687 getJavaExePaths_func pFunc
= gVendorMap
[pos
].getJavaFunc
;
690 char const* const* arExePaths
= (*pFunc
)(&size
);
691 vecPaths
= getVectorFromCharArray(arExePaths
, size
);
693 //make sure argument path does not end with '/'
694 OUString sBinPath
= path
;
695 if (path
.lastIndexOf('/') == (path
.getLength() - 1))
696 sBinPath
= path
.copy(0, path
.getLength() - 1);
698 typedef vector
<OUString
>::const_iterator c_it
;
699 for (c_it i
= vecPaths
.begin(); i
!= vecPaths
.end(); i
++)
701 //the map contains e.g. jre/bin/java.exe
702 //get the directory where the executable is contained
704 sal_Int32 index
= i
->lastIndexOf('/');
707 //map contained only : "java.exe, then the argument
708 //path is already the home directory
713 // jre/bin/jre -> jre/bin
714 OUString
sMapPath(i
->getStr(), index
);
715 index
= sBinPath
.lastIndexOf(sMapPath
);
717 && (index
+ sMapPath
.getLength() == sBinPath
.getLength())
718 && sBinPath
[index
- 1] == '/')
720 sHome
= OUString(sBinPath
.getStr(), index
- 1);
723 if (sHome
.getLength() > 0)
725 ret
= getJREInfoByPath(sHome
, vecInfos
);
736 vector
<Reference
<VendorBase
> > getAllJREInfos()
738 vector
<Reference
<VendorBase
> > vecInfos
;
741 // Get Javas from the registry
742 createJavaInfoFromWinReg(vecInfos
);
745 createJavaInfoFromJavaHome(vecInfos
);
746 //this function should be called after createJavaInfoDirScan.
747 //Otherwise in SDKs Java may be started twice
748 createJavaInfoFromPath(vecInfos
);
751 createJavaInfoDirScan(vecInfos
);
754 bubbleSortVersion(vecInfos
);
759 vector
<OUString
> getVectorFromCharArray(char const * const * ar
, int size
)
761 vector
<OUString
> vec
;
762 for( int i
= 0; i
< size
; i
++)
764 OUString
s(ar
[i
], strlen(ar
[i
]), RTL_TEXTENCODING_UTF8
);
769 bool getJREInfoByPath(const rtl::OUString
& path
,
770 std::vector
<rtl::Reference
<VendorBase
> > & vecInfos
)
774 rtl::Reference
<VendorBase
> aInfo
= getJREInfoByPath(path
);
778 vector
<rtl::Reference
<VendorBase
> >::const_iterator it_impl
= std::find_if(
779 vecInfos
.begin(),vecInfos
.end(), InfoFindSame(aInfo
->getHome()));
780 if(it_impl
== vecInfos
.end())
782 vecInfos
.push_back(aInfo
);
788 /** Checks if the path is a directory. Links are resolved.
789 In case of an error the returned string has the length 0.
790 Otherwise the returned string is the "resolved" file URL.
792 OUString
resolveDirPath(const OUString
& path
)
796 if (File::getAbsoluteFileURL(
797 rtl::OUString(), path
, sResolved
) != File::E_None
)
800 //check if this is a valid path and if it is a directory
802 if (DirectoryItem::get(sResolved
, item
) == File::E_None
)
804 FileStatus
status(FileStatusMask_Type
|
805 FileStatusMask_LinkTargetURL
|
806 FileStatusMask_FileURL
);
808 if (item
.getFileStatus(status
) == File::E_None
809 && status
.getFileType() == FileStatus::Directory
)
818 /** Checks if the path is a file. If it is a link to a file than
821 OUString
resolveFilePath(const OUString
& path
)
826 if (File::getAbsoluteFileURL(
827 rtl::OUString(), path
, sResolved
) != File::E_None
)
830 //check if this is a valid path to a file or and if it is a link
832 if (DirectoryItem::get(sResolved
, item
) == File::E_None
)
834 FileStatus
status(FileStatusMask_Type
|
835 FileStatusMask_LinkTargetURL
|
836 FileStatusMask_FileURL
);
837 if (item
.getFileStatus(status
) == File::E_None
838 && status
.getFileType() == FileStatus::Regular
)
849 rtl::Reference
<VendorBase
> getJREInfoByPath(
850 const OUString
& path
)
852 rtl::Reference
<VendorBase
> ret
;
853 static vector
<OUString
> vecBadPaths
;
855 static map
<OUString
, rtl::Reference
<VendorBase
> > mapJREs
;
856 typedef map
<OUString
, rtl::Reference
<VendorBase
> >::const_iterator MapIt
;
857 typedef map
<OUString
, rtl::Reference
<VendorBase
> > MAPJRE
;
859 typedef vector
<OUString
>::const_iterator cit_path
;
860 vector
<pair
<OUString
, OUString
> > props
;
862 OUString sResolvedDir
= resolveDirPath(path
);
863 // If this path is invalid then there is no chance to find a JRE here
864 if (sResolvedDir
.getLength() == 0)
867 //check if the directory path is good, that is a JRE was already recognized.
868 //Then we need not detect it again
869 //For example, a sun JKD contains <jdk>/bin/java and <jdk>/jre/bin/java.
870 //When <jdk>/bin/java has been found then we need not find <jdk>/jre/bin/java.
871 //Otherwise we would execute java two times for evers JDK found.
872 MapIt entry2
= find_if(mapJREs
.begin(), mapJREs
.end(),
873 SameOrSubDirJREMap(sResolvedDir
));
874 if (entry2
!= mapJREs
.end())
876 JFW_TRACE2(OUSTR("[Java framework] sunjavaplugin"SAL_DLLEXTENSION
": ")
877 + OUSTR("JRE found again (detected before): ") + sResolvedDir
879 return entry2
->second
;
882 for ( sal_Int32 pos
= 0;
883 gVendorMap
[pos
].sVendorName
!= NULL
; ++pos
)
885 vector
<OUString
> vecPaths
;
886 getJavaExePaths_func pFunc
= gVendorMap
[pos
].getJavaFunc
;
889 char const* const* arExePaths
= (*pFunc
)(&size
);
890 vecPaths
= getVectorFromCharArray(arExePaths
, size
);
893 typedef vector
<OUString
>::const_iterator c_it
;
894 for (c_it i
= vecPaths
.begin(); i
!= vecPaths
.end(); i
++)
896 //if the path is a link, then resolve it
897 //check if the executable exists at all
899 //path can be only "file:///". Then do not append a '/'
900 //sizeof counts the terminating 0
902 if (path
.getLength() == sizeof("file:///") - 1)
903 sFullPath
= sResolvedDir
+ (*i
);
905 sFullPath
= sResolvedDir
+
906 OUString(RTL_CONSTASCII_USTRINGPARAM("/")) + (*i
);
909 sFilePath
= resolveFilePath(sFullPath
);
911 if (sFilePath
.getLength() == 0)
913 //The file path (to java exe) is not valid
914 cit_path ifull
= find(vecBadPaths
.begin(), vecBadPaths
.end(), sFullPath
);
915 if (ifull
== vecBadPaths
.end())
916 vecBadPaths
.push_back(sFullPath
);
920 cit_path ifile
= find(vecBadPaths
.begin(), vecBadPaths
.end(), sFilePath
);
921 if (ifile
!= vecBadPaths
.end())
924 MapIt entry
= mapJREs
.find(sFilePath
);
925 if (entry
!= mapJREs
.end())
927 JFW_TRACE2(OUSTR("[Java framework] sunjavaplugin"SAL_DLLEXTENSION
": ")
928 + OUSTR("JRE found again (detected before): ") + sFilePath
931 return entry
->second
;
934 bool bProcessRun
= false;
935 if (getJavaProps(sFilePath
, props
, & bProcessRun
) == false)
937 //The java executable could not be run or the system properties
938 //could not be retrieved. We can assume that this java is corrupt.
939 vecBadPaths
.push_back(sFilePath
);
940 //If there was a java executable, that could be run but we did not get
941 //the system properties, then we also assume that the whole Java installation
942 //does not work. In a jdk there are two executables. One in jdk/bin and the other
943 //in jdk/jre/bin. We do not search any further, because we assume that if one java
944 //does not work then the other does not work as well. This saves us to run java
945 //again which is quite costly.
946 if (bProcessRun
== true)
948 // 1.3.1 special treatment: jdk/bin/java and /jdk/jre/bin/java are links to
949 //a script, named .java_wrapper. The script starts jdk/bin/sparc/native_threads/java
950 //or jdk/jre/bin/sparc/native_threads/java. The script uses the name with which it was
951 //invoked to build the path to the executable. It we start the script directy as .java_wrapper
952 //then it tries to start a jdk/.../native_threads/.java_wrapper. Therefore the link, which
953 //is named java, must be used to start the script.
954 getJavaProps(sFullPath
, props
, & bProcessRun
);
955 // Either we found a working 1.3.1
956 //Or the java is broken. In both cases we stop searchin under this "root" directory
960 //sFilePath is no working java executable. We continue with another possible
967 //sFilePath is a java and we could get the system properties. We proceed with this
979 if (props
.size() == 0)
980 return rtl::Reference
<VendorBase
>();
982 //find java.vendor property
983 typedef vector
<pair
<OUString
, OUString
> >::const_iterator c_ip
;
984 OUString
sVendor(RTL_CONSTASCII_USTRINGPARAM("java.vendor"));
985 OUString sVendorName
;
987 for (c_ip i
= props
.begin(); i
!= props
.end(); i
++)
989 if (sVendor
.equals(i
->first
))
991 sVendorName
= i
->second
;
996 if (sVendorName
.getLength() > 0)
998 //find the creator func for the respective vendor name
999 for ( sal_Int32 c
= 0;
1000 gVendorMap
[c
].sVendorName
!= NULL
; ++c
)
1002 OUString
sNameMap(gVendorMap
[c
].sVendorName
, strlen(gVendorMap
[c
].sVendorName
),
1003 RTL_TEXTENCODING_ASCII_US
);
1004 if (sNameMap
.equals(sVendorName
))
1006 ret
= createInstance(gVendorMap
[c
].createFunc
, props
);
1011 if (ret
.is() == false)
1012 vecBadPaths
.push_back(sFilePath
);
1015 JFW_TRACE2(OUSTR("[Java framework] sunjavaplugin"SAL_DLLEXTENSION
": ")
1016 + OUSTR("Found JRE: ") + sResolvedDir
1017 + OUSTR(" \n at: ") + path
+ OUSTR(".\n"));
1019 mapJREs
.insert(MAPJRE::value_type(sResolvedDir
, ret
));
1020 mapJREs
.insert(MAPJRE::value_type(sFilePath
, ret
));
1026 Reference
<VendorBase
> createInstance(createInstance_func pFunc
,
1027 vector
<pair
<OUString
, OUString
> > properties
)
1030 Reference
<VendorBase
> aBase
= (*pFunc
)();
1033 if (aBase
->initialize(properties
) == false)
1039 inline OUString
getDirFromFile(const OUString
& usFilePath
)
1041 sal_Int32 index
= usFilePath
.lastIndexOf('/');
1042 return OUString(usFilePath
.getStr(), index
);
1045 void createJavaInfoFromPath(vector
<rtl::Reference
<VendorBase
> >& vecInfos
)
1047 // Get Java from PATH environment variable
1048 static OUString
sCurDir(RTL_CONSTASCII_USTRINGPARAM("."));
1049 static OUString
sParentDir(RTL_CONSTASCII_USTRINGPARAM(".."));
1050 char *szPath
= getenv("PATH");
1053 OUString
usAllPath(szPath
, strlen(szPath
), osl_getThreadTextEncoding());
1054 sal_Int32 nIndex
= 0;
1057 OUString usToken
= usAllPath
.getToken( 0, SAL_PATHSEPARATOR
, nIndex
);
1058 OUString usTokenUrl
;
1059 if(File::getFileURLFromSystemPath(usToken
, usTokenUrl
) == File::E_None
)
1061 if(usTokenUrl
.getLength())
1065 if(usTokenUrl
.equals(sCurDir
))
1067 OUString usWorkDirUrl
;
1068 if(osl_Process_E_None
== osl_getProcessWorkingDir(&usWorkDirUrl
.pData
))
1069 usBin
= usWorkDirUrl
;
1072 else if(usTokenUrl
.equals(sParentDir
))
1075 if(osl_Process_E_None
== osl_getProcessWorkingDir(&usWorkDir
.pData
))
1076 usBin
= getDirFromFile(usWorkDir
);
1082 if(usBin
.getLength())
1084 getJREInfoFromBinPath(usBin
, vecInfos
);
1089 while ( nIndex
>= 0 );
1093 void createJavaInfoFromJavaHome(vector
<rtl::Reference
<VendorBase
> >& vecInfos
)
1095 // Get Java from JAVA_HOME environment
1096 char *szJavaHome
= getenv("JAVA_HOME");
1099 OUString
sHome(szJavaHome
,strlen(szJavaHome
),osl_getThreadTextEncoding());
1101 if(File::getFileURLFromSystemPath(sHome
, sHomeUrl
) == File::E_None
)
1103 getJREInfoByPath(sHomeUrl
, vecInfos
);
1108 bool makeDriveLetterSame(OUString
* fileURL
)
1112 if (DirectoryItem::get(*fileURL
, item
) == File::E_None
)
1114 FileStatus
status(FileStatusMask_FileURL
);
1115 if (item
.getFileStatus(status
) == File::E_None
)
1117 *fileURL
= status
.getFileURL();
1127 void createJavaInfoDirScan(vector
<rtl::Reference
<VendorBase
> >& vecInfos
)
1129 JFW_TRACE2(OUSTR("\n[Java framework] Checking \"/usr/jdk/latest\"\n"));
1130 getJREInfoByPath(OUSTR("file:////usr/jdk/latest"), vecInfos
);
1134 void createJavaInfoDirScan(vector
<rtl::Reference
<VendorBase
> >& vecInfos
)
1136 OUString excMessage
= OUSTR("[Java framework] sunjavaplugin: "
1137 "Error in function createJavaInfoDirScan in util.cxx.");
1138 int cJavaNames
= sizeof(g_arJavaNames
) / sizeof(char*);
1139 boost::scoped_array
<OUString
> sarJavaNames(new OUString
[cJavaNames
]);
1140 OUString
*arNames
= sarJavaNames
.get();
1141 for(int i
= 0; i
< cJavaNames
; i
++)
1142 arNames
[i
] = OUString(g_arJavaNames
[i
], strlen(g_arJavaNames
[i
]),
1143 RTL_TEXTENCODING_UTF8
);
1145 int cSearchPaths
= sizeof(g_arSearchPaths
) / sizeof(char*);
1146 boost::scoped_array
<OUString
> sarPathNames(new OUString
[cSearchPaths
]);
1147 OUString
*arPaths
= sarPathNames
.get();
1148 for(int c
= 0; c
< cSearchPaths
; c
++)
1149 arPaths
[c
] = OUString(g_arSearchPaths
[c
], strlen(g_arSearchPaths
[c
]),
1150 RTL_TEXTENCODING_UTF8
);
1152 int cCollectDirs
= sizeof(g_arCollectDirs
) / sizeof(char*);
1153 boost::scoped_array
<OUString
> sarCollectDirs(new OUString
[cCollectDirs
]);
1154 OUString
*arCollectDirs
= sarCollectDirs
.get();
1155 for(int d
= 0; d
< cCollectDirs
; d
++)
1156 arCollectDirs
[d
] = OUString(g_arCollectDirs
[d
], strlen(g_arCollectDirs
[d
]),
1157 RTL_TEXTENCODING_UTF8
);
1161 OUString
usFile(RTL_CONSTASCII_USTRINGPARAM("file:///"));
1162 for( int ii
= 0; ii
< cSearchPaths
; ii
++)
1164 OUString
usDir1(usFile
+ arPaths
[ii
]);
1166 if(DirectoryItem::get(usDir1
, item
) == File::E_None
)
1168 for(int j
= 0; j
< cCollectDirs
; j
++)
1170 OUString
usDir2(usDir1
+ arCollectDirs
[j
]);
1171 // prevent that we scan the whole /usr, /usr/lib, etc directories
1172 if (arCollectDirs
[j
] != OUString())
1175 //Examin every subdirectory
1176 Directory
aCollectionDir(usDir2
);
1178 Directory::RC openErr
= aCollectionDir
.open();
1184 case File::E_NOTDIR
:
1187 JFW_TRACE2(OUSTR("[Java framework] sunjavaplugin: "
1188 "Could not read directory ") + usDir2
+
1189 OUSTR(" because of missing access rights."));
1192 JFW_TRACE2(OUSTR("[Java framework] sunjavaplugin: "
1193 "Could not read directory ")
1194 + usDir2
+ OUSTR(". Osl file error: ")
1195 + OUString::valueOf((sal_Int32
) openErr
));
1199 DirectoryItem curIt
;
1200 File::RC errNext
= File::E_None
;
1201 while( (errNext
= aCollectionDir
.getNextItem(curIt
)) == File::E_None
)
1203 FileStatus
aStatus(FileStatusMask_FileURL
);
1204 File::RC errStatus
= File::E_None
;
1205 if ((errStatus
= curIt
.getFileStatus(aStatus
)) != File::E_None
)
1207 JFW_TRACE2(excMessage
+ OUSTR("getFileStatus failed with error ")
1208 + OUString::valueOf((sal_Int32
) errStatus
));
1211 JFW_TRACE2(OUSTR("[Java framework] sunjavaplugin: "
1212 "Checking if directory: ") + aStatus
.getFileURL() +
1213 OUSTR(" is a Java. \n"));
1215 getJREInfoByPath(aStatus
.getFileURL(),vecInfos
);
1218 JFW_ENSURE(errNext
== File::E_None
|| errNext
== File::E_NOENT
,
1219 OUSTR("[Java framework] sunjavaplugin: "
1220 "Error while iterating over contens of ")
1221 + usDir2
+ OUSTR(". Osl file error: ")
1222 + OUString::valueOf((sal_Int32
) openErr
));
1227 //When we look directly into a dir like /usr, /usr/lib, etc. then we only
1228 //look for certain java directories, such as jre, jdk, etc. Whe do not want
1229 //to examine the whole directory because of performance reasons.
1230 DirectoryItem item2
;
1231 if(DirectoryItem::get(usDir2
, item2
) == File::E_None
)
1233 for( int k
= 0; k
< cJavaNames
; k
++)
1235 // /usr/java/j2re1.4.0
1236 OUString
usDir3(usDir2
+ arNames
[k
]);
1238 DirectoryItem item3
;
1239 if(DirectoryItem::get(usDir3
, item
) == File::E_None
)
1241 //remove trailing '/'
1242 sal_Int32 islash
= usDir3
.lastIndexOf('/');
1243 if (islash
== usDir3
.getLength() - 1
1245 > RTL_CONSTASCII_LENGTH("file://")))
1246 usDir3
= usDir3
.copy(0, islash
);
1247 getJREInfoByPath(usDir3
,vecInfos
);
1256 #endif // ifdef SOLARIS