1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is Sun Microsystems.
18 * Portions created by the Initial Developer are Copyright (C) 2003
19 * the Initial Developer. All Rights Reserved.
22 * Pete Zha <pete.zha@sun.com> (original author)
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
39 #include "nsJVMConfigManagerUnix.h"
40 #include "nsAppDirectoryServiceDefs.h"
41 #include "nsDirectoryServiceDefs.h"
42 #include "nsIPrefService.h"
43 #include "nsIPrefBranch.h"
44 #include "nsReadableUtils.h"
45 #include "nsIMutableArray.h"
48 #include "nsIHttpProtocolHandler.h"
49 #include "nsIVariant.h"
50 #include "nsISimpleEnumerator.h"
51 #include <stdio.h> /* OSF/1 requires this before grp.h, so put it first */
54 #define NS_COMPILER_GNUC3 defined(__GXX_ABI_VERSION) && \
55 (__GXX_ABI_VERSION >= 102) /* G++ V3 ABI */
57 // Implementation of nsJVMConfigManagerUnix
58 NS_IMPL_ISUPPORTS1(nsJVMConfigManagerUnix
, nsIJVMConfigManager
)
60 nsJVMConfigManagerUnix::nsJVMConfigManagerUnix()
65 PR_STATIC_CALLBACK(PRBool
)
66 FreeJVMConfig(nsHashKey
*aKey
, void *aData
, void* aClosure
)
68 nsJVMConfig
* config
= static_cast<nsJVMConfig
*>(aData
);
70 NS_IF_RELEASE(config
);
75 PR_STATIC_CALLBACK(PRBool
)
76 AppendJVMConfig(nsHashKey
*aKey
, void *aData
, void* aClosure
)
78 nsJVMConfig
* config
= static_cast<nsJVMConfig
*>(aData
);
79 nsIMutableArray
*array
= static_cast<nsIMutableArray
*>(aClosure
);
80 NS_ENSURE_TRUE(config
&& array
, PR_FALSE
);
82 array
->AppendElement(config
, PR_FALSE
);
86 nsJVMConfigManagerUnix::~nsJVMConfigManagerUnix()
92 nsJVMConfigManagerUnix::ClearJVMConfigList()
94 if (mJVMConfigList
.Count() > 0) {
95 mJVMConfigList
.Reset(FreeJVMConfig
);
100 nsJVMConfigManagerUnix::GetJVMConfigList(nsIArray
**_retval
)
102 NS_ENSURE_ARG_POINTER(_retval
);
104 ClearJVMConfigList();
107 nsCOMPtr
<nsIMutableArray
> array
=
108 do_CreateInstance(NS_ARRAY_CONTRACTID
);
109 NS_ENSURE_STATE(array
);
111 if (mJVMConfigList
.Count() > 0) {
112 mJVMConfigList
.Enumerate(AppendJVMConfig
,
113 static_cast<void *>(array
));
114 *_retval
= static_cast<nsIArray
*>(array
);
115 NS_IF_ADDREF(*_retval
);
123 nsJVMConfigManagerUnix::InitJVMConfigList()
125 nsCOMPtr
<nsIPrefBranch
> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID
));
126 NS_ENSURE_TRUE(prefs
, NS_ERROR_FAILURE
);
128 nsCOMPtr
<nsILocalFile
> globalFile
;
129 prefs
->GetComplexValue("java.global_java_version_file",
130 NS_GET_IID(nsILocalFile
),
131 getter_AddRefs(globalFile
));
133 nsCOMPtr
<nsILocalFile
> privateFile
;
134 prefs
->GetComplexValue("java.private_java_version_file",
135 NS_GET_IID(nsILocalFile
),
136 getter_AddRefs(privateFile
));
138 nsCOMPtr
<nsILineInputStream
> globalStream
;
139 nsresult rv
= GetLineInputStream(globalFile
, getter_AddRefs(globalStream
));
140 NS_ENSURE_TRUE(NS_SUCCEEDED(rv
) || rv
== NS_ERROR_FILE_NOT_FOUND
, rv
);
142 nsCOMPtr
<nsILineInputStream
> privateStream
;
143 rv
= GetLineInputStream(privateFile
, getter_AddRefs(privateStream
));
144 NS_ENSURE_TRUE(NS_SUCCEEDED(rv
) || rv
== NS_ERROR_FILE_NOT_FOUND
, rv
);
146 rv
= InitJVMConfigList(globalStream
, privateStream
);
147 NS_ENSURE_SUCCESS(rv
, rv
);
149 // Search for a Java installation in the default install location.
150 return SearchDefault();
154 nsJVMConfigManagerUnix::SetCurrentJVMConfig(nsIJVMConfig
* aJVMConfig
)
156 NS_ENSURE_ARG_POINTER(aJVMConfig
);
158 nsCOMPtr
<nsIFile
> srcFile
;
159 nsresult rv
= aJVMConfig
->GetMozillaPluginPath(getter_AddRefs(srcFile
));
160 NS_ENSURE_SUCCESS(rv
, rv
);
162 nsCOMPtr
<nsIFile
> pluginDir
;
163 rv
= NS_GetSpecialDirectory(NS_APP_PLUGINS_DIR
, getter_AddRefs(pluginDir
));
164 NS_ENSURE_SUCCESS(rv
, rv
);
166 PRBool hasPermission
= PR_FALSE
;
167 pluginDir
->IsWritable(&hasPermission
);
168 if (!hasPermission
) {
169 return NS_ERROR_FAILURE
;
172 nsAutoString fileName
;
173 srcFile
->GetLeafName(fileName
);
174 nsCOMPtr
<nsILocalFile
> destFile(do_QueryInterface(pluginDir
));
175 if (TestExists(destFile
, fileName
))
176 destFile
->Remove(PR_FALSE
);
178 nsCAutoString srcFileName
;
179 rv
= srcFile
->GetNativePath(srcFileName
);
180 NS_ENSURE_SUCCESS(rv
, rv
);
182 nsCAutoString destFileName
;
183 destFile
->GetNativePath(destFileName
);
184 NS_ENSURE_SUCCESS(rv
, rv
);
187 result
= symlink(srcFileName
.get(), destFileName
.get());
189 return result
>= 0 ? NS_OK
: NS_ERROR_FAILURE
;
193 nsJVMConfigManagerUnix::InitJVMConfigList(nsILineInputStream
* aGlobal
,
194 nsILineInputStream
* aPrivate
)
199 rv
= ParseStream(aGlobal
);
200 NS_ENSURE_SUCCESS(rv
, rv
);
204 rv
= ParseStream(aPrivate
);
205 NS_ENSURE_SUCCESS(rv
, rv
);
212 nsJVMConfigManagerUnix::GetLineInputStream(nsIFile
* aFile
,
213 nsILineInputStream
** _retval
)
215 NS_ENSURE_ARG_POINTER(_retval
);
219 nsCOMPtr
<nsILocalFile
> file(do_QueryInterface(aFile
, &rv
));
220 NS_ENSURE_SUCCESS(rv
, rv
);
222 nsCOMPtr
<nsIFileInputStream
>
223 fileStream(do_CreateInstance(NS_LOCALFILEINPUTSTREAM_CONTRACTID
, &rv
));
224 NS_ENSURE_SUCCESS(rv
, rv
);
226 rv
= fileStream
->Init(file
, -1, -1, PR_FALSE
);
227 NS_ENSURE_SUCCESS(rv
, rv
);
229 nsCOMPtr
<nsILineInputStream
> lineStream(do_QueryInterface(fileStream
, &rv
));
230 NS_ENSURE_SUCCESS(rv
, rv
);
232 *_retval
= lineStream
;
233 NS_IF_ADDREF(*_retval
);
239 nsJVMConfigManagerUnix::ParseStream(nsILineInputStream
* aStream
)
241 NS_ENSURE_ARG_POINTER(aStream
);
243 PRBool notEOF
= PR_TRUE
;
245 nsAutoString lineBuffer
;
249 nsresult rv
= aStream
->ReadLine(cLine
, ¬EOF
);
250 NS_ENSURE_SUCCESS(rv
, rv
);
251 CopyASCIItoUTF16(cLine
, line
);
253 PRInt32 slashOffset
, equalsOffset
;
254 slashOffset
= line
.FindChar('\\');
255 equalsOffset
= line
.FindChar('=');
257 // Since one java installation contains several key/value pair
258 // and they are separeted by '\'. We need to join them together
259 // to a single line and then parse it.
260 if (slashOffset
!= kNotFound
&& equalsOffset
!= kNotFound
) {
261 // This means the line not finished, we need to append it to buffer
262 lineBuffer
.Append(Substring(line
, 0, slashOffset
));
263 } else if (slashOffset
== kNotFound
&& equalsOffset
!= kNotFound
) {
264 // This should the last one of a line. Append it to line
265 // and then we can Parse it and get necessary information
266 lineBuffer
.Append(line
);
267 ParseLine(lineBuffer
);
269 // Start of a new line
270 lineBuffer
.Truncate();
278 nsJVMConfigManagerUnix::ParseLine(nsAString
& aLine
)
280 #if (NS_COMPILER_GNUC3)
281 nsAutoString compiler
;
282 GetValueFromLine(aLine
, "compiler", compiler
);
284 NS_ENSURE_TRUE(compiler
.Find("gcc32") != kNotFound
, NS_OK
);
287 nsAutoString version
;
288 GetValueFromLine(aLine
, "version", version
);
291 GetValueFromLine(aLine
, "type", type
);
294 GetValueFromLine(aLine
, "os", os
);
297 GetValueFromLine(aLine
, "arch", arch
);
299 nsAutoString pathStr
;
300 GetValueFromLine(aLine
, "path", pathStr
);
302 nsAutoString mozillaPluginPath
;
303 GetMozillaPluginPath(aLine
, mozillaPluginPath
);
305 NS_ENSURE_TRUE(!mozillaPluginPath
.IsEmpty(), NS_OK
);
307 nsAutoString description
;
308 GetValueFromLine(aLine
, "description", description
);
309 description
.Trim("\"");
311 // Test whether the plugin file is existing.
313 nsCOMPtr
<nsILocalFile
>
314 testPath(do_CreateInstance(NS_LOCAL_FILE_CONTRACTID
, &rv
));
315 NS_ENSURE_SUCCESS(rv
, rv
);
317 nsAutoString
testPathStr(pathStr
);
318 if (type
.EqualsLiteral("jdk"))
319 testPathStr
.AppendLiteral("/jre");
321 testPathStr
.Append(mozillaPluginPath
);
322 testPath
->InitWithPath(testPathStr
);
324 // If the file doesn't exists, we just return NS_OK
326 testPath
->Exists(&exists
);
327 NS_ENSURE_TRUE(exists
, NS_OK
);
329 nsCOMPtr
<nsIFile
> mozPluginPath(do_QueryInterface(testPath
, &rv
));
330 NS_ENSURE_SUCCESS(rv
, rv
);
332 nsCOMPtr
<nsILocalFile
>
333 path(do_CreateInstance(NS_LOCAL_FILE_CONTRACTID
, &rv
));
334 path
->InitWithPath(pathStr
);
336 // We use java home as the key because one home
337 // will contain only one java installation.
338 // This could make sure we don't duplicate the config info in the list
339 nsStringKey
key(pathStr
);
340 nsJVMConfig
* config
= static_cast<nsJVMConfig
*>
341 (mJVMConfigList
.Get(&key
));
343 // Only create it and add the config to list if it doesn't exist.
345 config
= new nsJVMConfig(version
, type
, os
, arch
, path
,
346 mozPluginPath
, description
);
347 NS_ENSURE_TRUE(config
, NS_ERROR_OUT_OF_MEMORY
);
348 mJVMConfigList
.Put(&key
, static_cast<void *>(config
));
356 nsJVMConfigManagerUnix::GetMozillaPluginPath(nsAString
& aLine
,
359 nsCAutoString agentVersion
;
360 nsresult rv
= GetAgentVersion(agentVersion
);
361 NS_ENSURE_SUCCESS(rv
, rv
);
363 // Get mozilla plugin path from key
364 // mozilla<version>.plugin.path
365 // <version> should like this: "1.2", "1.3"
366 nsCAutoString
key("mozilla");
367 key
.Append(agentVersion
);
368 key
.Append(".plugin.path");
370 GetValueFromLine(aLine
, key
.get(), _retval
);
372 if (!_retval
.IsEmpty()) return NS_OK
;
374 nsAutoString versionStr
;
375 rv
= GetNSVersion(versionStr
);
376 NS_ENSURE_SUCCESS(rv
, rv
);
378 key
.AssignWithConversion(versionStr
);
379 key
.Append(".plugin.path");
381 GetValueFromLine(aLine
, key
.get(), _retval
);
383 // Fall back to use ns610.plugin.path if _retval is still empty.
384 if (_retval
.IsEmpty())
385 GetValueFromLine(aLine
, "ns610.plugin.path", _retval
);
391 nsJVMConfigManagerUnix::GetAgentVersion(nsCAutoString
& _retval
)
395 nsCOMPtr
<nsIHttpProtocolHandler
> http
= do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX
"http", &rv
);
396 NS_ENSURE_SUCCESS(rv
, rv
);
398 nsCAutoString userAgent
;
399 rv
= http
->GetUserAgent(userAgent
);
400 NS_ENSURE_SUCCESS(rv
, rv
);
401 PRInt32 rvOffset
= userAgent
.Find("rv:");
403 if (rvOffset
!= kNotFound
)
404 _retval
.Assign(Substring(userAgent
, rvOffset
+ 3, 3));
410 nsJVMConfigManagerUnix::GetAgentVersion(float* _retval
)
412 NS_ENSURE_ARG_POINTER(_retval
);
415 nsCAutoString agentVersion
;
416 GetAgentVersion(agentVersion
);
417 nsCOMPtr
<nsIWritableVariant
> p
=
418 do_CreateInstance(NS_VARIANT_CONTRACTID
, &rv
);
419 NS_ENSURE_SUCCESS(rv
, rv
);
421 rv
= p
->SetAsACString(agentVersion
);
422 NS_ENSURE_SUCCESS(rv
, rv
);
424 return p
->GetAsFloat(_retval
);
428 nsJVMConfigManagerUnix::GetValueFromLine(nsAString
& aLine
, const char* aKey
,
433 nsAutoString
line(aLine
);
434 // Find the offset of the given key in the line
435 PRInt32 keyOffset
= line
.Find(aKey
);
437 // make sure the key exists in the line.
438 NS_ENSURE_TRUE(keyOffset
!= kNotFound
, PR_FALSE
);
440 // Find '=' right after the key
441 PRInt32 equalsOffset
= aLine
.FindChar('=', keyOffset
);
442 NS_ENSURE_TRUE(equalsOffset
!= kNotFound
, PR_FALSE
);
444 // Find '|' which is the terminal of a pair of key/value
445 PRInt32 lineOffset
= aLine
.FindChar('|', equalsOffset
);
446 lineOffset
= lineOffset
!= kNotFound
? lineOffset
: aLine
.Length();
448 // OK, we separate the value from the line between '=' and '|'
449 nsAutoString
value(Substring(aLine
,
451 lineOffset
- equalsOffset
-1));
453 // Removing the leading/trailing spaces
460 nsJVMConfigManagerUnix::GetNSVersion(nsAString
& _retval
)
463 nsresult rv
= GetAgentVersion(&version
);
464 NS_ENSURE_SUCCESS(rv
, rv
);
466 // Check mozilla's version
467 // ns7 is for mozilla1.3 or later
468 // ns610 is for earlier version of mozilla.
469 if (version
>= 1.3) {
470 _retval
.AssignLiteral("ns7");
472 _retval
.AssignLiteral("ns610");
479 nsJVMConfigManagerUnix::SearchDefault()
482 const char* defaultLocationName
= "java.default_java_location_solaris";
484 const char* defaultLocationName
= "java.default_java_location_others";
487 nsCOMPtr
<nsIPrefBranch
> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID
));
488 NS_ENSURE_TRUE(prefs
, NS_ERROR_FAILURE
);
490 nsXPIDLCString defaultLocationXPIDLValue
;
491 prefs
->GetCharPref(defaultLocationName
,
492 getter_Copies(defaultLocationXPIDLValue
));
494 NS_ConvertUTF8toUTF16
defaultLocation(defaultLocationXPIDLValue
);
497 // On Solaris, the default location is the java home
498 return AddDirectory(defaultLocation
);
500 // On Linux and other platform,
501 // the default location can contain multiple java installations
502 return SearchDirectory(defaultLocation
);
507 nsJVMConfigManagerUnix::SearchDirectory(nsAString
& aDirName
)
511 nsCOMPtr
<nsILocalFile
>
512 localDir(do_CreateInstance(NS_LOCAL_FILE_CONTRACTID
, &rv
));
513 NS_ENSURE_SUCCESS(rv
, rv
);
515 rv
= localDir
->InitWithPath(aDirName
);
516 NS_ENSURE_SUCCESS(rv
, rv
);
518 nsCOMPtr
<nsIFile
> dir(do_QueryInterface(localDir
, &rv
));
519 NS_ENSURE_SUCCESS(rv
, rv
);
521 nsCOMPtr
<nsISimpleEnumerator
> entries
;
522 rv
= dir
->GetDirectoryEntries(getter_AddRefs(entries
));
523 NS_ENSURE_SUCCESS(rv
, rv
);
525 PRBool hasMoreElements
;
526 entries
->HasMoreElements(&hasMoreElements
);
527 while (hasMoreElements
) {
528 nsCOMPtr
<nsISupports
> next
;
529 rv
= entries
->GetNext(getter_AddRefs(next
));
530 NS_ENSURE_SUCCESS(rv
, rv
);
532 nsCOMPtr
<nsIFile
> entry(do_QueryInterface(next
, &rv
));
533 NS_ENSURE_SUCCESS(rv
, rv
);
536 entries
->HasMoreElements(&hasMoreElements
);
543 nsJVMConfigManagerUnix::AddDirectory(nsIFile
* aHomeDir
)
545 NS_ENSURE_ARG_POINTER(aHomeDir
);
546 nsAutoString homeDirName
;
547 aHomeDir
->GetPath(homeDirName
);
548 return AddDirectory(homeDirName
);
552 nsJVMConfigManagerUnix::AddDirectory(nsAString
& aHomeDirName
)
557 nsAutoString mozillaPluginPath
;
559 nsCOMPtr
<nsILocalFile
>
560 testPath(do_CreateInstance(NS_LOCAL_FILE_CONTRACTID
, &rv
));
561 NS_ENSURE_SUCCESS(rv
, rv
);
563 testPath
->InitWithPath(aHomeDirName
);
564 testPath
->Append(NS_LITERAL_STRING("jre"));
567 testPath
->Exists(&exists
);
569 type
.AssignLiteral("jdk");
571 type
.AssignLiteral("jre");
572 testPath
->InitWithPath(aHomeDirName
);
575 testPath
->Append(NS_LITERAL_STRING("plugin"));
577 // Get Arch. "sparc" or "i386"
579 NS_ENSURE_TRUE(TestArch(testPath
, arch
), NS_OK
);
581 // Get NS Version. "ns610" or "ns7"
582 nsAutoString nsVersion
;
583 NS_ENSURE_TRUE(TestNSVersion(testPath
, nsVersion
), NS_OK
);
585 nsCOMPtr
<nsIPrefBranch
> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID
));
586 NS_ENSURE_TRUE(prefs
, NS_ERROR_FAILURE
);
588 nsCAutoString
javaLibName("java.java_plugin_library_name");
589 nsXPIDLCString javaLibNameXPIDLValue
;
590 prefs
->GetCharPref(javaLibName
.get(),
591 getter_Copies(javaLibNameXPIDLValue
));
593 char* temp
= PR_GetLibraryName(nsnull
, javaLibNameXPIDLValue
.get());
594 nsCAutoString
pluginFileName(temp
);
595 testPath
->AppendNative(pluginFileName
);
596 PR_FreeLibraryName(temp
);
598 // If the plugin file doesn't exist, we just return NS_OK
599 testPath
->Exists(&exists
);
600 NS_ENSURE_TRUE(exists
, NS_OK
);
602 nsCOMPtr
<nsIFile
> mozPluginPath(do_QueryInterface(testPath
, &rv
));
603 NS_ENSURE_SUCCESS(rv
, rv
);
605 nsCOMPtr
<nsILocalFile
>
606 path(do_CreateInstance(NS_LOCAL_FILE_CONTRACTID
, &rv
));
607 NS_ENSURE_SUCCESS(rv
, rv
);
608 path
->InitWithPath(aHomeDirName
);
610 nsAutoString version
;
611 path
->GetLeafName(version
);
613 nsStringKey
key(aHomeDirName
);
614 nsJVMConfig
* config
= static_cast<nsJVMConfig
*>
615 (mJVMConfigList
.Get(&key
));
617 config
= new nsJVMConfig(version
, type
, EmptyString(), arch
, path
,
618 mozPluginPath
, EmptyString());
619 NS_ENSURE_TRUE(config
, NS_ERROR_OUT_OF_MEMORY
);
620 mJVMConfigList
.Put(&key
, static_cast<void *>(config
));
628 nsJVMConfigManagerUnix::TestArch(nsILocalFile
* aPluginPath
, nsAString
& aArch
)
631 aArch
.AssignLiteral("sparc");
633 aArch
.AssignLiteral("i386");
635 return TestExists(aPluginPath
, aArch
);
639 nsJVMConfigManagerUnix::TestNSVersion(nsILocalFile
* aArchPath
,
640 nsAString
& aNSVersion
)
642 nsAutoString versionStr
;
643 nsresult rv
= GetNSVersion(versionStr
);
644 NS_ENSURE_SUCCESS(rv
, PR_FALSE
);
646 aNSVersion
.Assign(versionStr
);
647 #if (NS_COMPILER_GNUC3)
648 aNSVersion
.AppendLiteral("-gcc32");
650 return TestExists(aArchPath
, aNSVersion
);
654 nsJVMConfigManagerUnix::TestExists(nsILocalFile
* aBaseDir
, nsAString
& aSubName
)
656 NS_ENSURE_ARG_POINTER(aBaseDir
);
658 aBaseDir
->Append(aSubName
);
660 aBaseDir
->Exists(&exists
);