tdf#130857 qt weld: Implement QtInstanceWidget::get_text_height
[LibreOffice.git] / codemaker / source / javamaker / javatype.cxx
blob974a8f31be6bfabea8bf03ac7c084c1ecd87e976
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 <string_view>
29 #include <utility>
30 #include <vector>
32 #include <codemaker/codemaker.hxx>
33 #include <codemaker/exceptiontree.hxx>
34 #include <codemaker/generatedtypeset.hxx>
35 #include <codemaker/global.hxx>
36 #include <codemaker/options.hxx>
37 #include <codemaker/typemanager.hxx>
38 #include <codemaker/unotype.hxx>
39 #include <codemaker/commonjava.hxx>
40 #include <rtl/ref.hxx>
41 #include <rtl/strbuf.hxx>
42 #include <rtl/string.hxx>
43 #include <rtl/ustrbuf.hxx>
44 #include <rtl/ustring.hxx>
45 #include <sal/types.h>
46 #include <unoidl/unoidl.hxx>
47 #include <o3tl/string_view.hxx>
49 #include "classfile.hxx"
50 #include "javaoptions.hxx"
51 #include "javatype.hxx"
53 using codemaker::javamaker::ClassFile;
55 namespace {
57 void appendUnoName(
58 rtl::Reference< TypeManager > const & manager, std::u16string_view nucleus,
59 sal_Int32 rank, std::vector< OUString > const & arguments,
60 OUStringBuffer * buffer)
62 assert(manager.is());
63 assert(rank >= 0);
64 assert(buffer != nullptr);
65 for (sal_Int32 i = 0; i != rank; ++i) {
66 buffer->append("[]");
68 buffer->append(nucleus);
69 if (arguments.empty())
70 return;
72 buffer->append('<');
73 for (std::vector< OUString >::const_iterator i(arguments.begin());
74 i != arguments.end(); ++i)
76 if (i != arguments.begin()) {
77 buffer->append(',');
79 OUString n;
80 sal_Int32 k;
81 std::vector< OUString > args;
82 manager->decompose(*i, false, &n, &k, &args, nullptr);
83 appendUnoName(manager, n, k, args, buffer);
85 buffer->append('>');
88 // Translate the name of a UNOIDL entity (enum type, plain struct type,
89 // polymorphic struct type template, or interface type, decomposed into nucleus,
90 // sequence rank, and template arguments) into a core UNO type name:
91 OUString createUnoName(
92 rtl::Reference< TypeManager > const & manager, std::u16string_view nucleus,
93 sal_Int32 rank, std::vector< OUString > const & arguments)
95 OUStringBuffer buf(256);
96 appendUnoName(manager, nucleus, rank, arguments, &buf);
97 return buf.makeStringAndClear();
100 enum SpecialType {
101 SPECIAL_TYPE_NONE,
102 SPECIAL_TYPE_ANY,
103 SPECIAL_TYPE_UNSIGNED,
104 SPECIAL_TYPE_INTERFACE
107 bool isSpecialType(SpecialType special) {
108 return special >= SPECIAL_TYPE_UNSIGNED;
111 OString translateUnoidlEntityNameToJavaFullyQualifiedName(
112 std::u16string_view name, std::string_view prefix)
114 assert(!o3tl::starts_with(name, u"[]"));
115 assert(name.find('<') == std::string_view::npos);
116 size_t i = name.rfind('.');
117 if (i == std::string_view::npos)
118 i = 0;
119 else
120 ++i;
121 return codemaker::convertString(OUString(name.substr(0, i))).replace('.', '/')
122 + codemaker::java::translateUnoToJavaIdentifier(
123 codemaker::convertString(OUString(name.substr(i))), prefix);
126 struct PolymorphicUnoType {
127 PolymorphicUnoType(): kind(KIND_NONE) {}
129 enum Kind { KIND_NONE, KIND_STRUCT, KIND_SEQUENCE };
130 Kind kind;
131 OUString name;
134 SpecialType translateUnoTypeToDescriptor(
135 rtl::Reference< TypeManager > const & manager, std::u16string_view type,
136 bool array, bool classType, std::set<OUString> * dependencies,
137 OStringBuffer * descriptor, OStringBuffer * signature,
138 bool * needsSignature, PolymorphicUnoType * polymorphicUnoType);
140 SpecialType translateUnoTypeToDescriptor(
141 rtl::Reference< TypeManager > const & manager,
142 codemaker::UnoType::Sort sort, OUString const & nucleus, sal_Int32 rank,
143 std::vector< OUString > const & arguments, bool array, bool classType,
144 std::set<OUString> * dependencies, OStringBuffer * descriptor,
145 OStringBuffer * signature, bool * needsSignature,
146 PolymorphicUnoType * polymorphicUnoType)
148 assert(rank >= 0);
149 assert((signature == nullptr) == (needsSignature == nullptr));
150 assert(
151 arguments.empty()
152 == (sort
153 != codemaker::UnoType::Sort::InstantiatedPolymorphicStruct));
154 if (rank > 0xFF - (array ? 1 : 0)) {
155 throw CannotDumpException(
156 u"Too many array dimensions for Java class file format"_ustr);
158 if (array) {
159 ++rank;
161 for (sal_Int32 i = 0; i != rank; ++i) {
162 if (descriptor != nullptr) {
163 descriptor->append('[');
165 if (signature != nullptr) {
166 signature->append('[');
169 if (polymorphicUnoType != nullptr) {
170 if (sort
171 == codemaker::UnoType::Sort::InstantiatedPolymorphicStruct)
173 polymorphicUnoType->kind = rank == 0
174 ? PolymorphicUnoType::KIND_STRUCT
175 : PolymorphicUnoType::KIND_SEQUENCE;
176 polymorphicUnoType->name = createUnoName(
177 manager, nucleus, rank, arguments);
178 } else {
179 polymorphicUnoType->kind = PolymorphicUnoType::KIND_NONE;
182 switch (sort) {
183 case codemaker::UnoType::Sort::Void:
184 case codemaker::UnoType::Sort::Boolean:
185 case codemaker::UnoType::Sort::Byte:
186 case codemaker::UnoType::Sort::Short:
187 case codemaker::UnoType::Sort::UnsignedShort:
188 case codemaker::UnoType::Sort::Long:
189 case codemaker::UnoType::Sort::UnsignedLong:
190 case codemaker::UnoType::Sort::Hyper:
191 case codemaker::UnoType::Sort::UnsignedHyper:
192 case codemaker::UnoType::Sort::Float:
193 case codemaker::UnoType::Sort::Double:
194 case codemaker::UnoType::Sort::Char:
195 case codemaker::UnoType::Sort::String:
196 case codemaker::UnoType::Sort::Type:
197 case codemaker::UnoType::Sort::Any:
199 static char const * const
200 simpleTypeDescriptors[static_cast<int>(codemaker::UnoType::Sort::Any) + 1][2] = {
201 { "V", "Ljava/lang/Void;" },
202 { "Z", "Ljava/lang/Boolean;" },
203 { "B", "Ljava/lang/Byte;" },
204 { "S", "Ljava/lang/Short;" },
205 { "S", "Ljava/lang/Short;" },
206 { "I", "Ljava/lang/Integer;" },
207 { "I", "Ljava/lang/Integer;" },
208 { "J", "Ljava/lang/Long;" },
209 { "J", "Ljava/lang/Long;" },
210 { "F", "Ljava/lang/Float;" },
211 { "D", "Ljava/lang/Double;" },
212 { "C", "Ljava/lang/Character;" },
213 { "Ljava/lang/String;", "Ljava/lang/String;" },
214 { "Lcom/sun/star/uno/Type;", "Lcom/sun/star/uno/Type;" },
215 { "Ljava/lang/Object;", "Ljava/lang/Object;" } };
216 char const * s
217 = simpleTypeDescriptors[static_cast<int>(sort)][rank == 0 && classType];
218 if (descriptor != nullptr) {
219 descriptor->append(s);
221 if (signature != nullptr) {
222 signature->append(s);
224 static SpecialType const
225 simpleTypeSpecials[static_cast<int>(codemaker::UnoType::Sort::Any) + 1] = {
226 SPECIAL_TYPE_NONE, SPECIAL_TYPE_NONE, SPECIAL_TYPE_NONE,
227 SPECIAL_TYPE_NONE, SPECIAL_TYPE_UNSIGNED, SPECIAL_TYPE_NONE,
228 SPECIAL_TYPE_UNSIGNED, SPECIAL_TYPE_NONE, SPECIAL_TYPE_UNSIGNED,
229 SPECIAL_TYPE_NONE, SPECIAL_TYPE_NONE, SPECIAL_TYPE_NONE,
230 SPECIAL_TYPE_NONE, SPECIAL_TYPE_NONE, SPECIAL_TYPE_ANY };
231 return simpleTypeSpecials[static_cast<int>(sort)];
233 case codemaker::UnoType::Sort::Interface:
234 if (nucleus == "com.sun.star.uno.XInterface") {
235 if (descriptor != nullptr) {
236 descriptor->append("Ljava/lang/Object;");
238 if (signature != nullptr) {
239 signature->append("Ljava/lang/Object;");
241 return SPECIAL_TYPE_INTERFACE;
243 [[fallthrough]];
244 case codemaker::UnoType::Sort::Sequence:
245 case codemaker::UnoType::Sort::Enum:
246 case codemaker::UnoType::Sort::PlainStruct:
247 case codemaker::UnoType::Sort::InstantiatedPolymorphicStruct:
248 if (dependencies != nullptr) {
249 dependencies->insert(nucleus);
251 if (descriptor != nullptr) {
252 descriptor->append(
253 "L" + codemaker::convertString(nucleus).replace('.', '/')
254 + ";");
256 if (signature != nullptr) {
257 signature->append(
258 "L" + codemaker::convertString(nucleus).replace('.', '/'));
259 if (!arguments.empty()) {
260 signature->append('<');
261 for (const OUString& arg : arguments)
263 translateUnoTypeToDescriptor(
264 manager, arg, false, true, dependencies, nullptr, signature,
265 needsSignature, nullptr);
267 signature->append('>');
268 *needsSignature = true;
270 signature->append(';');
272 return SPECIAL_TYPE_NONE;
273 default:
274 throw CannotDumpException(
275 "unexpected nucleus \"" + nucleus
276 + "\" in call to translateUnoTypeToDescriptor");
280 SpecialType translateUnoTypeToDescriptor(
281 rtl::Reference< TypeManager > const & manager, std::u16string_view type,
282 bool array, bool classType, std::set<OUString> * dependencies,
283 OStringBuffer * descriptor, OStringBuffer * signature,
284 bool * needsSignature, PolymorphicUnoType * polymorphicUnoType)
286 assert(manager.is());
287 OUString nucleus;
288 sal_Int32 rank;
289 std::vector< OUString > args;
290 codemaker::UnoType::Sort sort = manager->decompose(
291 type, true, &nucleus, &rank, &args, nullptr);
292 return translateUnoTypeToDescriptor(
293 manager, sort, nucleus, rank, args, array, classType, dependencies,
294 descriptor, signature, needsSignature, polymorphicUnoType);
297 SpecialType getFieldDescriptor(
298 rtl::Reference< TypeManager > const & manager, std::set<OUString> * dependencies,
299 std::u16string_view type, OString * descriptor, OString * signature,
300 PolymorphicUnoType * polymorphicUnoType)
302 assert(descriptor != nullptr);
303 OStringBuffer desc(64);
304 OStringBuffer sig(64);
305 bool needsSig = false;
306 SpecialType specialType = translateUnoTypeToDescriptor(
307 manager, type, false, false, dependencies, &desc, &sig, &needsSig,
308 polymorphicUnoType);
309 *descriptor = desc.makeStringAndClear();
310 if (signature != nullptr) {
311 if (needsSig) {
312 *signature = sig.makeStringAndClear();
313 } else {
314 signature->clear();
317 return specialType;
320 class MethodDescriptor {
321 public:
322 MethodDescriptor(
323 rtl::Reference< TypeManager > manager,
324 std::set<OUString> * dependencies, std::u16string_view returnType,
325 SpecialType * specialReturnType,
326 PolymorphicUnoType * polymorphicUnoType);
328 SpecialType addParameter(
329 std::u16string_view type, bool array, bool dependency,
330 PolymorphicUnoType * polymorphicUnoType);
332 void addTypeParameter(OUString const & name);
334 OString getDescriptor() const;
336 OString getSignature() const { return m_needsSignature ? m_signatureStart + m_signatureEnd : OString();}
338 private:
339 rtl::Reference< TypeManager > m_manager;
340 std::set<OUString> * m_dependencies;
341 OStringBuffer m_descriptorStart{16*1024};
342 OString m_descriptorEnd;
343 OStringBuffer m_signatureStart{16*1024};
344 OString m_signatureEnd;
345 bool m_needsSignature;
348 MethodDescriptor::MethodDescriptor(
349 rtl::Reference< TypeManager > manager, std::set<OUString> * dependencies,
350 std::u16string_view returnType, SpecialType * specialReturnType,
351 PolymorphicUnoType * polymorphicUnoType):
352 m_manager(std::move(manager)), m_dependencies(dependencies), m_needsSignature(false)
354 assert(dependencies != nullptr);
355 m_descriptorStart.append('(');
356 m_signatureStart.append('(');
357 OStringBuffer descEnd(128);
358 descEnd.append(')');
359 OStringBuffer sigEnd(128);
360 sigEnd.append(')');
361 SpecialType special = translateUnoTypeToDescriptor(
362 m_manager, returnType, false, false, m_dependencies, &descEnd, &sigEnd,
363 &m_needsSignature, polymorphicUnoType);
364 m_descriptorEnd = descEnd.makeStringAndClear();
365 m_signatureEnd = sigEnd.makeStringAndClear();
366 if (specialReturnType != nullptr) {
367 *specialReturnType = special;
371 SpecialType MethodDescriptor::addParameter(
372 std::u16string_view type, bool array, bool dependency,
373 PolymorphicUnoType * polymorphicUnoType)
375 return translateUnoTypeToDescriptor(
376 m_manager, type, array, false, dependency ? m_dependencies : nullptr,
377 &m_descriptorStart, &m_signatureStart, &m_needsSignature,
378 polymorphicUnoType);
381 void MethodDescriptor::addTypeParameter(OUString const & name) {
382 m_descriptorStart.append("Ljava/lang/Object;");
383 m_signatureStart.append("T" + codemaker::convertString(name) + ";");
384 m_needsSignature = true;
387 OString MethodDescriptor::getDescriptor() const {
388 return m_descriptorStart + m_descriptorEnd;
392 class TypeInfo {
393 public:
394 enum Kind { KIND_MEMBER, KIND_ATTRIBUTE, KIND_METHOD, KIND_PARAMETER };
396 // Same values as in com/sun/star/lib/uno/typeinfo/TypeInfo.java:
397 enum Flags {
398 FLAG_READONLY = 0x008, FLAG_BOUND = 0x100
401 // KIND_MEMBER:
402 TypeInfo(
403 OString name, SpecialType specialType, sal_Int32 index,
404 PolymorphicUnoType const & polymorphicUnoType,
405 sal_Int32 typeParameterIndex);
407 // KIND_ATTRIBUTE/METHOD:
408 TypeInfo(
409 Kind kind, OString name, SpecialType specialType, Flags flags,
410 sal_Int32 index, PolymorphicUnoType polymorphicUnoType);
412 // KIND_PARAMETER:
413 TypeInfo(
414 OString parameterName, SpecialType specialType,
415 bool inParameter, bool outParameter, OString methodName,
416 sal_Int32 index, PolymorphicUnoType polymorphicUnoType);
418 sal_uInt16 generateCode(ClassFile::Code & code, std::set<OUString> * dependencies)
419 const;
421 void generatePolymorphicUnoTypeCode(
422 ClassFile::Code & code, std::set<OUString> * dependencies) const;
424 private:
425 Kind m_kind;
426 OString m_name;
427 sal_Int32 m_flags;
428 sal_Int32 m_index;
429 OString m_methodName;
430 PolymorphicUnoType m_polymorphicUnoType;
431 sal_Int32 m_typeParameterIndex;
434 sal_Int32 translateSpecialTypeFlags(
435 SpecialType specialType, bool inParameter, bool outParameter)
437 static sal_Int32 const specialTypeFlags[SPECIAL_TYPE_INTERFACE + 1] = {
438 0, 0x0040 /* ANY */, 0x0004 /* UNSIGNED */, 0x0080 /* INTERFACE */ };
439 sal_Int32 flags = specialTypeFlags[specialType];
440 if (inParameter) {
441 flags |= 0x0001; /* IN */
443 if (outParameter) {
444 flags |= 0x0002; /* OUT */
446 return flags;
449 TypeInfo::TypeInfo(
450 OString name, SpecialType specialType, sal_Int32 index,
451 PolymorphicUnoType const & polymorphicUnoType,
452 sal_Int32 typeParameterIndex):
453 m_kind(KIND_MEMBER), m_name(std::move(name)),
454 m_flags(translateSpecialTypeFlags(specialType, false, false)),
455 m_index(index), m_polymorphicUnoType(polymorphicUnoType),
456 m_typeParameterIndex(typeParameterIndex)
458 assert(
459 polymorphicUnoType.kind == PolymorphicUnoType::KIND_NONE
460 ? typeParameterIndex >= -1 : typeParameterIndex == -1);
463 TypeInfo::TypeInfo(
464 Kind kind, OString name, SpecialType specialType, Flags flags,
465 sal_Int32 index, PolymorphicUnoType polymorphicUnoType):
466 m_kind(kind), m_name(std::move(name)),
467 m_flags(flags | translateSpecialTypeFlags(specialType, false, false)),
468 m_index(index), m_polymorphicUnoType(std::move(polymorphicUnoType)),
469 m_typeParameterIndex(0)
471 assert(kind == KIND_ATTRIBUTE || kind == KIND_METHOD);
474 TypeInfo::TypeInfo(
475 OString parameterName, SpecialType specialType, bool inParameter,
476 bool outParameter, OString methodName, sal_Int32 index,
477 PolymorphicUnoType polymorphicUnoType):
478 m_kind(KIND_PARAMETER), m_name(std::move(parameterName)),
479 m_flags(translateSpecialTypeFlags(specialType, inParameter, outParameter)),
480 m_index(index), m_methodName(std::move(methodName)),
481 m_polymorphicUnoType(std::move(polymorphicUnoType)),
482 m_typeParameterIndex(0)
485 sal_uInt16 TypeInfo::generateCode(
486 ClassFile::Code & code, std::set<OUString> * dependencies) const
488 switch (m_kind) {
489 case KIND_MEMBER:
490 code.instrNew("com/sun/star/lib/uno/typeinfo/MemberTypeInfo"_ostr);
491 code.instrDup();
492 code.loadStringConstant(m_name);
493 code.loadIntegerConstant(m_index);
494 code.loadIntegerConstant(m_flags);
495 if (m_polymorphicUnoType.kind != PolymorphicUnoType::KIND_NONE) {
496 generatePolymorphicUnoTypeCode(code, dependencies);
497 code.loadIntegerConstant(m_typeParameterIndex);
498 code.instrInvokespecial(
499 "com/sun/star/lib/uno/typeinfo/MemberTypeInfo"_ostr, "<init>"_ostr,
500 "(Ljava/lang/String;IILcom/sun/star/uno/Type;I)V"_ostr);
501 return 8;
502 } else if (m_typeParameterIndex >= 0) {
503 code.instrAconstNull();
504 code.loadIntegerConstant(m_typeParameterIndex);
505 code.instrInvokespecial(
506 "com/sun/star/lib/uno/typeinfo/MemberTypeInfo"_ostr, "<init>"_ostr,
507 "(Ljava/lang/String;IILcom/sun/star/uno/Type;I)V"_ostr);
508 return 6;
509 } else {
510 code.instrInvokespecial(
511 "com/sun/star/lib/uno/typeinfo/MemberTypeInfo"_ostr, "<init>"_ostr,
512 "(Ljava/lang/String;II)V"_ostr);
513 return 4;
515 case KIND_ATTRIBUTE:
516 code.instrNew("com/sun/star/lib/uno/typeinfo/AttributeTypeInfo"_ostr);
517 code.instrDup();
518 code.loadStringConstant(m_name);
519 code.loadIntegerConstant(m_index);
520 code.loadIntegerConstant(m_flags);
521 if (m_polymorphicUnoType.kind != PolymorphicUnoType::KIND_NONE) {
522 generatePolymorphicUnoTypeCode(code, dependencies);
523 code.instrInvokespecial(
524 "com/sun/star/lib/uno/typeinfo/AttributeTypeInfo"_ostr, "<init>"_ostr,
525 "(Ljava/lang/String;IILcom/sun/star/uno/Type;)V"_ostr);
526 return 8;
527 } else {
528 code.instrInvokespecial(
529 "com/sun/star/lib/uno/typeinfo/AttributeTypeInfo"_ostr, "<init>"_ostr,
530 "(Ljava/lang/String;II)V"_ostr);
531 return 4;
533 case KIND_METHOD:
534 code.instrNew("com/sun/star/lib/uno/typeinfo/MethodTypeInfo"_ostr);
535 code.instrDup();
536 code.loadStringConstant(m_name);
537 code.loadIntegerConstant(m_index);
538 code.loadIntegerConstant(m_flags);
539 if (m_polymorphicUnoType.kind != PolymorphicUnoType::KIND_NONE) {
540 generatePolymorphicUnoTypeCode(code, dependencies);
541 code.instrInvokespecial(
542 "com/sun/star/lib/uno/typeinfo/MethodTypeInfo"_ostr, "<init>"_ostr,
543 "(Ljava/lang/String;IILcom/sun/star/uno/Type;)V"_ostr);
544 return 8;
545 } else {
546 code.instrInvokespecial(
547 "com/sun/star/lib/uno/typeinfo/MethodTypeInfo"_ostr, "<init>"_ostr,
548 "(Ljava/lang/String;II)V"_ostr);
549 return 4;
551 case KIND_PARAMETER:
552 code.instrNew("com/sun/star/lib/uno/typeinfo/ParameterTypeInfo"_ostr);
553 code.instrDup();
554 code.loadStringConstant(m_name);
555 code.loadStringConstant(m_methodName);
556 code.loadIntegerConstant(m_index);
557 code.loadIntegerConstant(m_flags);
558 if (m_polymorphicUnoType.kind != PolymorphicUnoType::KIND_NONE) {
559 generatePolymorphicUnoTypeCode(code, dependencies);
560 code.instrInvokespecial(
561 "com/sun/star/lib/uno/typeinfo/ParameterTypeInfo"_ostr, "<init>"_ostr,
562 ("(Ljava/lang/String;Ljava/lang/String;II"
563 "Lcom/sun/star/uno/Type;)V"_ostr));
564 return 9;
565 } else {
566 code.instrInvokespecial(
567 "com/sun/star/lib/uno/typeinfo/ParameterTypeInfo"_ostr, "<init>"_ostr,
568 "(Ljava/lang/String;Ljava/lang/String;II)V"_ostr);
569 return 5;
571 default:
572 assert(false);
573 return 0;
577 void TypeInfo::generatePolymorphicUnoTypeCode(
578 ClassFile::Code & code, std::set<OUString> * dependencies) const
580 assert(dependencies != nullptr);
581 assert(m_polymorphicUnoType.kind != PolymorphicUnoType::KIND_NONE);
582 code.instrNew("com/sun/star/uno/Type"_ostr);
583 code.instrDup();
584 code.loadStringConstant(
585 codemaker::convertString(m_polymorphicUnoType.name));
586 if (m_polymorphicUnoType.kind == PolymorphicUnoType::KIND_STRUCT) {
587 code.instrGetstatic(
588 "com/sun/star/uno/TypeClass"_ostr, "STRUCT"_ostr,
589 "Lcom/sun/star/uno/TypeClass;"_ostr);
590 } else {
591 code.instrGetstatic(
592 "com/sun/star/uno/TypeClass"_ostr, "SEQUENCE"_ostr,
593 "Lcom/sun/star/uno/TypeClass;"_ostr);
595 dependencies->insert(u"com.sun.star.uno.TypeClass"_ustr);
596 code.instrInvokespecial(
597 "com/sun/star/uno/Type"_ostr, "<init>"_ostr,
598 "(Ljava/lang/String;Lcom/sun/star/uno/TypeClass;)V"_ostr);
601 void writeClassFile(
602 JavaOptions const & options, OString const & type,
603 ClassFile const & classFile)
605 OString path;
606 if (options.isValid("-O"_ostr)) {
607 path = options.getOption("-O"_ostr);
609 OString filename(createFileNameFromType(path, type, ".class"_ostr));
610 bool bCheck = false;
611 if (fileExists(filename)) {
612 if (options.isValid("-G"_ostr)) {
613 return;
615 bCheck = options.isValid("-Gc"_ostr);
617 FileStream tempfile;
618 tempfile.createTempFile(getTempDir(filename));
619 if (!tempfile.isValid()) {
620 throw CannotDumpException(
621 "Cannot create temporary file for " + b2u(filename));
623 OString tempname(tempfile.getName());
624 try {
625 classFile.write(tempfile);
626 } catch (...) {
627 // Remove existing file for consistency:
628 if (fileExists(filename)) {
629 removeTypeFile(filename);
631 tempfile.close();
632 removeTypeFile(tempname);
633 throw;
635 tempfile.close();
636 if (!makeValidTypeFile(filename, tempname, bCheck)) {
637 throw CannotDumpException(
638 "Cannot create " + b2u(filename) + " from temporary file "
639 + b2u(tempname));
643 void addTypeInfo(
644 OString const & className, std::vector< TypeInfo > const & typeInfo,
645 std::set<OUString> * dependencies, ClassFile * classFile)
647 assert(classFile != nullptr);
648 std::vector< TypeInfo >::size_type typeInfos = typeInfo.size();
649 if (typeInfos > SAL_MAX_INT32) {
650 throw CannotDumpException(
651 u"UNOTYPEINFO array too big for Java class file format"_ustr);
653 if (typeInfos == 0)
654 return;
656 classFile->addField(
657 static_cast< ClassFile::AccessFlags >(
658 ClassFile::ACC_PUBLIC | ClassFile::ACC_STATIC
659 | ClassFile::ACC_FINAL),
660 "UNOTYPEINFO"_ostr, "[Lcom/sun/star/lib/uno/typeinfo/TypeInfo;"_ostr,
661 0, ""_ostr);
662 std::unique_ptr< ClassFile::Code > code(classFile->newCode());
663 code->loadIntegerConstant(static_cast< sal_Int32 >(typeInfos));
664 code->instrAnewarray("com/sun/star/lib/uno/typeinfo/TypeInfo"_ostr);
665 sal_Int32 index = 0;
666 sal_uInt16 stack = 0;
667 for (const TypeInfo& ti : typeInfo)
669 code->instrDup();
670 code->loadIntegerConstant(index++);
671 stack = std::max(stack, ti.generateCode(*code, dependencies));
672 code->instrAastore();
674 code->instrPutstatic(
675 className, "UNOTYPEINFO"_ostr,
676 "[Lcom/sun/star/lib/uno/typeinfo/TypeInfo;"_ostr);
677 code->instrReturn();
678 if (stack > SAL_MAX_UINT16 - 4) {
679 throw CannotDumpException(
680 u"Stack too big for Java class file format"_ustr);
682 code->setMaxStackAndLocals(static_cast< sal_uInt16 >(stack + 4), 0);
683 classFile->addMethod(
684 static_cast< ClassFile::AccessFlags >(
685 ClassFile::ACC_PRIVATE | ClassFile::ACC_STATIC),
686 "<clinit>"_ostr, "()V"_ostr, code.get(), std::vector< OString >(), ""_ostr);
689 void handleEnumType(
690 const OUString& name, rtl::Reference< unoidl::EnumTypeEntity > const & entity,
691 JavaOptions const & options)
693 assert(entity.is());
694 OString className(codemaker::convertString(name).replace('.', '/'));
695 std::unique_ptr< ClassFile > cf(
696 new ClassFile(
697 static_cast< ClassFile::AccessFlags >(
698 ClassFile::ACC_PUBLIC | ClassFile::ACC_FINAL
699 | ClassFile::ACC_SUPER),
700 className, "com/sun/star/uno/Enum"_ostr, ""_ostr));
701 OString classDescriptor("L" + className + ";");
702 for (const unoidl::EnumTypeEntity::Member& member : entity->getMembers())
704 OString fieldName(codemaker::convertString(member.name));
705 cf->addField(
706 static_cast< ClassFile::AccessFlags >(
707 ClassFile::ACC_PUBLIC | ClassFile::ACC_STATIC
708 | ClassFile::ACC_FINAL),
709 fieldName, classDescriptor, 0, OString());
710 cf->addField(
711 static_cast< ClassFile::AccessFlags >(
712 ClassFile::ACC_PUBLIC | ClassFile::ACC_STATIC
713 | ClassFile::ACC_FINAL),
714 fieldName + "_value", "I"_ostr,
715 cf->addIntegerInfo(member.value), ""_ostr);
717 std::unique_ptr< ClassFile::Code > code(cf->newCode());
718 code->loadLocalReference(0);
719 code->loadLocalInteger(1);
720 code->instrInvokespecial("com/sun/star/uno/Enum"_ostr, "<init>"_ostr, "(I)V"_ostr);
721 code->instrReturn();
722 code->setMaxStackAndLocals(2, 2);
723 cf->addMethod(
724 ClassFile::ACC_PRIVATE,
725 "<init>"_ostr, "(I)V"_ostr, code.get(),
726 std::vector< OString >(), ""_ostr);
727 code = cf->newCode();
728 code->instrGetstatic(
729 className,
730 codemaker::convertString(entity->getMembers()[0].name),
731 classDescriptor);
732 code->instrAreturn();
733 code->setMaxStackAndLocals(1, 0);
734 cf->addMethod(
735 static_cast< ClassFile::AccessFlags >(
736 ClassFile::ACC_PUBLIC | ClassFile::ACC_STATIC),
737 "getDefault"_ostr, "()" + classDescriptor,
738 code.get(), std::vector< OString >(), ""_ostr);
739 code = cf->newCode();
740 code->loadLocalInteger(0);
741 std::map< sal_Int32, OString > map;
742 sal_Int32 min = SAL_MAX_INT32;
743 sal_Int32 max = SAL_MIN_INT32;
744 for (const unoidl::EnumTypeEntity::Member& member : entity->getMembers())
746 min = std::min(min, member.value);
747 max = std::max(max, member.value);
748 map.emplace(member.value, codemaker::convertString(member.name));
750 sal_uInt64 size = static_cast< sal_uInt64 >(map.size());
751 if ((static_cast< sal_uInt64 >(max) - static_cast< sal_uInt64 >(min)
752 <= 2 * size)
753 || size > SAL_MAX_INT32)
755 std::unique_ptr< ClassFile::Code > defCode(cf->newCode());
756 defCode->instrAconstNull();
757 defCode->instrAreturn();
758 std::vector< std::unique_ptr<ClassFile::Code> > blocks;
759 //FIXME: pointers contained in blocks may leak
760 sal_Int32 last = SAL_MAX_INT32;
761 for (const auto& pair : map)
763 sal_Int32 value = pair.first;
764 if (last != SAL_MAX_INT32) {
765 for (sal_Int32 j = last + 1; j < value; ++j) {
766 blocks.push_back(nullptr);
769 last = value;
770 std::unique_ptr< ClassFile::Code > blockCode(cf->newCode());
771 blockCode->instrGetstatic(className, pair.second, classDescriptor);
772 blockCode->instrAreturn();
773 blocks.push_back(std::move(blockCode));
775 code->instrTableswitch(defCode.get(), min, blocks);
776 } else{
777 std::unique_ptr< ClassFile::Code > defCode(cf->newCode());
778 defCode->instrAconstNull();
779 defCode->instrAreturn();
780 std::vector< std::pair< sal_Int32, ClassFile::Code * > > blocks;
781 //FIXME: pointers contained in blocks may leak
782 for (const auto& pair : map )
784 std::unique_ptr< ClassFile::Code > blockCode(cf->newCode());
785 blockCode->instrGetstatic(className, pair.second, classDescriptor);
786 blockCode->instrAreturn();
787 blocks.emplace_back(pair.first, blockCode.release());
789 code->instrLookupswitch(defCode.get(), blocks);
790 for (const std::pair< sal_Int32, ClassFile::Code * >& pair : blocks)
792 delete pair.second;
795 code->setMaxStackAndLocals(1, 1);
796 cf->addMethod(
797 static_cast< ClassFile::AccessFlags >(
798 ClassFile::ACC_PUBLIC | ClassFile::ACC_STATIC),
799 "fromInt"_ostr, "(I)" + classDescriptor, code.get(),
800 std::vector< OString >(), ""_ostr);
801 code = cf->newCode();
802 for (const unoidl::EnumTypeEntity::Member& member : entity->getMembers())
804 code->instrNew(className);
805 code->instrDup();
806 code->loadIntegerConstant(member.value);
807 code->instrInvokespecial(className, "<init>"_ostr, "(I)V"_ostr);
808 code->instrPutstatic(
809 className, codemaker::convertString(member.name), classDescriptor);
811 code->instrReturn();
812 code->setMaxStackAndLocals(3, 0);
813 cf->addMethod(
814 static_cast< ClassFile::AccessFlags >(
815 ClassFile::ACC_PRIVATE | ClassFile::ACC_STATIC),
816 "<clinit>"_ostr, "()V"_ostr, code.get(), std::vector< OString >(), ""_ostr);
817 writeClassFile(options, className, *cf);
820 void addField(
821 rtl::Reference< TypeManager > const & manager, std::set<OUString> * dependencies,
822 ClassFile * classFile, std::vector< TypeInfo > * typeInfo,
823 sal_Int32 typeParameterIndex, OUString const & type, OUString const & name,
824 sal_Int32 index)
826 assert(classFile != nullptr);
827 assert(typeInfo != nullptr);
828 OString descriptor;
829 OString signature;
830 SpecialType specialType;
831 PolymorphicUnoType polymorphicUnoType;
832 if (typeParameterIndex >= 0) {
833 descriptor = "Ljava/lang/Object;"_ostr;
834 signature = "T" + codemaker::convertString(type).replace('.', '/')
835 + ";";
836 specialType = SPECIAL_TYPE_NONE; //TODO: SPECIAL_TYPE_TYPE_PARAMETER?
837 } else {
838 specialType = getFieldDescriptor(
839 manager, dependencies, type, &descriptor, &signature,
840 &polymorphicUnoType);
842 classFile->addField(
843 ClassFile::ACC_PUBLIC, codemaker::convertString(name), descriptor, 0,
844 signature);
845 typeInfo->push_back(
846 TypeInfo(
847 codemaker::convertString(name), specialType, index,
848 polymorphicUnoType, typeParameterIndex));
851 sal_uInt16 addFieldInit(
852 rtl::Reference< TypeManager > const & manager, OString const & className,
853 OUString const & fieldName, bool typeParameter, std::u16string_view fieldType,
854 std::set<OUString> * dependencies, ClassFile::Code * code)
856 assert(manager.is());
857 assert(code != nullptr);
858 if (typeParameter) {
859 return 0;
861 OString name(codemaker::convertString(fieldName));
862 OUString nucleus;
863 sal_Int32 rank;
864 std::vector< OUString > args;
865 rtl::Reference< unoidl::Entity > ent;
866 codemaker::UnoType::Sort sort = manager->decompose(
867 fieldType, true, &nucleus, &rank, &args, &ent);
868 if (rank == 0) {
869 switch (sort) {
870 case codemaker::UnoType::Sort::Boolean:
871 case codemaker::UnoType::Sort::Byte:
872 case codemaker::UnoType::Sort::Short:
873 case codemaker::UnoType::Sort::UnsignedShort:
874 case codemaker::UnoType::Sort::Long:
875 case codemaker::UnoType::Sort::UnsignedLong:
876 case codemaker::UnoType::Sort::Hyper:
877 case codemaker::UnoType::Sort::UnsignedHyper:
878 case codemaker::UnoType::Sort::Float:
879 case codemaker::UnoType::Sort::Double:
880 case codemaker::UnoType::Sort::Char:
881 case codemaker::UnoType::Sort::Interface:
882 return 0;
883 case codemaker::UnoType::Sort::String:
884 code->loadLocalReference(0);
885 code->loadStringConstant(OString());
886 code->instrPutfield(className, name, "Ljava/lang/String;"_ostr);
887 return 2;
888 case codemaker::UnoType::Sort::Type:
889 code->loadLocalReference(0);
890 code->instrGetstatic(
891 "com/sun/star/uno/Type"_ostr, "VOID"_ostr, "Lcom/sun/star/uno/Type;"_ostr);
892 code->instrPutfield(className, name, "Lcom/sun/star/uno/Type;"_ostr);
893 return 2;
894 case codemaker::UnoType::Sort::Any:
895 code->loadLocalReference(0);
896 code->instrGetstatic(
897 "com/sun/star/uno/Any"_ostr, "VOID"_ostr, "Lcom/sun/star/uno/Any;"_ostr);
898 code->instrPutfield(className, name, "Ljava/lang/Object;"_ostr);
899 return 2;
900 case codemaker::UnoType::Sort::Enum:
902 rtl::Reference< unoidl::EnumTypeEntity > ent2(
903 dynamic_cast< unoidl::EnumTypeEntity * >(ent.get()));
904 assert(ent2.is());
905 code->loadLocalReference(0);
906 OStringBuffer descBuf(128);
907 translateUnoTypeToDescriptor(
908 manager, sort, nucleus, 0, std::vector< OUString >(), false,
909 false, dependencies, &descBuf, nullptr, nullptr, nullptr);
910 OString desc(descBuf.makeStringAndClear());
911 code->instrGetstatic(
912 codemaker::convertString(nucleus).replace('.', '/'),
913 codemaker::convertString(ent2->getMembers()[0].name), desc);
914 code->instrPutfield(className, name, desc);
915 return 2;
917 case codemaker::UnoType::Sort::PlainStruct:
918 case codemaker::UnoType::Sort::InstantiatedPolymorphicStruct:
920 code->loadLocalReference(0);
921 code->instrNew(
922 codemaker::convertString(nucleus).replace('.', '/'));
923 code->instrDup();
924 code->instrInvokespecial(
925 codemaker::convertString(nucleus).replace('.', '/'),
926 "<init>"_ostr, "()V"_ostr);
927 OStringBuffer desc(128);
928 translateUnoTypeToDescriptor(
929 manager, sort, nucleus, 0, args, false, false, dependencies,
930 &desc, nullptr, nullptr, nullptr);
931 code->instrPutfield(className, name, desc.makeStringAndClear());
932 return 3;
934 case codemaker::UnoType::Sort::Sequence:
935 case codemaker::UnoType::Sort::Typedef:
936 for (;;) std::abort(); // this cannot happen
937 default:
938 throw CannotDumpException(
939 OUString::Concat("unexpected entity \"") + fieldType
940 + "\" in call to addFieldInit");
943 code->loadLocalReference(0);
944 code->loadIntegerConstant(0);
945 if (rank == 1) {
946 if (sort >= codemaker::UnoType::Sort::Boolean
947 && sort <= codemaker::UnoType::Sort::Char)
949 code->instrNewarray(sort);
950 } else {
951 code->instrAnewarray(
952 codemaker::java::translateUnoToJavaType(
953 sort, codemaker::convertString(nucleus).replace('.', '/'),
954 false));
956 } else {
957 OStringBuffer desc(128);
958 translateUnoTypeToDescriptor(
959 manager, sort, nucleus, rank - 1, std::vector< OUString >(), false,
960 false, dependencies, &desc, nullptr, nullptr, nullptr);
961 code->instrAnewarray(desc.makeStringAndClear());
963 OStringBuffer desc(128);
964 translateUnoTypeToDescriptor(
965 manager, sort, nucleus, rank, std::vector< OUString >(), false, false,
966 dependencies, &desc, nullptr, nullptr, nullptr);
967 code->instrPutfield(className, name, desc.makeStringAndClear());
968 return 2;
971 sal_uInt16 addLoadLocal(
972 rtl::Reference< TypeManager > const & manager, ClassFile::Code * code,
973 sal_uInt16 * index, bool typeParameter, std::u16string_view type, bool any,
974 std::set<OUString> * dependencies)
976 assert(manager.is());
977 assert(code != nullptr);
978 assert(index != nullptr);
979 assert(!(typeParameter && any));
980 assert(dependencies != nullptr);
981 sal_uInt16 stack = 1;
982 sal_uInt16 size = 1;
983 if (typeParameter) {
984 code->loadLocalReference(*index);
985 stack = size = 1;
986 } else {
987 OUString nucleus;
988 sal_Int32 rank;
989 std::vector< OUString > args;
990 codemaker::UnoType::Sort sort = manager->decompose(
991 type, true, &nucleus, &rank, &args, nullptr);
992 if (rank == 0) {
993 switch (sort) {
994 case codemaker::UnoType::Sort::Boolean:
995 if (any) {
996 code->instrNew("java/lang/Boolean"_ostr);
997 code->instrDup();
998 code->loadLocalInteger(*index);
999 code->instrInvokespecial(
1000 "java/lang/Boolean"_ostr, "<init>"_ostr, "(Z)V"_ostr);
1001 stack = 3;
1002 } else {
1003 code->loadLocalInteger(*index);
1004 stack = 1;
1006 size = 1;
1007 break;
1008 case codemaker::UnoType::Sort::Byte:
1009 if (any) {
1010 code->instrNew("java/lang/Byte"_ostr);
1011 code->instrDup();
1012 code->loadLocalInteger(*index);
1013 code->instrInvokespecial(
1014 "java/lang/Byte"_ostr, "<init>"_ostr, "(B)V"_ostr);
1015 stack = 3;
1016 } else {
1017 code->loadLocalInteger(*index);
1018 stack = 1;
1020 size = 1;
1021 break;
1022 case codemaker::UnoType::Sort::Short:
1023 if (any) {
1024 code->instrNew("java/lang/Short"_ostr);
1025 code->instrDup();
1026 code->loadLocalInteger(*index);
1027 code->instrInvokespecial(
1028 "java/lang/Short"_ostr, "<init>"_ostr, "(S)V"_ostr);
1029 stack = 3;
1030 } else {
1031 code->loadLocalInteger(*index);
1032 stack = 1;
1034 size = 1;
1035 break;
1036 case codemaker::UnoType::Sort::UnsignedShort:
1037 if (any) {
1038 code->instrNew("com/sun/star/uno/Any"_ostr);
1039 code->instrDup();
1040 code->instrGetstatic(
1041 "com/sun/star/uno/Type"_ostr, "UNSIGNED_SHORT"_ostr,
1042 "Lcom/sun/star/uno/Type;"_ostr);
1043 code->instrNew("java/lang/Short"_ostr);
1044 code->instrDup();
1045 code->loadLocalInteger(*index);
1046 code->instrInvokespecial(
1047 "java/lang/Short"_ostr, "<init>"_ostr, "(S)V"_ostr);
1048 code->instrInvokespecial(
1049 "com/sun/star/uno/Any"_ostr, "<init>"_ostr,
1050 "(Lcom/sun/star/uno/Type;Ljava/lang/Object;)V"_ostr);
1051 stack = 6;
1052 } else {
1053 code->loadLocalInteger(*index);
1054 stack = 1;
1056 size = 1;
1057 break;
1058 case codemaker::UnoType::Sort::Long:
1059 if (any) {
1060 code->instrNew("java/lang/Integer"_ostr);
1061 code->instrDup();
1062 code->loadLocalInteger(*index);
1063 code->instrInvokespecial(
1064 "java/lang/Integer"_ostr, "<init>"_ostr, "(I)V"_ostr);
1065 stack = 3;
1066 } else {
1067 code->loadLocalInteger(*index);
1068 stack = 1;
1070 size = 1;
1071 break;
1072 case codemaker::UnoType::Sort::UnsignedLong:
1073 if (any) {
1074 code->instrNew("com/sun/star/uno/Any"_ostr);
1075 code->instrDup();
1076 code->instrGetstatic(
1077 "com/sun/star/uno/Type"_ostr, "UNSIGNED_LONG"_ostr,
1078 "Lcom/sun/star/uno/Type;"_ostr);
1079 code->instrNew("java/lang/Integer"_ostr);
1080 code->instrDup();
1081 code->loadLocalInteger(*index);
1082 code->instrInvokespecial(
1083 "java/lang/Integer"_ostr, "<init>"_ostr, "(I)V"_ostr);
1084 code->instrInvokespecial(
1085 "com/sun/star/uno/Any"_ostr, "<init>"_ostr,
1086 "(Lcom/sun/star/uno/Type;Ljava/lang/Object;)V"_ostr);
1087 stack = 6;
1088 } else {
1089 code->loadLocalInteger(*index);
1090 stack = 1;
1092 size = 1;
1093 break;
1094 case codemaker::UnoType::Sort::Hyper:
1095 if (any) {
1096 code->instrNew("java/lang/Long"_ostr);
1097 code->instrDup();
1098 code->loadLocalLong(*index);
1099 code->instrInvokespecial(
1100 "java/lang/Long"_ostr, "<init>"_ostr, "(J)V"_ostr);
1101 stack = 4;
1102 } else {
1103 code->loadLocalLong(*index);
1104 stack = 2;
1106 size = 2;
1107 break;
1108 case codemaker::UnoType::Sort::UnsignedHyper:
1109 if (any) {
1110 code->instrNew("com/sun/star/uno/Any"_ostr);
1111 code->instrDup();
1112 code->instrGetstatic(
1113 "com/sun/star/uno/Type"_ostr, "UNSIGNED_HYPER"_ostr,
1114 "Lcom/sun/star/uno/Type;"_ostr);
1115 code->instrNew("java/lang/Long"_ostr);
1116 code->instrDup();
1117 code->loadLocalLong(*index);
1118 code->instrInvokespecial(
1119 "java/lang/Long"_ostr, "<init>"_ostr, "(J)V"_ostr);
1120 code->instrInvokespecial(
1121 "com/sun/star/uno/Any"_ostr, "<init>"_ostr,
1122 "(Lcom/sun/star/uno/Type;Ljava/lang/Object;)V"_ostr);
1123 stack = 7;
1124 } else {
1125 code->loadLocalLong(*index);
1126 stack = 2;
1128 size = 2;
1129 break;
1130 case codemaker::UnoType::Sort::Float:
1131 if (any) {
1132 code->instrNew("java/lang/Float"_ostr);
1133 code->instrDup();
1134 code->loadLocalFloat(*index);
1135 code->instrInvokespecial(
1136 "java/lang/Float"_ostr, "<init>"_ostr, "(F)V"_ostr);
1137 stack = 3;
1138 } else {
1139 code->loadLocalFloat(*index);
1140 stack = 1;
1142 size = 1;
1143 break;
1144 case codemaker::UnoType::Sort::Double:
1145 if (any) {
1146 code->instrNew("java/lang/Double"_ostr);
1147 code->instrDup();
1148 code->loadLocalDouble(*index);
1149 code->instrInvokespecial(
1150 "java/lang/Double"_ostr, "<init>"_ostr, "(D)V"_ostr);
1151 stack = 4;
1152 } else {
1153 code->loadLocalDouble(*index);
1154 stack = 2;
1156 size = 2;
1157 break;
1158 case codemaker::UnoType::Sort::Char:
1159 if (any) {
1160 code->instrNew("java/lang/Character"_ostr);
1161 code->instrDup();
1162 code->loadLocalInteger(*index);
1163 code->instrInvokespecial(
1164 "java/lang/Character"_ostr, "<init>"_ostr, "(C)V"_ostr);
1165 stack = 3;
1166 } else {
1167 code->loadLocalInteger(*index);
1168 stack = 1;
1170 size = 1;
1171 break;
1172 case codemaker::UnoType::Sort::String:
1173 case codemaker::UnoType::Sort::Type:
1174 case codemaker::UnoType::Sort::Any:
1175 code->loadLocalReference(*index);
1176 stack = size = 1;
1177 break;
1178 case codemaker::UnoType::Sort::Enum:
1179 // Assuming that no Java types are derived from Java types that
1180 // are directly derived from com.sun.star.uno.Enum:
1181 code->loadLocalReference(*index);
1182 stack = size = 1;
1183 break;
1184 case codemaker::UnoType::Sort::PlainStruct:
1185 case codemaker::UnoType::Sort::InstantiatedPolymorphicStruct:
1186 if (any) {
1187 code->instrNew("com/sun/star/uno/Any"_ostr);
1188 code->instrDup();
1189 code->instrNew("com/sun/star/uno/Type"_ostr);
1190 code->instrDup();
1191 code->loadStringConstant(
1192 codemaker::convertString(
1193 createUnoName(manager, nucleus, rank, args)));
1194 code->instrGetstatic(
1195 "com/sun/star/uno/TypeClass"_ostr, "STRUCT"_ostr,
1196 "Lcom/sun/star/uno/TypeClass;"_ostr);
1197 dependencies->insert(u"com.sun.star.uno.TypeClass"_ustr);
1198 code->instrInvokespecial(
1199 "com/sun/star/uno/Type"_ostr, "<init>"_ostr,
1200 "(Ljava/lang/String;Lcom/sun/star/uno/TypeClass;)V"_ostr);
1201 code->loadLocalReference(*index);
1202 code->instrInvokespecial(
1203 "com/sun/star/uno/Any"_ostr, "<init>"_ostr,
1204 "(Lcom/sun/star/uno/Type;Ljava/lang/Object;)V"_ostr);
1205 stack = 6;
1206 } else {
1207 code->loadLocalReference(*index);
1208 stack = 1;
1210 size = 1;
1211 break;
1212 case codemaker::UnoType::Sort::Interface:
1213 if (any && nucleus != "com.sun.star.uno.XInterface") {
1214 code->instrNew("com/sun/star/uno/Any"_ostr);
1215 code->instrDup();
1216 code->instrNew("com/sun/star/uno/Type"_ostr);
1217 code->instrDup();
1218 code->loadStringConstant(codemaker::convertString(nucleus));
1219 code->instrGetstatic(
1220 "com/sun/star/uno/TypeClass"_ostr, "INTERFACE"_ostr,
1221 "Lcom/sun/star/uno/TypeClass;"_ostr);
1222 dependencies->insert(u"com.sun.star.uno.TypeClass"_ustr);
1223 code->instrInvokespecial(
1224 "com/sun/star/uno/Type"_ostr, "<init>"_ostr,
1225 "(Ljava/lang/String;Lcom/sun/star/uno/TypeClass;)V"_ostr);
1226 code->loadLocalReference(*index);
1227 code->instrInvokespecial(
1228 "com/sun/star/uno/Any"_ostr, "<init>"_ostr,
1229 "(Lcom/sun/star/uno/Type;Ljava/lang/Object;)V"_ostr);
1230 stack = 6;
1231 } else {
1232 code->loadLocalReference(*index);
1233 stack = 1;
1235 size = 1;
1236 break;
1237 case codemaker::UnoType::Sort::Sequence:
1238 case codemaker::UnoType::Sort::Typedef:
1239 for (;;) std::abort(); // this cannot happen
1240 default:
1241 throw CannotDumpException(
1242 OUString::Concat("unexpected entity \"") + type
1243 + "\" in call to addLoadLocal");
1245 } else {
1246 bool bWrap = false;
1247 if (any) {
1248 switch (sort) {
1249 case codemaker::UnoType::Sort::Boolean:
1250 case codemaker::UnoType::Sort::Byte:
1251 case codemaker::UnoType::Sort::Short:
1252 case codemaker::UnoType::Sort::Long:
1253 case codemaker::UnoType::Sort::Hyper:
1254 case codemaker::UnoType::Sort::Float:
1255 case codemaker::UnoType::Sort::Double:
1256 case codemaker::UnoType::Sort::Char:
1257 case codemaker::UnoType::Sort::String:
1258 case codemaker::UnoType::Sort::Type:
1259 // assuming that no Java types are derived from
1260 // com.sun.star.uno.Type
1261 case codemaker::UnoType::Sort::Enum:
1262 // assuming that no Java types are derived from Java
1263 // types that are directly derived from
1264 // com.sun.star.uno.Enum
1265 break;
1266 case codemaker::UnoType::Sort::UnsignedShort:
1267 case codemaker::UnoType::Sort::UnsignedLong:
1268 case codemaker::UnoType::Sort::UnsignedHyper:
1269 case codemaker::UnoType::Sort::Any:
1270 case codemaker::UnoType::Sort::PlainStruct:
1271 case codemaker::UnoType::Sort::InstantiatedPolymorphicStruct:
1272 case codemaker::UnoType::Sort::Interface:
1273 bWrap = true;
1274 break;
1275 case codemaker::UnoType::Sort::Sequence:
1276 case codemaker::UnoType::Sort::Typedef:
1277 for (;;) std::abort(); // this cannot happen
1278 default:
1279 throw CannotDumpException(
1280 OUString::Concat("unexpected entity \"") + type
1281 + "\" in call to addLoadLocal");
1284 if (bWrap) {
1285 code->instrNew("com/sun/star/uno/Any"_ostr);
1286 code->instrDup();
1287 code->instrNew("com/sun/star/uno/Type"_ostr);
1288 code->instrDup();
1289 code->loadStringConstant(
1290 codemaker::convertString(
1291 createUnoName(manager, nucleus, rank, args)));
1292 code->instrInvokespecial(
1293 "com/sun/star/uno/Type"_ostr, "<init>"_ostr, "(Ljava/lang/String;)V"_ostr);
1294 code->loadLocalReference(*index);
1295 code->instrInvokespecial(
1296 "com/sun/star/uno/Any"_ostr, "<init>"_ostr,
1297 "(Lcom/sun/star/uno/Type;Ljava/lang/Object;)V"_ostr);
1298 stack = 5;
1299 } else {
1300 code->loadLocalReference(*index);
1301 stack = 1;
1303 size = 1;
1306 if (*index > SAL_MAX_UINT16 - size) {
1307 throw CannotDumpException(
1308 u"Too many local variables for Java class file format"_ustr);
1310 *index = *index + size;
1311 return stack;
1314 sal_uInt16 addDirectArgument(
1315 rtl::Reference< TypeManager > const & manager, std::set<OUString> * dependencies,
1316 MethodDescriptor * methodDescriptor, ClassFile::Code * code,
1317 sal_uInt16 * index, OString const & className, OString const & fieldName,
1318 bool typeParameter, OUString const & fieldType)
1320 assert(methodDescriptor != nullptr);
1321 assert(code != nullptr);
1322 OString desc;
1323 if (typeParameter) {
1324 methodDescriptor->addTypeParameter(fieldType);
1325 desc = "Ljava/lang/Object;"_ostr;
1326 } else {
1327 methodDescriptor->addParameter(fieldType, false, true, nullptr);
1328 getFieldDescriptor(manager, dependencies, fieldType, &desc, nullptr, nullptr);
1330 code->loadLocalReference(0);
1331 sal_uInt16 stack = addLoadLocal(
1332 manager, code, index, typeParameter, fieldType, false, dependencies);
1333 code->instrPutfield(className, fieldName, desc);
1334 return stack + 1;
1337 void addPlainStructBaseArguments(
1338 rtl::Reference< TypeManager > const & manager, std::set<OUString> * dependencies,
1339 MethodDescriptor * methodDescriptor, ClassFile::Code * code,
1340 OUString const & base, sal_uInt16 * index)
1342 assert(manager.is());
1343 assert(methodDescriptor != nullptr);
1344 rtl::Reference< unoidl::Entity > ent;
1345 if (manager->getSort(base, &ent)
1346 != codemaker::UnoType::Sort::PlainStruct)
1348 throw CannotDumpException(
1349 "unexpected entity \"" + base
1350 + "\" in call to addPlainStructBaseArguments");
1352 unoidl::PlainStructTypeEntity& ent2(dynamic_cast<unoidl::PlainStructTypeEntity&>(*ent));
1353 if (!ent2.getDirectBase().isEmpty()) {
1354 addPlainStructBaseArguments(
1355 manager, dependencies, methodDescriptor, code,
1356 ent2.getDirectBase(), index);
1358 for (const unoidl::PlainStructTypeEntity::Member& member : ent2.getDirectMembers())
1360 methodDescriptor->addParameter(member.type, false, true, nullptr);
1361 addLoadLocal(manager, code, index, false, member.type, false, dependencies);
1365 void handlePlainStructType(
1366 const OUString& name,
1367 rtl::Reference< unoidl::PlainStructTypeEntity > const & entity,
1368 rtl::Reference< TypeManager > const & manager, JavaOptions const & options,
1369 std::set<OUString> * dependencies)
1371 assert(entity.is());
1372 assert(dependencies != nullptr);
1373 OString className(codemaker::convertString(name).replace('.', '/'));
1374 OString superClass;
1375 if (entity->getDirectBase().isEmpty()) {
1376 superClass = "java/lang/Object"_ostr;
1377 } else {
1378 superClass = codemaker::convertString(entity->getDirectBase()).
1379 replace('.', '/');
1380 dependencies->insert(entity->getDirectBase());
1382 std::unique_ptr< ClassFile > cf(
1383 new ClassFile(
1384 static_cast< ClassFile::AccessFlags >(
1385 ClassFile::ACC_PUBLIC | ClassFile::ACC_SUPER),
1386 className, superClass, ""_ostr));
1387 std::vector< TypeInfo > typeInfo;
1388 sal_Int32 index = 0;
1389 for (const unoidl::PlainStructTypeEntity::Member& member : entity->getDirectMembers())
1391 addField(
1392 manager, dependencies, cf.get(), &typeInfo, -1, member.type, member.name,
1393 index++);
1395 std::unique_ptr< ClassFile::Code > code(cf->newCode());
1396 code->loadLocalReference(0);
1397 code->instrInvokespecial(superClass, "<init>"_ostr, "()V"_ostr);
1398 sal_uInt16 stack = 0;
1399 for (const unoidl::PlainStructTypeEntity::Member& member : entity->getDirectMembers())
1401 stack = std::max(
1402 stack,
1403 addFieldInit(
1404 manager, className, member.name, false, member.type, dependencies,
1405 code.get()));
1407 code->instrReturn();
1408 code->setMaxStackAndLocals(stack + 1, 1);
1409 cf->addMethod(
1410 ClassFile::ACC_PUBLIC, "<init>"_ostr, "()V"_ostr, code.get(),
1411 std::vector< OString >(), ""_ostr);
1412 MethodDescriptor desc(manager, dependencies, u"void", nullptr, nullptr);
1413 code = cf->newCode();
1414 code->loadLocalReference(0);
1415 sal_uInt16 index2 = 1;
1416 if (!entity->getDirectBase().isEmpty()) {
1417 addPlainStructBaseArguments(
1418 manager, dependencies, &desc, code.get(), entity->getDirectBase(),
1419 &index2);
1421 code->instrInvokespecial(superClass, "<init>"_ostr, desc.getDescriptor());
1422 sal_uInt16 maxSize = index2;
1423 for (const unoidl::PlainStructTypeEntity::Member& member : entity->getDirectMembers())
1425 maxSize = std::max(
1426 maxSize,
1427 addDirectArgument(
1428 manager, dependencies, &desc, code.get(), &index2, className,
1429 codemaker::convertString(member.name), false, member.type));
1431 code->instrReturn();
1432 code->setMaxStackAndLocals(maxSize, index2);
1433 cf->addMethod(
1434 ClassFile::ACC_PUBLIC, "<init>"_ostr, desc.getDescriptor(), code.get(),
1435 std::vector< OString >(), desc.getSignature());
1436 addTypeInfo(className, typeInfo, dependencies, cf.get());
1437 writeClassFile(options, className, *cf);
1440 void handlePolyStructType(
1441 const OUString& name,
1442 rtl::Reference< unoidl::PolymorphicStructTypeTemplateEntity > const &
1443 entity,
1444 rtl::Reference< TypeManager > const & manager, JavaOptions const & options,
1445 std::set<OUString> * dependencies)
1447 assert(entity.is());
1448 OString className(codemaker::convertString(name).replace('.', '/'));
1449 std::map< OUString, sal_Int32 > typeParameters;
1450 OStringBuffer sig(128);
1451 sig.append("<");
1452 sal_Int32 index = 0;
1453 for (const OUString& param : entity->getTypeParameters())
1455 sig.append(codemaker::convertString(param) + ":Ljava/lang/Object;");
1456 if (!typeParameters.emplace(param, index++).second)
1458 throw CannotDumpException(u"Bad type information"_ustr); //TODO
1461 sig.append(">Ljava/lang/Object;");
1462 std::unique_ptr< ClassFile > cf(
1463 new ClassFile(
1464 static_cast< ClassFile::AccessFlags >(
1465 ClassFile::ACC_PUBLIC | ClassFile::ACC_SUPER),
1466 className, "java/lang/Object"_ostr, sig.makeStringAndClear()));
1467 std::vector< TypeInfo > typeInfo;
1468 index = 0;
1469 for (const unoidl::PolymorphicStructTypeTemplateEntity::Member& member : entity->getMembers())
1471 sal_Int32 typeParameterIndex;
1472 if (member.parameterized) {
1473 std::map< OUString, sal_Int32 >::iterator it(
1474 typeParameters.find(member.type));
1475 if (it == typeParameters.end()) {
1476 throw CannotDumpException(u"Bad type information"_ustr); //TODO
1478 typeParameterIndex = it->second;
1479 } else {
1480 typeParameterIndex = -1;
1482 addField(
1483 manager, dependencies, cf.get(), &typeInfo, typeParameterIndex,
1484 member.type, member.name, index++);
1486 std::unique_ptr< ClassFile::Code > code(cf->newCode());
1487 code->loadLocalReference(0);
1488 code->instrInvokespecial("java/lang/Object"_ostr, "<init>"_ostr, "()V"_ostr);
1489 sal_uInt16 stack = 0;
1490 for (const unoidl::PolymorphicStructTypeTemplateEntity::Member& member : entity->getMembers())
1492 stack = std::max(
1493 stack,
1494 addFieldInit(
1495 manager, className, member.name, member.parameterized, member.type,
1496 dependencies, code.get()));
1498 code->instrReturn();
1499 code->setMaxStackAndLocals(stack + 1, 1);
1500 cf->addMethod(
1501 ClassFile::ACC_PUBLIC, "<init>"_ostr, "()V"_ostr, code.get(),
1502 std::vector< OString >(), ""_ostr);
1503 MethodDescriptor desc(manager, dependencies, u"void", nullptr, nullptr);
1504 code = cf->newCode();
1505 code->loadLocalReference(0);
1506 sal_uInt16 index2 = 1;
1507 code->instrInvokespecial(
1508 "java/lang/Object"_ostr, "<init>"_ostr, desc.getDescriptor());
1509 sal_uInt16 maxSize = index2;
1510 for (const unoidl::PolymorphicStructTypeTemplateEntity::Member& member : entity->getMembers())
1512 maxSize = std::max(
1513 maxSize,
1514 addDirectArgument(
1515 manager, dependencies, &desc, code.get(), &index2, className,
1516 codemaker::convertString(member.name), member.parameterized, member.type));
1518 code->instrReturn();
1519 code->setMaxStackAndLocals(maxSize, index2);
1520 cf->addMethod(
1521 ClassFile::ACC_PUBLIC, "<init>"_ostr, desc.getDescriptor(), code.get(),
1522 std::vector< OString >(), desc.getSignature());
1523 addTypeInfo(className, typeInfo, dependencies, cf.get());
1524 writeClassFile(options, className, *cf);
1527 void addExceptionBaseArguments(
1528 rtl::Reference< TypeManager > const & manager, std::set<OUString> * dependencies,
1529 MethodDescriptor * methodDescriptor, ClassFile::Code * code,
1530 OUString const & base, sal_uInt16 * index)
1532 assert(manager.is());
1533 assert(methodDescriptor != nullptr);
1534 rtl::Reference< unoidl::Entity > ent;
1535 if (manager->getSort(base, &ent) != codemaker::UnoType::Sort::Exception)
1537 throw CannotDumpException(
1538 "unexpected entity \"" + base
1539 + "\" in call to addExceptionBaseArguments");
1541 unoidl::ExceptionTypeEntity& ent2(dynamic_cast<unoidl::ExceptionTypeEntity&>(*ent));
1542 bool baseException = base == "com.sun.star.uno.Exception";
1543 if (!baseException) {
1544 addExceptionBaseArguments(
1545 manager, dependencies, methodDescriptor, code,
1546 ent2.getDirectBase(), index);
1548 for (std::vector< unoidl::ExceptionTypeEntity::Member >::const_iterator i(
1549 ent2.getDirectMembers().begin());
1550 i != ent2.getDirectMembers().end(); ++i)
1552 if (!baseException || i != ent2.getDirectMembers().begin()) {
1553 methodDescriptor->addParameter(i->type, false, true, nullptr);
1554 addLoadLocal(
1555 manager, code, index, false, i->type, false, dependencies);
1560 void handleExceptionType(
1561 const OUString& name, rtl::Reference< unoidl::ExceptionTypeEntity > const & entity,
1562 rtl::Reference< TypeManager > const & manager, JavaOptions const & options,
1563 std::set<OUString> * dependencies)
1565 assert(entity.is());
1566 assert(dependencies != nullptr);
1567 OString className(codemaker::convertString(name).replace('.', '/'));
1568 bool baseException = false;
1569 bool baseRuntimeException = false;
1570 OString superClass;
1571 if (className == "com/sun/star/uno/Exception") {
1572 baseException = true;
1573 superClass = "java/lang/Exception"_ostr;
1574 } else if (className == "com/sun/star/uno/RuntimeException") {
1575 baseRuntimeException = true;
1576 superClass = "java/lang/RuntimeException"_ostr;
1577 } else {
1578 if (entity->getDirectBase().isEmpty()) {
1579 throw CannotDumpException(
1580 "Exception type \"" + name + "\" lacks base");
1582 superClass = codemaker::convertString(entity->getDirectBase()).
1583 replace('.', '/');
1584 dependencies->insert(entity->getDirectBase());
1586 std::unique_ptr< ClassFile > cf(
1587 new ClassFile(
1588 static_cast< ClassFile::AccessFlags >(
1589 ClassFile::ACC_PUBLIC | ClassFile::ACC_SUPER),
1590 className, superClass, ""_ostr));
1591 std::vector< TypeInfo > typeInfo;
1592 sal_Int32 index = 0;
1593 if (baseRuntimeException) {
1594 addField(
1595 manager, dependencies, cf.get(), &typeInfo, -1,
1596 u"com.sun.star.uno.XInterface"_ustr, u"Context"_ustr, index++);
1598 for (std::vector< unoidl::ExceptionTypeEntity::Member >::const_iterator i(
1599 entity->getDirectMembers().begin());
1600 i != entity->getDirectMembers().end(); ++i)
1602 if (!baseException || i != entity->getDirectMembers().begin()) {
1603 addField(
1604 manager, dependencies, cf.get(), &typeInfo, -1, i->type,
1605 i->name, index++);
1609 // create default constructor
1610 std::unique_ptr< ClassFile::Code > code(cf->newCode());
1611 code->loadLocalReference(0);
1612 code->instrInvokespecial(superClass, "<init>"_ostr, "()V"_ostr);
1613 sal_uInt16 stack = 0;
1614 if (baseRuntimeException) {
1615 stack = std::max(
1616 stack,
1617 addFieldInit(
1618 manager, className, u"Context"_ustr, false,
1619 u"com.sun.star.uno.XInterface", dependencies, code.get()));
1621 for (std::vector< unoidl::ExceptionTypeEntity::Member >::const_iterator i(
1622 entity->getDirectMembers().begin());
1623 i != entity->getDirectMembers().end(); ++i)
1625 if (!baseException || i != entity->getDirectMembers().begin()) {
1626 stack = std::max(
1627 stack,
1628 addFieldInit(
1629 manager, className, i->name, false, i->type, dependencies,
1630 code.get()));
1633 code->instrReturn();
1634 code->setMaxStackAndLocals(stack + 1, 1);
1635 cf->addMethod(
1636 ClassFile::ACC_PUBLIC, "<init>"_ostr, "()V"_ostr, code.get(),
1637 std::vector< OString >(), ""_ostr);
1640 // create (Throwable Cause) constructor
1641 code = cf->newCode();
1642 code->loadLocalReference(0);
1643 code->loadLocalReference(1);
1644 code->instrInvokespecial(superClass, "<init>"_ostr, "(Ljava/lang/Throwable;)V"_ostr);
1645 stack = 0;
1646 if (baseRuntimeException) {
1647 stack = std::max(
1648 stack,
1649 addFieldInit(
1650 manager, className, u"Context"_ustr, false,
1651 u"com.sun.star.uno.XInterface", dependencies, code.get()));
1653 for (std::vector< unoidl::ExceptionTypeEntity::Member >::const_iterator i(
1654 entity->getDirectMembers().begin());
1655 i != entity->getDirectMembers().end(); ++i)
1657 if (!baseException || i != entity->getDirectMembers().begin()) {
1658 stack = std::max(
1659 stack,
1660 addFieldInit(
1661 manager, className, i->name, false, i->type, dependencies,
1662 code.get()));
1665 code->instrReturn();
1666 code->setMaxStackAndLocals(stack + 2, 2);
1667 cf->addMethod(
1668 ClassFile::ACC_PUBLIC, "<init>"_ostr, "(Ljava/lang/Throwable;)V"_ostr, code.get(),
1669 std::vector< OString >(), ""_ostr);
1671 // create (Throwable Cause, String Message) constructor
1672 code = cf->newCode();
1673 code->loadLocalReference(0);
1674 if (baseException || baseRuntimeException) {
1675 code->loadLocalReference(2);
1676 code->loadLocalReference(1);
1677 code->instrInvokespecial(superClass, "<init>"_ostr, "(Ljava/lang/String;Ljava/lang/Throwable;)V"_ostr);
1678 } else {
1679 code->loadLocalReference(1);
1680 code->loadLocalReference(2);
1681 code->instrInvokespecial(superClass, "<init>"_ostr, "(Ljava/lang/Throwable;Ljava/lang/String;)V"_ostr);
1683 stack = 0;
1684 if (baseRuntimeException) {
1685 stack = std::max(
1686 stack,
1687 addFieldInit(
1688 manager, className, u"Context"_ustr, false,
1689 u"com.sun.star.uno.XInterface", dependencies, code.get()));
1691 for (std::vector< unoidl::ExceptionTypeEntity::Member >::const_iterator i(
1692 entity->getDirectMembers().begin());
1693 i != entity->getDirectMembers().end(); ++i)
1695 if (!baseException || i != entity->getDirectMembers().begin()) {
1696 stack = std::max(
1697 stack,
1698 addFieldInit(
1699 manager, className, i->name, false, i->type, dependencies,
1700 code.get()));
1703 code->instrReturn();
1704 code->setMaxStackAndLocals(stack + 3, 3);
1705 cf->addMethod(
1706 ClassFile::ACC_PUBLIC, "<init>"_ostr, "(Ljava/lang/Throwable;Ljava/lang/String;)V"_ostr, code.get(),
1707 std::vector< OString >(), ""_ostr);
1709 // create (String Message) constructor
1710 code = cf->newCode();
1711 code->loadLocalReference(0);
1712 code->loadLocalReference(1);
1713 code->instrInvokespecial(superClass, "<init>"_ostr, "(Ljava/lang/String;)V"_ostr);
1714 stack = 0;
1715 if (baseRuntimeException) {
1716 stack = std::max(
1717 stack,
1718 addFieldInit(
1719 manager, className, u"Context"_ustr, false,
1720 u"com.sun.star.uno.XInterface", dependencies, code.get()));
1722 for (std::vector< unoidl::ExceptionTypeEntity::Member >::const_iterator i(
1723 entity->getDirectMembers().begin());
1724 i != entity->getDirectMembers().end(); ++i)
1726 if (!baseException || i != entity->getDirectMembers().begin()) {
1727 stack = std::max(
1728 stack,
1729 addFieldInit(
1730 manager, className, i->name, false, i->type, dependencies,
1731 code.get()));
1734 code->instrReturn();
1735 code->setMaxStackAndLocals(stack + 2, 2);
1736 cf->addMethod(
1737 ClassFile::ACC_PUBLIC, "<init>"_ostr, "(Ljava/lang/String;)V"_ostr, code.get(),
1738 std::vector< OString >(), ""_ostr);
1741 // create (String Message, Object Context, T1 m1, ..., Tn mn) constructor
1742 MethodDescriptor desc1(manager, dependencies, u"void", nullptr, nullptr);
1743 code = cf->newCode();
1744 code->loadLocalReference(0);
1745 sal_uInt16 index2 = 1;
1746 code->loadLocalReference(index2++);
1747 desc1.addParameter(u"string", false, true, nullptr);
1748 if (!(baseException || baseRuntimeException)) {
1749 addExceptionBaseArguments(
1750 manager, dependencies, &desc1, code.get(), entity->getDirectBase(),
1751 &index2);
1753 code->instrInvokespecial(superClass, "<init>"_ostr, desc1.getDescriptor());
1754 sal_uInt16 maxSize = index2;
1755 if (baseRuntimeException) {
1756 maxSize = std::max(
1757 maxSize,
1758 addDirectArgument(
1759 manager, dependencies, &desc1, code.get(), &index2, className,
1760 "Context"_ostr, false, u"com.sun.star.uno.XInterface"_ustr));
1762 for (std::vector< unoidl::ExceptionTypeEntity::Member >::const_iterator i(
1763 entity->getDirectMembers().begin());
1764 i != entity->getDirectMembers().end(); ++i)
1766 if (!baseException || i != entity->getDirectMembers().begin()) {
1767 maxSize = std::max(
1768 maxSize,
1769 addDirectArgument(
1770 manager, dependencies, &desc1, code.get(), &index2,
1771 className, codemaker::convertString(i->name), false,
1772 i->type));
1775 code->instrReturn();
1776 code->setMaxStackAndLocals(maxSize, index2);
1777 cf->addMethod(
1778 ClassFile::ACC_PUBLIC, "<init>"_ostr, desc1.getDescriptor(), code.get(),
1779 std::vector< OString >(), desc1.getSignature());
1781 // create (Throwable Cause, String Message, Object Context, T1 m1, ..., Tn mn) constructor
1782 MethodDescriptor desc2(manager, dependencies, u"void", nullptr, nullptr);
1783 code = cf->newCode();
1784 code->loadLocalReference(0);
1785 sal_uInt16 index3 = 3;
1786 // Note that we hack in the java.lang.Throwable parameter further down,
1787 // because MethodDescriptor does not know how to handle it.
1788 desc2.addParameter(u"string", false, true, nullptr);
1789 if (baseException || baseRuntimeException) {
1790 code->loadLocalReference(2);
1791 code->loadLocalReference(1);
1792 code->instrInvokespecial(superClass, "<init>"_ostr, "(Ljava/lang/String;Ljava/lang/Throwable;)V"_ostr);
1793 } else {
1794 code->loadLocalReference(1);
1795 code->loadLocalReference(2);
1796 addExceptionBaseArguments(
1797 manager, dependencies, &desc2, code.get(), entity->getDirectBase(),
1798 &index3);
1799 code->instrInvokespecial(superClass, "<init>"_ostr, OString::Concat("(Ljava/lang/Throwable;") + desc2.getDescriptor().subView(1));
1801 sal_uInt16 maxSize2 = index3;
1802 if (baseRuntimeException) {
1803 maxSize2 = std::max(
1804 maxSize2,
1805 addDirectArgument(
1806 manager, dependencies, &desc2, code.get(), &index3, className,
1807 "Context"_ostr, false, u"com.sun.star.uno.XInterface"_ustr));
1809 for (std::vector< unoidl::ExceptionTypeEntity::Member >::const_iterator i(
1810 entity->getDirectMembers().begin());
1811 i != entity->getDirectMembers().end(); ++i)
1813 if (!baseException || i != entity->getDirectMembers().begin()) {
1814 maxSize2 = std::max(
1815 maxSize2,
1816 addDirectArgument(
1817 manager, dependencies, &desc2, code.get(), &index3,
1818 className, codemaker::convertString(i->name), false,
1819 i->type));
1822 code->instrReturn();
1823 code->setMaxStackAndLocals(maxSize2, index3);
1824 cf->addMethod(
1825 ClassFile::ACC_PUBLIC, "<init>"_ostr, OString::Concat("(Ljava/lang/Throwable;") + desc2.getDescriptor().subView(1), code.get(),
1826 std::vector< OString >(), desc2.getSignature());
1828 addTypeInfo(className, typeInfo, dependencies, cf.get());
1829 writeClassFile(options, className, *cf);
1832 void createExceptionsAttribute(
1833 rtl::Reference< TypeManager > const & manager,
1834 std::vector< OUString > const & exceptionTypes,
1835 std::set<OUString> * dependencies, std::vector< OString > * exceptions,
1836 codemaker::ExceptionTree * tree)
1838 assert(dependencies != nullptr);
1839 assert(exceptions != nullptr);
1840 for (const OUString& ex : exceptionTypes)
1842 dependencies->insert(ex);
1843 OString type(codemaker::convertString(ex).replace('.', '/'));
1844 exceptions->push_back(type);
1845 if (tree != nullptr) {
1846 tree->add(type.replace('/', '.'), manager);
1851 void handleInterfaceType(
1852 const OUString& name, rtl::Reference< unoidl::InterfaceTypeEntity > const & entity,
1853 rtl::Reference< TypeManager > const & manager, JavaOptions const & options,
1854 std::set<OUString> * dependencies)
1856 assert(entity.is());
1857 assert(dependencies != nullptr);
1858 OString className(codemaker::convertString(name).replace('.', '/'));
1859 std::unique_ptr< ClassFile > cf(
1860 new ClassFile(
1861 static_cast< ClassFile::AccessFlags >(
1862 ClassFile::ACC_PUBLIC | ClassFile::ACC_INTERFACE
1863 | ClassFile::ACC_ABSTRACT),
1864 className, "java/lang/Object"_ostr, ""_ostr));
1865 for (const unoidl::AnnotatedReference& ar : entity->getDirectMandatoryBases())
1867 dependencies->insert(ar.name);
1868 cf->addInterface(codemaker::convertString(ar.name).replace('.', '/'));
1870 // As a special case, let com.sun.star.lang.XEventListener extend
1871 // java.util.EventListener ("A tagging interface that all event listener
1872 // interfaces must extend"):
1873 if (className == "com/sun/star/lang/XEventListener") {
1874 cf->addInterface("java/util/EventListener"_ostr);
1876 std::vector< TypeInfo > typeInfo;
1877 if (className != "com/sun/star/uno/XInterface") {
1878 sal_Int32 index = 0;
1879 for (const unoidl::InterfaceTypeEntity::Attribute& attr : entity->getDirectAttributes())
1881 SpecialType specialType;
1882 PolymorphicUnoType polymorphicUnoType;
1883 MethodDescriptor gdesc(
1884 manager, dependencies, attr.type, &specialType,
1885 &polymorphicUnoType);
1886 std::vector< OString > exc;
1887 createExceptionsAttribute(
1888 manager, attr.getExceptions, dependencies, &exc, nullptr);
1889 OString attrName(codemaker::convertString(attr.name));
1890 cf->addMethod(
1891 static_cast< ClassFile::AccessFlags >(
1892 ClassFile::ACC_PUBLIC | ClassFile::ACC_ABSTRACT),
1893 "get" + attrName, gdesc.getDescriptor(), nullptr, exc,
1894 gdesc.getSignature());
1895 if (!attr.readOnly) {
1896 MethodDescriptor sdesc(manager, dependencies, u"void", nullptr, nullptr);
1897 sdesc.addParameter(attr.type, false, true, nullptr);
1898 std::vector< OString > exc2;
1899 createExceptionsAttribute(
1900 manager, attr.setExceptions, dependencies, &exc2, nullptr);
1901 cf->addMethod(
1902 static_cast< ClassFile::AccessFlags >(
1903 ClassFile::ACC_PUBLIC | ClassFile::ACC_ABSTRACT),
1904 "set" + attrName, sdesc.getDescriptor(), nullptr, exc2,
1905 sdesc.getSignature());
1907 typeInfo.emplace_back(
1908 TypeInfo::KIND_ATTRIBUTE, attrName, specialType,
1909 static_cast< TypeInfo::Flags >(
1910 (attr.readOnly ? TypeInfo::FLAG_READONLY : 0)
1911 | (attr.bound ? TypeInfo::FLAG_BOUND : 0)),
1912 index, polymorphicUnoType);
1913 index += (attr.readOnly ? 1 : 2);
1915 for (const unoidl::InterfaceTypeEntity::Method& method : entity->getDirectMethods())
1917 OString methodName(codemaker::convertString(method.name));
1918 SpecialType specialReturnType;
1919 PolymorphicUnoType polymorphicUnoReturnType;
1920 MethodDescriptor desc(
1921 manager, dependencies, method.returnType, &specialReturnType,
1922 &polymorphicUnoReturnType);
1923 typeInfo.emplace_back(
1924 TypeInfo::KIND_METHOD, methodName, specialReturnType,
1925 static_cast< TypeInfo::Flags >(0), index++,
1926 polymorphicUnoReturnType);
1927 sal_Int32 paramIndex = 0;
1928 for (const unoidl::InterfaceTypeEntity::Method::Parameter& param : method.parameters)
1930 bool in = param.direction
1931 != unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_OUT;
1932 bool out = param.direction
1933 != unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN;
1934 PolymorphicUnoType polymorphicUnoType;
1935 SpecialType specialType = desc.addParameter(
1936 param.type, out, true, &polymorphicUnoType);
1937 if (out || isSpecialType(specialType)
1938 || polymorphicUnoType.kind != PolymorphicUnoType::KIND_NONE)
1940 typeInfo.emplace_back(
1941 codemaker::convertString(param.name), specialType, in,
1942 out, methodName, paramIndex, polymorphicUnoType);
1944 ++paramIndex;
1946 std::vector< OString > exc2;
1947 createExceptionsAttribute(
1948 manager, method.exceptions, dependencies, &exc2, nullptr);
1949 cf->addMethod(
1950 static_cast< ClassFile::AccessFlags >(
1951 ClassFile::ACC_PUBLIC | ClassFile::ACC_ABSTRACT),
1952 methodName, desc.getDescriptor(), nullptr, exc2, desc.getSignature());
1955 addTypeInfo(className, typeInfo, dependencies, cf.get());
1956 writeClassFile(options, className, *cf);
1959 void handleTypedef(
1960 rtl::Reference< unoidl::TypedefEntity > const & entity,
1961 rtl::Reference< TypeManager > const & manager, std::set<OUString> * dependencies)
1963 assert(entity.is());
1964 assert(manager.is());
1965 assert(dependencies != nullptr);
1966 OUString nucleus;
1967 switch (manager->decompose(entity->getType(), false, &nucleus, nullptr, nullptr, nullptr))
1969 case codemaker::UnoType::Sort::Boolean:
1970 case codemaker::UnoType::Sort::Byte:
1971 case codemaker::UnoType::Sort::Short:
1972 case codemaker::UnoType::Sort::UnsignedShort:
1973 case codemaker::UnoType::Sort::Long:
1974 case codemaker::UnoType::Sort::UnsignedLong:
1975 case codemaker::UnoType::Sort::Hyper:
1976 case codemaker::UnoType::Sort::UnsignedHyper:
1977 case codemaker::UnoType::Sort::Float:
1978 case codemaker::UnoType::Sort::Double:
1979 case codemaker::UnoType::Sort::Char:
1980 case codemaker::UnoType::Sort::String:
1981 case codemaker::UnoType::Sort::Type:
1982 case codemaker::UnoType::Sort::Any:
1983 break;
1984 case codemaker::UnoType::Sort::Enum:
1985 case codemaker::UnoType::Sort::PlainStruct:
1986 case codemaker::UnoType::Sort::Interface:
1987 case codemaker::UnoType::Sort::Typedef:
1988 dependencies->insert(nucleus);
1989 break;
1990 default:
1991 assert(false); // this cannot happen
1995 void handleConstantGroup(
1996 const OUString& name, rtl::Reference< unoidl::ConstantGroupEntity > const & entity,
1997 rtl::Reference< TypeManager > const & manager, JavaOptions const & options,
1998 std::set<OUString> * dependencies)
2000 assert(entity.is());
2001 OString className(codemaker::convertString(name).replace('.', '/'));
2002 std::unique_ptr< ClassFile > cf(
2003 new ClassFile(
2004 static_cast< ClassFile::AccessFlags >(
2005 ClassFile::ACC_PUBLIC | ClassFile::ACC_INTERFACE
2006 | ClassFile::ACC_ABSTRACT),
2007 className, "java/lang/Object"_ostr, ""_ostr));
2008 for (const unoidl::ConstantGroupEntity::Member& member : entity->getMembers())
2010 OUString type;
2011 sal_uInt16 valueIndex = sal_uInt16(); // avoid false warnings
2012 switch (member.value.type) {
2013 case unoidl::ConstantValue::TYPE_BOOLEAN:
2014 type = "boolean";
2015 valueIndex = cf->addIntegerInfo(sal_Int32(member.value.booleanValue));
2016 break;
2017 case unoidl::ConstantValue::TYPE_BYTE:
2018 type = "byte";
2019 valueIndex = cf->addIntegerInfo(member.value.byteValue);
2020 break;
2021 case unoidl::ConstantValue::TYPE_SHORT:
2022 type = "short";
2023 valueIndex = cf->addIntegerInfo(member.value.shortValue);
2024 break;
2025 case unoidl::ConstantValue::TYPE_UNSIGNED_SHORT:
2026 type = "unsigned short";
2027 valueIndex = cf->addIntegerInfo(member.value.unsignedShortValue);
2028 break;
2029 case unoidl::ConstantValue::TYPE_LONG:
2030 type = "long";
2031 valueIndex = cf->addIntegerInfo(member.value.longValue);
2032 break;
2033 case unoidl::ConstantValue::TYPE_UNSIGNED_LONG:
2034 type = "unsigned long";
2035 valueIndex = cf->addIntegerInfo(
2036 static_cast< sal_Int32 >(member.value.unsignedLongValue));
2037 break;
2038 case unoidl::ConstantValue::TYPE_HYPER:
2039 type = "hyper";
2040 valueIndex = cf->addLongInfo(member.value.hyperValue);
2041 break;
2042 case unoidl::ConstantValue::TYPE_UNSIGNED_HYPER:
2043 type = "unsigned hyper";
2044 valueIndex = cf->addLongInfo(
2045 static_cast< sal_Int64 >(member.value.unsignedHyperValue));
2046 break;
2047 case unoidl::ConstantValue::TYPE_FLOAT:
2048 type = "float";
2049 valueIndex = cf->addFloatInfo(member.value.floatValue);
2050 break;
2051 case unoidl::ConstantValue::TYPE_DOUBLE:
2052 type = "double";
2053 valueIndex = cf->addDoubleInfo(member.value.doubleValue);
2054 break;
2056 OString desc;
2057 OString sig;
2058 getFieldDescriptor(manager, dependencies, type, &desc, &sig, nullptr);
2059 cf->addField(
2060 static_cast< ClassFile::AccessFlags >(
2061 ClassFile::ACC_PUBLIC | ClassFile::ACC_STATIC
2062 | ClassFile::ACC_FINAL),
2063 codemaker::convertString(member.name), desc, valueIndex, sig);
2065 writeClassFile(options, className, *cf);
2068 void addExceptionHandlers(
2069 codemaker::ExceptionTreeNode const * node,
2070 ClassFile::Code::Position start, ClassFile::Code::Position end,
2071 ClassFile::Code::Position handler, ClassFile::Code * code)
2073 assert(node != nullptr);
2074 assert(code != nullptr);
2075 if (node->present) {
2076 code->addException(start, end, handler, node->name.replace('.', '/'));
2077 } else {
2078 for (std::unique_ptr<codemaker::ExceptionTreeNode> const & p : node->children)
2080 addExceptionHandlers(p.get(), start, end, handler, code);
2085 void addConstructor(
2086 rtl::Reference< TypeManager > const & manager,
2087 std::string_view realJavaBaseName, OString const & unoName,
2088 OString const & className,
2089 unoidl::SingleInterfaceBasedServiceEntity::Constructor const & constructor,
2090 OUString const & returnType, std::set<OUString> * dependencies,
2091 ClassFile * classFile)
2093 assert(dependencies != nullptr);
2094 assert(classFile != nullptr);
2095 MethodDescriptor desc(manager, dependencies, returnType, nullptr, nullptr);
2096 desc.addParameter(u"com.sun.star.uno.XComponentContext", false, false, nullptr);
2097 std::unique_ptr< ClassFile::Code > code(classFile->newCode());
2098 code->loadLocalReference(0);
2099 // stack: context
2100 code->instrInvokeinterface(
2101 "com/sun/star/uno/XComponentContext"_ostr, "getServiceManager"_ostr,
2102 "()Lcom/sun/star/lang/XMultiComponentFactory;"_ostr, 1);
2103 // stack: factory
2104 code->loadStringConstant(unoName);
2105 // stack: factory serviceName
2106 codemaker::ExceptionTree tree;
2107 ClassFile::Code::Position tryStart;
2108 ClassFile::Code::Position tryEnd;
2109 std::vector< OString > exc;
2110 sal_uInt16 stack;
2111 sal_uInt16 localIndex = 1;
2112 ClassFile::AccessFlags access = static_cast< ClassFile::AccessFlags >(
2113 ClassFile::ACC_PUBLIC | ClassFile::ACC_STATIC);
2114 if (constructor.defaultConstructor) {
2115 code->loadLocalReference(0);
2116 // stack: factory serviceName context
2117 tryStart = code->getPosition();
2118 code->instrInvokeinterface(
2119 "com/sun/star/lang/XMultiComponentFactory"_ostr,
2120 "createInstanceWithContext"_ostr,
2121 ("(Ljava/lang/String;Lcom/sun/star/uno/XComponentContext;)"
2122 "Ljava/lang/Object;"_ostr),
2124 tryEnd = code->getPosition();
2125 // stack: instance
2126 stack = 3;
2127 } else {
2128 if (constructor.parameters.size() == 1
2129 && constructor.parameters[0].rest)
2131 desc.addParameter(u"any", true, true, nullptr);
2132 code->loadLocalReference(localIndex++);
2133 // stack: factory serviceName args
2134 stack = 4;
2135 access = static_cast< ClassFile::AccessFlags >(
2136 access | ClassFile::ACC_VARARGS);
2137 } else {
2138 code->loadIntegerConstant(constructor.parameters.size());
2139 // stack: factory serviceName N
2140 code->instrAnewarray("java/lang/Object"_ostr);
2141 // stack: factory serviceName args
2142 stack = 0;
2143 sal_Int32 n = 0;
2144 for (const unoidl::SingleInterfaceBasedServiceEntity::Constructor::Parameter& param :
2145 constructor.parameters)
2147 desc.addParameter(param.type, false, true, nullptr);
2148 code->instrDup();
2149 // stack: factory serviceName args args
2150 code->loadIntegerConstant(n++);
2151 // stack: factory serviceName args args i
2152 stack = std::max(
2153 stack,
2154 addLoadLocal(
2155 manager, code.get(), &localIndex, false, param.type, true,
2156 dependencies));
2157 // stack: factory serviceName args args i any
2158 code->instrAastore();
2159 // stack: factory serviceName args
2161 stack += 5;
2163 code->loadLocalReference(0);
2164 // stack: factory serviceName args context
2165 tryStart = code->getPosition();
2166 code->instrInvokeinterface(
2167 "com/sun/star/lang/XMultiComponentFactory"_ostr,
2168 "createInstanceWithArgumentsAndContext"_ostr,
2169 ("(Ljava/lang/String;[Ljava/lang/Object;"
2170 "Lcom/sun/star/uno/XComponentContext;)Ljava/lang/Object;"_ostr),
2172 tryEnd = code->getPosition();
2173 // stack: instance
2174 createExceptionsAttribute(
2175 manager, constructor.exceptions, dependencies, &exc, &tree);
2177 code->loadLocalReference(0);
2178 // stack: instance context
2179 code->instrInvokestatic(
2180 className, "$castInstance"_ostr,
2181 ("(Ljava/lang/Object;Lcom/sun/star/uno/XComponentContext;)"
2182 "Ljava/lang/Object;"_ostr));
2183 // stack: instance
2184 code->instrCheckcast(
2185 codemaker::convertString(returnType).replace('.', '/'));
2186 // stack: instance
2187 code->instrAreturn();
2188 if (!tree.getRoot().present) {
2189 ClassFile::Code::Position pos1 = code->getPosition();
2190 // stack: e
2191 code->instrInvokevirtual(
2192 "java/lang/Throwable"_ostr, "toString"_ostr, "()Ljava/lang/String;"_ostr);
2193 // stack: str
2194 localIndex = std::max< sal_uInt16 >(localIndex, 2);
2195 code->storeLocalReference(1);
2196 // stack: -
2197 code->instrNew("com/sun/star/uno/DeploymentException"_ostr);
2198 // stack: ex
2199 code->instrDup();
2200 // stack: ex ex
2201 code->loadStringConstant(
2202 "component context fails to supply service " + unoName + " of type "
2203 + realJavaBaseName + ": ");
2204 // stack: ex ex "..."
2205 code->loadLocalReference(1);
2206 // stack: ex ex "..." str
2207 code->instrInvokevirtual(
2208 "java/lang/String"_ostr, "concat"_ostr,
2209 "(Ljava/lang/String;)Ljava/lang/String;"_ostr);
2210 // stack: ex ex "..."
2211 code->loadLocalReference(0);
2212 // stack: ex ex "..." context
2213 code->instrInvokespecial(
2214 "com/sun/star/uno/DeploymentException"_ostr, "<init>"_ostr,
2215 "(Ljava/lang/String;Ljava/lang/Object;)V"_ostr);
2216 // stack: ex
2217 ClassFile::Code::Position pos2 = code->getPosition();
2218 code->instrAthrow();
2219 addExceptionHandlers(
2220 &tree.getRoot(), tryStart, tryEnd, pos2, code.get());
2221 code->addException(
2222 tryStart, tryEnd, pos1, "com/sun/star/uno/Exception"_ostr);
2223 dependencies->insert(u"com.sun.star.uno.Exception"_ustr);
2224 stack = std::max< sal_uInt16 >(stack, 4);
2226 code->setMaxStackAndLocals(stack, localIndex);
2227 classFile->addMethod(
2228 access,
2229 codemaker::java::translateUnoToJavaIdentifier(
2230 (constructor.defaultConstructor
2231 ? "create"_ostr : codemaker::convertString(constructor.name)),
2232 "method"),
2233 desc.getDescriptor(), code.get(), exc, desc.getSignature());
2236 void handleService(
2237 const OUString& name,
2238 rtl::Reference< unoidl::SingleInterfaceBasedServiceEntity > const & entity,
2239 rtl::Reference< TypeManager > const & manager, JavaOptions const & options,
2240 std::set<OUString> * dependencies)
2242 assert(entity.is());
2243 assert(dependencies != nullptr);
2244 OString unoName(codemaker::convertString(name));
2245 OString className(
2246 translateUnoidlEntityNameToJavaFullyQualifiedName(name, "service"));
2247 std::unique_ptr< ClassFile > cf(
2248 new ClassFile(
2249 static_cast< ClassFile::AccessFlags >(
2250 ClassFile::ACC_PUBLIC | ClassFile::ACC_FINAL
2251 | ClassFile::ACC_SUPER),
2252 className, "java/lang/Object"_ostr, ""_ostr));
2253 if (!entity->getConstructors().empty()) {
2254 OString realJavaBaseName(
2255 codemaker::convertString(entity->getBase()));
2256 dependencies->insert(entity->getBase());
2257 dependencies->insert(u"com.sun.star.lang.XMultiComponentFactory"_ustr);
2258 dependencies->insert(u"com.sun.star.uno.DeploymentException"_ustr);
2259 dependencies->insert(u"com.sun.star.uno.TypeClass"_ustr);
2260 dependencies->insert(u"com.sun.star.uno.XComponentContext"_ustr);
2261 for (const unoidl::SingleInterfaceBasedServiceEntity::Constructor& cons :
2262 entity->getConstructors())
2264 addConstructor(
2265 manager, realJavaBaseName, unoName, className, cons,
2266 entity->getBase(), dependencies, cf.get());
2268 // Synthetic castInstance method:
2270 std::unique_ptr< ClassFile::Code > code(cf->newCode());
2271 code->instrNew("com/sun/star/uno/Type"_ostr);
2272 // stack: type
2273 code->instrDup();
2274 // stack: type type
2275 code->loadStringConstant(realJavaBaseName);
2276 // stack: type type "..."
2277 code->instrGetstatic(
2278 "com/sun/star/uno/TypeClass"_ostr, "INTERFACE"_ostr,
2279 "Lcom/sun/star/uno/TypeClass;"_ostr);
2280 // stack: type type "..." INTERFACE
2281 code->instrInvokespecial(
2282 "com/sun/star/uno/Type"_ostr, "<init>"_ostr,
2283 "(Ljava/lang/String;Lcom/sun/star/uno/TypeClass;)V"_ostr);
2284 // stack: type
2285 code->loadLocalReference(0);
2286 // stack: type instance
2287 code->instrInvokestatic(
2288 "com/sun/star/uno/UnoRuntime"_ostr, "queryInterface"_ostr,
2289 ("(Lcom/sun/star/uno/Type;Ljava/lang/Object;)"
2290 "Ljava/lang/Object;"_ostr));
2291 // stack: instance
2292 code->instrDup();
2293 // stack: instance instance
2294 ClassFile::Code::Branch branch = code->instrIfnull();
2295 // stack: instance
2296 code->instrAreturn();
2297 code->branchHere(branch);
2298 code->instrPop();
2299 // stack: -
2300 code->instrNew("com/sun/star/uno/DeploymentException"_ostr);
2301 // stack: ex
2302 code->instrDup();
2303 // stack: ex ex
2304 code->loadStringConstant(
2305 "component context fails to supply service " + unoName
2306 + " of type " + realJavaBaseName);
2307 // stack: ex ex "..."
2308 code->loadLocalReference(1);
2309 // stack: ex ex "..." context
2310 code->instrInvokespecial(
2311 "com/sun/star/uno/DeploymentException"_ostr, "<init>"_ostr,
2312 "(Ljava/lang/String;Ljava/lang/Object;)V"_ostr);
2313 // stack: ex
2314 code->instrAthrow();
2315 code->setMaxStackAndLocals(4, 2);
2316 cf->addMethod(
2317 static_cast< ClassFile::AccessFlags >(
2318 ClassFile::ACC_PRIVATE | ClassFile::ACC_STATIC
2319 | ClassFile::ACC_SYNTHETIC),
2320 "$castInstance"_ostr,
2321 ("(Ljava/lang/Object;Lcom/sun/star/uno/XComponentContext;)"
2322 "Ljava/lang/Object;"_ostr),
2323 code.get(), std::vector< OString >(), ""_ostr);
2326 writeClassFile(options, className, *cf);
2329 void handleSingleton(
2330 const OUString& name,
2331 rtl::Reference< unoidl::InterfaceBasedSingletonEntity > const & entity,
2332 rtl::Reference< TypeManager > const & manager, JavaOptions const & options,
2333 std::set<OUString> * dependencies)
2335 assert(entity.is());
2336 assert(dependencies != nullptr);
2337 OString realJavaBaseName(codemaker::convertString(entity->getBase()));
2338 OString base(realJavaBaseName.replace('.', '/'));
2339 dependencies->insert(entity->getBase());
2340 OString unoName(codemaker::convertString(name));
2341 OString className(
2342 translateUnoidlEntityNameToJavaFullyQualifiedName(name, "singleton"));
2343 dependencies->insert(u"com.sun.star.uno.DeploymentException"_ustr);
2344 dependencies->insert(u"com.sun.star.uno.TypeClass"_ustr);
2345 dependencies->insert(u"com.sun.star.uno.XComponentContext"_ustr);
2346 std::unique_ptr< ClassFile > cf(
2347 new ClassFile(
2348 static_cast< ClassFile::AccessFlags >(
2349 ClassFile::ACC_PUBLIC | ClassFile::ACC_FINAL
2350 | ClassFile::ACC_SUPER),
2351 className, "java/lang/Object"_ostr, ""_ostr));
2352 MethodDescriptor desc(manager, dependencies, entity->getBase(), nullptr, nullptr);
2353 desc.addParameter(u"com.sun.star.uno.XComponentContext", false, false, nullptr);
2354 std::unique_ptr< ClassFile::Code > code(cf->newCode());
2355 code->loadLocalReference(0);
2356 // stack: context
2357 code->loadStringConstant("/singletons/" + unoName);
2358 // stack: context "..."
2359 code->instrInvokeinterface(
2360 "com/sun/star/uno/XComponentContext"_ostr, "getValueByName"_ostr,
2361 "(Ljava/lang/String;)Ljava/lang/Object;"_ostr, 2);
2362 // stack: value
2363 code->instrDup();
2364 // stack: value value
2365 code->instrInstanceof("com/sun/star/uno/Any"_ostr);
2366 // stack: value 0/1
2367 ClassFile::Code::Branch branch1 = code->instrIfeq();
2368 // stack: value
2369 code->instrCheckcast("com/sun/star/uno/Any"_ostr);
2370 // stack: value
2371 code->instrDup();
2372 // stack: value value
2373 code->instrInvokevirtual(
2374 "com/sun/star/uno/Any"_ostr, "getType"_ostr, "()Lcom/sun/star/uno/Type;"_ostr);
2375 // stack: value type
2376 code->instrInvokevirtual(
2377 "com/sun/star/uno/Type"_ostr, "getTypeClass"_ostr,
2378 "()Lcom/sun/star/uno/TypeClass;"_ostr);
2379 // stack: value typeClass
2380 code->instrGetstatic(
2381 "com/sun/star/uno/TypeClass"_ostr, "INTERFACE"_ostr,
2382 "Lcom/sun/star/uno/TypeClass;"_ostr);
2383 // stack: value typeClass INTERFACE
2384 ClassFile::Code::Branch branch2 = code->instrIfAcmpne();
2385 // stack: value
2386 code->instrInvokevirtual(
2387 "com/sun/star/uno/Any"_ostr, "getObject"_ostr, "()Ljava/lang/Object;"_ostr);
2388 // stack: value
2389 code->branchHere(branch1);
2390 code->instrNew("com/sun/star/uno/Type"_ostr);
2391 // stack: value type
2392 code->instrDup();
2393 // stack: value type type
2394 code->loadStringConstant(realJavaBaseName);
2395 // stack: value type type "..."
2396 code->instrGetstatic(
2397 "com/sun/star/uno/TypeClass"_ostr, "INTERFACE"_ostr,
2398 "Lcom/sun/star/uno/TypeClass;"_ostr);
2399 // stack: value type type "..." INTERFACE
2400 code->instrInvokespecial(
2401 "com/sun/star/uno/Type"_ostr, "<init>"_ostr,
2402 "(Ljava/lang/String;Lcom/sun/star/uno/TypeClass;)V"_ostr);
2403 // stack: value type
2404 code->instrSwap();
2405 // stack: type value
2406 code->instrInvokestatic(
2407 "com/sun/star/uno/UnoRuntime"_ostr, "queryInterface"_ostr,
2408 "(Lcom/sun/star/uno/Type;Ljava/lang/Object;)Ljava/lang/Object;"_ostr);
2409 // stack: instance
2410 code->instrDup();
2411 // stack: instance instance
2412 ClassFile::Code::Branch branch3 = code->instrIfnull();
2413 // stack: instance
2414 code->instrCheckcast(base);
2415 // stack: instance
2416 code->instrAreturn();
2417 code->branchHere(branch2);
2418 code->branchHere(branch3);
2419 code->instrPop();
2420 // stack: -
2421 code->instrNew("com/sun/star/uno/DeploymentException"_ostr);
2422 // stack: ex
2423 code->instrDup();
2424 // stack: ex ex
2425 code->loadStringConstant(
2426 "component context fails to supply singleton " + unoName + " of type "
2427 + realJavaBaseName);
2428 // stack: ex ex "..."
2429 code->loadLocalReference(0);
2430 // stack: ex ex "..." context
2431 code->instrInvokespecial(
2432 "com/sun/star/uno/DeploymentException"_ostr, "<init>"_ostr,
2433 "(Ljava/lang/String;Ljava/lang/Object;)V"_ostr);
2434 // stack: ex
2435 code->instrAthrow();
2436 code->setMaxStackAndLocals(5, 1);
2437 cf->addMethod(
2438 static_cast< ClassFile::AccessFlags >(
2439 ClassFile::ACC_PUBLIC | ClassFile::ACC_STATIC),
2440 "get"_ostr, desc.getDescriptor(), code.get(), std::vector< OString >(),
2441 desc.getSignature());
2442 writeClassFile(options, className, *cf);
2447 void produce(
2448 OUString const & name, rtl::Reference< TypeManager > const & manager,
2449 codemaker::GeneratedTypeSet & generated, JavaOptions const & options)
2451 if (generated.contains(u2b(name))) {
2452 return;
2454 generated.add(u2b(name));
2455 if (!manager->foundAtPrimaryProvider(name)) {
2456 return;
2458 std::set<OUString> deps;
2459 rtl::Reference< unoidl::Entity > ent;
2460 rtl::Reference< unoidl::MapCursor > cur;
2461 switch (manager->getSort(name, &ent, &cur)) {
2462 case codemaker::UnoType::Sort::Module:
2464 OUString prefix;
2465 if (!name.isEmpty()) {
2466 prefix = name + ".";
2468 for (;;) {
2469 OUString mem;
2470 if (!cur->getNext(&mem).is()) {
2471 break;
2473 produce(prefix + mem, manager, generated, options);
2475 return;
2477 case codemaker::UnoType::Sort::Enum:
2478 handleEnumType(
2479 name, dynamic_cast< unoidl::EnumTypeEntity * >(ent.get()), options);
2480 break;
2481 case codemaker::UnoType::Sort::PlainStruct:
2482 handlePlainStructType(
2483 name, dynamic_cast< unoidl::PlainStructTypeEntity * >(ent.get()),
2484 manager, options, &deps);
2485 break;
2486 case codemaker::UnoType::Sort::PolymorphicStructTemplate:
2487 handlePolyStructType(
2488 name,
2489 dynamic_cast< unoidl::PolymorphicStructTypeTemplateEntity * >(
2490 ent.get()),
2491 manager, options, &deps);
2492 break;
2493 case codemaker::UnoType::Sort::Exception:
2494 handleExceptionType(
2495 name, dynamic_cast< unoidl::ExceptionTypeEntity * >(ent.get()),
2496 manager, options, &deps);
2497 break;
2498 case codemaker::UnoType::Sort::Interface:
2499 handleInterfaceType(
2500 name, dynamic_cast< unoidl::InterfaceTypeEntity * >(ent.get()),
2501 manager, options, &deps);
2502 break;
2503 case codemaker::UnoType::Sort::Typedef:
2504 handleTypedef(
2505 dynamic_cast< unoidl::TypedefEntity * >(ent.get()), manager, &deps);
2506 break;
2507 case codemaker::UnoType::Sort::ConstantGroup:
2508 handleConstantGroup(
2509 name, dynamic_cast< unoidl::ConstantGroupEntity * >(ent.get()),
2510 manager, options, &deps);
2511 break;
2512 case codemaker::UnoType::Sort::SingleInterfaceBasedService:
2513 handleService(
2514 name,
2515 dynamic_cast< unoidl::SingleInterfaceBasedServiceEntity * >(
2516 ent.get()),
2517 manager, options, &deps);
2518 break;
2519 case codemaker::UnoType::Sort::InterfaceBasedSingleton:
2520 handleSingleton(
2521 name,
2522 dynamic_cast< unoidl::InterfaceBasedSingletonEntity * >(ent.get()),
2523 manager, options, &deps);
2524 break;
2525 case codemaker::UnoType::Sort::AccumulationBasedService:
2526 case codemaker::UnoType::Sort::ServiceBasedSingleton:
2527 break;
2528 default:
2529 throw CannotDumpException(
2530 "unexpected entity \"" + name + "\" in call to produce");
2532 if (!options.isValid("-nD"_ostr)) {
2533 for (const OUString& d : deps) {
2534 produce(d, manager, generated, options);
2539 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */