b=450088 backing out (new reftest failed)
[wine-gecko.git] / modules / oji / src / nsJVMConfigManagerUnix.cpp
blob587e691dfb47331b7528ab4d2bbaf7c0510c47e6
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
13 * License.
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.
21 * Contributor(s):
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 ***** */
38 #include <stdlib.h>
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"
46 #include "prprf.h"
47 #include "nsNetCID.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 */
52 #include <unistd.h>
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()
62 InitJVMConfigList();
65 static PRBool
66 FreeJVMConfig(nsHashKey *aKey, void *aData, void* aClosure)
68 nsJVMConfig* config = static_cast<nsJVMConfig *>(aData);
70 NS_IF_RELEASE(config);
72 return PR_TRUE;
75 static 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);
83 return PR_TRUE;
86 nsJVMConfigManagerUnix::~nsJVMConfigManagerUnix()
88 ClearJVMConfigList();
91 void
92 nsJVMConfigManagerUnix::ClearJVMConfigList()
94 if (mJVMConfigList.Count() > 0) {
95 mJVMConfigList.Reset(FreeJVMConfig);
99 NS_IMETHODIMP
100 nsJVMConfigManagerUnix::GetJVMConfigList(nsIArray **_retval)
102 NS_ENSURE_ARG_POINTER(_retval);
104 ClearJVMConfigList();
105 InitJVMConfigList();
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);
116 } else
117 *_retval = nsnull;
119 return NS_OK;
122 NS_IMETHODIMP
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();
153 NS_IMETHODIMP
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);
186 PRInt16 result = 0;
187 result = symlink(srcFileName.get(), destFileName.get());
189 return result >= 0 ? NS_OK : NS_ERROR_FAILURE;
192 nsresult
193 nsJVMConfigManagerUnix::InitJVMConfigList(nsILineInputStream* aGlobal,
194 nsILineInputStream* aPrivate)
196 nsresult rv = NS_OK;
198 if (aGlobal) {
199 rv = ParseStream(aGlobal);
200 NS_ENSURE_SUCCESS(rv, rv);
203 if (aPrivate) {
204 rv = ParseStream(aPrivate);
205 NS_ENSURE_SUCCESS(rv, rv);
208 return NS_OK;
211 nsresult
212 nsJVMConfigManagerUnix::GetLineInputStream(nsIFile* aFile,
213 nsILineInputStream** _retval)
215 NS_ENSURE_ARG_POINTER(_retval);
217 nsresult rv = NS_OK;
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);
235 return NS_OK;
238 nsresult
239 nsJVMConfigManagerUnix::ParseStream(nsILineInputStream* aStream)
241 NS_ENSURE_ARG_POINTER(aStream);
243 PRBool notEOF = PR_TRUE;
245 nsAutoString lineBuffer;
246 do {
247 nsAutoString line;
248 nsCAutoString cLine;
249 nsresult rv = aStream->ReadLine(cLine, &notEOF);
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);
268 } else {
269 // Start of a new line
270 lineBuffer.Truncate();
272 } while (notEOF);
274 return NS_OK;
277 nsresult
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);
285 #endif
287 nsAutoString version;
288 GetValueFromLine(aLine, "version", version);
290 nsAutoString type;
291 GetValueFromLine(aLine, "type", type);
293 nsAutoString os;
294 GetValueFromLine(aLine, "os", os);
296 nsAutoString arch;
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.
312 nsresult rv = NS_OK;
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
325 PRBool exists;
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.
344 if (!config) {
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));
349 NS_ADDREF(config);
352 return NS_OK;
355 nsresult
356 nsJVMConfigManagerUnix::GetMozillaPluginPath(nsAString& aLine,
357 nsAString& _retval)
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);
387 return NS_OK;
390 nsresult
391 nsJVMConfigManagerUnix::GetAgentVersion(nsCAutoString& _retval)
393 nsresult rv = NS_OK;
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));
406 return NS_OK;
409 nsresult
410 nsJVMConfigManagerUnix::GetAgentVersion(float* _retval)
412 NS_ENSURE_ARG_POINTER(_retval);
413 nsresult rv = NS_OK;
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);
427 PRBool
428 nsJVMConfigManagerUnix::GetValueFromLine(nsAString& aLine, const char* aKey,
429 nsAString& _retval)
431 _retval.Truncate();
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,
450 equalsOffset + 1,
451 lineOffset - equalsOffset -1));
453 // Removing the leading/trailing spaces
454 value.Trim(" ");
455 _retval = value;
456 return PR_TRUE;
459 nsresult
460 nsJVMConfigManagerUnix::GetNSVersion(nsAString& _retval)
462 float version;
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");
471 } else {
472 _retval.AssignLiteral("ns610");
475 return NS_OK;
478 nsresult
479 nsJVMConfigManagerUnix::SearchDefault()
481 #ifdef SPARC
482 const char* defaultLocationName = "java.default_java_location_solaris";
483 #else
484 const char* defaultLocationName = "java.default_java_location_others";
485 #endif
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);
496 #ifdef SPARC
497 // On Solaris, the default location is the java home
498 return AddDirectory(defaultLocation);
499 #else
500 // On Linux and other platform,
501 // the default location can contain multiple java installations
502 return SearchDirectory(defaultLocation);
503 #endif
506 nsresult
507 nsJVMConfigManagerUnix::SearchDirectory(nsAString& aDirName)
509 nsresult rv = NS_OK;
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);
535 AddDirectory(entry);
536 entries->HasMoreElements(&hasMoreElements);
539 return NS_OK;
542 nsresult
543 nsJVMConfigManagerUnix::AddDirectory(nsIFile* aHomeDir)
545 NS_ENSURE_ARG_POINTER(aHomeDir);
546 nsAutoString homeDirName;
547 aHomeDir->GetPath(homeDirName);
548 return AddDirectory(homeDirName);
551 nsresult
552 nsJVMConfigManagerUnix::AddDirectory(nsAString& aHomeDirName)
554 nsresult rv = NS_OK;
556 nsAutoString type;
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"));
566 PRBool exists;
567 testPath->Exists(&exists);
568 if (exists) {
569 type.AssignLiteral("jdk");
570 } else {
571 type.AssignLiteral("jre");
572 testPath->InitWithPath(aHomeDirName);
575 testPath->Append(NS_LITERAL_STRING("plugin"));
577 // Get Arch. "sparc" or "i386"
578 nsAutoString arch;
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));
616 if (!config) {
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));
621 NS_ADDREF(config);
624 return NS_OK;
627 PRBool
628 nsJVMConfigManagerUnix::TestArch(nsILocalFile* aPluginPath, nsAString& aArch)
630 #ifdef SPARC
631 aArch.AssignLiteral("sparc");
632 #else
633 aArch.AssignLiteral("i386");
634 #endif
635 return TestExists(aPluginPath, aArch);
638 PRBool
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");
649 #endif
650 return TestExists(aArchPath, aNSVersion);
653 PRBool
654 nsJVMConfigManagerUnix::TestExists(nsILocalFile* aBaseDir, nsAString& aSubName)
656 NS_ENSURE_ARG_POINTER(aBaseDir);
658 aBaseDir->Append(aSubName);
659 PRBool exists;
660 aBaseDir->Exists(&exists);
662 return exists;