VirtualBox

source: vbox/trunk/src/libs/xpcom18a4/java/tools/genifaces/GenerateJavaInterfaces.cpp@ 29157

Last change on this file since 29157 was 29157, checked in by vboxsync, 15 years ago

attempt to fix genjifaces crash

  • Property svn:eol-style set to native
File size: 27.9 KB
Line 
1/* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
3 *
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
8 *
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
13 *
14 * The Original Code is Java XPCOM Bindings.
15 *
16 * The Initial Developer of the Original Code is
17 * IBM Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 2005
19 * IBM Corporation. All Rights Reserved.
20 *
21 * Contributor(s):
22 * Javier Pedemonte ([email protected])
23 *
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.
35 *
36 * ***** END LICENSE BLOCK ***** */
37
38#include "nsXPCOM.h"
39#include "nsString.h"
40#include "nsILocalFile.h"
41#include "nsIInterfaceInfoManager.h"
42#include "xptinfo.h"
43#include "nsCOMPtr.h"
44#include "prmem.h"
45#include "xptcall.h"
46#ifdef VBOX
47#include "nsFileStreams.h"
48static nsresult
49NS_NewLocalFileInputStream(nsIInputStream **aResult,
50 nsIFile *aFile,
51 PRInt32 aIOFlags = -1,
52 PRInt32 aPerm = -1,
53 PRInt32 aBehaviorFlags = 0)
54{
55 nsFileInputStream* in = new nsFileInputStream();
56 nsresult rv;
57
58 rv = in->Init(aFile, aIOFlags, aPerm, aBehaviorFlags);
59 if (NS_SUCCEEDED(rv))
60 NS_ADDREF(*aResult = in);
61
62 return rv;
63}
64
65inline nsresult
66NS_NewLocalFileOutputStream(nsIOutputStream **aResult,
67 nsIFile *aFile,
68 PRInt32 aIOFlags = -1,
69 PRInt32 aPerm = -1,
70 PRInt32 aBehaviorFlags = 0)
71{
72 nsFileOutputStream* in = new nsFileOutputStream();
73 nsresult rv;
74
75 rv = in->Init(aFile, aIOFlags, aPerm, aBehaviorFlags);
76 if (NS_SUCCEEDED(rv))
77 NS_ADDREF(*aResult = in);
78
79 return rv;
80}
81
82
83#else
84#include "nsNetUtil.h"
85#endif
86#include "nsHashSets.h"
87#include "nsIWeakReference.h"
88#include <stdio.h>
89
90#ifdef WIN32
91#define snprintf _snprintf
92#endif
93
94#define WRITE_NOSCRIPT_METHODS
95
96
97class TypeInfo
98{
99public:
100 static nsresult GetParentInfo(nsIInterfaceInfo* aIInfo,
101 nsIInterfaceInfo** aParentInfo,
102 PRUint16* aParentMethodCount,
103 PRUint16* aParentConstCount)
104 {
105 nsCOMPtr<nsIInterfaceInfo> parent;
106 nsresult rv = aIInfo->GetParent(getter_AddRefs(parent));
107 NS_ENSURE_SUCCESS(rv, rv);
108
109 if (!parent) {
110 *aParentInfo = nsnull;
111 *aParentMethodCount = 0;
112 return NS_OK;
113 }
114
115 rv = parent->GetMethodCount(aParentMethodCount);
116 NS_ENSURE_SUCCESS(rv, rv);
117 rv = parent->GetConstantCount(aParentConstCount);
118 NS_ENSURE_SUCCESS(rv, rv);
119
120 *aParentInfo = parent;
121 NS_ADDREF(*aParentInfo);
122 return rv;
123 }
124
125 static nsresult GetInterfaceName(nsIInterfaceInfo* aIInfo,
126 PRUint16 aMethodIndex,
127 const nsXPTParamInfo* aParamInfo,
128 char** aResult)
129 {
130 static const char isupp_str[] = "nsISupports";
131
132 nsIID* iid;
133 nsresult rv = aIInfo->GetIIDForParam(aMethodIndex, aParamInfo, &iid);
134 if (NS_FAILED(rv)) {
135 // GetIIDForParam will sometimes fail to find an interface, particularly
136 // if that interface is not defined in an IDL file. In those cases, just
137 // return |nsISupports|.
138 //
139 // For example, the |onStreamComplete| method for the interface
140 // |nsIUnicharStreamLoaderObserver| takes a param of
141 // |nsIUnicharInputStream|, which is defined in a simple header file, not
142 // an IDL file.
143 *aResult = (char*) nsMemory::Clone(isupp_str, sizeof(isupp_str));
144 rv = (*aResult == nsnull) ? NS_ERROR_OUT_OF_MEMORY : NS_OK;
145
146 } else {
147
148 // In Javaconnect, we handle weak references internally; no need for the
149 // |nsIWeakReference| interface. So just return |nsISupports|.
150 if (iid->Equals(NS_GET_IID(nsIWeakReference))) {
151 *aResult = (char*) nsMemory::Clone(isupp_str, sizeof(isupp_str));
152 rv = (*aResult == nsnull) ? NS_ERROR_OUT_OF_MEMORY : NS_OK;
153
154 } else {
155
156 // Some methods take parameters of non-scriptable interfaces. But we
157 // only output scriptable interfaces. So if one of the param types is
158 // a non-scriptable interface, output |nsISupports| instead of the
159 // interface name.
160 nsCOMPtr<nsIInterfaceInfo> info;
161 nsCOMPtr<nsIInterfaceInfoManager> iim =
162 getter_AddRefs(XPTI_GetInterfaceInfoManager());
163 NS_ASSERTION(iim, "could not get interface info manager");
164 rv = iim->GetInfoForIID(iid, getter_AddRefs(info));
165 NS_ENSURE_SUCCESS(rv, rv);
166 PRBool scriptable;
167 if (NS_SUCCEEDED(rv)) {
168 info->IsScriptable(&scriptable);
169 }
170 if (NS_FAILED(rv) || !scriptable) {
171 *aResult = (char*) nsMemory::Clone(isupp_str, sizeof(isupp_str));
172 rv = (*aResult == nsnull) ? NS_ERROR_OUT_OF_MEMORY : NS_OK;
173 } else {
174
175 // If is scriptable, get name for given IID
176 rv = iim->GetNameForIID(iid, aResult);
177 }
178 }
179
180 nsMemory::Free(iid);
181 }
182
183 return rv;
184 }
185};
186
187
188static const char* kJavaKeywords[] = {
189 "abstract", "default", "if" , "private" , "this" ,
190 "boolean" , "do" , "implements", "protected" , "throw" ,
191 "break" , "double" , "import", "public" , "throws" ,
192 "byte" , "else" , "instanceof", "return" , "transient",
193 "case" , "extends", "int" , "short" , "try" ,
194 "catch" , "final" , "interface" , "static" , "void" ,
195 "char" , "finally", "long" , "strictfp" , "volatile" ,
196 "class" , "float" , "native" , "super" , "while" ,
197 "const" , "for" , "new" , "switch" ,
198 "continue", "goto" , "package" , "synchronized",
199 "assert" , /* added in Java 1.4 */
200 "enum" , /* added in Java 5.0 */
201 "clone" , /* clone is a member function of java.lang.Object */
202 "finalize" /* finalize is a member function of java.lang.Object */
203};
204
205#ifdef WRITE_NOSCRIPT_METHODS
206// SWT uses [noscript] methods of the following interfaces, so we need to
207// output the [noscript] methods for these interfaces.
208static const char* kNoscriptMethodIfaces[] = {
209 "nsIBaseWindow", "nsIEmbeddingSiteWindow"
210};
211#endif
212
213
214class Generate
215{
216 nsILocalFile* mOutputDir;
217 nsCStringHashSet mIfaceTable;
218 nsCStringHashSet mJavaKeywords;
219#ifdef WRITE_NOSCRIPT_METHODS
220 nsCStringHashSet mNoscriptMethodsTable;
221#endif
222
223public:
224 Generate(nsILocalFile* aOutputDir)
225 : mOutputDir(aOutputDir)
226 {
227 mIfaceTable.Init(100);
228
229 PRUint32 size = NS_ARRAY_LENGTH(kJavaKeywords);
230 mJavaKeywords.Init(size);
231 for (PRUint32 i = 0; i < size; i++) {
232 mJavaKeywords.Put(nsDependentCString(kJavaKeywords[i]));
233 }
234
235#ifdef WRITE_NOSCRIPT_METHODS
236 size = NS_ARRAY_LENGTH(kNoscriptMethodIfaces);
237 mNoscriptMethodsTable.Init(size);
238 for (PRUint32 j = 0; j < size; j++) {
239 mNoscriptMethodsTable.Put(nsDependentCString(kNoscriptMethodIfaces[j]));
240 }
241#endif
242 }
243
244 ~Generate()
245 {
246 }
247
248 nsresult GenerateInterfaces()
249 {
250 nsresult rv;
251
252 nsCOMPtr<nsIInterfaceInfoManager> iim =
253 getter_AddRefs(XPTI_GetInterfaceInfoManager());
254 NS_ASSERTION(iim, "could not get interface info manager");
255 nsCOMPtr<nsIEnumerator> etor;
256 rv = iim->EnumerateInterfaces(getter_AddRefs(etor));
257 NS_ENSURE_SUCCESS(rv, rv);
258
259 // loop over interfaces
260 etor->First();
261 do {
262 // get current interface
263 nsCOMPtr<nsISupports> item;
264 rv = etor->CurrentItem(getter_AddRefs(item));
265 NS_ENSURE_SUCCESS(rv, rv);
266
267 nsCOMPtr<nsIInterfaceInfo> iface(do_QueryInterface(item));
268 if (!iface)
269 break;
270
271 // we only care about scriptable interfaces, so skip over those
272 // that aren't
273 PRBool scriptable;
274 iface->IsScriptable(&scriptable);
275 if (!scriptable) {
276 // XXX SWT uses non-scriptable interface 'nsIAppShell' (bug 270892), so
277 // include that one.
278 const char* iface_name;
279 iface->GetNameShared(&iface_name);
280 if (strcmp("nsIAppShell", iface_name) != 0)
281 continue;
282 }
283
284 rv = WriteOneInterface(iface);
285 NS_ENSURE_SUCCESS(rv, rv);
286
287 } while (NS_SUCCEEDED(etor->Next()));
288
289 return NS_OK;
290 }
291
292 nsresult WriteOneInterface(nsIInterfaceInfo* aIInfo)
293 {
294 nsresult rv;
295
296 // write each interface only once
297 const char* iface_name;
298 aIInfo->GetNameShared(&iface_name);
299 if (mIfaceTable.Contains(nsDependentCString(iface_name)))
300 return NS_OK;
301
302 // write any parent interface
303 nsCOMPtr<nsIInterfaceInfo> parentInfo;
304 PRUint16 parentMethodCount, parentConstCount;
305 rv = TypeInfo::GetParentInfo(aIInfo, getter_AddRefs(parentInfo),
306 &parentMethodCount, &parentConstCount);
307 NS_ENSURE_SUCCESS(rv, rv);
308 if (parentInfo)
309 WriteOneInterface(parentInfo);
310
311 mIfaceTable.Put(nsDependentCString(iface_name));
312
313 // create file for interface
314 nsCOMPtr<nsIOutputStream> out;
315 rv = OpenIfaceFileStream(iface_name, getter_AddRefs(out));
316 NS_ENSURE_SUCCESS(rv, rv);
317
318 // write contents to file
319 rv = WriteHeader(out, iface_name);
320 NS_ENSURE_SUCCESS(rv, rv);
321 rv = WriteInterfaceStart(out, aIInfo, parentInfo);
322 NS_ENSURE_SUCCESS(rv, rv);
323 rv = WriteIID(out, aIInfo);
324 NS_ENSURE_SUCCESS(rv, rv);
325 rv = WriteConstants(out, aIInfo, parentConstCount);
326 NS_ENSURE_SUCCESS(rv, rv);
327 rv = WriteMethods(out, aIInfo, parentMethodCount);
328 NS_ENSURE_SUCCESS(rv, rv);
329 rv = WriteInterfaceEnd(out);
330 NS_ENSURE_SUCCESS(rv, rv);
331
332 rv = CloseIfaceFileStream(out);
333
334 return rv;
335 }
336
337 nsresult OpenIfaceFileStream(const char* aIfaceName,
338 nsIOutputStream** aResult)
339 {
340 nsresult rv;
341
342 // create interface file in output dir
343 nsCOMPtr<nsIFile> iface_file;
344 rv = mOutputDir->Clone(getter_AddRefs(iface_file));
345 NS_ENSURE_SUCCESS(rv, rv);
346 nsAutoString filename;
347 filename.AppendASCII(aIfaceName);
348 filename.AppendLiteral(".java");
349 rv = iface_file->Append(filename);
350 NS_ENSURE_SUCCESS(rv, rv);
351
352 // create interface file
353 PRBool exists;
354 iface_file->Exists(&exists);
355 if (exists)
356 iface_file->Remove(PR_FALSE);
357 rv = iface_file->Create(nsIFile::NORMAL_FILE_TYPE, 0644);
358 NS_ENSURE_SUCCESS(rv, rv);
359
360 // create output stream for writing to file
361 nsCOMPtr<nsIOutputStream> out;
362 rv = NS_NewLocalFileOutputStream(getter_AddRefs(out), iface_file);
363 NS_ENSURE_SUCCESS(rv, rv);
364
365 *aResult = out;
366 NS_ADDREF(*aResult);
367 return NS_OK;
368 }
369
370 nsresult CloseIfaceFileStream(nsIOutputStream* out)
371 {
372 return out->Close();
373 }
374
375 nsresult WriteHeader(nsIOutputStream* out, const char* aIfaceName)
376 {
377 static const char kHeader1[] =
378 "/**\n"
379 " * NOTE: THIS IS A GENERATED FILE. PLEASE CONSULT THE ORIGINAL IDL FILE\n"
380 " * FOR THE FULL DOCUMENTION AND LICENSE.\n"
381 " *\n"
382 " * @see <a href=\"http://lxr.mozilla.org/mozilla/search?string=";
383 static const char kHeader2[]= "\">\n **/\n\n";
384 static const char kPackage[] = "package org.mozilla.interfaces;\n\n";
385
386 PRUint32 count;
387 nsresult rv = out->Write(kHeader1, sizeof(kHeader1) - 1, &count);
388 NS_ENSURE_SUCCESS(rv, rv);
389
390 nsCAutoString searchTerm;
391 searchTerm.AppendLiteral("interface+");
392 searchTerm.AppendASCII(aIfaceName);
393 // LXR limits to 29 chars
394 rv = out->Write(searchTerm.get(), PR_MIN(29, searchTerm.Length()), &count);
395 NS_ENSURE_SUCCESS(rv, rv);
396
397 rv = out->Write(kHeader2, sizeof(kHeader2) - 1, &count);
398 NS_ENSURE_SUCCESS(rv, rv);
399 rv = out->Write(kPackage, sizeof(kPackage) - 1, &count);
400 return rv;
401 }
402
403 nsresult WriteInterfaceStart(nsIOutputStream* out, nsIInterfaceInfo* aIInfo,
404 nsIInterfaceInfo* aParentInfo)
405 {
406 static const char kIfaceDecl1[] = "public interface ";
407 static const char kParentDecl[] = " extends ";
408 static const char kIfaceDecl2[] = "\n{\n";
409
410 const char* iface_name;
411 aIInfo->GetNameShared(&iface_name);
412 PRUint32 count;
413 nsresult rv = out->Write(kIfaceDecl1, sizeof(kIfaceDecl1) - 1, &count);
414 NS_ENSURE_SUCCESS(rv, rv);
415 rv = out->Write(iface_name, strlen(iface_name), &count);
416 NS_ENSURE_SUCCESS(rv, rv);
417
418 if (aParentInfo) {
419 const char* parent_name;
420 aParentInfo->GetNameShared(&parent_name);
421 rv = out->Write(kParentDecl, sizeof(kParentDecl) - 1, &count);
422 NS_ENSURE_SUCCESS(rv, rv);
423 rv = out->Write(parent_name, strlen(parent_name), &count);
424 NS_ENSURE_SUCCESS(rv, rv);
425 }
426
427 rv = out->Write(kIfaceDecl2, sizeof(kIfaceDecl2) - 1, &count);
428 return rv;
429 }
430
431 nsresult WriteInterfaceEnd(nsIOutputStream* out)
432 {
433 PRUint32 count;
434 return out->Write("}\n", 2, &count);
435 }
436
437 nsresult WriteIID(nsIOutputStream* out, nsIInterfaceInfo* aIInfo)
438 {
439 static const char kIIDDecl1[] = " public static final String ";
440 static const char kIIDDecl2[] = " =\n \"";
441 static const char kIIDDecl3[] = "\";\n\n";
442
443 nsIID* iid = nsnull;
444 aIInfo->GetInterfaceIID(&iid);
445 if (!iid)
446 return NS_ERROR_OUT_OF_MEMORY;
447
448 // create iid field name
449 nsCAutoString iid_name;
450 const char* iface_name;
451 aIInfo->GetNameShared(&iface_name);
452 if (strncmp("ns", iface_name, 2) == 0) {
453 iid_name.AppendLiteral("NS_");
454 iid_name.Append(iface_name + 2);
455 } else {
456 iid_name.Append(iface_name);
457 }
458 iid_name.AppendLiteral("_IID");
459 ToUpperCase(iid_name);
460
461 // get iid string
462 char* iid_str = iid->ToString();
463 if (!iid_str)
464 return NS_ERROR_OUT_OF_MEMORY;
465
466 PRUint32 count;
467 nsresult rv = out->Write(kIIDDecl1, sizeof(kIIDDecl1) - 1, &count);
468 NS_ENSURE_SUCCESS(rv, rv);
469 rv = out->Write(iid_name.get(), iid_name.Length(), &count);
470 NS_ENSURE_SUCCESS(rv, rv);
471 rv = out->Write(kIIDDecl2, sizeof(kIIDDecl2) - 1, &count);
472 NS_ENSURE_SUCCESS(rv, rv);
473 rv = out->Write(iid_str, strlen(iid_str), &count);
474 NS_ENSURE_SUCCESS(rv, rv);
475 rv = out->Write(kIIDDecl3, sizeof(kIIDDecl3) - 1, &count);
476 NS_ENSURE_SUCCESS(rv, rv);
477
478 // cleanup
479 PR_Free(iid_str);
480 nsMemory::Free(iid);
481 return NS_OK;
482 }
483
484 nsresult WriteConstants(nsIOutputStream* out, nsIInterfaceInfo* aIInfo,
485 PRUint16 aParentConstCount)
486 {
487 static const char kConstDecl1[] = " public static final ";
488 static const char kConstDecl2[] = " = ";
489 static const char kConstDecl3[] = ";\n\n";
490
491 PRUint16 constCount;
492 nsresult rv = aIInfo->GetConstantCount(&constCount);
493 NS_ENSURE_SUCCESS(rv, rv);
494
495 for (PRUint16 i = aParentConstCount; i < constCount; i++) {
496 const nsXPTConstant* constInfo;
497 rv = aIInfo->GetConstant(i, &constInfo);
498 NS_ENSURE_SUCCESS(rv, rv);
499
500 PRUint32 count;
501 rv = out->Write(kConstDecl1, sizeof(kConstDecl1) - 1, &count);
502 NS_ENSURE_SUCCESS(rv, rv);
503 const nsXPTType &type = constInfo->GetType();
504 rv = WriteType(out, &type, aIInfo, nsnull, nsnull);
505 NS_ENSURE_SUCCESS(rv, rv);
506 rv = out->Write(" ", 1, &count);
507 NS_ENSURE_SUCCESS(rv, rv);
508 const char* name = constInfo->GetName();
509 rv = out->Write(name, strlen(name), &count);
510 NS_ENSURE_SUCCESS(rv, rv);
511 rv = out->Write(kConstDecl2, sizeof(kConstDecl2) - 1, &count);
512 NS_ENSURE_SUCCESS(rv, rv);
513
514 rv = WriteConstantValue(out, &type, constInfo->GetValue());
515 NS_ENSURE_SUCCESS(rv, rv);
516 rv = out->Write(kConstDecl3, sizeof(kConstDecl3) - 1, &count);
517 NS_ENSURE_SUCCESS(rv, rv);
518 }
519
520 return NS_OK;
521 }
522
523 nsresult WriteConstantValue(nsIOutputStream* out, const nsXPTType* aType,
524 const nsXPTCMiniVariant* aValue)
525 {
526 char buf[32];
527 switch (aType->TagPart()) {
528 case nsXPTType::T_I8:
529 snprintf(buf, sizeof(buf), "%d", aValue->val.i8);
530 break;
531
532 case nsXPTType::T_U8:
533 snprintf(buf, sizeof(buf), "%u", aValue->val.u8);
534 break;
535
536 case nsXPTType::T_I16:
537 snprintf(buf, sizeof(buf), "%d", aValue->val.i16);
538 break;
539
540 case nsXPTType::T_U16:
541 snprintf(buf, sizeof(buf), "%u", aValue->val.u16);
542 break;
543
544 case nsXPTType::T_I32:
545 snprintf(buf, sizeof(buf), "%d", aValue->val.i32);
546 break;
547
548 case nsXPTType::T_U32:
549 snprintf(buf, sizeof(buf), "%uL", aValue->val.u32);
550 break;
551
552 case nsXPTType::T_I64:
553 snprintf(buf, sizeof(buf), "%lldL", aValue->val.i64);
554 break;
555
556 case nsXPTType::T_U64:
557 snprintf(buf, sizeof(buf), "%lluL", aValue->val.u64);
558 break;
559
560 case nsXPTType::T_FLOAT:
561 snprintf(buf, sizeof(buf), "%f", aValue->val.f);
562 break;
563
564 case nsXPTType::T_DOUBLE:
565 snprintf(buf, sizeof(buf), "%f", aValue->val.d);
566 break;
567
568 case nsXPTType::T_BOOL:
569 if (aValue->val.b)
570 sprintf(buf, "true");
571 else
572 sprintf(buf, "false");
573 break;
574
575 case nsXPTType::T_CHAR:
576 snprintf(buf, sizeof(buf), "%c", aValue->val.c);
577 break;
578
579 case nsXPTType::T_WCHAR:
580 snprintf(buf, sizeof(buf), "%c", aValue->val.wc);
581 break;
582
583 default:
584 NS_WARNING("unexpected constant type");
585 return NS_ERROR_UNEXPECTED;
586 }
587
588 PRUint32 count;
589 return out->Write(buf, strlen(buf), &count);
590 }
591
592 nsresult WriteMethods(nsIOutputStream* out, nsIInterfaceInfo* aIInfo,
593 PRUint16 aParentMethodCount)
594 {
595 PRUint16 methodCount;
596 nsresult rv = aIInfo->GetMethodCount(&methodCount);
597 NS_ENSURE_SUCCESS(rv, rv);
598
599 for (PRUint16 i = aParentMethodCount; i < methodCount; i++) {
600 const nsXPTMethodInfo* methodInfo;
601 rv = aIInfo->GetMethodInfo(i, &methodInfo);
602 NS_ENSURE_SUCCESS(rv, rv);
603
604#ifdef WRITE_NOSCRIPT_METHODS
605 // XXX
606 // SWT makes use of [noscript] methods in some classes, so output them
607 // for those classes.
608
609 // skip [notxpcom] methods
610 if (methodInfo->IsNotXPCOM())
611 continue;
612
613 // skip most hidden ([noscript]) methods
614 if (methodInfo->IsHidden()) {
615 const char* iface_name;
616 aIInfo->GetNameShared(&iface_name);
617 if (!mNoscriptMethodsTable.Contains(nsDependentCString(iface_name)))
618 continue;
619 }
620#else
621 // skip hidden ([noscript]) or [notxpcom] methods
622 if (methodInfo->IsHidden() || methodInfo->IsNotXPCOM())
623 continue;
624#endif
625
626 rv = WriteOneMethod(out, aIInfo, methodInfo, i);
627 NS_ENSURE_SUCCESS(rv, rv);
628 }
629
630 return NS_OK;
631 }
632
633 nsresult WriteOneMethod(nsIOutputStream* out, nsIInterfaceInfo* aIInfo,
634 const nsXPTMethodInfo* aMethodInfo,
635 PRUint16 aMethodIndex)
636 {
637 static const char kMethodDecl1[] = " public ";
638 static const char kVoidReturn[] = "void";
639 static const char kParamSeparator[] = ", ";
640 static const char kMethodDecl2[] = ");\n\n";
641
642 PRUint32 count;
643 nsresult rv = out->Write(kMethodDecl1, sizeof(kMethodDecl1) - 1, &count);
644 NS_ENSURE_SUCCESS(rv, rv);
645
646 // write return type
647 PRUint8 paramCount = aMethodInfo->GetParamCount();
648 const nsXPTParamInfo* resultInfo = nsnull;
649 for (PRUint8 i = 0; i < paramCount; i++) {
650 const nsXPTParamInfo &paramInfo = aMethodInfo->GetParam(i);
651 if (paramInfo.IsRetval()) {
652 resultInfo = &paramInfo;
653 break;
654 }
655 }
656 if (resultInfo) {
657 rv = WriteParam(out, aIInfo, aMethodIndex, resultInfo, 0);
658 } else {
659 rv = out->Write(kVoidReturn, sizeof(kVoidReturn) - 1, &count);
660 }
661 NS_ENSURE_SUCCESS(rv, rv);
662
663 // write method name string
664 nsCAutoString method_name;
665 const char* name = aMethodInfo->GetName();
666 if (aMethodInfo->IsGetter() || aMethodInfo->IsSetter()) {
667 if (aMethodInfo->IsGetter())
668 method_name.AppendLiteral("get");
669 else
670 method_name.AppendLiteral("set");
671 method_name.Append(toupper(name[0]));
672 method_name.AppendASCII(name + 1);
673 } else {
674 method_name.Append(tolower(name[0]));
675 method_name.AppendASCII(name + 1);
676 // don't use Java keywords as method names
677 if (mJavaKeywords.Contains(method_name))
678 method_name.Append('_');
679 }
680 rv = out->Write(" ", 1, &count);
681 NS_ENSURE_SUCCESS(rv, rv);
682 rv = out->Write(method_name.get(), method_name.Length(), &count);
683 NS_ENSURE_SUCCESS(rv, rv);
684 rv = out->Write("(", 1, &count);
685 NS_ENSURE_SUCCESS(rv, rv);
686
687 // write parameters
688 for (PRUint8 j = 0; j < paramCount; j++) {
689 const nsXPTParamInfo &paramInfo = aMethodInfo->GetParam(j);
690 if (paramInfo.IsRetval())
691 continue;
692
693 if (j != 0) {
694 rv = out->Write(kParamSeparator, sizeof(kParamSeparator) - 1, &count);
695 NS_ENSURE_SUCCESS(rv, rv);
696 }
697
698 rv = WriteParam(out, aIInfo, aMethodIndex, &paramInfo, j + 1);
699 NS_ENSURE_SUCCESS(rv, rv);
700 }
701
702 rv = out->Write(kMethodDecl2, sizeof(kMethodDecl2) - 1, &count);
703 return rv;
704 }
705
706 nsresult WriteParam(nsIOutputStream* out, nsIInterfaceInfo* aIInfo,
707 PRUint16 aMethodIndex, const nsXPTParamInfo* aParamInfo,
708 PRUint8 aIndex)
709 {
710 const nsXPTType &type = aParamInfo->GetType();
711 nsresult rv = WriteType(out, &type, aIInfo, aMethodIndex, aParamInfo);
712 NS_ENSURE_SUCCESS(rv, rv);
713
714 // if parameter is 'out' or 'inout', make it a Java array
715 PRUint32 count;
716 if (aParamInfo->IsOut() && !aParamInfo->IsRetval()) {
717 rv = out->Write("[]", 2, &count);
718 NS_ENSURE_SUCCESS(rv, rv);
719 }
720
721 // write name for parameter (but not for 'retval' param)
722 if (aIndex) {
723 char buf[10];
724 snprintf(buf, sizeof(buf), " arg%d", aIndex);
725 rv = out->Write(buf, strlen(buf), &count);
726 NS_ENSURE_SUCCESS(rv, rv);
727 }
728
729 return NS_OK;
730 }
731
732 /**
733 * Write out the Java type for the given XPIDL type.
734 *
735 * NOTE: Java doesn't support unsigned types. So for any unsigned XPIDL type,
736 * we move up to the next largest Java type. This way we ensure that we don't
737 * lose any info.
738 */
739 nsresult WriteType(nsIOutputStream* out, const nsXPTType* aType,
740 nsIInterfaceInfo* aIInfo, PRUint16 aMethodIndex,
741 const nsXPTParamInfo* aParamInfo)
742 {
743 nsresult rv;
744 PRUint32 count;
745 switch (aType->TagPart()) {
746 case nsXPTType::T_I8:
747 rv = out->Write("byte", 4, &count);
748 break;
749
750 case nsXPTType::T_I16:
751 case nsXPTType::T_U8:
752 rv = out->Write("short", 5, &count);
753 break;
754
755 case nsXPTType::T_I32:
756 case nsXPTType::T_U16:
757 rv = out->Write("int", 3, &count);
758 break;
759
760 case nsXPTType::T_I64:
761 case nsXPTType::T_U32:
762 rv = out->Write("long", 4, &count);
763 break;
764
765 case nsXPTType::T_FLOAT:
766 rv = out->Write("float", 5, &count);
767 break;
768
769 // XXX how should we handle 64-bit values?
770 case nsXPTType::T_U64:
771 case nsXPTType::T_DOUBLE:
772 rv = out->Write("double", 6, &count);
773 break;
774
775 case nsXPTType::T_BOOL:
776 rv = out->Write("boolean", 7, &count);
777 break;
778
779 case nsXPTType::T_CHAR:
780 case nsXPTType::T_WCHAR:
781 rv = out->Write("char", 4, &count);
782 break;
783
784 case nsXPTType::T_CHAR_STR:
785 case nsXPTType::T_WCHAR_STR:
786 case nsXPTType::T_IID:
787 case nsXPTType::T_ASTRING:
788 case nsXPTType::T_DOMSTRING:
789 case nsXPTType::T_UTF8STRING:
790 case nsXPTType::T_CSTRING:
791 case nsXPTType::T_PSTRING_SIZE_IS:
792 case nsXPTType::T_PWSTRING_SIZE_IS:
793 rv = out->Write("String", 6, &count);
794 break;
795
796 case nsXPTType::T_INTERFACE:
797 {
798 char* iface_name = nsnull;
799 rv = TypeInfo::GetInterfaceName(aIInfo, aMethodIndex, aParamInfo,
800 &iface_name);
801 if (NS_FAILED(rv) || !iface_name) {
802 rv = NS_ERROR_FAILURE;
803 break;
804 }
805
806 rv = out->Write(iface_name, strlen(iface_name), &count);
807 nsMemory::Free(iface_name);
808 break;
809 }
810
811 case nsXPTType::T_INTERFACE_IS:
812 rv = out->Write("nsISupports", 11, &count);
813 break;
814
815 case nsXPTType::T_VOID:
816 rv = out->Write("int", 3, &count);
817 break;
818
819 case nsXPTType::T_ARRAY:
820 {
821 // get array type
822 nsXPTType xpttype;
823 rv = aIInfo->GetTypeForParam(aMethodIndex, aParamInfo, 1, &xpttype);
824 if (NS_FAILED(rv))
825 break;
826
827 rv = WriteType(out, &xpttype, aIInfo, aMethodIndex, aParamInfo);
828 if (NS_FAILED(rv))
829 break;
830
831 rv = out->Write("[]", 2, &count);
832 break;
833 }
834
835 default:
836 fprintf(stderr, "WARNING: unexpected parameter type %d\n",
837 aType->TagPart());
838 return NS_ERROR_UNEXPECTED;
839 }
840
841 return rv;
842 }
843};
844
845void PrintUsage(char** argv)
846{
847 static const char usage_str[] =
848 "Usage: %s -d path\n"
849 " -d output directory for Java interface files\n";
850 fprintf(stderr, usage_str, argv[0]);
851}
852#ifdef VBOX
853#include <VBox/com/com.h>
854using namespace com;
855
856#include <iprt/initterm.h>
857#include <iprt/string.h>
858#include <iprt/alloca.h>
859#include <iprt/stream.h>
860#endif
861
862int main(int argc, char** argv)
863{
864 nsresult rv = NS_OK;
865 nsCOMPtr<nsILocalFile> output_dir;
866
867#ifdef VBOX
868#if defined(VBOX_PATH_APP_PRIVATE_ARCH) && defined(VBOX_PATH_SHARED_LIBS)
869 rv = RTR3Init();
870#else
871 const char *home = getenv("VBOX_PROGRAM_PATH");
872 if (home) {
873 size_t len = strlen(home);
874 char *exepath = (char *)alloca(len + 32);
875 memcpy(exepath, home, len);
876 memcpy(exepath + len, "/pythonfake", sizeof("/pythonfake"));
877 rv = RTR3InitWithProgramPath(exepath);
878 } else {
879 rv = RTR3Init();
880 }
881#endif
882#endif
883
884 // handle command line arguments
885 for (int i = 1; i < argc; i++) {
886 if (argv[i][0] != '-') {
887 rv = NS_ERROR_FAILURE;
888 break;
889 }
890
891 switch (argv[i][1]) {
892 case 'd': {
893 if (i + 1 == argc) {
894 fprintf(stderr, "ERROR: missing output directory after -d\n");
895 rv = NS_ERROR_FAILURE;
896 break;
897 }
898
899 // see if given path exists
900 rv = NS_NewNativeLocalFile(nsDependentCString(argv[++i]), PR_TRUE,
901 getter_AddRefs(output_dir));
902 PRBool val;
903 if (NS_FAILED(rv) || NS_FAILED(output_dir->Exists(&val)) || !val ||
904 NS_FAILED(output_dir->IsDirectory(&val)) || !val)
905 {
906 fprintf(stderr,
907 "ERROR: output directory doesn't exist / isn't a directory\n");
908 rv = NS_ERROR_FAILURE;
909 break;
910 }
911
912 break;
913 }
914
915 default: {
916 fprintf(stderr, "ERROR: unknown option %s\n", argv[i]);
917 rv = NS_ERROR_FAILURE;
918 break;
919 }
920 }
921 }
922
923 if (NS_FAILED(rv)) {
924 PrintUsage(argv);
925 return 1;
926 }
927
928#ifdef VBOX
929 rv = com::Initialize();
930#else
931 rv = NS_InitXPCOM2(nsnull, nsnull, nsnull);
932#endif
933 NS_ENSURE_SUCCESS(rv, rv);
934
935 Generate gen(output_dir);
936 rv = gen.GenerateInterfaces();
937
938#ifdef VBOX
939 // very short-living XPCOM processes trigger problem on shutdown - ignoring it not a big deal anyway
940 //com::Shutdown();
941#else
942 NS_ShutdownXPCOM(nsnull);
943#endif
944 return rv;
945}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette