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 OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) )
70 #define HKEY_SUN_JRE L"Software\\JavaSoft\\Java Runtime Environment"
71 #define HKEY_SUN_SDK L"Software\\JavaSoft\\Java Development Kit"
76 char const *g_arJavaNames
[] = {
87 /* These are directory names which could contain multiple java installations.
89 char const *g_arCollectDirs
[] = {
100 /* These are directories in which a java installation is
103 char const *g_arSearchPaths
[] = {
106 "System/Library/Frameworks/JavaVM.framework/Versions/1.4.2/"
111 "usr/local/IBMJava2-ppc-142",
112 "usr/local/j2sdk1.3.1",
125 extern VendorSupportMapEntry gVendorMap
[];
127 bool getSDKInfoFromRegistry(vector
<OUString
> & vecHome
);
128 bool getJREInfoFromRegistry(vector
<OUString
>& vecJavaHome
);
129 rtl::OUString
decodeOutput(const rtl::OString
& s
);
135 rtl::OUString
getLibraryLocation()
137 rtl::OUString libraryFileUrl
;
138 OSL_VERIFY(osl::Module::getUrlFromAddress((void *)(sal_IntPtr
)getLibraryLocation
, libraryFileUrl
));
139 return getDirFromFile(libraryFileUrl
);
144 rtl::Bootstrap
* operator()(const OUString
& sIni
)
146 static rtl::Bootstrap
aInstance(sIni
);
152 struct InitBootstrapData
154 OUString
const & operator()()
156 // osl::Guard<osl::Mutex> g(osl::GetGlobalMutex());
157 static OUString sIni
;
158 rtl::OUStringBuffer
buf( 255);
159 buf
.append( getLibraryLocation());
160 buf
.appendAscii( SAL_CONFIGFILE("/sunjavaplugin") );
161 sIni
= buf
.makeStringAndClear();
162 JFW_TRACE2(OUSTR("[Java framework] sunjavaplugin: "
163 "Using configuration file \n") + sIni
);
169 rtl::Bootstrap
* getBootstrap()
171 return rtl_Instance
< rtl::Bootstrap
, InitBootstrap
,
172 ::osl::MutexGuard
, ::osl::GetGlobalMutex
,
173 OUString
, InitBootstrapData
>::create(
174 InitBootstrap(), ::osl::GetGlobalMutex(), InitBootstrapData());
180 class FileHandleGuard
183 inline FileHandleGuard(oslFileHandle
& rHandle
) SAL_THROW(()):
184 m_rHandle(rHandle
) {}
186 inline ~FileHandleGuard() SAL_THROW(());
188 inline oslFileHandle
& getHandle() SAL_THROW(()) { return m_rHandle
; }
191 oslFileHandle
& m_rHandle
;
193 FileHandleGuard(FileHandleGuard
&); // not implemented
194 void operator =(FileHandleGuard
); // not implemented
197 inline FileHandleGuard::~FileHandleGuard() SAL_THROW(())
201 if (osl_closeFile(m_rHandle
) != osl_File_E_None
)
203 OSL_ENSURE(false, "unexpected situation");
209 class FileHandleReader
219 inline FileHandleReader(oslFileHandle
& rHandle
) SAL_THROW(()):
220 m_aGuard(rHandle
), m_nSize(0), m_nIndex(0), m_bLf(false) {}
222 Result
readLine(rtl::OString
* pLine
) SAL_THROW(());
225 enum { BUFFER_SIZE
= 1024 };
227 sal_Char m_aBuffer
[BUFFER_SIZE
];
228 FileHandleGuard m_aGuard
;
234 FileHandleReader::Result
235 FileHandleReader::readLine(rtl::OString
* pLine
)
238 OSL_ENSURE(pLine
, "specification violation");
240 for (bool bEof
= true;; bEof
= false)
242 if (m_nIndex
== m_nSize
)
245 switch (osl_readFile(
246 m_aGuard
.getHandle(), m_aBuffer
, BUFFER_SIZE
, &nRead
))
248 case osl_File_E_PIPE
: //HACK! for windows
250 case osl_File_E_None
:
254 return bEof
? RESULT_EOF
: RESULT_OK
;
257 m_nSize
= static_cast< int >(nRead
);
259 case osl_File_E_INTR
:
267 if (m_bLf
&& m_aBuffer
[m_nIndex
] == 0x0A)
271 int nStart
= m_nIndex
;
272 while (m_nIndex
!= m_nSize
)
273 switch (m_aBuffer
[m_nIndex
++])
278 *pLine
+= rtl::OString(m_aBuffer
+ nStart
,
279 m_nIndex
- 1 - nStart
);
280 //TODO! check for overflow, and not very efficient
284 *pLine
+= rtl::OString(m_aBuffer
+ nStart
, m_nIndex
- nStart
);
285 //TODO! check for overflow, and not very efficient
289 class AsynchReader
: public Thread
292 boost::scoped_array
<sal_Char
> m_arData
;
296 FileHandleGuard m_aGuard
;
301 AsynchReader(oslFileHandle
& rHandle
);
303 /** only call this function after this thread has finished.
305 That is, call join on this instance and then call getData.
311 AsynchReader::AsynchReader(oslFileHandle
& rHandle
):
312 m_nDataSize(0), m_bError(false), m_bDone(false), m_aGuard(rHandle
)
316 OString
AsynchReader::getData()
318 OSL_ASSERT(isRunning() == sal_False
);
319 return OString(m_arData
.get(), m_nDataSize
);
322 void AsynchReader::run()
324 const sal_uInt64 BUFFER_SIZE
= 4096;
325 sal_Char aBuffer
[BUFFER_SIZE
];
329 //the function blocks until something could be read or the pipe closed.
330 switch (osl_readFile(
331 m_aGuard
.getHandle(), aBuffer
, BUFFER_SIZE
, &nRead
))
333 case osl_File_E_PIPE
: //HACK! for windows
335 case osl_File_E_None
:
347 else if (nRead
<= BUFFER_SIZE
)
349 //Save the data we have in m_arData into a temporary array
350 boost::scoped_array
<sal_Char
> arTmp( new sal_Char
[m_nDataSize
]);
351 memcpy(arTmp
.get(), m_arData
.get(), m_nDataSize
);
352 //Enlarge m_arData to hold the newly read data
353 m_arData
.reset(new sal_Char
[(size_t)(m_nDataSize
+ nRead
)]);
354 //Copy back the data that was already in m_arData
355 memcpy(m_arData
.get(), arTmp
.get(), m_nDataSize
);
356 //Add the newly read data to m_arData
357 memcpy(m_arData
.get() + m_nDataSize
, aBuffer
, (size_t) nRead
);
358 m_nDataSize
+= (size_t) nRead
;
364 bool getJavaProps(const OUString
& exePath
,
365 std::vector
<std::pair
<rtl::OUString
, rtl::OUString
> >& props
,
370 OSL_ASSERT( exePath
.getLength() > 0);
372 //We need to set the CLASSPATH in case the office is started from
373 //a different directory. The JREProperties.class is expected to reside
374 //next to the plugin.
375 rtl::OUString sThisLib
;
376 if (osl_getModuleURLFromAddress((void *) (sal_IntPtr
)& getJavaProps
,
377 & sThisLib
.pData
) == sal_False
)
379 sThisLib
= getDirFromFile(sThisLib
);
381 if (osl_getSystemPathFromFileURL(sThisLib
.pData
, & sClassPath
.pData
)
385 //check if we shall examine a Java for accessibility support
386 //If the bootstrap variable is "1" then we pass the argument
387 //"noaccessibility" to JREProperties.class. This will prevent
388 //that it calls java.awt.Toolkit.getDefaultToolkit();
390 getBootstrap()->getFrom(OUSTR("JFW_PLUGIN_DO_NOT_CHECK_ACCESSIBILITY"), sValue
);
392 //prepare the arguments
394 OUString arg1
= OUString(RTL_CONSTASCII_USTRINGPARAM("-classpath"));// + sClassPath;
395 OUString arg2
= sClassPath
;
396 OUString
arg3(RTL_CONSTASCII_USTRINGPARAM("JREProperties"));
397 OUString arg4
= OUSTR("noaccessibility");
398 rtl_uString
*args
[4] = {arg1
.pData
, arg2
.pData
, arg3
.pData
};
400 // Only add the fourth param if the bootstrap parameter is set.
401 if (sValue
.equals(OUString::valueOf((sal_Int32
) 1)))
403 args
[3] = arg4
.pData
;
407 oslProcess javaProcess
= 0;
408 oslFileHandle fileOut
= 0;
409 oslFileHandle fileErr
= 0;
411 FileHandleReader
stdoutReader(fileOut
);
412 AsynchReader
stderrReader(fileErr
);
414 JFW_TRACE2(OUSTR("\n[Java framework] Executing: ") + exePath
+ OUSTR(".\n"));
415 oslProcessError procErr
=
416 osl_executeProcess_WithRedirectedIO( exePath
.pData
,//usExe.pData,
418 cArgs
, //sal_uInt32 nArguments,
419 osl_Process_HIDDEN
, //oslProcessOption Options,
420 NULL
, //oslSecurity Security,
421 usStartDir
.pData
,//usStartDir.pData,//usWorkDir.pData, //rtl_uString *strWorkDir,
422 NULL
, //rtl_uString *strEnvironment[],
423 0, // sal_uInt32 nEnvironmentVars,
424 &javaProcess
, //oslProcess *pProcess,
425 NULL
,//oslFileHandle *pChildInputWrite,
426 &fileOut
,//oslFileHandle *pChildOutputRead,
427 &fileErr
);//oslFileHandle *pChildErrorRead);
429 if( procErr
!= osl_Process_E_None
)
431 JFW_TRACE2("[Java framework] Execution failed. \n");
432 *bProcessRun
= false;
437 JFW_TRACE2("[Java framework] Java executed successfully.\n");
441 //Start asynchronous reading (different thread) of error stream
442 stderrReader
.create();
444 //Use this thread to read output stream
445 FileHandleReader::Result rs
= FileHandleReader::RESULT_OK
;
449 rs
= stdoutReader
.readLine( & aLine
);
450 if (rs
!= FileHandleReader::RESULT_OK
)
452 OUString sLine
= decodeOutput(aLine
);
453 sLine
= sLine
.trim();
454 if (sLine
.getLength() == 0)
456 //The JREProperties class writes key value pairs, separated by '='
457 sal_Int32 index
= sLine
.indexOf('=', 0);
458 OSL_ASSERT(index
!= -1);
459 OUString sKey
= sLine
.copy(0, index
);
460 OUString sVal
= sLine
.copy(index
+ 1);
462 props
.push_back(std::make_pair(sKey
, sVal
));
465 if (rs
!= FileHandleReader::RESULT_ERROR
&& props
.size()>0)
468 //process error stream data
470 JFW_TRACE2(OString("[Java framework] Java wrote to stderr:\" ")
471 + stderrReader
.getData() + OString(" \".\n"));
473 TimeValue waitMax
= {5 ,0};
474 procErr
= osl_joinProcessWithTimeout(javaProcess
, &waitMax
);
475 OSL_ASSERT(procErr
== osl_Process_E_None
);
476 osl_freeProcessHandle(javaProcess
);
480 /* converts the properties printed by JREProperties.class into
481 readable strings. The strings are encoded as integer values separated
484 rtl::OUString
decodeOutput(const rtl::OString
& s
)
486 OUString sEncoded
= OStringToOUString(s
, RTL_TEXTENCODING_ASCII_US
);
487 OUStringBuffer
buff(512);
488 sal_Int32 nIndex
= 0;
491 OUString aToken
= sEncoded
.getToken( 0, ' ', nIndex
);
492 if (aToken
.getLength())
494 sal_Unicode value
= (sal_Unicode
) aToken
.toInt32();
497 } while (nIndex
>= 0);
498 return buff
.makeStringAndClear();
503 void createJavaInfoFromWinReg(std::vector
<rtl::Reference
<VendorBase
> > & vecInfos
)
505 // Get Java s from registry
506 std::vector
<OUString
> vecJavaHome
;
507 if(getSDKInfoFromRegistry(vecJavaHome
))
509 // create impl objects
510 typedef std::vector
<OUString
>::iterator ItHome
;
511 for(ItHome it_home
= vecJavaHome
.begin(); it_home
!= vecJavaHome
.end();
514 getJREInfoByPath(*it_home
, vecInfos
);
519 if(getJREInfoFromRegistry(vecJavaHome
))
521 typedef std::vector
<OUString
>::iterator ItHome
;
522 for(ItHome it_home
= vecJavaHome
.begin(); it_home
!= vecJavaHome
.end();
525 getJREInfoByPath(*it_home
, vecInfos
);
531 bool getJavaInfoFromRegistry(const wchar_t* szRegKey
,
532 vector
<OUString
>& vecJavaHome
)
535 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, szRegKey
, 0, KEY_ENUMERATE_SUB_KEYS
, &hRoot
)
539 const DWORD BUFFSIZE
= 1024;
540 wchar_t bufVersion
[BUFFSIZE
];
541 // char bufVersion[BUFFSIZE];
542 DWORD nNameLen
= BUFFSIZE
;
544 nNameLen
= sizeof(bufVersion
);
546 // Iterate over all subkeys of HKEY_LOCAL_MACHINE\Software\JavaSoft\Java Runtime Environment
547 while (RegEnumKeyExW(hRoot
, dwIndex
, bufVersion
, &nNameLen
, NULL
, NULL
, NULL
, &fileTime
) != ERROR_NO_MORE_ITEMS
)
550 // Open a Java Runtime Environment sub key, e.g. "1.4.0"
551 if (RegOpenKeyExW(hRoot
, bufVersion
, 0, KEY_QUERY_VALUE
, &hKey
) == ERROR_SUCCESS
)
554 DWORD dwTmpPathLen
= 0;
555 // Get the path to the JavaHome every JRE entry
556 // Find out how long the string for JavaHome is and allocate memory to hold the path
557 if( RegQueryValueExW(hKey
, L
"JavaHome", 0, &dwType
, NULL
, &dwTmpPathLen
)== ERROR_SUCCESS
)
559 char* szTmpPath
= (char *) malloc( dwTmpPathLen
);
560 // Get the path for the runtime lib
561 if(RegQueryValueExW(hKey
, L
"JavaHome", 0, &dwType
, (unsigned char*) szTmpPath
, &dwTmpPathLen
) == ERROR_SUCCESS
)
563 // There can be several version entries refering with the same JavaHome,e.g 1.4 and 1.4.1
564 OUString
usHome((sal_Unicode
*) szTmpPath
);
565 // check if there is already an entry with the same JavaHomeruntime lib
566 // if so, we use the one with the more accurate version
569 if (osl_getFileURLFromSystemPath(usHome
.pData
, & usHomeUrl
.pData
) ==
572 //iterate over the vector with java home strings
573 typedef vector
<OUString
>::iterator ItHome
;
574 for(ItHome itHome
= vecJavaHome
.begin();
575 itHome
!= vecJavaHome
.end(); itHome
++)
577 if(usHomeUrl
.equals(*itHome
))
586 vecJavaHome
.push_back(usHomeUrl
);
604 bool getSDKInfoFromRegistry(vector
<OUString
> & vecHome
)
606 return getJavaInfoFromRegistry(HKEY_SUN_SDK
, vecHome
);
609 bool getJREInfoFromRegistry(vector
<OUString
>& vecJavaHome
)
611 return getJavaInfoFromRegistry(HKEY_SUN_JRE
, vecJavaHome
);
616 void bubbleSortVersion(vector
<rtl::Reference
<VendorBase
> >& vec
)
620 int size
= vec
.size() - 1;
623 for(int i
= 0; i
< size
; i
++)
625 for(int j
= size
; j
> 0 + cIter
; j
--)
627 rtl::Reference
<VendorBase
>& cur
= vec
.at(j
);
628 rtl::Reference
<VendorBase
>& next
= vec
.at(j
-1);
631 // comparing invalid SunVersion s is possible, they will be less than a
634 //check if version of current is recognized, by comparing it with itself
637 cur
->compareVersions(cur
->getVersion());
639 catch (MalformedVersionException
&)
641 nCmp
= -1; // current < next
643 //The version of cur is valid, now compare with the second version
648 nCmp
= cur
->compareVersions(next
->getVersion());
650 catch (MalformedVersionException
& )
652 //The second version is invalid, therefor it is regardes less.
656 if(nCmp
== 1) // cur > next
658 rtl::Reference
<VendorBase
> less
= next
;
668 bool getJREInfoFromBinPath(
669 const rtl::OUString
& path
, vector
<rtl::Reference
<VendorBase
> > & vecInfos
)
671 // file:///c:/jre/bin
672 //map: jre/bin/java.exe
674 vector
<pair
<OUString
, OUString
> > props
;
676 for ( sal_Int32 pos
= 0;
677 gVendorMap
[pos
].sVendorName
!= NULL
; ++pos
)
679 vector
<OUString
> vecPaths
;
680 getJavaExePaths_func pFunc
= gVendorMap
[pos
].getJavaFunc
;
683 char const* const* arExePaths
= (*pFunc
)(&size
);
684 vecPaths
= getVectorFromCharArray(arExePaths
, size
);
686 //make sure argument path does not end with '/'
687 OUString sBinPath
= path
;
688 if (path
.lastIndexOf('/') == (path
.getLength() - 1))
689 sBinPath
= path
.copy(0, path
.getLength() - 1);
691 typedef vector
<OUString
>::const_iterator c_it
;
692 for (c_it i
= vecPaths
.begin(); i
!= vecPaths
.end(); i
++)
694 //the map contains e.g. jre/bin/java.exe
695 //get the directory where the executable is contained
697 sal_Int32 index
= i
->lastIndexOf('/');
700 //map contained only : "java.exe, then the argument
701 //path is already the home directory
706 // jre/bin/jre -> jre/bin
707 OUString
sMapPath(i
->getStr(), index
);
708 index
= sBinPath
.lastIndexOf(sMapPath
);
710 && (index
+ sMapPath
.getLength() == sBinPath
.getLength())
711 && sBinPath
[index
- 1] == '/')
713 sHome
= OUString(sBinPath
.getStr(), index
- 1);
716 if (sHome
.getLength() > 0)
718 ret
= getJREInfoByPath(sHome
, vecInfos
);
729 vector
<Reference
<VendorBase
> > getAllJREInfos()
731 vector
<Reference
<VendorBase
> > vecInfos
;
734 // Get Javas from the registry
735 createJavaInfoFromWinReg(vecInfos
);
738 createJavaInfoFromJavaHome(vecInfos
);
739 //this function should be called after createJavaInfoDirScan.
740 //Otherwise in SDKs Java may be started twice
741 createJavaInfoFromPath(vecInfos
);
744 createJavaInfoDirScan(vecInfos
);
747 bubbleSortVersion(vecInfos
);
752 vector
<OUString
> getVectorFromCharArray(char const * const * ar
, int size
)
754 vector
<OUString
> vec
;
755 for( int i
= 0; i
< size
; i
++)
757 OUString
s(ar
[i
], strlen(ar
[i
]), RTL_TEXTENCODING_UTF8
);
762 bool getJREInfoByPath(const rtl::OUString
& path
,
763 std::vector
<rtl::Reference
<VendorBase
> > & vecInfos
)
767 rtl::Reference
<VendorBase
> aInfo
= getJREInfoByPath(path
);
771 vector
<rtl::Reference
<VendorBase
> >::const_iterator it_impl
= std::find_if(
772 vecInfos
.begin(),vecInfos
.end(), InfoFindSame(aInfo
->getHome()));
773 if(it_impl
== vecInfos
.end())
775 vecInfos
.push_back(aInfo
);
781 /** Checks if the path is a directory. Links are resolved.
782 In case of an error the returned string has the length 0.
783 Otherwise the returned string is the "resolved" file URL.
785 OUString
resolveDirPath(const OUString
& path
)
789 if (File::getAbsoluteFileURL(
790 rtl::OUString(), path
, sResolved
) != File::E_None
)
793 //check if this is a valid path and if it is a directory
795 if (DirectoryItem::get(sResolved
, item
) == File::E_None
)
797 FileStatus
status(FileStatusMask_Type
|
798 FileStatusMask_LinkTargetURL
|
799 FileStatusMask_FileURL
);
801 if (item
.getFileStatus(status
) == File::E_None
802 && status
.getFileType() == FileStatus::Directory
)
811 /** Checks if the path is a file. If it is a link to a file than
814 OUString
resolveFilePath(const OUString
& path
)
819 if (File::getAbsoluteFileURL(
820 rtl::OUString(), path
, sResolved
) != File::E_None
)
823 //check if this is a valid path to a file or and if it is a link
825 if (DirectoryItem::get(sResolved
, item
) == File::E_None
)
827 FileStatus
status(FileStatusMask_Type
|
828 FileStatusMask_LinkTargetURL
|
829 FileStatusMask_FileURL
);
830 if (item
.getFileStatus(status
) == File::E_None
831 && status
.getFileType() == FileStatus::Regular
)
842 rtl::Reference
<VendorBase
> getJREInfoByPath(
843 const OUString
& path
)
845 rtl::Reference
<VendorBase
> ret
;
846 static vector
<OUString
> vecBadPaths
;
848 static map
<OUString
, rtl::Reference
<VendorBase
> > mapJREs
;
849 typedef map
<OUString
, rtl::Reference
<VendorBase
> >::const_iterator MapIt
;
850 typedef map
<OUString
, rtl::Reference
<VendorBase
> > MAPJRE
;
852 typedef vector
<OUString
>::const_iterator cit_path
;
853 vector
<pair
<OUString
, OUString
> > props
;
855 OUString sResolvedDir
= resolveDirPath(path
);
856 // If this path is invalid then there is no chance to find a JRE here
857 if (sResolvedDir
.getLength() == 0)
860 //check if the directory path is good, that is a JRE was already recognized.
861 //Then we need not detect it again
862 //For example, a sun JKD contains <jdk>/bin/java and <jdk>/jre/bin/java.
863 //When <jdk>/bin/java has been found then we need not find <jdk>/jre/bin/java.
864 //Otherwise we would execute java two times for evers JDK found.
865 MapIt entry2
= find_if(mapJREs
.begin(), mapJREs
.end(),
866 SameOrSubDirJREMap(sResolvedDir
));
867 if (entry2
!= mapJREs
.end())
869 JFW_TRACE2(OUSTR("[Java framework] sunjavaplugin"SAL_DLLEXTENSION
": ")
870 + OUSTR("JRE found again (detected before): ") + sResolvedDir
872 return entry2
->second
;
875 for ( sal_Int32 pos
= 0;
876 gVendorMap
[pos
].sVendorName
!= NULL
; ++pos
)
878 vector
<OUString
> vecPaths
;
879 getJavaExePaths_func pFunc
= gVendorMap
[pos
].getJavaFunc
;
882 char const* const* arExePaths
= (*pFunc
)(&size
);
883 vecPaths
= getVectorFromCharArray(arExePaths
, size
);
886 typedef vector
<OUString
>::const_iterator c_it
;
887 for (c_it i
= vecPaths
.begin(); i
!= vecPaths
.end(); i
++)
889 //if the path is a link, then resolve it
890 //check if the executable exists at all
892 //path can be only "file:///". Then do not append a '/'
893 //sizeof counts the terminating 0
895 if (path
.getLength() == sizeof("file:///") - 1)
896 sFullPath
= sResolvedDir
+ (*i
);
898 sFullPath
= sResolvedDir
+
899 OUString(RTL_CONSTASCII_USTRINGPARAM("/")) + (*i
);
902 sFilePath
= resolveFilePath(sFullPath
);
904 if (sFilePath
.getLength() == 0)
906 //The file path (to java exe) is not valid
907 cit_path ifull
= find(vecBadPaths
.begin(), vecBadPaths
.end(), sFullPath
);
908 if (ifull
== vecBadPaths
.end())
909 vecBadPaths
.push_back(sFullPath
);
913 cit_path ifile
= find(vecBadPaths
.begin(), vecBadPaths
.end(), sFilePath
);
914 if (ifile
!= vecBadPaths
.end())
917 MapIt entry
= mapJREs
.find(sFilePath
);
918 if (entry
!= mapJREs
.end())
920 JFW_TRACE2(OUSTR("[Java framework] sunjavaplugin"SAL_DLLEXTENSION
": ")
921 + OUSTR("JRE found again (detected before): ") + sFilePath
924 return entry
->second
;
927 bool bProcessRun
= false;
928 if (getJavaProps(sFilePath
, props
, & bProcessRun
) == false)
930 //The java executable could not be run or the system properties
931 //could not be retrieved. We can assume that this java is corrupt.
932 vecBadPaths
.push_back(sFilePath
);
933 //If there was a java executable, that could be run but we did not get
934 //the system properties, then we also assume that the whole Java installation
935 //does not work. In a jdk there are two executables. One in jdk/bin and the other
936 //in jdk/jre/bin. We do not search any further, because we assume that if one java
937 //does not work then the other does not work as well. This saves us to run java
938 //again which is quite costly.
939 if (bProcessRun
== true)
941 // 1.3.1 special treatment: jdk/bin/java and /jdk/jre/bin/java are links to
942 //a script, named .java_wrapper. The script starts jdk/bin/sparc/native_threads/java
943 //or jdk/jre/bin/sparc/native_threads/java. The script uses the name with which it was
944 //invoked to build the path to the executable. It we start the script directy as .java_wrapper
945 //then it tries to start a jdk/.../native_threads/.java_wrapper. Therefore the link, which
946 //is named java, must be used to start the script.
947 getJavaProps(sFullPath
, props
, & bProcessRun
);
948 // Either we found a working 1.3.1
949 //Or the java is broken. In both cases we stop searchin under this "root" directory
953 //sFilePath is no working java executable. We continue with another possible
960 //sFilePath is a java and we could get the system properties. We proceed with this
972 if (props
.size() == 0)
973 return rtl::Reference
<VendorBase
>();
975 //find java.vendor property
976 typedef vector
<pair
<OUString
, OUString
> >::const_iterator c_ip
;
977 OUString
sVendor(RTL_CONSTASCII_USTRINGPARAM("java.vendor"));
978 OUString sVendorName
;
980 for (c_ip i
= props
.begin(); i
!= props
.end(); i
++)
982 if (sVendor
.equals(i
->first
))
984 sVendorName
= i
->second
;
989 if (sVendorName
.getLength() > 0)
991 //find the creator func for the respective vendor name
992 for ( sal_Int32 c
= 0;
993 gVendorMap
[c
].sVendorName
!= NULL
; ++c
)
995 OUString
sNameMap(gVendorMap
[c
].sVendorName
, strlen(gVendorMap
[c
].sVendorName
),
996 RTL_TEXTENCODING_ASCII_US
);
997 if (sNameMap
.equals(sVendorName
))
999 ret
= createInstance(gVendorMap
[c
].createFunc
, props
);
1004 if (ret
.is() == false)
1005 vecBadPaths
.push_back(sFilePath
);
1008 JFW_TRACE2(OUSTR("[Java framework] sunjavaplugin"SAL_DLLEXTENSION
": ")
1009 + OUSTR("Found JRE: ") + sResolvedDir
1010 + OUSTR(" \n at: ") + path
+ OUSTR(".\n"));
1012 mapJREs
.insert(MAPJRE::value_type(sResolvedDir
, ret
));
1013 mapJREs
.insert(MAPJRE::value_type(sFilePath
, ret
));
1019 Reference
<VendorBase
> createInstance(createInstance_func pFunc
,
1020 vector
<pair
<OUString
, OUString
> > properties
)
1023 Reference
<VendorBase
> aBase
= (*pFunc
)();
1026 if (aBase
->initialize(properties
) == false)
1032 inline OUString
getDirFromFile(const OUString
& usFilePath
)
1034 sal_Int32 index
= usFilePath
.lastIndexOf('/');
1035 return OUString(usFilePath
.getStr(), index
);
1038 void createJavaInfoFromPath(vector
<rtl::Reference
<VendorBase
> >& vecInfos
)
1040 // Get Java from PATH environment variable
1041 static OUString
sCurDir(RTL_CONSTASCII_USTRINGPARAM("."));
1042 static OUString
sParentDir(RTL_CONSTASCII_USTRINGPARAM(".."));
1043 char *szPath
= getenv("PATH");
1046 OUString
usAllPath(szPath
, strlen(szPath
), osl_getThreadTextEncoding());
1047 sal_Int32 nIndex
= 0;
1050 OUString usToken
= usAllPath
.getToken( 0, SAL_PATHSEPARATOR
, nIndex
);
1051 OUString usTokenUrl
;
1052 if(File::getFileURLFromSystemPath(usToken
, usTokenUrl
) == File::E_None
)
1054 if(usTokenUrl
.getLength())
1058 if(usTokenUrl
.equals(sCurDir
))
1060 OUString usWorkDirUrl
;
1061 if(osl_Process_E_None
== osl_getProcessWorkingDir(&usWorkDirUrl
.pData
))
1062 usBin
= usWorkDirUrl
;
1065 else if(usTokenUrl
.equals(sParentDir
))
1068 if(osl_Process_E_None
== osl_getProcessWorkingDir(&usWorkDir
.pData
))
1069 usBin
= getDirFromFile(usWorkDir
);
1075 if(usBin
.getLength())
1077 getJREInfoFromBinPath(usBin
, vecInfos
);
1082 while ( nIndex
>= 0 );
1086 void createJavaInfoFromJavaHome(vector
<rtl::Reference
<VendorBase
> >& vecInfos
)
1088 // Get Java from JAVA_HOME environment
1089 char *szJavaHome
= getenv("JAVA_HOME");
1092 OUString
sHome(szJavaHome
,strlen(szJavaHome
),osl_getThreadTextEncoding());
1094 if(File::getFileURLFromSystemPath(sHome
, sHomeUrl
) == File::E_None
)
1096 getJREInfoByPath(sHomeUrl
, vecInfos
);
1101 bool makeDriveLetterSame(OUString
* fileURL
)
1105 if (DirectoryItem::get(*fileURL
, item
) == File::E_None
)
1107 FileStatus
status(FileStatusMask_FileURL
);
1108 if (item
.getFileStatus(status
) == File::E_None
)
1110 *fileURL
= status
.getFileURL();
1120 void createJavaInfoDirScan(vector
<rtl::Reference
<VendorBase
> >& vecInfos
)
1122 JFW_TRACE2(OUSTR("\n[Java framework] Checking \"/usr/jdk/latest\"\n"));
1123 getJREInfoByPath(OUSTR("file:////usr/jdk/latest"), vecInfos
);
1127 void createJavaInfoDirScan(vector
<rtl::Reference
<VendorBase
> >& vecInfos
)
1129 OUString excMessage
= OUSTR("[Java framework] sunjavaplugin: "
1130 "Error in function createJavaInfoDirScan in util.cxx.");
1131 int cJavaNames
= sizeof(g_arJavaNames
) / sizeof(char*);
1132 boost::scoped_array
<OUString
> sarJavaNames(new OUString
[cJavaNames
]);
1133 OUString
*arNames
= sarJavaNames
.get();
1134 for(int i
= 0; i
< cJavaNames
; i
++)
1135 arNames
[i
] = OUString(g_arJavaNames
[i
], strlen(g_arJavaNames
[i
]),
1136 RTL_TEXTENCODING_UTF8
);
1138 int cSearchPaths
= sizeof(g_arSearchPaths
) / sizeof(char*);
1139 boost::scoped_array
<OUString
> sarPathNames(new OUString
[cSearchPaths
]);
1140 OUString
*arPaths
= sarPathNames
.get();
1141 for(int c
= 0; c
< cSearchPaths
; c
++)
1142 arPaths
[c
] = OUString(g_arSearchPaths
[c
], strlen(g_arSearchPaths
[c
]),
1143 RTL_TEXTENCODING_UTF8
);
1145 int cCollectDirs
= sizeof(g_arCollectDirs
) / sizeof(char*);
1146 boost::scoped_array
<OUString
> sarCollectDirs(new OUString
[cCollectDirs
]);
1147 OUString
*arCollectDirs
= sarCollectDirs
.get();
1148 for(int d
= 0; d
< cCollectDirs
; d
++)
1149 arCollectDirs
[d
] = OUString(g_arCollectDirs
[d
], strlen(g_arCollectDirs
[d
]),
1150 RTL_TEXTENCODING_UTF8
);
1154 OUString
usFile(RTL_CONSTASCII_USTRINGPARAM("file:///"));
1155 for( int ii
= 0; ii
< cSearchPaths
; ii
++)
1157 OUString
usDir1(usFile
+ arPaths
[ii
]);
1159 if(DirectoryItem::get(usDir1
, item
) == File::E_None
)
1161 for(int j
= 0; j
< cCollectDirs
; j
++)
1163 OUString
usDir2(usDir1
+ arCollectDirs
[j
]);
1164 // prevent that we scan the whole /usr, /usr/lib, etc directories
1165 if (arCollectDirs
[j
] != OUString())
1168 //Examin every subdirectory
1169 Directory
aCollectionDir(usDir2
);
1171 Directory::RC openErr
= aCollectionDir
.open();
1177 case File::E_NOTDIR
:
1180 JFW_TRACE2(OUSTR("[Java framework] sunjavaplugin: "
1181 "Could not read directory ") + usDir2
+
1182 OUSTR(" because of missing access rights."));
1185 JFW_TRACE2(OUSTR("[Java framework] sunjavaplugin: "
1186 "Could not read directory ")
1187 + usDir2
+ OUSTR(". Osl file error: ")
1188 + OUString::valueOf((sal_Int32
) openErr
));
1192 DirectoryItem curIt
;
1193 File::RC errNext
= File::E_None
;
1194 while( (errNext
= aCollectionDir
.getNextItem(curIt
)) == File::E_None
)
1196 FileStatus
aStatus(FileStatusMask_FileURL
);
1197 File::RC errStatus
= File::E_None
;
1198 if ((errStatus
= curIt
.getFileStatus(aStatus
)) != File::E_None
)
1200 JFW_TRACE2(excMessage
+ OUSTR("getFileStatus failed with error ")
1201 + OUString::valueOf((sal_Int32
) errStatus
));
1204 JFW_TRACE2(OUSTR("[Java framework] sunjavaplugin: "
1205 "Checking if directory: ") + aStatus
.getFileURL() +
1206 OUSTR(" is a Java. \n"));
1208 getJREInfoByPath(aStatus
.getFileURL(),vecInfos
);
1211 JFW_ENSURE(errNext
== File::E_None
|| errNext
== File::E_NOENT
,
1212 OUSTR("[Java framework] sunjavaplugin: "
1213 "Error while iterating over contens of ")
1214 + usDir2
+ OUSTR(". Osl file error: ")
1215 + OUString::valueOf((sal_Int32
) openErr
));
1220 //When we look directly into a dir like /usr, /usr/lib, etc. then we only
1221 //look for certain java directories, such as jre, jdk, etc. Whe do not want
1222 //to examine the whole directory because of performance reasons.
1223 DirectoryItem item2
;
1224 if(DirectoryItem::get(usDir2
, item2
) == File::E_None
)
1226 for( int k
= 0; k
< cJavaNames
; k
++)
1228 // /usr/java/j2re1.4.0
1229 OUString
usDir3(usDir2
+ arNames
[k
]);
1231 DirectoryItem item3
;
1232 if(DirectoryItem::get(usDir3
, item
) == File::E_None
)
1234 //remove trailing '/'
1235 sal_Int32 islash
= usDir3
.lastIndexOf('/');
1236 if (islash
== usDir3
.getLength() - 1
1238 > RTL_CONSTASCII_LENGTH("file://")))
1239 usDir3
= usDir3
.copy(0, islash
);
1240 getJREInfoByPath(usDir3
,vecInfos
);
1249 #endif // ifdef SOLARIS