lok: vcl: fix multiple floatwin removal case more robustly.
[LibreOffice.git] / codemaker / source / javamaker / javatype.cxx
blob4cd5b50050b059d689f84a0ba783791558f4a5d1
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
22 #include <algorithm>
23 #include <cassert>
24 #include <cstdlib>
25 #include <map>
26 #include <memory>
27 #include <set>
28 #include <utility>
29 #include <vector>
31 #include <codemaker/codemaker.hxx>
32 #include <codemaker/exceptiontree.hxx>
33 #include <codemaker/generatedtypeset.hxx>
34 #include <codemaker/global.hxx>
35 #include <codemaker/options.hxx>
36 #include <codemaker/typemanager.hxx>
37 #include <codemaker/unotype.hxx>
38 #include <codemaker/commonjava.hxx>
39 #include <rtl/ref.hxx>
40 #include <rtl/strbuf.hxx>
41 #include <rtl/string.hxx>
42 #include <rtl/ustrbuf.hxx>
43 #include <rtl/ustring.hxx>
44 #include <sal/types.h>
45 #include <unoidl/unoidl.hxx>
47 #include "classfile.hxx"
48 #include "javaoptions.hxx"
49 #include "javatype.hxx"
51 using codemaker::javamaker::ClassFile;
53 namespace {
55 void appendUnoName(
56 rtl::Reference< TypeManager > const & manager, OUString const & nucleus,
57 sal_Int32 rank, std::vector< OUString > const & arguments,
58 OUStringBuffer * buffer)
60 assert(manager.is());
61 assert(rank >= 0);
62 assert(buffer != nullptr);
63 for (sal_Int32 i = 0; i != rank; ++i) {
64 buffer->append("[]");
66 buffer->append(nucleus);
67 if (!arguments.empty()) {
68 buffer->append('<');
69 for (std::vector< OUString >::const_iterator i(arguments.begin());
70 i != arguments.end(); ++i)
72 if (i != arguments.begin()) {
73 buffer->append(',');
75 OUString n;
76 sal_Int32 k;
77 std::vector< OUString > args;
78 manager->decompose(*i, false, &n, &k, &args, nullptr);
79 appendUnoName(manager, n, k, args, buffer);
81 buffer->append('>');
85 // Translate the name of a UNOIDL entity (enum type, plain struct type,
86 // polymorphic struct type template, or interface type, decomposed into nucleus,
87 // sequence rank, and template arguments) into a core UNO type name:
88 OUString createUnoName(
89 rtl::Reference< TypeManager > const & manager, OUString const & nucleus,
90 sal_Int32 rank, std::vector< OUString > const & arguments)
92 OUStringBuffer buf;
93 appendUnoName(manager, nucleus, rank, arguments, &buf);
94 return buf.makeStringAndClear();
97 enum SpecialType {
98 SPECIAL_TYPE_NONE,
99 SPECIAL_TYPE_ANY,
100 SPECIAL_TYPE_UNSIGNED,
101 SPECIAL_TYPE_INTERFACE
104 bool isSpecialType(SpecialType special) {
105 return special >= SPECIAL_TYPE_UNSIGNED;
108 OString translateUnoidlEntityNameToJavaFullyQualifiedName(
109 OUString const & name, OString const & prefix)
111 assert(!name.startsWith("[]"));
112 assert(name.indexOf('<') == -1);
113 sal_Int32 i = name.lastIndexOf('.') + 1;
114 return codemaker::convertString(name.copy(0, i)).replace('.', '/')
115 + codemaker::java::translateUnoToJavaIdentifier(
116 codemaker::convertString(name.copy(i)), prefix);
119 struct PolymorphicUnoType {
120 PolymorphicUnoType(): kind(KIND_NONE) {}
122 enum Kind { KIND_NONE, KIND_STRUCT, KIND_SEQUENCE };
123 Kind kind;
124 OUString name;
127 SpecialType translateUnoTypeToDescriptor(
128 rtl::Reference< TypeManager > const & manager, OUString const & type,
129 bool array, bool classType, std::set<OUString> * dependencies,
130 OStringBuffer * descriptor, OStringBuffer * signature,
131 bool * needsSignature, PolymorphicUnoType * polymorphicUnoType);
133 SpecialType translateUnoTypeToDescriptor(
134 rtl::Reference< TypeManager > const & manager,
135 codemaker::UnoType::Sort sort, OUString const & nucleus, sal_Int32 rank,
136 std::vector< OUString > const & arguments, bool array, bool classType,
137 std::set<OUString> * dependencies, OStringBuffer * descriptor,
138 OStringBuffer * signature, bool * needsSignature,
139 PolymorphicUnoType * polymorphicUnoType)
141 assert(rank >= 0);
142 assert((signature == nullptr) == (needsSignature == nullptr));
143 assert(
144 arguments.empty()
145 == (sort
146 != codemaker::UnoType::Sort::InstantiatedPolymorphicStruct));
147 if (rank > 0xFF - (array ? 1 : 0)) {
148 throw CannotDumpException(
149 "Too many array dimensions for Java class file format");
151 if (array) {
152 ++rank;
154 for (sal_Int32 i = 0; i != rank; ++i) {
155 if (descriptor != nullptr) {
156 descriptor->append('[');
158 if (signature != nullptr) {
159 signature->append('[');
162 if (polymorphicUnoType != nullptr) {
163 if (sort
164 == codemaker::UnoType::Sort::InstantiatedPolymorphicStruct)
166 polymorphicUnoType->kind = rank == 0
167 ? PolymorphicUnoType::KIND_STRUCT
168 : PolymorphicUnoType::KIND_SEQUENCE;
169 polymorphicUnoType->name = createUnoName(
170 manager, nucleus, rank, arguments);
171 } else {
172 polymorphicUnoType->kind = PolymorphicUnoType::KIND_NONE;
175 switch (sort) {
176 case codemaker::UnoType::Sort::Void:
177 case codemaker::UnoType::Sort::Boolean:
178 case codemaker::UnoType::Sort::Byte:
179 case codemaker::UnoType::Sort::Short:
180 case codemaker::UnoType::Sort::UnsignedShort:
181 case codemaker::UnoType::Sort::Long:
182 case codemaker::UnoType::Sort::UnsignedLong:
183 case codemaker::UnoType::Sort::Hyper:
184 case codemaker::UnoType::Sort::UnsignedHyper:
185 case codemaker::UnoType::Sort::Float:
186 case codemaker::UnoType::Sort::Double:
187 case codemaker::UnoType::Sort::Char:
188 case codemaker::UnoType::Sort::String:
189 case codemaker::UnoType::Sort::Type:
190 case codemaker::UnoType::Sort::Any:
192 static char const * const
193 simpleTypeDescriptors[static_cast<int>(codemaker::UnoType::Sort::Any) + 1][2] = {
194 { "V", "Ljava/lang/Void;" },
195 { "Z", "Ljava/lang/Boolean;" },
196 { "B", "Ljava/lang/Byte;" },
197 { "S", "Ljava/lang/Short;" },
198 { "S", "Ljava/lang/Short;" },
199 { "I", "Ljava/lang/Integer;" },
200 { "I", "Ljava/lang/Integer;" },
201 { "J", "Ljava/lang/Long;" },
202 { "J", "Ljava/lang/Long;" },
203 { "F", "Ljava/lang/Float;" },
204 { "D", "Ljava/lang/Double;" },
205 { "C", "Ljava/lang/Character;" },
206 { "Ljava/lang/String;", "Ljava/lang/String;" },
207 { "Lcom/sun/star/uno/Type;", "Lcom/sun/star/uno/Type;" },
208 { "Ljava/lang/Object;", "Ljava/lang/Object;" } };
209 char const * s
210 = simpleTypeDescriptors[static_cast<int>(sort)][rank == 0 && classType];
211 if (descriptor != nullptr) {
212 descriptor->append(s);
214 if (signature != nullptr) {
215 signature->append(s);
217 static SpecialType const
218 simpleTypeSpecials[static_cast<int>(codemaker::UnoType::Sort::Any) + 1] = {
219 SPECIAL_TYPE_NONE, SPECIAL_TYPE_NONE, SPECIAL_TYPE_NONE,
220 SPECIAL_TYPE_NONE, SPECIAL_TYPE_UNSIGNED, SPECIAL_TYPE_NONE,
221 SPECIAL_TYPE_UNSIGNED, SPECIAL_TYPE_NONE, SPECIAL_TYPE_UNSIGNED,
222 SPECIAL_TYPE_NONE, SPECIAL_TYPE_NONE, SPECIAL_TYPE_NONE,
223 SPECIAL_TYPE_NONE, SPECIAL_TYPE_NONE, SPECIAL_TYPE_ANY };
224 return simpleTypeSpecials[static_cast<int>(sort)];
226 case codemaker::UnoType::Sort::Interface:
227 if (nucleus == "com.sun.star.uno.XInterface") {
228 if (descriptor != nullptr) {
229 descriptor->append("Ljava/lang/Object;");
231 if (signature != nullptr) {
232 signature->append("Ljava/lang/Object;");
234 return SPECIAL_TYPE_INTERFACE;
236 SAL_FALLTHROUGH;
237 case codemaker::UnoType::Sort::Sequence:
238 case codemaker::UnoType::Sort::Enum:
239 case codemaker::UnoType::Sort::PlainStruct:
240 case codemaker::UnoType::Sort::InstantiatedPolymorphicStruct:
241 if (dependencies != nullptr) {
242 dependencies->insert(nucleus);
244 if (descriptor != nullptr) {
245 descriptor->append(
246 "L" + codemaker::convertString(nucleus).replace('.', '/')
247 + ";");
249 if (signature != nullptr) {
250 signature->append(
251 "L" + codemaker::convertString(nucleus).replace('.', '/'));
252 if (!arguments.empty()) {
253 signature->append('<');
254 for (const OUString& arg : arguments)
256 translateUnoTypeToDescriptor(
257 manager, arg, false, true, dependencies, nullptr, signature,
258 needsSignature, nullptr);
260 signature->append('>');
261 *needsSignature = true;
263 signature->append(';');
265 return SPECIAL_TYPE_NONE;
266 default:
267 throw CannotDumpException(
268 "unexpected nucleus \"" + nucleus
269 + "\" in call to translateUnoTypeToDescriptor");
273 SpecialType translateUnoTypeToDescriptor(
274 rtl::Reference< TypeManager > const & manager, OUString const & type,
275 bool array, bool classType, std::set<OUString> * dependencies,
276 OStringBuffer * descriptor, OStringBuffer * signature,
277 bool * needsSignature, PolymorphicUnoType * polymorphicUnoType)
279 assert(manager.is());
280 OUString nucleus;
281 sal_Int32 rank;
282 std::vector< OUString > args;
283 codemaker::UnoType::Sort sort = manager->decompose(
284 type, true, &nucleus, &rank, &args, nullptr);
285 return translateUnoTypeToDescriptor(
286 manager, sort, nucleus, rank, args, array, classType, dependencies,
287 descriptor, signature, needsSignature, polymorphicUnoType);
290 SpecialType getFieldDescriptor(
291 rtl::Reference< TypeManager > const & manager, std::set<OUString> * dependencies,
292 OUString const & type, OString * descriptor, OString * signature,
293 PolymorphicUnoType * polymorphicUnoType)
295 assert(descriptor != nullptr);
296 OStringBuffer desc;
297 OStringBuffer sig;
298 bool needsSig = false;
299 SpecialType specialType = translateUnoTypeToDescriptor(
300 manager, type, false, false, dependencies, &desc, &sig, &needsSig,
301 polymorphicUnoType);
302 *descriptor = desc.makeStringAndClear();
303 if (signature != nullptr) {
304 if (needsSig) {
305 *signature = sig.makeStringAndClear();
306 } else {
307 signature->clear();
310 return specialType;
313 class MethodDescriptor {
314 public:
315 MethodDescriptor(
316 rtl::Reference< TypeManager > const & manager,
317 std::set<OUString> * dependencies, OUString const & returnType,
318 SpecialType * specialReturnType,
319 PolymorphicUnoType * polymorphicUnoType);
321 SpecialType addParameter(
322 OUString const & type, bool array, bool dependency,
323 PolymorphicUnoType * polymorphicUnoType);
325 void addTypeParameter(OUString const & name);
327 OString getDescriptor() const;
329 OString getSignature() const { return m_needsSignature ? m_signatureStart.toString() + m_signatureEnd : OString();}
331 private:
332 rtl::Reference< TypeManager > m_manager;
333 std::set<OUString> * m_dependencies;
334 OStringBuffer m_descriptorStart;
335 OString m_descriptorEnd;
336 OStringBuffer m_signatureStart;
337 OString m_signatureEnd;
338 bool m_needsSignature;
341 MethodDescriptor::MethodDescriptor(
342 rtl::Reference< TypeManager > const & manager, std::set<OUString> * dependencies,
343 OUString const & returnType, SpecialType * specialReturnType,
344 PolymorphicUnoType * polymorphicUnoType):
345 m_manager(manager), m_dependencies(dependencies), m_needsSignature(false)
347 assert(dependencies != nullptr);
348 m_descriptorStart.append('(');
349 m_signatureStart.append('(');
350 OStringBuffer descEnd;
351 descEnd.append(')');
352 OStringBuffer sigEnd;
353 sigEnd.append(')');
354 SpecialType special = translateUnoTypeToDescriptor(
355 m_manager, returnType, false, false, m_dependencies, &descEnd, &sigEnd,
356 &m_needsSignature, polymorphicUnoType);
357 m_descriptorEnd = descEnd.makeStringAndClear();
358 m_signatureEnd = sigEnd.makeStringAndClear();
359 if (specialReturnType != nullptr) {
360 *specialReturnType = special;
364 SpecialType MethodDescriptor::addParameter(
365 OUString const & type, bool array, bool dependency,
366 PolymorphicUnoType * polymorphicUnoType)
368 return translateUnoTypeToDescriptor(
369 m_manager, type, array, false, dependency ? m_dependencies : nullptr,
370 &m_descriptorStart, &m_signatureStart, &m_needsSignature,
371 polymorphicUnoType);
374 void MethodDescriptor::addTypeParameter(OUString const & name) {
375 m_descriptorStart.append("Ljava/lang/Object;");
376 m_signatureStart.append("T" + codemaker::convertString(name) + ";");
377 m_needsSignature = true;
380 OString MethodDescriptor::getDescriptor() const {
381 OStringBuffer buf(m_descriptorStart);
382 buf.append(m_descriptorEnd);
383 return buf.makeStringAndClear();
387 class TypeInfo {
388 public:
389 enum Kind { KIND_MEMBER, KIND_ATTRIBUTE, KIND_METHOD, KIND_PARAMETER };
391 // Same values as in com/sun/star/lib/uno/typeinfo/TypeInfo.java:
392 enum Flags {
393 FLAG_READONLY = 0x008, FLAG_BOUND = 0x100
396 // KIND_MEMBER:
397 TypeInfo(
398 OString const & name, SpecialType specialType, sal_Int32 index,
399 PolymorphicUnoType const & polymorphicUnoType,
400 sal_Int32 typeParameterIndex);
402 // KIND_ATTRIBUTE/METHOD:
403 TypeInfo(
404 Kind kind, OString const & name, SpecialType specialType, Flags flags,
405 sal_Int32 index, PolymorphicUnoType const & polymorphicUnoType);
407 // KIND_PARAMETER:
408 TypeInfo(
409 OString const & parameterName, SpecialType specialType,
410 bool inParameter, bool outParameter, OString const & methodName,
411 sal_Int32 index, PolymorphicUnoType const & polymorphicUnoType);
413 sal_uInt16 generateCode(ClassFile::Code & code, std::set<OUString> * dependencies)
414 const;
416 void generatePolymorphicUnoTypeCode(
417 ClassFile::Code & code, std::set<OUString> * dependencies) const;
419 private:
420 Kind m_kind;
421 OString m_name;
422 sal_Int32 m_flags;
423 sal_Int32 m_index;
424 OString m_methodName;
425 PolymorphicUnoType m_polymorphicUnoType;
426 sal_Int32 m_typeParameterIndex;
429 sal_Int32 translateSpecialTypeFlags(
430 SpecialType specialType, bool inParameter, bool outParameter)
432 static sal_Int32 const specialTypeFlags[SPECIAL_TYPE_INTERFACE + 1] = {
433 0, 0x0040 /* ANY */, 0x0004 /* UNSIGNED */, 0x0080 /* INTERFACE */ };
434 sal_Int32 flags = specialTypeFlags[specialType];
435 if (inParameter) {
436 flags |= 0x0001; /* IN */
438 if (outParameter) {
439 flags |= 0x0002; /* OUT */
441 return flags;
444 TypeInfo::TypeInfo(
445 OString const & name, SpecialType specialType, sal_Int32 index,
446 PolymorphicUnoType const & polymorphicUnoType,
447 sal_Int32 typeParameterIndex):
448 m_kind(KIND_MEMBER), m_name(name),
449 m_flags(translateSpecialTypeFlags(specialType, false, false)),
450 m_index(index), m_polymorphicUnoType(polymorphicUnoType),
451 m_typeParameterIndex(typeParameterIndex)
453 assert(
454 polymorphicUnoType.kind == PolymorphicUnoType::KIND_NONE
455 ? typeParameterIndex >= -1 : typeParameterIndex == -1);
458 TypeInfo::TypeInfo(
459 Kind kind, OString const & name, SpecialType specialType, Flags flags,
460 sal_Int32 index, PolymorphicUnoType const & polymorphicUnoType):
461 m_kind(kind), m_name(name),
462 m_flags(flags | translateSpecialTypeFlags(specialType, false, false)),
463 m_index(index), m_polymorphicUnoType(polymorphicUnoType),
464 m_typeParameterIndex(0)
466 assert(kind == KIND_ATTRIBUTE || kind == KIND_METHOD);
469 TypeInfo::TypeInfo(
470 OString const & parameterName, SpecialType specialType, bool inParameter,
471 bool outParameter, OString const & methodName, sal_Int32 index,
472 PolymorphicUnoType const & polymorphicUnoType):
473 m_kind(KIND_PARAMETER), m_name(parameterName),
474 m_flags(translateSpecialTypeFlags(specialType, inParameter, outParameter)),
475 m_index(index), m_methodName(methodName),
476 m_polymorphicUnoType(polymorphicUnoType),
477 m_typeParameterIndex(0)
480 sal_uInt16 TypeInfo::generateCode(
481 ClassFile::Code & code, std::set<OUString> * dependencies) const
483 switch (m_kind) {
484 case KIND_MEMBER:
485 code.instrNew("com/sun/star/lib/uno/typeinfo/MemberTypeInfo");
486 code.instrDup();
487 code.loadStringConstant(m_name);
488 code.loadIntegerConstant(m_index);
489 code.loadIntegerConstant(m_flags);
490 if (m_polymorphicUnoType.kind != PolymorphicUnoType::KIND_NONE) {
491 generatePolymorphicUnoTypeCode(code, dependencies);
492 code.loadIntegerConstant(m_typeParameterIndex);
493 code.instrInvokespecial(
494 "com/sun/star/lib/uno/typeinfo/MemberTypeInfo", "<init>",
495 "(Ljava/lang/String;IILcom/sun/star/uno/Type;I)V");
496 return 8;
497 } else if (m_typeParameterIndex >= 0) {
498 code.instrAconstNull();
499 code.loadIntegerConstant(m_typeParameterIndex);
500 code.instrInvokespecial(
501 "com/sun/star/lib/uno/typeinfo/MemberTypeInfo", "<init>",
502 "(Ljava/lang/String;IILcom/sun/star/uno/Type;I)V");
503 return 6;
504 } else {
505 code.instrInvokespecial(
506 "com/sun/star/lib/uno/typeinfo/MemberTypeInfo", "<init>",
507 "(Ljava/lang/String;II)V");
508 return 4;
510 case KIND_ATTRIBUTE:
511 code.instrNew("com/sun/star/lib/uno/typeinfo/AttributeTypeInfo");
512 code.instrDup();
513 code.loadStringConstant(m_name);
514 code.loadIntegerConstant(m_index);
515 code.loadIntegerConstant(m_flags);
516 if (m_polymorphicUnoType.kind != PolymorphicUnoType::KIND_NONE) {
517 generatePolymorphicUnoTypeCode(code, dependencies);
518 code.instrInvokespecial(
519 "com/sun/star/lib/uno/typeinfo/AttributeTypeInfo", "<init>",
520 "(Ljava/lang/String;IILcom/sun/star/uno/Type;)V");
521 return 8;
522 } else {
523 code.instrInvokespecial(
524 "com/sun/star/lib/uno/typeinfo/AttributeTypeInfo", "<init>",
525 "(Ljava/lang/String;II)V");
526 return 4;
528 case KIND_METHOD:
529 code.instrNew("com/sun/star/lib/uno/typeinfo/MethodTypeInfo");
530 code.instrDup();
531 code.loadStringConstant(m_name);
532 code.loadIntegerConstant(m_index);
533 code.loadIntegerConstant(m_flags);
534 if (m_polymorphicUnoType.kind != PolymorphicUnoType::KIND_NONE) {
535 generatePolymorphicUnoTypeCode(code, dependencies);
536 code.instrInvokespecial(
537 "com/sun/star/lib/uno/typeinfo/MethodTypeInfo", "<init>",
538 "(Ljava/lang/String;IILcom/sun/star/uno/Type;)V");
539 return 8;
540 } else {
541 code.instrInvokespecial(
542 "com/sun/star/lib/uno/typeinfo/MethodTypeInfo", "<init>",
543 "(Ljava/lang/String;II)V");
544 return 4;
546 case KIND_PARAMETER:
547 code.instrNew("com/sun/star/lib/uno/typeinfo/ParameterTypeInfo");
548 code.instrDup();
549 code.loadStringConstant(m_name);
550 code.loadStringConstant(m_methodName);
551 code.loadIntegerConstant(m_index);
552 code.loadIntegerConstant(m_flags);
553 if (m_polymorphicUnoType.kind != PolymorphicUnoType::KIND_NONE) {
554 generatePolymorphicUnoTypeCode(code, dependencies);
555 code.instrInvokespecial(
556 "com/sun/star/lib/uno/typeinfo/ParameterTypeInfo", "<init>",
557 ("(Ljava/lang/String;Ljava/lang/String;II"
558 "Lcom/sun/star/uno/Type;)V"));
559 return 9;
560 } else {
561 code.instrInvokespecial(
562 "com/sun/star/lib/uno/typeinfo/ParameterTypeInfo", "<init>",
563 "(Ljava/lang/String;Ljava/lang/String;II)V");
564 return 5;
566 default:
567 assert(false);
568 return 0;
572 void TypeInfo::generatePolymorphicUnoTypeCode(
573 ClassFile::Code & code, std::set<OUString> * dependencies) const
575 assert(dependencies != nullptr);
576 assert(m_polymorphicUnoType.kind != PolymorphicUnoType::KIND_NONE);
577 code.instrNew("com/sun/star/uno/Type");
578 code.instrDup();
579 code.loadStringConstant(
580 codemaker::convertString(m_polymorphicUnoType.name));
581 if (m_polymorphicUnoType.kind == PolymorphicUnoType::KIND_STRUCT) {
582 code.instrGetstatic(
583 "com/sun/star/uno/TypeClass", "STRUCT",
584 "Lcom/sun/star/uno/TypeClass;");
585 } else {
586 code.instrGetstatic(
587 "com/sun/star/uno/TypeClass", "SEQUENCE",
588 "Lcom/sun/star/uno/TypeClass;");
590 dependencies->insert("com.sun.star.uno.TypeClass");
591 code.instrInvokespecial(
592 "com/sun/star/uno/Type", "<init>",
593 "(Ljava/lang/String;Lcom/sun/star/uno/TypeClass;)V");
596 void writeClassFile(
597 JavaOptions const & options, OString const & type,
598 ClassFile const & classFile)
600 OString path;
601 if (options.isValid("-O")) {
602 path = options.getOption("-O");
604 OString filename(createFileNameFromType(path, type, ".class"));
605 bool bCheck = false;
606 if (fileExists(filename)) {
607 if (options.isValid("-G")) {
608 return;
610 bCheck = options.isValid("-Gc");
612 FileStream tempfile;
613 tempfile.createTempFile(getTempDir(filename));
614 if (!tempfile.isValid()) {
615 throw CannotDumpException(
616 "Cannot create temporary file for " + b2u(filename));
618 OString tempname(tempfile.getName());
619 try {
620 classFile.write(tempfile);
621 } catch (...) {
622 // Remove existing file for consistency:
623 if (fileExists(filename)) {
624 removeTypeFile(filename);
626 tempfile.close();
627 removeTypeFile(tempname);
628 throw;
630 tempfile.close();
631 if (!makeValidTypeFile(filename, tempname, bCheck)) {
632 throw CannotDumpException(
633 "Cannot create " + b2u(filename) + " from temporary file "
634 + b2u(tempname));
638 void addTypeInfo(
639 OString const & className, std::vector< TypeInfo > const & typeInfo,
640 std::set<OUString> * dependencies, ClassFile * classFile)
642 assert(classFile != nullptr);
643 std::vector< TypeInfo >::size_type typeInfos = typeInfo.size();
644 if (typeInfos > SAL_MAX_INT32) {
645 throw CannotDumpException(
646 "UNOTYPEINFO array too big for Java class file format");
648 if (typeInfos != 0) {
649 classFile->addField(
650 static_cast< ClassFile::AccessFlags >(
651 ClassFile::ACC_PUBLIC | ClassFile::ACC_STATIC
652 | ClassFile::ACC_FINAL),
653 "UNOTYPEINFO", "[Lcom/sun/star/lib/uno/typeinfo/TypeInfo;",
654 0, "");
655 std::unique_ptr< ClassFile::Code > code(classFile->newCode());
656 code->loadIntegerConstant(static_cast< sal_Int32 >(typeInfos));
657 code->instrAnewarray("com/sun/star/lib/uno/typeinfo/TypeInfo");
658 sal_Int32 index = 0;
659 sal_uInt16 stack = 0;
660 for (const TypeInfo& ti : typeInfo)
662 code->instrDup();
663 code->loadIntegerConstant(index++);
664 stack = std::max(stack, ti.generateCode(*code, dependencies));
665 code->instrAastore();
667 code->instrPutstatic(
668 className, "UNOTYPEINFO",
669 "[Lcom/sun/star/lib/uno/typeinfo/TypeInfo;");
670 code->instrReturn();
671 if (stack > SAL_MAX_UINT16 - 4) {
672 throw CannotDumpException(
673 "Stack too big for Java class file format");
675 code->setMaxStackAndLocals(static_cast< sal_uInt16 >(stack + 4), 0);
676 classFile->addMethod(
677 static_cast< ClassFile::AccessFlags >(
678 ClassFile::ACC_PRIVATE | ClassFile::ACC_STATIC),
679 "<clinit>", "()V", code.get(), std::vector< OString >(), "");
683 void handleEnumType(
684 const OUString& name, rtl::Reference< unoidl::EnumTypeEntity > const & entity,
685 JavaOptions const & options)
687 assert(entity.is());
688 OString className(codemaker::convertString(name).replace('.', '/'));
689 std::unique_ptr< ClassFile > cf(
690 new ClassFile(
691 static_cast< ClassFile::AccessFlags >(
692 ClassFile::ACC_PUBLIC | ClassFile::ACC_FINAL
693 | ClassFile::ACC_SUPER),
694 className, "com/sun/star/uno/Enum", ""));
695 OString classDescriptor("L" + className + ";");
696 for (const unoidl::EnumTypeEntity::Member& member : entity->getMembers())
698 OString fieldName(codemaker::convertString(member.name));
699 cf->addField(
700 static_cast< ClassFile::AccessFlags >(
701 ClassFile::ACC_PUBLIC | ClassFile::ACC_STATIC
702 | ClassFile::ACC_FINAL),
703 fieldName, classDescriptor, 0, OString());
704 cf->addField(
705 static_cast< ClassFile::AccessFlags >(
706 ClassFile::ACC_PUBLIC | ClassFile::ACC_STATIC
707 | ClassFile::ACC_FINAL),
708 fieldName + "_value", "I",
709 cf->addIntegerInfo(member.value), "");
711 std::unique_ptr< ClassFile::Code > code(cf->newCode());
712 code->loadLocalReference(0);
713 code->loadLocalInteger(1);
714 code->instrInvokespecial("com/sun/star/uno/Enum", "<init>", "(I)V");
715 code->instrReturn();
716 code->setMaxStackAndLocals(2, 2);
717 cf->addMethod(
718 ClassFile::ACC_PRIVATE,
719 "<init>", "(I)V", code.get(),
720 std::vector< OString >(), "");
721 code.reset(cf->newCode());
722 code->instrGetstatic(
723 className,
724 codemaker::convertString(entity->getMembers()[0].name),
725 classDescriptor);
726 code->instrAreturn();
727 code->setMaxStackAndLocals(1, 0);
728 cf->addMethod(
729 static_cast< ClassFile::AccessFlags >(
730 ClassFile::ACC_PUBLIC | ClassFile::ACC_STATIC),
731 "getDefault", "()" + classDescriptor,
732 code.get(), std::vector< OString >(), "");
733 code.reset(cf->newCode());
734 code->loadLocalInteger(0);
735 std::map< sal_Int32, OString > map;
736 sal_Int32 min = SAL_MAX_INT32;
737 sal_Int32 max = SAL_MIN_INT32;
738 for (const unoidl::EnumTypeEntity::Member& member : entity->getMembers())
740 min = std::min(min, member.value);
741 max = std::max(max, member.value);
742 map.emplace(member.value, codemaker::convertString(member.name));
744 sal_uInt64 size = static_cast< sal_uInt64 >(map.size());
745 if ((static_cast< sal_uInt64 >(max) - static_cast< sal_uInt64 >(min)
746 <= 2 * size)
747 || size > SAL_MAX_INT32)
749 std::unique_ptr< ClassFile::Code > defCode(cf->newCode());
750 defCode->instrAconstNull();
751 defCode->instrAreturn();
752 std::vector< std::unique_ptr<ClassFile::Code> > blocks;
753 //FIXME: pointers contained in blocks may leak
754 sal_Int32 last = SAL_MAX_INT32;
755 for (const auto& pair : map)
757 sal_Int32 value = pair.first;
758 if (last != SAL_MAX_INT32) {
759 for (sal_Int32 j = last + 1; j < value; ++j) {
760 blocks.push_back(nullptr);
763 last = value;
764 std::unique_ptr< ClassFile::Code > blockCode(cf->newCode());
765 blockCode->instrGetstatic(className, pair.second, classDescriptor);
766 blockCode->instrAreturn();
767 blocks.push_back(std::move(blockCode));
769 code->instrTableswitch(defCode.get(), min, blocks);
770 } else{
771 std::unique_ptr< ClassFile::Code > defCode(cf->newCode());
772 defCode->instrAconstNull();
773 defCode->instrAreturn();
774 std::vector< std::pair< sal_Int32, ClassFile::Code * > > blocks;
775 //FIXME: pointers contained in blocks may leak
776 for (const auto& pair : map )
778 std::unique_ptr< ClassFile::Code > blockCode(cf->newCode());
779 blockCode->instrGetstatic(className, pair.second, classDescriptor);
780 blockCode->instrAreturn();
781 blocks.emplace_back(pair.first, blockCode.get());
782 blockCode.release();
784 code->instrLookupswitch(defCode.get(), blocks);
785 for (const std::pair< sal_Int32, ClassFile::Code * >& pair : blocks)
787 delete pair.second;
790 code->setMaxStackAndLocals(1, 1);
791 cf->addMethod(
792 static_cast< ClassFile::AccessFlags >(
793 ClassFile::ACC_PUBLIC | ClassFile::ACC_STATIC),
794 "fromInt", "(I)" + classDescriptor, code.get(),
795 std::vector< OString >(), "");
796 code.reset(cf->newCode());
797 for (const unoidl::EnumTypeEntity::Member& member : entity->getMembers())
799 code->instrNew(className);
800 code->instrDup();
801 code->loadIntegerConstant(member.value);
802 code->instrInvokespecial(className, "<init>", "(I)V");
803 code->instrPutstatic(
804 className, codemaker::convertString(member.name), classDescriptor);
806 code->instrReturn();
807 code->setMaxStackAndLocals(3, 0);
808 cf->addMethod(
809 static_cast< ClassFile::AccessFlags >(
810 ClassFile::ACC_PRIVATE | ClassFile::ACC_STATIC),
811 "<clinit>", "()V", code.get(), std::vector< OString >(), "");
812 writeClassFile(options, className, *cf);
815 void addField(
816 rtl::Reference< TypeManager > const & manager, std::set<OUString> * dependencies,
817 ClassFile * classFile, std::vector< TypeInfo > * typeInfo,
818 sal_Int32 typeParameterIndex, OUString const & type, OUString const & name,
819 sal_Int32 index)
821 assert(classFile != nullptr);
822 assert(typeInfo != nullptr);
823 OString descriptor;
824 OString signature;
825 SpecialType specialType;
826 PolymorphicUnoType polymorphicUnoType;
827 if (typeParameterIndex >= 0) {
828 descriptor = "Ljava/lang/Object;";
829 signature = "T" + codemaker::convertString(type).replace('.', '/')
830 + ";";
831 specialType = SPECIAL_TYPE_NONE; //TODO: SPECIAL_TYPE_TYPE_PARAMETER?
832 } else {
833 specialType = getFieldDescriptor(
834 manager, dependencies, type, &descriptor, &signature,
835 &polymorphicUnoType);
837 classFile->addField(
838 ClassFile::ACC_PUBLIC, codemaker::convertString(name), descriptor, 0,
839 signature);
840 typeInfo->push_back(
841 TypeInfo(
842 codemaker::convertString(name), specialType, index,
843 polymorphicUnoType, typeParameterIndex));
846 sal_uInt16 addFieldInit(
847 rtl::Reference< TypeManager > const & manager, OString const & className,
848 OUString const & fieldName, bool typeParameter, OUString const & fieldType,
849 std::set<OUString> * dependencies, ClassFile::Code * code)
851 assert(manager.is());
852 assert(code != nullptr);
853 if (typeParameter) {
854 return 0;
856 OString name(codemaker::convertString(fieldName));
857 OUString nucleus;
858 sal_Int32 rank;
859 std::vector< OUString > args;
860 rtl::Reference< unoidl::Entity > ent;
861 codemaker::UnoType::Sort sort = manager->decompose(
862 fieldType, true, &nucleus, &rank, &args, &ent);
863 if (rank == 0) {
864 switch (sort) {
865 case codemaker::UnoType::Sort::Boolean:
866 case codemaker::UnoType::Sort::Byte:
867 case codemaker::UnoType::Sort::Short:
868 case codemaker::UnoType::Sort::UnsignedShort:
869 case codemaker::UnoType::Sort::Long:
870 case codemaker::UnoType::Sort::UnsignedLong:
871 case codemaker::UnoType::Sort::Hyper:
872 case codemaker::UnoType::Sort::UnsignedHyper:
873 case codemaker::UnoType::Sort::Float:
874 case codemaker::UnoType::Sort::Double:
875 case codemaker::UnoType::Sort::Char:
876 case codemaker::UnoType::Sort::Interface:
877 return 0;
878 case codemaker::UnoType::Sort::String:
879 code->loadLocalReference(0);
880 code->loadStringConstant(OString());
881 code->instrPutfield(className, name, "Ljava/lang/String;");
882 return 2;
883 case codemaker::UnoType::Sort::Type:
884 code->loadLocalReference(0);
885 code->instrGetstatic(
886 "com/sun/star/uno/Type", "VOID", "Lcom/sun/star/uno/Type;");
887 code->instrPutfield(className, name, "Lcom/sun/star/uno/Type;");
888 return 2;
889 case codemaker::UnoType::Sort::Any:
890 code->loadLocalReference(0);
891 code->instrGetstatic(
892 "com/sun/star/uno/Any", "VOID", "Lcom/sun/star/uno/Any;");
893 code->instrPutfield(className, name, "Ljava/lang/Object;");
894 return 2;
895 case codemaker::UnoType::Sort::Enum:
897 rtl::Reference< unoidl::EnumTypeEntity > ent2(
898 dynamic_cast< unoidl::EnumTypeEntity * >(ent.get()));
899 assert(ent2.is());
900 code->loadLocalReference(0);
901 OStringBuffer descBuf;
902 translateUnoTypeToDescriptor(
903 manager, sort, nucleus, 0, std::vector< OUString >(), false,
904 false, dependencies, &descBuf, nullptr, nullptr, nullptr);
905 OString desc(descBuf.makeStringAndClear());
906 code->instrGetstatic(
907 codemaker::convertString(nucleus).replace('.', '/'),
908 codemaker::convertString(ent2->getMembers()[0].name), desc);
909 code->instrPutfield(className, name, desc);
910 return 2;
912 case codemaker::UnoType::Sort::PlainStruct:
913 case codemaker::UnoType::Sort::InstantiatedPolymorphicStruct:
915 code->loadLocalReference(0);
916 code->instrNew(
917 codemaker::convertString(nucleus).replace('.', '/'));
918 code->instrDup();
919 code->instrInvokespecial(
920 codemaker::convertString(nucleus).replace('.', '/'),
921 "<init>", "()V");
922 OStringBuffer desc;
923 translateUnoTypeToDescriptor(
924 manager, sort, nucleus, 0, args, false, false, dependencies,
925 &desc, nullptr, nullptr, nullptr);
926 code->instrPutfield(className, name, desc.makeStringAndClear());
927 return 3;
929 case codemaker::UnoType::Sort::Sequence:
930 case codemaker::UnoType::Sort::Typedef:
931 for (;;) std::abort(); // this cannot happen
932 default:
933 throw CannotDumpException(
934 "unexpected entity \"" + fieldType
935 + "\" in call to addFieldInit");
938 code->loadLocalReference(0);
939 code->loadIntegerConstant(0);
940 if (rank == 1) {
941 if (sort >= codemaker::UnoType::Sort::Boolean
942 && sort <= codemaker::UnoType::Sort::Char)
944 code->instrNewarray(sort);
945 } else {
946 code->instrAnewarray(
947 codemaker::java::translateUnoToJavaType(
948 sort, codemaker::convertString(nucleus).replace('.', '/'),
949 false));
951 } else {
952 OStringBuffer desc;
953 translateUnoTypeToDescriptor(
954 manager, sort, nucleus, rank - 1, std::vector< OUString >(), false,
955 false, dependencies, &desc, nullptr, nullptr, nullptr);
956 code->instrAnewarray(desc.makeStringAndClear());
958 OStringBuffer desc;
959 translateUnoTypeToDescriptor(
960 manager, sort, nucleus, rank, std::vector< OUString >(), false, false,
961 dependencies, &desc, nullptr, nullptr, nullptr);
962 code->instrPutfield(className, name, desc.makeStringAndClear());
963 return 2;
966 sal_uInt16 addLoadLocal(
967 rtl::Reference< TypeManager > const & manager, ClassFile::Code * code,
968 sal_uInt16 * index, bool typeParameter, OUString const & type, bool any,
969 std::set<OUString> * dependencies)
971 assert(manager.is());
972 assert(code != nullptr);
973 assert(index != nullptr);
974 assert(!(typeParameter && any));
975 assert(dependencies != nullptr);
976 sal_uInt16 stack = 1;
977 sal_uInt16 size = 1;
978 if (typeParameter) {
979 code->loadLocalReference(*index);
980 stack = size = 1;
981 } else {
982 OUString nucleus;
983 sal_Int32 rank;
984 std::vector< OUString > args;
985 codemaker::UnoType::Sort sort = manager->decompose(
986 type, true, &nucleus, &rank, &args, nullptr);
987 if (rank == 0) {
988 switch (sort) {
989 case codemaker::UnoType::Sort::Boolean:
990 if (any) {
991 code->instrNew("java/lang/Boolean");
992 code->instrDup();
993 code->loadLocalInteger(*index);
994 code->instrInvokespecial(
995 "java/lang/Boolean", "<init>", "(Z)V");
996 stack = 3;
997 } else {
998 code->loadLocalInteger(*index);
999 stack = 1;
1001 size = 1;
1002 break;
1003 case codemaker::UnoType::Sort::Byte:
1004 if (any) {
1005 code->instrNew("java/lang/Byte");
1006 code->instrDup();
1007 code->loadLocalInteger(*index);
1008 code->instrInvokespecial(
1009 "java/lang/Byte", "<init>", "(B)V");
1010 stack = 3;
1011 } else {
1012 code->loadLocalInteger(*index);
1013 stack = 1;
1015 size = 1;
1016 break;
1017 case codemaker::UnoType::Sort::Short:
1018 if (any) {
1019 code->instrNew("java/lang/Short");
1020 code->instrDup();
1021 code->loadLocalInteger(*index);
1022 code->instrInvokespecial(
1023 "java/lang/Short", "<init>", "(S)V");
1024 stack = 3;
1025 } else {
1026 code->loadLocalInteger(*index);
1027 stack = 1;
1029 size = 1;
1030 break;
1031 case codemaker::UnoType::Sort::UnsignedShort:
1032 if (any) {
1033 code->instrNew("com/sun/star/uno/Any");
1034 code->instrDup();
1035 code->instrGetstatic(
1036 "com/sun/star/uno/Type", "UNSIGNED_SHORT",
1037 "Lcom/sun/star/uno/Type;");
1038 code->instrNew("java/lang/Short");
1039 code->instrDup();
1040 code->loadLocalInteger(*index);
1041 code->instrInvokespecial(
1042 "java/lang/Short", "<init>", "(S)V");
1043 code->instrInvokespecial(
1044 "com/sun/star/uno/Any", "<init>",
1045 "(Lcom/sun/star/uno/Type;Ljava/lang/Object;)V");
1046 stack = 6;
1047 } else {
1048 code->loadLocalInteger(*index);
1049 stack = 1;
1051 size = 1;
1052 break;
1053 case codemaker::UnoType::Sort::Long:
1054 if (any) {
1055 code->instrNew("java/lang/Integer");
1056 code->instrDup();
1057 code->loadLocalInteger(*index);
1058 code->instrInvokespecial(
1059 "java/lang/Integer", "<init>", "(I)V");
1060 stack = 3;
1061 } else {
1062 code->loadLocalInteger(*index);
1063 stack = 1;
1065 size = 1;
1066 break;
1067 case codemaker::UnoType::Sort::UnsignedLong:
1068 if (any) {
1069 code->instrNew("com/sun/star/uno/Any");
1070 code->instrDup();
1071 code->instrGetstatic(
1072 "com/sun/star/uno/Type", "UNSIGNED_LONG",
1073 "Lcom/sun/star/uno/Type;");
1074 code->instrNew("java/lang/Integer");
1075 code->instrDup();
1076 code->loadLocalInteger(*index);
1077 code->instrInvokespecial(
1078 "java/lang/Integer", "<init>", "(I)V");
1079 code->instrInvokespecial(
1080 "com/sun/star/uno/Any", "<init>",
1081 "(Lcom/sun/star/uno/Type;Ljava/lang/Object;)V");
1082 stack = 6;
1083 } else {
1084 code->loadLocalInteger(*index);
1085 stack = 1;
1087 size = 1;
1088 break;
1089 case codemaker::UnoType::Sort::Hyper:
1090 if (any) {
1091 code->instrNew("java/lang/Long");
1092 code->instrDup();
1093 code->loadLocalLong(*index);
1094 code->instrInvokespecial(
1095 "java/lang/Long", "<init>", "(J)V");
1096 stack = 4;
1097 } else {
1098 code->loadLocalLong(*index);
1099 stack = 2;
1101 size = 2;
1102 break;
1103 case codemaker::UnoType::Sort::UnsignedHyper:
1104 if (any) {
1105 code->instrNew("com/sun/star/uno/Any");
1106 code->instrDup();
1107 code->instrGetstatic(
1108 "com/sun/star/uno/Type", "UNSIGNED_HYPER",
1109 "Lcom/sun/star/uno/Type;");
1110 code->instrNew("java/lang/Long");
1111 code->instrDup();
1112 code->loadLocalLong(*index);
1113 code->instrInvokespecial(
1114 "java/lang/Long", "<init>", "(J)V");
1115 code->instrInvokespecial(
1116 "com/sun/star/uno/Any", "<init>",
1117 "(Lcom/sun/star/uno/Type;Ljava/lang/Object;)V");
1118 stack = 7;
1119 } else {
1120 code->loadLocalLong(*index);
1121 stack = 2;
1123 size = 2;
1124 break;
1125 case codemaker::UnoType::Sort::Float:
1126 if (any) {
1127 code->instrNew("java/lang/Float");
1128 code->instrDup();
1129 code->loadLocalFloat(*index);
1130 code->instrInvokespecial(
1131 "java/lang/Float", "<init>", "(F)V");
1132 stack = 3;
1133 } else {
1134 code->loadLocalFloat(*index);
1135 stack = 1;
1137 size = 1;
1138 break;
1139 case codemaker::UnoType::Sort::Double:
1140 if (any) {
1141 code->instrNew("java/lang/Double");
1142 code->instrDup();
1143 code->loadLocalDouble(*index);
1144 code->instrInvokespecial(
1145 "java/lang/Double", "<init>", "(D)V");
1146 stack = 4;
1147 } else {
1148 code->loadLocalDouble(*index);
1149 stack = 2;
1151 size = 2;
1152 break;
1153 case codemaker::UnoType::Sort::Char:
1154 if (any) {
1155 code->instrNew("java/lang/Character");
1156 code->instrDup();
1157 code->loadLocalInteger(*index);
1158 code->instrInvokespecial(
1159 "java/lang/Character", "<init>", "(C)V");
1160 stack = 3;
1161 } else {
1162 code->loadLocalInteger(*index);
1163 stack = 1;
1165 size = 1;
1166 break;
1167 case codemaker::UnoType::Sort::String:
1168 case codemaker::UnoType::Sort::Type:
1169 case codemaker::UnoType::Sort::Any:
1170 code->loadLocalReference(*index);
1171 stack = size = 1;
1172 break;
1173 case codemaker::UnoType::Sort::Enum:
1174 // Assuming that no Java types are derived from Java types that
1175 // are directly derived from com.sun.star.uno.Enum:
1176 code->loadLocalReference(*index);
1177 stack = size = 1;
1178 break;
1179 case codemaker::UnoType::Sort::PlainStruct:
1180 case codemaker::UnoType::Sort::InstantiatedPolymorphicStruct:
1181 if (any) {
1182 code->instrNew("com/sun/star/uno/Any");
1183 code->instrDup();
1184 code->instrNew("com/sun/star/uno/Type");
1185 code->instrDup();
1186 code->loadStringConstant(
1187 codemaker::convertString(
1188 createUnoName(manager, nucleus, rank, args)));
1189 code->instrGetstatic(
1190 "com/sun/star/uno/TypeClass", "STRUCT",
1191 "Lcom/sun/star/uno/TypeClass;");
1192 dependencies->insert("com.sun.star.uno.TypeClass");
1193 code->instrInvokespecial(
1194 "com/sun/star/uno/Type", "<init>",
1195 "(Ljava/lang/String;Lcom/sun/star/uno/TypeClass;)V");
1196 code->loadLocalReference(*index);
1197 code->instrInvokespecial(
1198 "com/sun/star/uno/Any", "<init>",
1199 "(Lcom/sun/star/uno/Type;Ljava/lang/Object;)V");
1200 stack = 6;
1201 } else {
1202 code->loadLocalReference(*index);
1203 stack = 1;
1205 size = 1;
1206 break;
1207 case codemaker::UnoType::Sort::Interface:
1208 if (any && nucleus != "com.sun.star.uno.XInterface") {
1209 code->instrNew("com/sun/star/uno/Any");
1210 code->instrDup();
1211 code->instrNew("com/sun/star/uno/Type");
1212 code->instrDup();
1213 code->loadStringConstant(codemaker::convertString(nucleus));
1214 code->instrGetstatic(
1215 "com/sun/star/uno/TypeClass", "INTERFACE",
1216 "Lcom/sun/star/uno/TypeClass;");
1217 dependencies->insert("com.sun.star.uno.TypeClass");
1218 code->instrInvokespecial(
1219 "com/sun/star/uno/Type", "<init>",
1220 "(Ljava/lang/String;Lcom/sun/star/uno/TypeClass;)V");
1221 code->loadLocalReference(*index);
1222 code->instrInvokespecial(
1223 "com/sun/star/uno/Any", "<init>",
1224 "(Lcom/sun/star/uno/Type;Ljava/lang/Object;)V");
1225 stack = 6;
1226 } else {
1227 code->loadLocalReference(*index);
1228 stack = 1;
1230 size = 1;
1231 break;
1232 case codemaker::UnoType::Sort::Sequence:
1233 case codemaker::UnoType::Sort::Typedef:
1234 for (;;) std::abort(); // this cannot happen
1235 default:
1236 throw CannotDumpException(
1237 "unexpected entity \"" + type
1238 + "\" in call to addLoadLocal");
1240 } else {
1241 bool bWrap = false;
1242 if (any) {
1243 switch (sort) {
1244 case codemaker::UnoType::Sort::Boolean:
1245 case codemaker::UnoType::Sort::Byte:
1246 case codemaker::UnoType::Sort::Short:
1247 case codemaker::UnoType::Sort::Long:
1248 case codemaker::UnoType::Sort::Hyper:
1249 case codemaker::UnoType::Sort::Float:
1250 case codemaker::UnoType::Sort::Double:
1251 case codemaker::UnoType::Sort::Char:
1252 case codemaker::UnoType::Sort::String:
1253 case codemaker::UnoType::Sort::Type:
1254 // assuming that no Java types are derived from
1255 // com.sun.star.uno.Type
1256 case codemaker::UnoType::Sort::Enum:
1257 // assuming that no Java types are derived from Java
1258 // types that are directly derived from
1259 // com.sun.star.uno.Enum
1260 break;
1261 case codemaker::UnoType::Sort::UnsignedShort:
1262 case codemaker::UnoType::Sort::UnsignedLong:
1263 case codemaker::UnoType::Sort::UnsignedHyper:
1264 case codemaker::UnoType::Sort::Any:
1265 case codemaker::UnoType::Sort::PlainStruct:
1266 case codemaker::UnoType::Sort::InstantiatedPolymorphicStruct:
1267 case codemaker::UnoType::Sort::Interface:
1268 bWrap = true;
1269 break;
1270 case codemaker::UnoType::Sort::Sequence:
1271 case codemaker::UnoType::Sort::Typedef:
1272 for (;;) std::abort(); // this cannot happen
1273 default:
1274 throw CannotDumpException(
1275 "unexpected entity \"" + type
1276 + "\" in call to addLoadLocal");
1279 if (bWrap) {
1280 code->instrNew("com/sun/star/uno/Any");
1281 code->instrDup();
1282 code->instrNew("com/sun/star/uno/Type");
1283 code->instrDup();
1284 code->loadStringConstant(
1285 codemaker::convertString(
1286 createUnoName(manager, nucleus, rank, args)));
1287 code->instrInvokespecial(
1288 "com/sun/star/uno/Type", "<init>", "(Ljava/lang/String;)V");
1289 code->loadLocalReference(*index);
1290 code->instrInvokespecial(
1291 "com/sun/star/uno/Any", "<init>",
1292 "(Lcom/sun/star/uno/Type;Ljava/lang/Object;)V");
1293 stack = 5;
1294 } else {
1295 code->loadLocalReference(*index);
1296 stack = 1;
1298 size = 1;
1301 if (*index > SAL_MAX_UINT16 - size) {
1302 throw CannotDumpException(
1303 "Too many local variables for Java class file format");
1305 *index = *index + size;
1306 return stack;
1309 sal_uInt16 addDirectArgument(
1310 rtl::Reference< TypeManager > const & manager, std::set<OUString> * dependencies,
1311 MethodDescriptor * methodDescriptor, ClassFile::Code * code,
1312 sal_uInt16 * index, OString const & className, OString const & fieldName,
1313 bool typeParameter, OUString const & fieldType)
1315 assert(methodDescriptor != nullptr);
1316 assert(code != nullptr);
1317 OString desc;
1318 if (typeParameter) {
1319 methodDescriptor->addTypeParameter(fieldType);
1320 desc = "Ljava/lang/Object;";
1321 } else {
1322 methodDescriptor->addParameter(fieldType, false, true, nullptr);
1323 getFieldDescriptor(manager, dependencies, fieldType, &desc, nullptr, nullptr);
1325 code->loadLocalReference(0);
1326 sal_uInt16 stack = addLoadLocal(
1327 manager, code, index, typeParameter, fieldType, false, dependencies);
1328 code->instrPutfield(className, fieldName, desc);
1329 return stack + 1;
1332 void addPlainStructBaseArguments(
1333 rtl::Reference< TypeManager > const & manager, std::set<OUString> * dependencies,
1334 MethodDescriptor * methodDescriptor, ClassFile::Code * code,
1335 OUString const & base, sal_uInt16 * index)
1337 assert(manager.is());
1338 assert(methodDescriptor != nullptr);
1339 rtl::Reference< unoidl::Entity > ent;
1340 if (manager->getSort(base, &ent)
1341 != codemaker::UnoType::Sort::PlainStruct)
1343 throw CannotDumpException(
1344 "unexpected entity \"" + base
1345 + "\" in call to addPlainStructBaseArguments");
1347 unoidl::PlainStructTypeEntity& ent2(dynamic_cast<unoidl::PlainStructTypeEntity&>(*ent));
1348 if (!ent2.getDirectBase().isEmpty()) {
1349 addPlainStructBaseArguments(
1350 manager, dependencies, methodDescriptor, code,
1351 ent2.getDirectBase(), index);
1353 for (const unoidl::PlainStructTypeEntity::Member& member : ent2.getDirectMembers())
1355 methodDescriptor->addParameter(member.type, false, true, nullptr);
1356 addLoadLocal(manager, code, index, false, member.type, false, dependencies);
1360 void handlePlainStructType(
1361 const OUString& name,
1362 rtl::Reference< unoidl::PlainStructTypeEntity > const & entity,
1363 rtl::Reference< TypeManager > const & manager, JavaOptions const & options,
1364 std::set<OUString> * dependencies)
1366 assert(entity.is());
1367 assert(dependencies != nullptr);
1368 OString className(codemaker::convertString(name).replace('.', '/'));
1369 OString superClass;
1370 if (entity->getDirectBase().isEmpty()) {
1371 superClass = "java/lang/Object";
1372 } else {
1373 superClass = codemaker::convertString(entity->getDirectBase()).
1374 replace('.', '/');
1375 dependencies->insert(entity->getDirectBase());
1377 std::unique_ptr< ClassFile > cf(
1378 new ClassFile(
1379 static_cast< ClassFile::AccessFlags >(
1380 ClassFile::ACC_PUBLIC | ClassFile::ACC_SUPER),
1381 className, superClass, ""));
1382 std::vector< TypeInfo > typeInfo;
1383 sal_Int32 index = 0;
1384 for (const unoidl::PlainStructTypeEntity::Member& member : entity->getDirectMembers())
1386 addField(
1387 manager, dependencies, cf.get(), &typeInfo, -1, member.type, member.name,
1388 index++);
1390 std::unique_ptr< ClassFile::Code > code(cf->newCode());
1391 code->loadLocalReference(0);
1392 code->instrInvokespecial(superClass, "<init>", "()V");
1393 sal_uInt16 stack = 0;
1394 for (const unoidl::PlainStructTypeEntity::Member& member : entity->getDirectMembers())
1396 stack = std::max(
1397 stack,
1398 addFieldInit(
1399 manager, className, member.name, false, member.type, dependencies,
1400 code.get()));
1402 code->instrReturn();
1403 code->setMaxStackAndLocals(stack + 1, 1);
1404 cf->addMethod(
1405 ClassFile::ACC_PUBLIC, "<init>", "()V", code.get(),
1406 std::vector< OString >(), "");
1407 MethodDescriptor desc(manager, dependencies, "void", nullptr, nullptr);
1408 code.reset(cf->newCode());
1409 code->loadLocalReference(0);
1410 sal_uInt16 index2 = 1;
1411 if (!entity->getDirectBase().isEmpty()) {
1412 addPlainStructBaseArguments(
1413 manager, dependencies, &desc, code.get(), entity->getDirectBase(),
1414 &index2);
1416 code->instrInvokespecial(superClass, "<init>", desc.getDescriptor());
1417 sal_uInt16 maxSize = index2;
1418 for (const unoidl::PlainStructTypeEntity::Member& member : entity->getDirectMembers())
1420 maxSize = std::max(
1421 maxSize,
1422 addDirectArgument(
1423 manager, dependencies, &desc, code.get(), &index2, className,
1424 codemaker::convertString(member.name), false, member.type));
1426 code->instrReturn();
1427 code->setMaxStackAndLocals(maxSize, index2);
1428 cf->addMethod(
1429 ClassFile::ACC_PUBLIC, "<init>", desc.getDescriptor(), code.get(),
1430 std::vector< OString >(), desc.getSignature());
1431 addTypeInfo(className, typeInfo, dependencies, cf.get());
1432 writeClassFile(options, className, *cf);
1435 void handlePolyStructType(
1436 const OUString& name,
1437 rtl::Reference< unoidl::PolymorphicStructTypeTemplateEntity > const &
1438 entity,
1439 rtl::Reference< TypeManager > const & manager, JavaOptions const & options,
1440 std::set<OUString> * dependencies)
1442 assert(entity.is());
1443 OString className(codemaker::convertString(name).replace('.', '/'));
1444 std::map< OUString, sal_Int32 > typeParameters;
1445 OStringBuffer sig("<");
1446 sal_Int32 index = 0;
1447 for (const OUString& param : entity->getTypeParameters())
1449 sig.append(codemaker::convertString(param) + ":Ljava/lang/Object;");
1450 if (!typeParameters.emplace(param, index++).second)
1452 throw CannotDumpException("Bad type information"); //TODO
1455 sig.append(">Ljava/lang/Object;");
1456 std::unique_ptr< ClassFile > cf(
1457 new ClassFile(
1458 static_cast< ClassFile::AccessFlags >(
1459 ClassFile::ACC_PUBLIC | ClassFile::ACC_SUPER),
1460 className, "java/lang/Object", sig.makeStringAndClear()));
1461 std::vector< TypeInfo > typeInfo;
1462 index = 0;
1463 for (const unoidl::PolymorphicStructTypeTemplateEntity::Member& member : entity->getMembers())
1465 sal_Int32 typeParameterIndex;
1466 if (member.parameterized) {
1467 std::map< OUString, sal_Int32 >::iterator it(
1468 typeParameters.find(member.type));
1469 if (it == typeParameters.end()) {
1470 throw CannotDumpException("Bad type information"); //TODO
1472 typeParameterIndex = it->second;
1473 } else {
1474 typeParameterIndex = -1;
1476 addField(
1477 manager, dependencies, cf.get(), &typeInfo, typeParameterIndex,
1478 member.type, member.name, index++);
1480 std::unique_ptr< ClassFile::Code > code(cf->newCode());
1481 code->loadLocalReference(0);
1482 code->instrInvokespecial("java/lang/Object", "<init>", "()V");
1483 sal_uInt16 stack = 0;
1484 for (const unoidl::PolymorphicStructTypeTemplateEntity::Member& member : entity->getMembers())
1486 stack = std::max(
1487 stack,
1488 addFieldInit(
1489 manager, className, member.name, member.parameterized, member.type,
1490 dependencies, code.get()));
1492 code->instrReturn();
1493 code->setMaxStackAndLocals(stack + 1, 1);
1494 cf->addMethod(
1495 ClassFile::ACC_PUBLIC, "<init>", "()V", code.get(),
1496 std::vector< OString >(), "");
1497 MethodDescriptor desc(manager, dependencies, "void", nullptr, nullptr);
1498 code.reset(cf->newCode());
1499 code->loadLocalReference(0);
1500 sal_uInt16 index2 = 1;
1501 code->instrInvokespecial(
1502 "java/lang/Object", "<init>", desc.getDescriptor());
1503 sal_uInt16 maxSize = index2;
1504 for (const unoidl::PolymorphicStructTypeTemplateEntity::Member& member : entity->getMembers())
1506 maxSize = std::max(
1507 maxSize,
1508 addDirectArgument(
1509 manager, dependencies, &desc, code.get(), &index2, className,
1510 codemaker::convertString(member.name), member.parameterized, member.type));
1512 code->instrReturn();
1513 code->setMaxStackAndLocals(maxSize, index2);
1514 cf->addMethod(
1515 ClassFile::ACC_PUBLIC, "<init>", desc.getDescriptor(), code.get(),
1516 std::vector< OString >(), desc.getSignature());
1517 addTypeInfo(className, typeInfo, dependencies, cf.get());
1518 writeClassFile(options, className, *cf);
1521 void addExceptionBaseArguments(
1522 rtl::Reference< TypeManager > const & manager, std::set<OUString> * dependencies,
1523 MethodDescriptor * methodDescriptor, ClassFile::Code * code,
1524 OUString const & base, sal_uInt16 * index)
1526 assert(manager.is());
1527 assert(methodDescriptor != nullptr);
1528 rtl::Reference< unoidl::Entity > ent;
1529 if (manager->getSort(base, &ent) != codemaker::UnoType::Sort::Exception)
1531 throw CannotDumpException(
1532 "unexpected entity \"" + base
1533 + "\" in call to addExceptionBaseArguments");
1535 unoidl::ExceptionTypeEntity& ent2(dynamic_cast<unoidl::ExceptionTypeEntity&>(*ent));
1536 bool baseException = base == "com.sun.star.uno.Exception";
1537 if (!baseException) {
1538 addExceptionBaseArguments(
1539 manager, dependencies, methodDescriptor, code,
1540 ent2.getDirectBase(), index);
1542 for (std::vector< unoidl::ExceptionTypeEntity::Member >::const_iterator i(
1543 ent2.getDirectMembers().begin());
1544 i != ent2.getDirectMembers().end(); ++i)
1546 if (!baseException || i != ent2.getDirectMembers().begin()) {
1547 methodDescriptor->addParameter(i->type, false, true, nullptr);
1548 addLoadLocal(
1549 manager, code, index, false, i->type, false, dependencies);
1554 void handleExceptionType(
1555 const OUString& name, rtl::Reference< unoidl::ExceptionTypeEntity > const & entity,
1556 rtl::Reference< TypeManager > const & manager, JavaOptions const & options,
1557 std::set<OUString> * dependencies)
1559 assert(entity.is());
1560 assert(dependencies != nullptr);
1561 OString className(codemaker::convertString(name).replace('.', '/'));
1562 bool baseException = false;
1563 bool baseRuntimeException = false;
1564 OString superClass;
1565 if (className == "com/sun/star/uno/Exception") {
1566 baseException = true;
1567 superClass = "java/lang/Exception";
1568 } else if (className == "com/sun/star/uno/RuntimeException") {
1569 baseRuntimeException = true;
1570 superClass = "java/lang/RuntimeException";
1571 } else {
1572 if (entity->getDirectBase().isEmpty()) {
1573 throw CannotDumpException(
1574 "Exception type \"" + name + "\" lacks base");
1576 superClass = codemaker::convertString(entity->getDirectBase()).
1577 replace('.', '/');
1578 dependencies->insert(entity->getDirectBase());
1580 std::unique_ptr< ClassFile > cf(
1581 new ClassFile(
1582 static_cast< ClassFile::AccessFlags >(
1583 ClassFile::ACC_PUBLIC | ClassFile::ACC_SUPER),
1584 className, superClass, ""));
1585 std::vector< TypeInfo > typeInfo;
1586 sal_Int32 index = 0;
1587 if (baseRuntimeException) {
1588 addField(
1589 manager, dependencies, cf.get(), &typeInfo, -1,
1590 "com.sun.star.uno.XInterface", "Context", index++);
1592 for (std::vector< unoidl::ExceptionTypeEntity::Member >::const_iterator i(
1593 entity->getDirectMembers().begin());
1594 i != entity->getDirectMembers().end(); ++i)
1596 if (!baseException || i != entity->getDirectMembers().begin()) {
1597 addField(
1598 manager, dependencies, cf.get(), &typeInfo, -1, i->type,
1599 i->name, index++);
1603 // create default constructor
1604 std::unique_ptr< ClassFile::Code > code(cf->newCode());
1605 code->loadLocalReference(0);
1606 code->instrInvokespecial(superClass, "<init>", "()V");
1607 sal_uInt16 stack = 0;
1608 if (baseRuntimeException) {
1609 stack = std::max(
1610 stack,
1611 addFieldInit(
1612 manager, className, "Context", false,
1613 "com.sun.star.uno.XInterface", dependencies, code.get()));
1615 for (std::vector< unoidl::ExceptionTypeEntity::Member >::const_iterator i(
1616 entity->getDirectMembers().begin());
1617 i != entity->getDirectMembers().end(); ++i)
1619 if (!baseException || i != entity->getDirectMembers().begin()) {
1620 stack = std::max(
1621 stack,
1622 addFieldInit(
1623 manager, className, i->name, false, i->type, dependencies,
1624 code.get()));
1627 code->instrReturn();
1628 code->setMaxStackAndLocals(stack + 1, 1);
1629 cf->addMethod(
1630 ClassFile::ACC_PUBLIC, "<init>", "()V", code.get(),
1631 std::vector< OString >(), "");
1634 // create (Throwable Cause) constructor
1635 code.reset(cf->newCode());
1636 code->loadLocalReference(0);
1637 code->loadLocalReference(1);
1638 code->instrInvokespecial(superClass, "<init>", "(Ljava/lang/Throwable;)V");
1639 stack = 0;
1640 if (baseRuntimeException) {
1641 stack = std::max(
1642 stack,
1643 addFieldInit(
1644 manager, className, "Context", false,
1645 "com.sun.star.uno.XInterface", dependencies, code.get()));
1647 for (std::vector< unoidl::ExceptionTypeEntity::Member >::const_iterator i(
1648 entity->getDirectMembers().begin());
1649 i != entity->getDirectMembers().end(); ++i)
1651 if (!baseException || i != entity->getDirectMembers().begin()) {
1652 stack = std::max(
1653 stack,
1654 addFieldInit(
1655 manager, className, i->name, false, i->type, dependencies,
1656 code.get()));
1659 code->instrReturn();
1660 code->setMaxStackAndLocals(stack + 2, 2);
1661 cf->addMethod(
1662 ClassFile::ACC_PUBLIC, "<init>", "(Ljava/lang/Throwable;)V", code.get(),
1663 std::vector< OString >(), "");
1665 // create (Throwable Cause, String Message) constructor
1666 code.reset(cf->newCode());
1667 code->loadLocalReference(0);
1668 if (baseException || baseRuntimeException) {
1669 code->loadLocalReference(2);
1670 code->loadLocalReference(1);
1671 code->instrInvokespecial(superClass, "<init>", "(Ljava/lang/String;Ljava/lang/Throwable;)V");
1672 } else {
1673 code->loadLocalReference(1);
1674 code->loadLocalReference(2);
1675 code->instrInvokespecial(superClass, "<init>", "(Ljava/lang/Throwable;Ljava/lang/String;)V");
1677 stack = 0;
1678 if (baseRuntimeException) {
1679 stack = std::max(
1680 stack,
1681 addFieldInit(
1682 manager, className, "Context", false,
1683 "com.sun.star.uno.XInterface", dependencies, code.get()));
1685 for (std::vector< unoidl::ExceptionTypeEntity::Member >::const_iterator i(
1686 entity->getDirectMembers().begin());
1687 i != entity->getDirectMembers().end(); ++i)
1689 if (!baseException || i != entity->getDirectMembers().begin()) {
1690 stack = std::max(
1691 stack,
1692 addFieldInit(
1693 manager, className, i->name, false, i->type, dependencies,
1694 code.get()));
1697 code->instrReturn();
1698 code->setMaxStackAndLocals(stack + 3, 3);
1699 cf->addMethod(
1700 ClassFile::ACC_PUBLIC, "<init>", "(Ljava/lang/Throwable;Ljava/lang/String;)V", code.get(),
1701 std::vector< OString >(), "");
1703 // create (String Message) constructor
1704 code.reset(cf->newCode());
1705 code->loadLocalReference(0);
1706 code->loadLocalReference(1);
1707 code->instrInvokespecial(superClass, "<init>", "(Ljava/lang/String;)V");
1708 stack = 0;
1709 if (baseRuntimeException) {
1710 stack = std::max(
1711 stack,
1712 addFieldInit(
1713 manager, className, "Context", false,
1714 "com.sun.star.uno.XInterface", dependencies, code.get()));
1716 for (std::vector< unoidl::ExceptionTypeEntity::Member >::const_iterator i(
1717 entity->getDirectMembers().begin());
1718 i != entity->getDirectMembers().end(); ++i)
1720 if (!baseException || i != entity->getDirectMembers().begin()) {
1721 stack = std::max(
1722 stack,
1723 addFieldInit(
1724 manager, className, i->name, false, i->type, dependencies,
1725 code.get()));
1728 code->instrReturn();
1729 code->setMaxStackAndLocals(stack + 2, 2);
1730 cf->addMethod(
1731 ClassFile::ACC_PUBLIC, "<init>", "(Ljava/lang/String;)V", code.get(),
1732 std::vector< OString >(), "");
1735 // create (String Message, Object Context, T1 m1, ..., Tn mn) constructor
1736 MethodDescriptor desc1(manager, dependencies, "void", nullptr, nullptr);
1737 code.reset(cf->newCode());
1738 code->loadLocalReference(0);
1739 sal_uInt16 index2 = 1;
1740 code->loadLocalReference(index2++);
1741 desc1.addParameter("string", false, true, nullptr);
1742 if (!(baseException || baseRuntimeException)) {
1743 addExceptionBaseArguments(
1744 manager, dependencies, &desc1, code.get(), entity->getDirectBase(),
1745 &index2);
1747 code->instrInvokespecial(superClass, "<init>", desc1.getDescriptor());
1748 sal_uInt16 maxSize = index2;
1749 if (baseRuntimeException) {
1750 maxSize = std::max(
1751 maxSize,
1752 addDirectArgument(
1753 manager, dependencies, &desc1, code.get(), &index2, className,
1754 "Context", false, "com.sun.star.uno.XInterface"));
1756 for (std::vector< unoidl::ExceptionTypeEntity::Member >::const_iterator i(
1757 entity->getDirectMembers().begin());
1758 i != entity->getDirectMembers().end(); ++i)
1760 if (!baseException || i != entity->getDirectMembers().begin()) {
1761 maxSize = std::max(
1762 maxSize,
1763 addDirectArgument(
1764 manager, dependencies, &desc1, code.get(), &index2,
1765 className, codemaker::convertString(i->name), false,
1766 i->type));
1769 code->instrReturn();
1770 code->setMaxStackAndLocals(maxSize, index2);
1771 cf->addMethod(
1772 ClassFile::ACC_PUBLIC, "<init>", desc1.getDescriptor(), code.get(),
1773 std::vector< OString >(), desc1.getSignature());
1775 // create (Throwable Cause, String Message, Object Context, T1 m1, ..., Tn mn) constructor
1776 MethodDescriptor desc2(manager, dependencies, "void", nullptr, nullptr);
1777 code.reset(cf->newCode());
1778 code->loadLocalReference(0);
1779 sal_uInt16 index3 = 3;
1780 // Note that we hack in the java.lang.Throwable parameter further down,
1781 // because MethodDescriptor does not know how to handle it.
1782 desc2.addParameter("string", false, true, nullptr);
1783 if (baseException || baseRuntimeException) {
1784 code->loadLocalReference(2);
1785 code->loadLocalReference(1);
1786 code->instrInvokespecial(superClass, "<init>", "(Ljava/lang/String;Ljava/lang/Throwable;)V");
1787 } else {
1788 code->loadLocalReference(1);
1789 code->loadLocalReference(2);
1790 addExceptionBaseArguments(
1791 manager, dependencies, &desc2, code.get(), entity->getDirectBase(),
1792 &index3);
1793 code->instrInvokespecial(superClass, "<init>", "(Ljava/lang/Throwable;" + desc2.getDescriptor().copy(1));
1795 sal_uInt16 maxSize2 = index3;
1796 if (baseRuntimeException) {
1797 maxSize2 = std::max(
1798 maxSize2,
1799 addDirectArgument(
1800 manager, dependencies, &desc2, code.get(), &index3, className,
1801 "Context", false, "com.sun.star.uno.XInterface"));
1803 for (std::vector< unoidl::ExceptionTypeEntity::Member >::const_iterator i(
1804 entity->getDirectMembers().begin());
1805 i != entity->getDirectMembers().end(); ++i)
1807 if (!baseException || i != entity->getDirectMembers().begin()) {
1808 maxSize2 = std::max(
1809 maxSize2,
1810 addDirectArgument(
1811 manager, dependencies, &desc2, code.get(), &index3,
1812 className, codemaker::convertString(i->name), false,
1813 i->type));
1816 code->instrReturn();
1817 code->setMaxStackAndLocals(maxSize2, index3);
1818 cf->addMethod(
1819 ClassFile::ACC_PUBLIC, "<init>", "(Ljava/lang/Throwable;" + desc2.getDescriptor().copy(1), code.get(),
1820 std::vector< OString >(), desc2.getSignature());
1822 addTypeInfo(className, typeInfo, dependencies, cf.get());
1823 writeClassFile(options, className, *cf);
1826 void createExceptionsAttribute(
1827 rtl::Reference< TypeManager > const & manager,
1828 std::vector< OUString > const & exceptionTypes,
1829 std::set<OUString> * dependencies, std::vector< OString > * exceptions,
1830 codemaker::ExceptionTree * tree)
1832 assert(dependencies != nullptr);
1833 assert(exceptions != nullptr);
1834 for (const OUString& ex : exceptionTypes)
1836 dependencies->insert(ex);
1837 OString type(codemaker::convertString(ex).replace('.', '/'));
1838 exceptions->push_back(type);
1839 if (tree != nullptr) {
1840 tree->add(type.replace('/', '.'), manager);
1845 void handleInterfaceType(
1846 const OUString& name, rtl::Reference< unoidl::InterfaceTypeEntity > const & entity,
1847 rtl::Reference< TypeManager > const & manager, JavaOptions const & options,
1848 std::set<OUString> * dependencies)
1850 assert(entity.is());
1851 assert(dependencies != nullptr);
1852 OString className(codemaker::convertString(name).replace('.', '/'));
1853 std::unique_ptr< ClassFile > cf(
1854 new ClassFile(
1855 static_cast< ClassFile::AccessFlags >(
1856 ClassFile::ACC_PUBLIC | ClassFile::ACC_INTERFACE
1857 | ClassFile::ACC_ABSTRACT),
1858 className, "java/lang/Object", ""));
1859 for (const unoidl::AnnotatedReference& ar : entity->getDirectMandatoryBases())
1861 dependencies->insert(ar.name);
1862 cf->addInterface(codemaker::convertString(ar.name).replace('.', '/'));
1864 // As a special case, let com.sun.star.lang.XEventListener extend
1865 // java.util.EventListener ("A tagging interface that all event listener
1866 // interfaces must extend"):
1867 if (className == "com/sun/star/lang/XEventListener") {
1868 cf->addInterface("java/util/EventListener");
1870 std::vector< TypeInfo > typeInfo;
1871 if (className != "com/sun/star/uno/XInterface") {
1872 sal_Int32 index = 0;
1873 for (const unoidl::InterfaceTypeEntity::Attribute& attr : entity->getDirectAttributes())
1875 SpecialType specialType;
1876 PolymorphicUnoType polymorphicUnoType;
1877 MethodDescriptor gdesc(
1878 manager, dependencies, attr.type, &specialType,
1879 &polymorphicUnoType);
1880 std::vector< OString > exc;
1881 createExceptionsAttribute(
1882 manager, attr.getExceptions, dependencies, &exc, nullptr);
1883 OString attrName(codemaker::convertString(attr.name));
1884 cf->addMethod(
1885 static_cast< ClassFile::AccessFlags >(
1886 ClassFile::ACC_PUBLIC | ClassFile::ACC_ABSTRACT),
1887 "get" + attrName, gdesc.getDescriptor(), nullptr, exc,
1888 gdesc.getSignature());
1889 if (!attr.readOnly) {
1890 MethodDescriptor sdesc(manager, dependencies, "void", nullptr, nullptr);
1891 sdesc.addParameter(attr.type, false, true, nullptr);
1892 std::vector< OString > exc2;
1893 createExceptionsAttribute(
1894 manager, attr.setExceptions, dependencies, &exc2, nullptr);
1895 cf->addMethod(
1896 static_cast< ClassFile::AccessFlags >(
1897 ClassFile::ACC_PUBLIC | ClassFile::ACC_ABSTRACT),
1898 "set" + attrName, sdesc.getDescriptor(), nullptr, exc2,
1899 sdesc.getSignature());
1901 typeInfo.emplace_back(
1902 TypeInfo::KIND_ATTRIBUTE, attrName, specialType,
1903 static_cast< TypeInfo::Flags >(
1904 (attr.readOnly ? TypeInfo::FLAG_READONLY : 0)
1905 | (attr.bound ? TypeInfo::FLAG_BOUND : 0)),
1906 index, polymorphicUnoType);
1907 index += (attr.readOnly ? 1 : 2);
1909 for (const unoidl::InterfaceTypeEntity::Method& method : entity->getDirectMethods())
1911 OString methodName(codemaker::convertString(method.name));
1912 SpecialType specialReturnType;
1913 PolymorphicUnoType polymorphicUnoReturnType;
1914 MethodDescriptor desc(
1915 manager, dependencies, method.returnType, &specialReturnType,
1916 &polymorphicUnoReturnType);
1917 typeInfo.emplace_back(
1918 TypeInfo::KIND_METHOD, methodName, specialReturnType,
1919 static_cast< TypeInfo::Flags >(0), index++,
1920 polymorphicUnoReturnType);
1921 sal_Int32 paramIndex = 0;
1922 for (const unoidl::InterfaceTypeEntity::Method::Parameter& param : method.parameters)
1924 bool in = param.direction
1925 != unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_OUT;
1926 bool out = param.direction
1927 != unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN;
1928 PolymorphicUnoType polymorphicUnoType;
1929 SpecialType specialType = desc.addParameter(
1930 param.type, out, true, &polymorphicUnoType);
1931 if (out || isSpecialType(specialType)
1932 || polymorphicUnoType.kind != PolymorphicUnoType::KIND_NONE)
1934 typeInfo.emplace_back(
1935 codemaker::convertString(param.name), specialType, in,
1936 out, methodName, paramIndex, polymorphicUnoType);
1938 ++paramIndex;
1940 std::vector< OString > exc2;
1941 createExceptionsAttribute(
1942 manager, method.exceptions, dependencies, &exc2, nullptr);
1943 cf->addMethod(
1944 static_cast< ClassFile::AccessFlags >(
1945 ClassFile::ACC_PUBLIC | ClassFile::ACC_ABSTRACT),
1946 methodName, desc.getDescriptor(), nullptr, exc2, desc.getSignature());
1949 addTypeInfo(className, typeInfo, dependencies, cf.get());
1950 writeClassFile(options, className, *cf);
1953 void handleTypedef(
1954 rtl::Reference< unoidl::TypedefEntity > const & entity,
1955 rtl::Reference< TypeManager > const & manager, std::set<OUString> * dependencies)
1957 assert(entity.is());
1958 assert(manager.is());
1959 assert(dependencies != nullptr);
1960 OUString nucleus;
1961 switch (manager->decompose(entity->getType(), false, &nucleus, nullptr, nullptr, nullptr))
1963 case codemaker::UnoType::Sort::Boolean:
1964 case codemaker::UnoType::Sort::Byte:
1965 case codemaker::UnoType::Sort::Short:
1966 case codemaker::UnoType::Sort::UnsignedShort:
1967 case codemaker::UnoType::Sort::Long:
1968 case codemaker::UnoType::Sort::UnsignedLong:
1969 case codemaker::UnoType::Sort::Hyper:
1970 case codemaker::UnoType::Sort::UnsignedHyper:
1971 case codemaker::UnoType::Sort::Float:
1972 case codemaker::UnoType::Sort::Double:
1973 case codemaker::UnoType::Sort::Char:
1974 case codemaker::UnoType::Sort::String:
1975 case codemaker::UnoType::Sort::Type:
1976 case codemaker::UnoType::Sort::Any:
1977 break;
1978 case codemaker::UnoType::Sort::Enum:
1979 case codemaker::UnoType::Sort::PlainStruct:
1980 case codemaker::UnoType::Sort::Interface:
1981 case codemaker::UnoType::Sort::Typedef:
1982 dependencies->insert(nucleus);
1983 break;
1984 default:
1985 assert(false); // this cannot happen
1989 void handleConstantGroup(
1990 const OUString& name, rtl::Reference< unoidl::ConstantGroupEntity > const & entity,
1991 rtl::Reference< TypeManager > const & manager, JavaOptions const & options,
1992 std::set<OUString> * dependencies)
1994 assert(entity.is());
1995 OString className(codemaker::convertString(name).replace('.', '/'));
1996 std::unique_ptr< ClassFile > cf(
1997 new ClassFile(
1998 static_cast< ClassFile::AccessFlags >(
1999 ClassFile::ACC_PUBLIC | ClassFile::ACC_INTERFACE
2000 | ClassFile::ACC_ABSTRACT),
2001 className, "java/lang/Object", ""));
2002 for (const unoidl::ConstantGroupEntity::Member& member : entity->getMembers())
2004 OUString type;
2005 sal_uInt16 valueIndex = sal_uInt16(); // avoid false warnings
2006 switch (member.value.type) {
2007 case unoidl::ConstantValue::TYPE_BOOLEAN:
2008 type = "boolean";
2009 valueIndex = cf->addIntegerInfo(sal_Int32(member.value.booleanValue));
2010 break;
2011 case unoidl::ConstantValue::TYPE_BYTE:
2012 type = "byte";
2013 valueIndex = cf->addIntegerInfo(member.value.byteValue);
2014 break;
2015 case unoidl::ConstantValue::TYPE_SHORT:
2016 type = "short";
2017 valueIndex = cf->addIntegerInfo(member.value.shortValue);
2018 break;
2019 case unoidl::ConstantValue::TYPE_UNSIGNED_SHORT:
2020 type = "unsigned short";
2021 valueIndex = cf->addIntegerInfo(member.value.unsignedShortValue);
2022 break;
2023 case unoidl::ConstantValue::TYPE_LONG:
2024 type = "long";
2025 valueIndex = cf->addIntegerInfo(member.value.longValue);
2026 break;
2027 case unoidl::ConstantValue::TYPE_UNSIGNED_LONG:
2028 type = "unsigned long";
2029 valueIndex = cf->addIntegerInfo(
2030 static_cast< sal_Int32 >(member.value.unsignedLongValue));
2031 break;
2032 case unoidl::ConstantValue::TYPE_HYPER:
2033 type = "hyper";
2034 valueIndex = cf->addLongInfo(member.value.hyperValue);
2035 break;
2036 case unoidl::ConstantValue::TYPE_UNSIGNED_HYPER:
2037 type = "unsigned hyper";
2038 valueIndex = cf->addLongInfo(
2039 static_cast< sal_Int64 >(member.value.unsignedHyperValue));
2040 break;
2041 case unoidl::ConstantValue::TYPE_FLOAT:
2042 type = "float";
2043 valueIndex = cf->addFloatInfo(member.value.floatValue);
2044 break;
2045 case unoidl::ConstantValue::TYPE_DOUBLE:
2046 type = "double";
2047 valueIndex = cf->addDoubleInfo(member.value.doubleValue);
2048 break;
2050 OString desc;
2051 OString sig;
2052 getFieldDescriptor(manager, dependencies, type, &desc, &sig, nullptr);
2053 cf->addField(
2054 static_cast< ClassFile::AccessFlags >(
2055 ClassFile::ACC_PUBLIC | ClassFile::ACC_STATIC
2056 | ClassFile::ACC_FINAL),
2057 codemaker::convertString(member.name), desc, valueIndex, sig);
2059 writeClassFile(options, className, *cf);
2062 void addExceptionHandlers(
2063 codemaker::ExceptionTreeNode const * node,
2064 ClassFile::Code::Position start, ClassFile::Code::Position end,
2065 ClassFile::Code::Position handler, ClassFile::Code * code)
2067 assert(node != nullptr);
2068 assert(code != nullptr);
2069 if (node->present) {
2070 code->addException(start, end, handler, node->name.replace('.', '/'));
2071 } else {
2072 for (std::unique_ptr<codemaker::ExceptionTreeNode> const & p : node->children)
2074 addExceptionHandlers(p.get(), start, end, handler, code);
2079 void addConstructor(
2080 rtl::Reference< TypeManager > const & manager,
2081 OString const & realJavaBaseName, OString const & unoName,
2082 OString const & className,
2083 unoidl::SingleInterfaceBasedServiceEntity::Constructor const & constructor,
2084 OUString const & returnType, std::set<OUString> * dependencies,
2085 ClassFile * classFile)
2087 assert(dependencies != nullptr);
2088 assert(classFile != nullptr);
2089 MethodDescriptor desc(manager, dependencies, returnType, nullptr, nullptr);
2090 desc.addParameter("com.sun.star.uno.XComponentContext", false, false, nullptr);
2091 std::unique_ptr< ClassFile::Code > code(classFile->newCode());
2092 code->loadLocalReference(0);
2093 // stack: context
2094 code->instrInvokeinterface(
2095 "com/sun/star/uno/XComponentContext", "getServiceManager",
2096 "()Lcom/sun/star/lang/XMultiComponentFactory;", 1);
2097 // stack: factory
2098 code->loadStringConstant(unoName);
2099 // stack: factory serviceName
2100 codemaker::ExceptionTree tree;
2101 ClassFile::Code::Position tryStart;
2102 ClassFile::Code::Position tryEnd;
2103 std::vector< OString > exc;
2104 sal_uInt16 stack;
2105 sal_uInt16 localIndex = 1;
2106 ClassFile::AccessFlags access = static_cast< ClassFile::AccessFlags >(
2107 ClassFile::ACC_PUBLIC | ClassFile::ACC_STATIC);
2108 if (constructor.defaultConstructor) {
2109 code->loadLocalReference(0);
2110 // stack: factory serviceName context
2111 tryStart = code->getPosition();
2112 code->instrInvokeinterface(
2113 "com/sun/star/lang/XMultiComponentFactory",
2114 "createInstanceWithContext",
2115 ("(Ljava/lang/String;Lcom/sun/star/uno/XComponentContext;)"
2116 "Ljava/lang/Object;"),
2118 tryEnd = code->getPosition();
2119 // stack: instance
2120 stack = 3;
2121 } else {
2122 if (constructor.parameters.size() == 1
2123 && constructor.parameters[0].rest)
2125 desc.addParameter("any", true, true, nullptr);
2126 code->loadLocalReference(localIndex++);
2127 // stack: factory serviceName args
2128 stack = 4;
2129 access = static_cast< ClassFile::AccessFlags >(
2130 access | ClassFile::ACC_VARARGS);
2131 } else {
2132 code->loadIntegerConstant(constructor.parameters.size());
2133 // stack: factory serviceName N
2134 code->instrAnewarray("java/lang/Object");
2135 // stack: factory serviceName args
2136 stack = 0;
2137 sal_Int32 n = 0;
2138 for (const unoidl::SingleInterfaceBasedServiceEntity::Constructor::Parameter& param :
2139 constructor.parameters)
2141 desc.addParameter(param.type, false, true, nullptr);
2142 code->instrDup();
2143 // stack: factory serviceName args args
2144 code->loadIntegerConstant(n++);
2145 // stack: factory serviceName args args i
2146 stack = std::max(
2147 stack,
2148 addLoadLocal(
2149 manager, code.get(), &localIndex, false, param.type, true,
2150 dependencies));
2151 // stack: factory serviceName args args i any
2152 code->instrAastore();
2153 // stack: factory serviceName args
2155 stack += 5;
2157 code->loadLocalReference(0);
2158 // stack: factory serviceName args context
2159 tryStart = code->getPosition();
2160 code->instrInvokeinterface(
2161 "com/sun/star/lang/XMultiComponentFactory",
2162 "createInstanceWithArgumentsAndContext",
2163 ("(Ljava/lang/String;[Ljava/lang/Object;"
2164 "Lcom/sun/star/uno/XComponentContext;)Ljava/lang/Object;"),
2166 tryEnd = code->getPosition();
2167 // stack: instance
2168 createExceptionsAttribute(
2169 manager, constructor.exceptions, dependencies, &exc, &tree);
2171 code->loadLocalReference(0);
2172 // stack: instance context
2173 code->instrInvokestatic(
2174 className, "$castInstance",
2175 ("(Ljava/lang/Object;Lcom/sun/star/uno/XComponentContext;)"
2176 "Ljava/lang/Object;"));
2177 // stack: instance
2178 code->instrCheckcast(
2179 codemaker::convertString(returnType).replace('.', '/'));
2180 // stack: instance
2181 code->instrAreturn();
2182 if (!tree.getRoot().present) {
2183 ClassFile::Code::Position pos1 = code->getPosition();
2184 // stack: e
2185 code->instrInvokevirtual(
2186 "java/lang/Throwable", "toString", "()Ljava/lang/String;");
2187 // stack: str
2188 localIndex = std::max< sal_uInt16 >(localIndex, 2);
2189 code->storeLocalReference(1);
2190 // stack: -
2191 code->instrNew("com/sun/star/uno/DeploymentException");
2192 // stack: ex
2193 code->instrDup();
2194 // stack: ex ex
2195 code->loadStringConstant(
2196 "component context fails to supply service " + unoName + " of type "
2197 + realJavaBaseName + ": ");
2198 // stack: ex ex "..."
2199 code->loadLocalReference(1);
2200 // stack: ex ex "..." str
2201 code->instrInvokevirtual(
2202 "java/lang/String", "concat",
2203 "(Ljava/lang/String;)Ljava/lang/String;");
2204 // stack: ex ex "..."
2205 code->loadLocalReference(0);
2206 // stack: ex ex "..." context
2207 code->instrInvokespecial(
2208 "com/sun/star/uno/DeploymentException", "<init>",
2209 "(Ljava/lang/String;Ljava/lang/Object;)V");
2210 // stack: ex
2211 ClassFile::Code::Position pos2 = code->getPosition();
2212 code->instrAthrow();
2213 addExceptionHandlers(
2214 &tree.getRoot(), tryStart, tryEnd, pos2, code.get());
2215 code->addException(
2216 tryStart, tryEnd, pos1, "com/sun/star/uno/Exception");
2217 dependencies->insert("com.sun.star.uno.Exception");
2218 stack = std::max< sal_uInt16 >(stack, 4);
2220 code->setMaxStackAndLocals(stack, localIndex);
2221 classFile->addMethod(
2222 access,
2223 codemaker::java::translateUnoToJavaIdentifier(
2224 (constructor.defaultConstructor
2225 ? OString("create") : codemaker::convertString(constructor.name)),
2226 "method"),
2227 desc.getDescriptor(), code.get(), exc, desc.getSignature());
2230 void handleService(
2231 const OUString& name,
2232 rtl::Reference< unoidl::SingleInterfaceBasedServiceEntity > const & entity,
2233 rtl::Reference< TypeManager > const & manager, JavaOptions const & options,
2234 std::set<OUString> * dependencies)
2236 assert(entity.is());
2237 assert(dependencies != nullptr);
2238 OString unoName(codemaker::convertString(name));
2239 OString className(
2240 translateUnoidlEntityNameToJavaFullyQualifiedName(name, "service"));
2241 std::unique_ptr< ClassFile > cf(
2242 new ClassFile(
2243 static_cast< ClassFile::AccessFlags >(
2244 ClassFile::ACC_PUBLIC | ClassFile::ACC_FINAL
2245 | ClassFile::ACC_SUPER),
2246 className, "java/lang/Object", ""));
2247 if (!entity->getConstructors().empty()) {
2248 OString realJavaBaseName(
2249 codemaker::convertString(entity->getBase()));
2250 dependencies->insert(entity->getBase());
2251 dependencies->insert("com.sun.star.lang.XMultiComponentFactory");
2252 dependencies->insert("com.sun.star.uno.DeploymentException");
2253 dependencies->insert("com.sun.star.uno.TypeClass");
2254 dependencies->insert("com.sun.star.uno.XComponentContext");
2255 for (const unoidl::SingleInterfaceBasedServiceEntity::Constructor& cons :
2256 entity->getConstructors())
2258 addConstructor(
2259 manager, realJavaBaseName, unoName, className, cons,
2260 entity->getBase(), dependencies, cf.get());
2262 // Synthetic castInstance method:
2264 std::unique_ptr< ClassFile::Code > code(cf->newCode());
2265 code->instrNew("com/sun/star/uno/Type");
2266 // stack: type
2267 code->instrDup();
2268 // stack: type type
2269 code->loadStringConstant(realJavaBaseName);
2270 // stack: type type "..."
2271 code->instrGetstatic(
2272 "com/sun/star/uno/TypeClass", "INTERFACE",
2273 "Lcom/sun/star/uno/TypeClass;");
2274 // stack: type type "..." INTERFACE
2275 code->instrInvokespecial(
2276 "com/sun/star/uno/Type", "<init>",
2277 "(Ljava/lang/String;Lcom/sun/star/uno/TypeClass;)V");
2278 // stack: type
2279 code->loadLocalReference(0);
2280 // stack: type instance
2281 code->instrInvokestatic(
2282 "com/sun/star/uno/UnoRuntime", "queryInterface",
2283 ("(Lcom/sun/star/uno/Type;Ljava/lang/Object;)"
2284 "Ljava/lang/Object;"));
2285 // stack: instance
2286 code->instrDup();
2287 // stack: instance instance
2288 ClassFile::Code::Branch branch = code->instrIfnull();
2289 // stack: instance
2290 code->instrAreturn();
2291 code->branchHere(branch);
2292 code->instrPop();
2293 // stack: -
2294 code->instrNew("com/sun/star/uno/DeploymentException");
2295 // stack: ex
2296 code->instrDup();
2297 // stack: ex ex
2298 code->loadStringConstant(
2299 "component context fails to supply service " + unoName
2300 + " of type " + realJavaBaseName);
2301 // stack: ex ex "..."
2302 code->loadLocalReference(1);
2303 // stack: ex ex "..." context
2304 code->instrInvokespecial(
2305 "com/sun/star/uno/DeploymentException", "<init>",
2306 "(Ljava/lang/String;Ljava/lang/Object;)V");
2307 // stack: ex
2308 code->instrAthrow();
2309 code->setMaxStackAndLocals(4, 2);
2310 cf->addMethod(
2311 static_cast< ClassFile::AccessFlags >(
2312 ClassFile::ACC_PRIVATE | ClassFile::ACC_STATIC
2313 | ClassFile::ACC_SYNTHETIC),
2314 "$castInstance",
2315 ("(Ljava/lang/Object;Lcom/sun/star/uno/XComponentContext;)"
2316 "Ljava/lang/Object;"),
2317 code.get(), std::vector< OString >(), "");
2320 writeClassFile(options, className, *cf);
2323 void handleSingleton(
2324 const OUString& name,
2325 rtl::Reference< unoidl::InterfaceBasedSingletonEntity > const & entity,
2326 rtl::Reference< TypeManager > const & manager, JavaOptions const & options,
2327 std::set<OUString> * dependencies)
2329 assert(entity.is());
2330 assert(dependencies != nullptr);
2331 OString realJavaBaseName(codemaker::convertString(entity->getBase()));
2332 OString base(realJavaBaseName.replace('.', '/'));
2333 dependencies->insert(entity->getBase());
2334 OString unoName(codemaker::convertString(name));
2335 OString className(
2336 translateUnoidlEntityNameToJavaFullyQualifiedName(name, "singleton"));
2337 dependencies->insert("com.sun.star.uno.DeploymentException");
2338 dependencies->insert("com.sun.star.uno.TypeClass");
2339 dependencies->insert("com.sun.star.uno.XComponentContext");
2340 std::unique_ptr< ClassFile > cf(
2341 new ClassFile(
2342 static_cast< ClassFile::AccessFlags >(
2343 ClassFile::ACC_PUBLIC | ClassFile::ACC_FINAL
2344 | ClassFile::ACC_SUPER),
2345 className, "java/lang/Object", ""));
2346 MethodDescriptor desc(manager, dependencies, entity->getBase(), nullptr, nullptr);
2347 desc.addParameter("com.sun.star.uno.XComponentContext", false, false, nullptr);
2348 std::unique_ptr< ClassFile::Code > code(cf->newCode());
2349 code->loadLocalReference(0);
2350 // stack: context
2351 code->loadStringConstant("/singletons/" + unoName);
2352 // stack: context "..."
2353 code->instrInvokeinterface(
2354 "com/sun/star/uno/XComponentContext", "getValueByName",
2355 "(Ljava/lang/String;)Ljava/lang/Object;", 2);
2356 // stack: value
2357 code->instrDup();
2358 // stack: value value
2359 code->instrInstanceof("com/sun/star/uno/Any");
2360 // stack: value 0/1
2361 ClassFile::Code::Branch branch1 = code->instrIfeq();
2362 // stack: value
2363 code->instrCheckcast("com/sun/star/uno/Any");
2364 // stack: value
2365 code->instrDup();
2366 // stack: value value
2367 code->instrInvokevirtual(
2368 "com/sun/star/uno/Any", "getType", "()Lcom/sun/star/uno/Type;");
2369 // stack: value type
2370 code->instrInvokevirtual(
2371 "com/sun/star/uno/Type", "getTypeClass",
2372 "()Lcom/sun/star/uno/TypeClass;");
2373 // stack: value typeClass
2374 code->instrGetstatic(
2375 "com/sun/star/uno/TypeClass", "INTERFACE",
2376 "Lcom/sun/star/uno/TypeClass;");
2377 // stack: value typeClass INTERFACE
2378 ClassFile::Code::Branch branch2 = code->instrIfAcmpne();
2379 // stack: value
2380 code->instrInvokevirtual(
2381 "com/sun/star/uno/Any", "getObject", "()Ljava/lang/Object;");
2382 // stack: value
2383 code->branchHere(branch1);
2384 code->instrNew("com/sun/star/uno/Type");
2385 // stack: value type
2386 code->instrDup();
2387 // stack: value type type
2388 code->loadStringConstant(realJavaBaseName);
2389 // stack: value type type "..."
2390 code->instrGetstatic(
2391 "com/sun/star/uno/TypeClass", "INTERFACE",
2392 "Lcom/sun/star/uno/TypeClass;");
2393 // stack: value type type "..." INTERFACE
2394 code->instrInvokespecial(
2395 "com/sun/star/uno/Type", "<init>",
2396 "(Ljava/lang/String;Lcom/sun/star/uno/TypeClass;)V");
2397 // stack: value type
2398 code->instrSwap();
2399 // stack: type value
2400 code->instrInvokestatic(
2401 "com/sun/star/uno/UnoRuntime", "queryInterface",
2402 "(Lcom/sun/star/uno/Type;Ljava/lang/Object;)Ljava/lang/Object;");
2403 // stack: instance
2404 code->instrDup();
2405 // stack: instance instance
2406 ClassFile::Code::Branch branch3 = code->instrIfnull();
2407 // stack: instance
2408 code->instrCheckcast(base);
2409 // stack: instance
2410 code->instrAreturn();
2411 code->branchHere(branch2);
2412 code->branchHere(branch3);
2413 code->instrPop();
2414 // stack: -
2415 code->instrNew("com/sun/star/uno/DeploymentException");
2416 // stack: ex
2417 code->instrDup();
2418 // stack: ex ex
2419 code->loadStringConstant(
2420 "component context fails to supply singleton " + unoName + " of type "
2421 + realJavaBaseName);
2422 // stack: ex ex "..."
2423 code->loadLocalReference(0);
2424 // stack: ex ex "..." context
2425 code->instrInvokespecial(
2426 "com/sun/star/uno/DeploymentException", "<init>",
2427 "(Ljava/lang/String;Ljava/lang/Object;)V");
2428 // stack: ex
2429 code->instrAthrow();
2430 code->setMaxStackAndLocals(5, 1);
2431 cf->addMethod(
2432 static_cast< ClassFile::AccessFlags >(
2433 ClassFile::ACC_PUBLIC | ClassFile::ACC_STATIC),
2434 "get", desc.getDescriptor(), code.get(), std::vector< OString >(),
2435 desc.getSignature());
2436 writeClassFile(options, className, *cf);
2441 void produce(
2442 OUString const & name, rtl::Reference< TypeManager > const & manager,
2443 codemaker::GeneratedTypeSet & generated, JavaOptions const & options)
2445 if (generated.contains(u2b(name))) {
2446 return;
2448 generated.add(u2b(name));
2449 if (!manager->foundAtPrimaryProvider(name)) {
2450 return;
2452 std::set<OUString> deps;
2453 rtl::Reference< unoidl::Entity > ent;
2454 rtl::Reference< unoidl::MapCursor > cur;
2455 switch (manager->getSort(name, &ent, &cur)) {
2456 case codemaker::UnoType::Sort::Module:
2458 OUString prefix;
2459 if (!name.isEmpty()) {
2460 prefix = name + ".";
2462 for (;;) {
2463 OUString mem;
2464 if (!cur->getNext(&mem).is()) {
2465 break;
2467 produce(prefix + mem, manager, generated, options);
2469 return;
2471 case codemaker::UnoType::Sort::Enum:
2472 handleEnumType(
2473 name, dynamic_cast< unoidl::EnumTypeEntity * >(ent.get()), options);
2474 break;
2475 case codemaker::UnoType::Sort::PlainStruct:
2476 handlePlainStructType(
2477 name, dynamic_cast< unoidl::PlainStructTypeEntity * >(ent.get()),
2478 manager, options, &deps);
2479 break;
2480 case codemaker::UnoType::Sort::PolymorphicStructTemplate:
2481 handlePolyStructType(
2482 name,
2483 dynamic_cast< unoidl::PolymorphicStructTypeTemplateEntity * >(
2484 ent.get()),
2485 manager, options, &deps);
2486 break;
2487 case codemaker::UnoType::Sort::Exception:
2488 handleExceptionType(
2489 name, dynamic_cast< unoidl::ExceptionTypeEntity * >(ent.get()),
2490 manager, options, &deps);
2491 break;
2492 case codemaker::UnoType::Sort::Interface:
2493 handleInterfaceType(
2494 name, dynamic_cast< unoidl::InterfaceTypeEntity * >(ent.get()),
2495 manager, options, &deps);
2496 break;
2497 case codemaker::UnoType::Sort::Typedef:
2498 handleTypedef(
2499 dynamic_cast< unoidl::TypedefEntity * >(ent.get()), manager, &deps);
2500 break;
2501 case codemaker::UnoType::Sort::ConstantGroup:
2502 handleConstantGroup(
2503 name, dynamic_cast< unoidl::ConstantGroupEntity * >(ent.get()),
2504 manager, options, &deps);
2505 break;
2506 case codemaker::UnoType::Sort::SingleInterfaceBasedService:
2507 handleService(
2508 name,
2509 dynamic_cast< unoidl::SingleInterfaceBasedServiceEntity * >(
2510 ent.get()),
2511 manager, options, &deps);
2512 break;
2513 case codemaker::UnoType::Sort::InterfaceBasedSingleton:
2514 handleSingleton(
2515 name,
2516 dynamic_cast< unoidl::InterfaceBasedSingletonEntity * >(ent.get()),
2517 manager, options, &deps);
2518 break;
2519 case codemaker::UnoType::Sort::AccumulationBasedService:
2520 case codemaker::UnoType::Sort::ServiceBasedSingleton:
2521 break;
2522 default:
2523 throw CannotDumpException(
2524 "unexpected entity \"" + name + "\" in call to produce");
2526 if (!options.isValid("-nD")) {
2527 for (const OUString& d : deps) {
2528 produce(d, manager, generated, options);
2533 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */