cURL: follow redirects
[LibreOffice.git] / codemaker / source / javamaker / javatype.cxx
blob2da2e5f925f2730df40dc7a72ac37d481c6fa9be
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 <list>
26 #include <map>
27 #include <memory>
28 #include <set>
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"
48 #include "classfile.hxx"
49 #include "javaoptions.hxx"
50 #include "javatype.hxx"
52 using codemaker::javamaker::ClassFile;
54 namespace {
56 void appendUnoName(
57 rtl::Reference< TypeManager > const & manager, OUString const & nucleus,
58 sal_Int32 rank, std::vector< OUString > const & arguments,
59 OUStringBuffer * buffer)
61 assert(manager.is());
62 assert(rank >= 0);
63 assert(buffer != nullptr);
64 for (sal_Int32 i = 0; i != rank; ++i) {
65 buffer->append("[]");
67 buffer->append(nucleus);
68 if (!arguments.empty()) {
69 buffer->append('<');
70 for (std::vector< OUString >::const_iterator i(arguments.begin());
71 i != arguments.end(); ++i)
73 if (i != arguments.begin()) {
74 buffer->append(',');
76 OUString n;
77 sal_Int32 k;
78 std::vector< OUString > args;
79 manager->decompose(*i, false, &n, &k, &args, nullptr);
80 appendUnoName(manager, n, k, args, buffer);
82 buffer->append('>');
86 // Translate the name of a UNOIDL entity (enum type, plain struct type,
87 // polymorphic struct type template, or interface type, decomposed into nucleus,
88 // sequence rank, and template arguments) into a core UNO type name:
89 OUString createUnoName(
90 rtl::Reference< TypeManager > const & manager, OUString const & nucleus,
91 sal_Int32 rank, std::vector< OUString > const & arguments)
93 OUStringBuffer buf;
94 appendUnoName(manager, nucleus, rank, arguments, &buf);
95 return buf.makeStringAndClear();
98 typedef std::set< OUString > Dependencies;
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 OUString const & name, OString const & prefix)
114 assert(!name.startsWith("[]"));
115 assert(name.indexOf('<') == -1);
116 sal_Int32 i = name.lastIndexOf('.') + 1;
117 return codemaker::convertString(name.copy(0, i)).replace('.', '/')
118 + codemaker::java::translateUnoToJavaIdentifier(
119 codemaker::convertString(name.copy(i)), prefix);
122 struct PolymorphicUnoType {
123 PolymorphicUnoType(): kind(KIND_NONE) {}
125 enum Kind { KIND_NONE, KIND_STRUCT, KIND_SEQUENCE };
126 Kind kind;
127 OUString name;
130 SpecialType translateUnoTypeToDescriptor(
131 rtl::Reference< TypeManager > const & manager, OUString const & type,
132 bool array, bool classType, Dependencies * dependencies,
133 OStringBuffer * descriptor, OStringBuffer * signature,
134 bool * needsSignature, PolymorphicUnoType * polymorphicUnoType);
136 SpecialType translateUnoTypeToDescriptor(
137 rtl::Reference< TypeManager > const & manager,
138 codemaker::UnoType::Sort sort, OUString const & nucleus, sal_Int32 rank,
139 std::vector< OUString > const & arguments, bool array, bool classType,
140 Dependencies * dependencies, OStringBuffer * descriptor,
141 OStringBuffer * signature, bool * needsSignature,
142 PolymorphicUnoType * polymorphicUnoType)
144 assert(rank >= 0);
145 assert((signature == nullptr) == (needsSignature == nullptr));
146 assert(
147 arguments.empty()
148 == (sort
149 != codemaker::UnoType::Sort::InstantiatedPolymorphicStruct));
150 if (rank > 0xFF - (array ? 1 : 0)) {
151 throw CannotDumpException(
152 "Too many array dimensions for Java class file format");
154 if (array) {
155 ++rank;
157 for (sal_Int32 i = 0; i != rank; ++i) {
158 if (descriptor != nullptr) {
159 descriptor->append('[');
161 if (signature != nullptr) {
162 signature->append('[');
165 if (polymorphicUnoType != nullptr) {
166 if (sort
167 == codemaker::UnoType::Sort::InstantiatedPolymorphicStruct)
169 polymorphicUnoType->kind = rank == 0
170 ? PolymorphicUnoType::KIND_STRUCT
171 : PolymorphicUnoType::KIND_SEQUENCE;
172 polymorphicUnoType->name = createUnoName(
173 manager, nucleus, rank, arguments);
174 } else {
175 polymorphicUnoType->kind = PolymorphicUnoType::KIND_NONE;
178 switch (sort) {
179 case codemaker::UnoType::Sort::Void:
180 case codemaker::UnoType::Sort::Boolean:
181 case codemaker::UnoType::Sort::Byte:
182 case codemaker::UnoType::Sort::Short:
183 case codemaker::UnoType::Sort::UnsignedShort:
184 case codemaker::UnoType::Sort::Long:
185 case codemaker::UnoType::Sort::UnsignedLong:
186 case codemaker::UnoType::Sort::Hyper:
187 case codemaker::UnoType::Sort::UnsignedHyper:
188 case codemaker::UnoType::Sort::Float:
189 case codemaker::UnoType::Sort::Double:
190 case codemaker::UnoType::Sort::Char:
191 case codemaker::UnoType::Sort::String:
192 case codemaker::UnoType::Sort::Type:
193 case codemaker::UnoType::Sort::Any:
195 static char const * const
196 simpleTypeDescriptors[static_cast<int>(codemaker::UnoType::Sort::Any) + 1][2] = {
197 { "V", "Ljava/lang/Void;" },
198 { "Z", "Ljava/lang/Boolean;" },
199 { "B", "Ljava/lang/Byte;" },
200 { "S", "Ljava/lang/Short;" },
201 { "S", "Ljava/lang/Short;" },
202 { "I", "Ljava/lang/Integer;" },
203 { "I", "Ljava/lang/Integer;" },
204 { "J", "Ljava/lang/Long;" },
205 { "J", "Ljava/lang/Long;" },
206 { "F", "Ljava/lang/Float;" },
207 { "D", "Ljava/lang/Double;" },
208 { "C", "Ljava/lang/Character;" },
209 { "Ljava/lang/String;", "Ljava/lang/String;" },
210 { "Lcom/sun/star/uno/Type;", "Lcom/sun/star/uno/Type;" },
211 { "Ljava/lang/Object;", "Ljava/lang/Object;" } };
212 char const * s
213 = simpleTypeDescriptors[static_cast<int>(sort)][rank == 0 && classType];
214 if (descriptor != nullptr) {
215 descriptor->append(s);
217 if (signature != nullptr) {
218 signature->append(s);
220 static SpecialType const
221 simpleTypeSpecials[static_cast<int>(codemaker::UnoType::Sort::Any) + 1] = {
222 SPECIAL_TYPE_NONE, SPECIAL_TYPE_NONE, SPECIAL_TYPE_NONE,
223 SPECIAL_TYPE_NONE, SPECIAL_TYPE_UNSIGNED, SPECIAL_TYPE_NONE,
224 SPECIAL_TYPE_UNSIGNED, SPECIAL_TYPE_NONE, SPECIAL_TYPE_UNSIGNED,
225 SPECIAL_TYPE_NONE, SPECIAL_TYPE_NONE, SPECIAL_TYPE_NONE,
226 SPECIAL_TYPE_NONE, SPECIAL_TYPE_NONE, SPECIAL_TYPE_ANY };
227 return simpleTypeSpecials[static_cast<int>(sort)];
229 case codemaker::UnoType::Sort::Interface:
230 if (nucleus == "com.sun.star.uno.XInterface") {
231 if (descriptor != nullptr) {
232 descriptor->append("Ljava/lang/Object;");
234 if (signature != nullptr) {
235 signature->append("Ljava/lang/Object;");
237 return SPECIAL_TYPE_INTERFACE;
239 SAL_FALLTHROUGH;
240 case codemaker::UnoType::Sort::Sequence:
241 case codemaker::UnoType::Sort::Enum:
242 case codemaker::UnoType::Sort::PlainStruct:
243 case codemaker::UnoType::Sort::InstantiatedPolymorphicStruct:
244 if (dependencies != nullptr) {
245 dependencies->insert(nucleus);
247 if (descriptor != nullptr) {
248 descriptor->append(
249 "L" + codemaker::convertString(nucleus).replace('.', '/')
250 + ";");
252 if (signature != nullptr) {
253 signature->append(
254 "L" + codemaker::convertString(nucleus).replace('.', '/'));
255 if (!arguments.empty()) {
256 signature->append('<');
257 for (const OUString& arg : arguments)
259 translateUnoTypeToDescriptor(
260 manager, arg, false, true, dependencies, nullptr, signature,
261 needsSignature, nullptr);
263 signature->append('>');
264 *needsSignature = true;
266 signature->append(';');
268 return SPECIAL_TYPE_NONE;
269 default:
270 throw CannotDumpException(
271 "unexpected nucleus \"" + nucleus
272 + "\" in call to translateUnoTypeToDescriptor");
276 SpecialType translateUnoTypeToDescriptor(
277 rtl::Reference< TypeManager > const & manager, OUString const & type,
278 bool array, bool classType, Dependencies * dependencies,
279 OStringBuffer * descriptor, OStringBuffer * signature,
280 bool * needsSignature, PolymorphicUnoType * polymorphicUnoType)
282 assert(manager.is());
283 OUString nucleus;
284 sal_Int32 rank;
285 std::vector< OUString > args;
286 codemaker::UnoType::Sort sort = manager->decompose(
287 type, true, &nucleus, &rank, &args, nullptr);
288 return translateUnoTypeToDescriptor(
289 manager, sort, nucleus, rank, args, array, classType, dependencies,
290 descriptor, signature, needsSignature, polymorphicUnoType);
293 SpecialType getFieldDescriptor(
294 rtl::Reference< TypeManager > const & manager, Dependencies * dependencies,
295 OUString const & type, OString * descriptor, OString * signature,
296 PolymorphicUnoType * polymorphicUnoType)
298 assert(descriptor != nullptr);
299 OStringBuffer desc;
300 OStringBuffer sig;
301 bool needsSig = false;
302 SpecialType specialType = translateUnoTypeToDescriptor(
303 manager, type, false, false, dependencies, &desc, &sig, &needsSig,
304 polymorphicUnoType);
305 *descriptor = desc.makeStringAndClear();
306 if (signature != nullptr) {
307 if (needsSig) {
308 *signature = sig.makeStringAndClear();
309 } else {
310 signature->clear();
313 return specialType;
316 class MethodDescriptor {
317 public:
318 MethodDescriptor(
319 rtl::Reference< TypeManager > const & manager,
320 Dependencies * dependencies, OUString const & returnType,
321 SpecialType * specialReturnType,
322 PolymorphicUnoType * polymorphicUnoType);
324 SpecialType addParameter(
325 OUString const & type, bool array, bool dependency,
326 PolymorphicUnoType * polymorphicUnoType);
328 void addTypeParameter(OUString const & name);
330 OString getDescriptor() const;
332 OString getSignature() const { return m_needsSignature ? m_signatureStart.toString() + m_signatureEnd : OString();}
334 private:
335 rtl::Reference< TypeManager > m_manager;
336 Dependencies * m_dependencies;
337 OStringBuffer m_descriptorStart;
338 OString m_descriptorEnd;
339 OStringBuffer m_signatureStart;
340 OString m_signatureEnd;
341 bool m_needsSignature;
344 MethodDescriptor::MethodDescriptor(
345 rtl::Reference< TypeManager > const & manager, Dependencies * dependencies,
346 OUString const & returnType, SpecialType * specialReturnType,
347 PolymorphicUnoType * polymorphicUnoType):
348 m_manager(manager), m_dependencies(dependencies), m_needsSignature(false)
350 assert(dependencies != nullptr);
351 m_descriptorStart.append('(');
352 m_signatureStart.append('(');
353 OStringBuffer descEnd;
354 descEnd.append(')');
355 OStringBuffer sigEnd;
356 sigEnd.append(')');
357 SpecialType special = translateUnoTypeToDescriptor(
358 m_manager, returnType, false, false, m_dependencies, &descEnd, &sigEnd,
359 &m_needsSignature, polymorphicUnoType);
360 m_descriptorEnd = descEnd.makeStringAndClear();
361 m_signatureEnd = sigEnd.makeStringAndClear();
362 if (specialReturnType != nullptr) {
363 *specialReturnType = special;
367 SpecialType MethodDescriptor::addParameter(
368 OUString const & type, bool array, bool dependency,
369 PolymorphicUnoType * polymorphicUnoType)
371 return translateUnoTypeToDescriptor(
372 m_manager, type, array, false, dependency ? m_dependencies : nullptr,
373 &m_descriptorStart, &m_signatureStart, &m_needsSignature,
374 polymorphicUnoType);
377 void MethodDescriptor::addTypeParameter(OUString const & name) {
378 m_descriptorStart.append("Ljava/lang/Object;");
379 m_signatureStart.append("T" + codemaker::convertString(name) + ";");
380 m_needsSignature = true;
383 OString MethodDescriptor::getDescriptor() const {
384 OStringBuffer buf(m_descriptorStart);
385 buf.append(m_descriptorEnd);
386 return buf.makeStringAndClear();
390 class TypeInfo {
391 public:
392 enum Kind { KIND_MEMBER, KIND_ATTRIBUTE, KIND_METHOD, KIND_PARAMETER };
394 // Same values as in com/sun/star/lib/uno/typeinfo/TypeInfo.java:
395 enum Flags {
396 FLAG_READONLY = 0x008, FLAG_BOUND = 0x100
399 // KIND_MEMBER:
400 TypeInfo(
401 OString const & name, SpecialType specialType, sal_Int32 index,
402 PolymorphicUnoType const & polymorphicUnoType,
403 sal_Int32 typeParameterIndex);
405 // KIND_ATTRIBUTE/METHOD:
406 TypeInfo(
407 Kind kind, OString const & name, SpecialType specialType, Flags flags,
408 sal_Int32 index, PolymorphicUnoType const & polymorphicUnoType);
410 // KIND_PARAMETER:
411 TypeInfo(
412 OString const & parameterName, SpecialType specialType,
413 bool inParameter, bool outParameter, OString const & methodName,
414 sal_Int32 index, PolymorphicUnoType const & polymorphicUnoType);
416 sal_uInt16 generateCode(ClassFile::Code & code, Dependencies * dependencies)
417 const;
419 void generatePolymorphicUnoTypeCode(
420 ClassFile::Code & code, Dependencies * dependencies) const;
422 private:
423 Kind m_kind;
424 OString m_name;
425 sal_Int32 m_flags;
426 sal_Int32 m_index;
427 OString m_methodName;
428 PolymorphicUnoType m_polymorphicUnoType;
429 sal_Int32 m_typeParameterIndex;
432 sal_Int32 translateSpecialTypeFlags(
433 SpecialType specialType, bool inParameter, bool outParameter)
435 static sal_Int32 const specialTypeFlags[SPECIAL_TYPE_INTERFACE + 1] = {
436 0, 0x0040 /* ANY */, 0x0004 /* UNSIGNED */, 0x0080 /* INTERFACE */ };
437 sal_Int32 flags = specialTypeFlags[specialType];
438 if (inParameter) {
439 flags |= 0x0001; /* IN */
441 if (outParameter) {
442 flags |= 0x0002; /* OUT */
444 return flags;
447 TypeInfo::TypeInfo(
448 OString const & name, SpecialType specialType, sal_Int32 index,
449 PolymorphicUnoType const & polymorphicUnoType,
450 sal_Int32 typeParameterIndex):
451 m_kind(KIND_MEMBER), m_name(name),
452 m_flags(translateSpecialTypeFlags(specialType, false, false)),
453 m_index(index), m_polymorphicUnoType(polymorphicUnoType),
454 m_typeParameterIndex(typeParameterIndex)
456 assert(
457 polymorphicUnoType.kind == PolymorphicUnoType::KIND_NONE
458 ? typeParameterIndex >= -1 : typeParameterIndex == -1);
461 TypeInfo::TypeInfo(
462 Kind kind, OString const & name, SpecialType specialType, Flags flags,
463 sal_Int32 index, PolymorphicUnoType const & polymorphicUnoType):
464 m_kind(kind), m_name(name),
465 m_flags(flags | translateSpecialTypeFlags(specialType, false, false)),
466 m_index(index), m_polymorphicUnoType(polymorphicUnoType),
467 m_typeParameterIndex(0)
469 assert(kind == KIND_ATTRIBUTE || kind == KIND_METHOD);
472 TypeInfo::TypeInfo(
473 OString const & parameterName, SpecialType specialType, bool inParameter,
474 bool outParameter, OString const & methodName, sal_Int32 index,
475 PolymorphicUnoType const & polymorphicUnoType):
476 m_kind(KIND_PARAMETER), m_name(parameterName),
477 m_flags(translateSpecialTypeFlags(specialType, inParameter, outParameter)),
478 m_index(index), m_methodName(methodName),
479 m_polymorphicUnoType(polymorphicUnoType),
480 m_typeParameterIndex(0)
483 sal_uInt16 TypeInfo::generateCode(
484 ClassFile::Code & code, Dependencies * dependencies) const
486 switch (m_kind) {
487 case KIND_MEMBER:
488 code.instrNew("com/sun/star/lib/uno/typeinfo/MemberTypeInfo");
489 code.instrDup();
490 code.loadStringConstant(m_name);
491 code.loadIntegerConstant(m_index);
492 code.loadIntegerConstant(m_flags);
493 if (m_polymorphicUnoType.kind != PolymorphicUnoType::KIND_NONE) {
494 generatePolymorphicUnoTypeCode(code, dependencies);
495 code.loadIntegerConstant(m_typeParameterIndex);
496 code.instrInvokespecial(
497 "com/sun/star/lib/uno/typeinfo/MemberTypeInfo", "<init>",
498 "(Ljava/lang/String;IILcom/sun/star/uno/Type;I)V");
499 return 8;
500 } else if (m_typeParameterIndex >= 0) {
501 code.instrAconstNull();
502 code.loadIntegerConstant(m_typeParameterIndex);
503 code.instrInvokespecial(
504 "com/sun/star/lib/uno/typeinfo/MemberTypeInfo", "<init>",
505 "(Ljava/lang/String;IILcom/sun/star/uno/Type;I)V");
506 return 6;
507 } else {
508 code.instrInvokespecial(
509 "com/sun/star/lib/uno/typeinfo/MemberTypeInfo", "<init>",
510 "(Ljava/lang/String;II)V");
511 return 4;
513 case KIND_ATTRIBUTE:
514 code.instrNew("com/sun/star/lib/uno/typeinfo/AttributeTypeInfo");
515 code.instrDup();
516 code.loadStringConstant(m_name);
517 code.loadIntegerConstant(m_index);
518 code.loadIntegerConstant(m_flags);
519 if (m_polymorphicUnoType.kind != PolymorphicUnoType::KIND_NONE) {
520 generatePolymorphicUnoTypeCode(code, dependencies);
521 code.instrInvokespecial(
522 "com/sun/star/lib/uno/typeinfo/AttributeTypeInfo", "<init>",
523 "(Ljava/lang/String;IILcom/sun/star/uno/Type;)V");
524 return 8;
525 } else {
526 code.instrInvokespecial(
527 "com/sun/star/lib/uno/typeinfo/AttributeTypeInfo", "<init>",
528 "(Ljava/lang/String;II)V");
529 return 4;
531 case KIND_METHOD:
532 code.instrNew("com/sun/star/lib/uno/typeinfo/MethodTypeInfo");
533 code.instrDup();
534 code.loadStringConstant(m_name);
535 code.loadIntegerConstant(m_index);
536 code.loadIntegerConstant(m_flags);
537 if (m_polymorphicUnoType.kind != PolymorphicUnoType::KIND_NONE) {
538 generatePolymorphicUnoTypeCode(code, dependencies);
539 code.instrInvokespecial(
540 "com/sun/star/lib/uno/typeinfo/MethodTypeInfo", "<init>",
541 "(Ljava/lang/String;IILcom/sun/star/uno/Type;)V");
542 return 8;
543 } else {
544 code.instrInvokespecial(
545 "com/sun/star/lib/uno/typeinfo/MethodTypeInfo", "<init>",
546 "(Ljava/lang/String;II)V");
547 return 4;
549 case KIND_PARAMETER:
550 code.instrNew("com/sun/star/lib/uno/typeinfo/ParameterTypeInfo");
551 code.instrDup();
552 code.loadStringConstant(m_name);
553 code.loadStringConstant(m_methodName);
554 code.loadIntegerConstant(m_index);
555 code.loadIntegerConstant(m_flags);
556 if (m_polymorphicUnoType.kind != PolymorphicUnoType::KIND_NONE) {
557 generatePolymorphicUnoTypeCode(code, dependencies);
558 code.instrInvokespecial(
559 "com/sun/star/lib/uno/typeinfo/ParameterTypeInfo", "<init>",
560 ("(Ljava/lang/String;Ljava/lang/String;II"
561 "Lcom/sun/star/uno/Type;)V"));
562 return 9;
563 } else {
564 code.instrInvokespecial(
565 "com/sun/star/lib/uno/typeinfo/ParameterTypeInfo", "<init>",
566 "(Ljava/lang/String;Ljava/lang/String;II)V");
567 return 5;
569 default:
570 assert(false);
571 return 0;
575 void TypeInfo::generatePolymorphicUnoTypeCode(
576 ClassFile::Code & code, Dependencies * dependencies) const
578 assert(dependencies != nullptr);
579 assert(m_polymorphicUnoType.kind != PolymorphicUnoType::KIND_NONE);
580 code.instrNew("com/sun/star/uno/Type");
581 code.instrDup();
582 code.loadStringConstant(
583 codemaker::convertString(m_polymorphicUnoType.name));
584 if (m_polymorphicUnoType.kind == PolymorphicUnoType::KIND_STRUCT) {
585 code.instrGetstatic(
586 "com/sun/star/uno/TypeClass", "STRUCT",
587 "Lcom/sun/star/uno/TypeClass;");
588 } else {
589 code.instrGetstatic(
590 "com/sun/star/uno/TypeClass", "SEQUENCE",
591 "Lcom/sun/star/uno/TypeClass;");
593 dependencies->insert("com.sun.star.uno.TypeClass");
594 code.instrInvokespecial(
595 "com/sun/star/uno/Type", "<init>",
596 "(Ljava/lang/String;Lcom/sun/star/uno/TypeClass;)V");
599 void writeClassFile(
600 JavaOptions const & options, OString const & type,
601 ClassFile const & classFile)
603 OString path;
604 if (options.isValid("-O")) {
605 path = options.getOption("-O");
607 OString filename(createFileNameFromType(path, type, ".class"));
608 bool bCheck = false;
609 if (fileExists(filename)) {
610 if (options.isValid("-G")) {
611 return;
613 bCheck = options.isValid("-Gc");
615 FileStream tempfile;
616 tempfile.createTempFile(getTempDir(filename));
617 if (!tempfile.isValid()) {
618 throw CannotDumpException(
619 "Cannot create temporary file for " + b2u(filename));
621 OString tempname(tempfile.getName());
622 try {
623 classFile.write(tempfile);
624 } catch (...) {
625 // Remove existing file for consistency:
626 if (fileExists(filename)) {
627 removeTypeFile(filename);
629 tempfile.close();
630 removeTypeFile(tempname);
631 throw;
633 tempfile.close();
634 if (!makeValidTypeFile(filename, tempname, bCheck)) {
635 throw CannotDumpException(
636 "Cannot create " + b2u(filename) + " from temporary file "
637 + b2u(tempname));
641 void addTypeInfo(
642 OString const & className, std::vector< TypeInfo > const & typeInfo,
643 Dependencies * dependencies, ClassFile * classFile)
645 assert(classFile != nullptr);
646 std::vector< TypeInfo >::size_type typeInfos = typeInfo.size();
647 if (typeInfos > SAL_MAX_INT32) {
648 throw CannotDumpException(
649 "UNOTYPEINFO array too big for Java class file format");
651 if (typeInfos != 0) {
652 classFile->addField(
653 static_cast< ClassFile::AccessFlags >(
654 ClassFile::ACC_PUBLIC | ClassFile::ACC_STATIC
655 | ClassFile::ACC_FINAL),
656 "UNOTYPEINFO", "[Lcom/sun/star/lib/uno/typeinfo/TypeInfo;",
657 0, "");
658 std::unique_ptr< ClassFile::Code > code(classFile->newCode());
659 code->loadIntegerConstant(static_cast< sal_Int32 >(typeInfos));
660 code->instrAnewarray("com/sun/star/lib/uno/typeinfo/TypeInfo");
661 sal_Int32 index = 0;
662 sal_uInt16 stack = 0;
663 for (const TypeInfo& ti : typeInfo)
665 code->instrDup();
666 code->loadIntegerConstant(index++);
667 stack = std::max(stack, ti.generateCode(*code, dependencies));
668 code->instrAastore();
670 code->instrPutstatic(
671 className, "UNOTYPEINFO",
672 "[Lcom/sun/star/lib/uno/typeinfo/TypeInfo;");
673 code->instrReturn();
674 if (stack > SAL_MAX_UINT16 - 4) {
675 throw CannotDumpException(
676 "Stack too big for Java class file format");
678 code->setMaxStackAndLocals(static_cast< sal_uInt16 >(stack + 4), 0);
679 classFile->addMethod(
680 static_cast< ClassFile::AccessFlags >(
681 ClassFile::ACC_PRIVATE | ClassFile::ACC_STATIC),
682 "<clinit>", "()V", code.get(), std::vector< OString >(), "");
686 void handleEnumType(
687 const OUString& name, rtl::Reference< unoidl::EnumTypeEntity > const & entity,
688 JavaOptions const & options)
690 assert(entity.is());
691 OString className(codemaker::convertString(name).replace('.', '/'));
692 std::unique_ptr< ClassFile > cf(
693 new ClassFile(
694 static_cast< ClassFile::AccessFlags >(
695 ClassFile::ACC_PUBLIC | ClassFile::ACC_FINAL
696 | ClassFile::ACC_SUPER),
697 className, "com/sun/star/uno/Enum", ""));
698 OString classDescriptor("L" + className + ";");
699 for (const unoidl::EnumTypeEntity::Member& member : entity->getMembers())
701 OString fieldName(codemaker::convertString(member.name));
702 cf->addField(
703 static_cast< ClassFile::AccessFlags >(
704 ClassFile::ACC_PUBLIC | ClassFile::ACC_STATIC
705 | ClassFile::ACC_FINAL),
706 fieldName, classDescriptor, 0, OString());
707 cf->addField(
708 static_cast< ClassFile::AccessFlags >(
709 ClassFile::ACC_PUBLIC | ClassFile::ACC_STATIC
710 | ClassFile::ACC_FINAL),
711 fieldName + "_value", "I",
712 cf->addIntegerInfo(member.value), "");
714 std::unique_ptr< ClassFile::Code > code(cf->newCode());
715 code->loadLocalReference(0);
716 code->loadLocalInteger(1);
717 code->instrInvokespecial("com/sun/star/uno/Enum", "<init>", "(I)V");
718 code->instrReturn();
719 code->setMaxStackAndLocals(2, 2);
720 cf->addMethod(
721 ClassFile::ACC_PRIVATE,
722 "<init>", "(I)V", code.get(),
723 std::vector< OString >(), "");
724 code.reset(cf->newCode());
725 code->instrGetstatic(
726 className,
727 codemaker::convertString(entity->getMembers()[0].name),
728 classDescriptor);
729 code->instrAreturn();
730 code->setMaxStackAndLocals(1, 0);
731 cf->addMethod(
732 static_cast< ClassFile::AccessFlags >(
733 ClassFile::ACC_PUBLIC | ClassFile::ACC_STATIC),
734 "getDefault", "()" + classDescriptor,
735 code.get(), std::vector< OString >(), "");
736 code.reset(cf->newCode());
737 code->loadLocalInteger(0);
738 std::map< sal_Int32, OString > map;
739 sal_Int32 min = SAL_MAX_INT32;
740 sal_Int32 max = SAL_MIN_INT32;
741 for (const unoidl::EnumTypeEntity::Member& member : entity->getMembers())
743 min = std::min(min, member.value);
744 max = std::max(max, member.value);
745 map.insert(
746 std::map< sal_Int32, OString >::value_type(
747 member.value, codemaker::convertString(member.name)));
749 sal_uInt64 size = static_cast< sal_uInt64 >(map.size());
750 if ((static_cast< sal_uInt64 >(max) - static_cast< sal_uInt64 >(min)
751 <= 2 * size)
752 || size > SAL_MAX_INT32)
754 std::unique_ptr< ClassFile::Code > defCode(cf->newCode());
755 defCode->instrAconstNull();
756 defCode->instrAreturn();
757 std::list< ClassFile::Code * > blocks;
758 //FIXME: pointers contained in blocks may leak
759 sal_Int32 last = SAL_MAX_INT32;
760 for (const auto& pair : map)
762 sal_Int32 value = pair.first;
763 if (last != SAL_MAX_INT32) {
764 for (sal_Int32 j = last + 1; j < value; ++j) {
765 blocks.push_back(nullptr);
768 last = value;
769 std::unique_ptr< ClassFile::Code > blockCode(cf->newCode());
770 blockCode->instrGetstatic(className, pair.second, classDescriptor);
771 blockCode->instrAreturn();
772 blocks.push_back(blockCode.get());
773 blockCode.release();
775 code->instrTableswitch(defCode.get(), min, blocks);
776 for (ClassFile::Code *p : blocks)
778 delete p;
780 } else{
781 std::unique_ptr< ClassFile::Code > defCode(cf->newCode());
782 defCode->instrAconstNull();
783 defCode->instrAreturn();
784 std::list< std::pair< sal_Int32, ClassFile::Code * > > blocks;
785 //FIXME: pointers contained in blocks may leak
786 for (const auto& pair : map )
788 std::unique_ptr< ClassFile::Code > blockCode(cf->newCode());
789 blockCode->instrGetstatic(className, pair.second, classDescriptor);
790 blockCode->instrAreturn();
791 blocks.push_back(std::make_pair(pair.first, blockCode.get()));
792 blockCode.release();
794 code->instrLookupswitch(defCode.get(), blocks);
795 for (const std::pair< sal_Int32, ClassFile::Code * >& pair : blocks)
797 delete pair.second;
800 code->setMaxStackAndLocals(1, 1);
801 cf->addMethod(
802 static_cast< ClassFile::AccessFlags >(
803 ClassFile::ACC_PUBLIC | ClassFile::ACC_STATIC),
804 "fromInt", "(I)" + classDescriptor, code.get(),
805 std::vector< OString >(), "");
806 code.reset(cf->newCode());
807 for (const unoidl::EnumTypeEntity::Member& member : entity->getMembers())
809 code->instrNew(className);
810 code->instrDup();
811 code->loadIntegerConstant(member.value);
812 code->instrInvokespecial(className, "<init>", "(I)V");
813 code->instrPutstatic(
814 className, codemaker::convertString(member.name), classDescriptor);
816 code->instrReturn();
817 code->setMaxStackAndLocals(3, 0);
818 cf->addMethod(
819 static_cast< ClassFile::AccessFlags >(
820 ClassFile::ACC_PRIVATE | ClassFile::ACC_STATIC),
821 "<clinit>", "()V", code.get(), std::vector< OString >(), "");
822 writeClassFile(options, className, *cf.get());
825 void addField(
826 rtl::Reference< TypeManager > const & manager, Dependencies * dependencies,
827 ClassFile * classFile, std::vector< TypeInfo > * typeInfo,
828 sal_Int32 typeParameterIndex, OUString const & type, OUString const & name,
829 sal_Int32 index)
831 assert(classFile != nullptr);
832 assert(typeInfo != nullptr);
833 OString descriptor;
834 OString signature;
835 SpecialType specialType;
836 PolymorphicUnoType polymorphicUnoType;
837 if (typeParameterIndex >= 0) {
838 descriptor = "Ljava/lang/Object;";
839 signature = "T" + codemaker::convertString(type).replace('.', '/')
840 + ";";
841 specialType = SPECIAL_TYPE_NONE; //TODO: SPECIAL_TYPE_TYPE_PARAMETER?
842 } else {
843 specialType = getFieldDescriptor(
844 manager, dependencies, type, &descriptor, &signature,
845 &polymorphicUnoType);
847 classFile->addField(
848 ClassFile::ACC_PUBLIC, codemaker::convertString(name), descriptor, 0,
849 signature);
850 typeInfo->push_back(
851 TypeInfo(
852 codemaker::convertString(name), specialType, index,
853 polymorphicUnoType, typeParameterIndex));
856 sal_uInt16 addFieldInit(
857 rtl::Reference< TypeManager > const & manager, OString const & className,
858 OUString const & fieldName, bool typeParameter, OUString const & fieldType,
859 Dependencies * dependencies, ClassFile::Code * code)
861 assert(manager.is());
862 assert(code != nullptr);
863 if (typeParameter) {
864 return 0;
866 OString name(codemaker::convertString(fieldName));
867 OUString nucleus;
868 sal_Int32 rank;
869 std::vector< rtl::OUString > args;
870 rtl::Reference< unoidl::Entity > ent;
871 codemaker::UnoType::Sort sort = manager->decompose(
872 fieldType, true, &nucleus, &rank, &args, &ent);
873 if (rank == 0) {
874 switch (sort) {
875 case codemaker::UnoType::Sort::Boolean:
876 case codemaker::UnoType::Sort::Byte:
877 case codemaker::UnoType::Sort::Short:
878 case codemaker::UnoType::Sort::UnsignedShort:
879 case codemaker::UnoType::Sort::Long:
880 case codemaker::UnoType::Sort::UnsignedLong:
881 case codemaker::UnoType::Sort::Hyper:
882 case codemaker::UnoType::Sort::UnsignedHyper:
883 case codemaker::UnoType::Sort::Float:
884 case codemaker::UnoType::Sort::Double:
885 case codemaker::UnoType::Sort::Char:
886 case codemaker::UnoType::Sort::Interface:
887 return 0;
888 case codemaker::UnoType::Sort::String:
889 code->loadLocalReference(0);
890 code->loadStringConstant(OString());
891 code->instrPutfield(className, name, "Ljava/lang/String;");
892 return 2;
893 case codemaker::UnoType::Sort::Type:
894 code->loadLocalReference(0);
895 code->instrGetstatic(
896 "com/sun/star/uno/Type", "VOID", "Lcom/sun/star/uno/Type;");
897 code->instrPutfield(className, name, "Lcom/sun/star/uno/Type;");
898 return 2;
899 case codemaker::UnoType::Sort::Any:
900 code->loadLocalReference(0);
901 code->instrGetstatic(
902 "com/sun/star/uno/Any", "VOID", "Lcom/sun/star/uno/Any;");
903 code->instrPutfield(className, name, "Ljava/lang/Object;");
904 return 2;
905 case codemaker::UnoType::Sort::Enum:
907 rtl::Reference< unoidl::EnumTypeEntity > ent2(
908 dynamic_cast< unoidl::EnumTypeEntity * >(ent.get()));
909 assert(ent2.is());
910 code->loadLocalReference(0);
911 OStringBuffer descBuf;
912 translateUnoTypeToDescriptor(
913 manager, sort, nucleus, 0, std::vector< OUString >(), false,
914 false, dependencies, &descBuf, nullptr, nullptr, nullptr);
915 OString desc(descBuf.makeStringAndClear());
916 code->instrGetstatic(
917 codemaker::convertString(nucleus).replace('.', '/'),
918 codemaker::convertString(ent2->getMembers()[0].name), desc);
919 code->instrPutfield(className, name, desc);
920 return 2;
922 case codemaker::UnoType::Sort::PlainStruct:
923 case codemaker::UnoType::Sort::InstantiatedPolymorphicStruct:
925 code->loadLocalReference(0);
926 code->instrNew(
927 codemaker::convertString(nucleus).replace('.', '/'));
928 code->instrDup();
929 code->instrInvokespecial(
930 codemaker::convertString(nucleus).replace('.', '/'),
931 "<init>", "()V");
932 OStringBuffer desc;
933 translateUnoTypeToDescriptor(
934 manager, sort, nucleus, 0, args, false, false, dependencies,
935 &desc, nullptr, nullptr, nullptr);
936 code->instrPutfield(className, name, desc.makeStringAndClear());
937 return 3;
939 case codemaker::UnoType::Sort::Sequence:
940 case codemaker::UnoType::Sort::Typedef:
941 for (;;) std::abort(); // this cannot happen
942 default:
943 throw CannotDumpException(
944 "unexpected entity \"" + fieldType
945 + "\" in call to addFieldInit");
948 code->loadLocalReference(0);
949 code->loadIntegerConstant(0);
950 if (rank == 1) {
951 if (sort >= codemaker::UnoType::Sort::Boolean
952 && sort <= codemaker::UnoType::Sort::Char)
954 code->instrNewarray(sort);
955 } else {
956 code->instrAnewarray(
957 codemaker::java::translateUnoToJavaType(
958 sort, codemaker::convertString(nucleus).replace('.', '/'),
959 false));
961 } else {
962 OStringBuffer desc;
963 translateUnoTypeToDescriptor(
964 manager, sort, nucleus, rank - 1, std::vector< OUString >(), false,
965 false, dependencies, &desc, nullptr, nullptr, nullptr);
966 code->instrAnewarray(desc.makeStringAndClear());
968 OStringBuffer desc;
969 translateUnoTypeToDescriptor(
970 manager, sort, nucleus, rank, std::vector< OUString >(), false, false,
971 dependencies, &desc, nullptr, nullptr, nullptr);
972 code->instrPutfield(className, name, desc.makeStringAndClear());
973 return 2;
976 sal_uInt16 addLoadLocal(
977 rtl::Reference< TypeManager > const & manager, ClassFile::Code * code,
978 sal_uInt16 * index, bool typeParameter, OUString const & type, bool any,
979 Dependencies * dependencies)
981 assert(manager.is());
982 assert(code != nullptr);
983 assert(index != nullptr);
984 assert(!(typeParameter && any));
985 assert(dependencies != nullptr);
986 sal_uInt16 stack = 1;
987 sal_uInt16 size = 1;
988 if (typeParameter) {
989 code->loadLocalReference(*index);
990 stack = size = 1;
991 } else {
992 OUString nucleus;
993 sal_Int32 rank;
994 std::vector< OUString > args;
995 codemaker::UnoType::Sort sort = manager->decompose(
996 type, true, &nucleus, &rank, &args, nullptr);
997 if (rank == 0) {
998 switch (sort) {
999 case codemaker::UnoType::Sort::Boolean:
1000 if (any) {
1001 code->instrNew("java/lang/Boolean");
1002 code->instrDup();
1003 code->loadLocalInteger(*index);
1004 code->instrInvokespecial(
1005 "java/lang/Boolean", "<init>", "(Z)V");
1006 stack = 3;
1007 } else {
1008 code->loadLocalInteger(*index);
1009 stack = 1;
1011 size = 1;
1012 break;
1013 case codemaker::UnoType::Sort::Byte:
1014 if (any) {
1015 code->instrNew("java/lang/Byte");
1016 code->instrDup();
1017 code->loadLocalInteger(*index);
1018 code->instrInvokespecial(
1019 "java/lang/Byte", "<init>", "(B)V");
1020 stack = 3;
1021 } else {
1022 code->loadLocalInteger(*index);
1023 stack = 1;
1025 size = 1;
1026 break;
1027 case codemaker::UnoType::Sort::Short:
1028 if (any) {
1029 code->instrNew("java/lang/Short");
1030 code->instrDup();
1031 code->loadLocalInteger(*index);
1032 code->instrInvokespecial(
1033 "java/lang/Short", "<init>", "(S)V");
1034 stack = 3;
1035 } else {
1036 code->loadLocalInteger(*index);
1037 stack = 1;
1039 size = 1;
1040 break;
1041 case codemaker::UnoType::Sort::UnsignedShort:
1042 if (any) {
1043 code->instrNew("com/sun/star/uno/Any");
1044 code->instrDup();
1045 code->instrGetstatic(
1046 "com/sun/star/uno/Type", "UNSIGNED_SHORT",
1047 "Lcom/sun/star/uno/Type;");
1048 code->instrNew("java/lang/Short");
1049 code->instrDup();
1050 code->loadLocalInteger(*index);
1051 code->instrInvokespecial(
1052 "java/lang/Short", "<init>", "(S)V");
1053 code->instrInvokespecial(
1054 "com/sun/star/uno/Any", "<init>",
1055 "(Lcom/sun/star/uno/Type;Ljava/lang/Object;)V");
1056 stack = 6;
1057 } else {
1058 code->loadLocalInteger(*index);
1059 stack = 1;
1061 size = 1;
1062 break;
1063 case codemaker::UnoType::Sort::Long:
1064 if (any) {
1065 code->instrNew("java/lang/Integer");
1066 code->instrDup();
1067 code->loadLocalInteger(*index);
1068 code->instrInvokespecial(
1069 "java/lang/Integer", "<init>", "(I)V");
1070 stack = 3;
1071 } else {
1072 code->loadLocalInteger(*index);
1073 stack = 1;
1075 size = 1;
1076 break;
1077 case codemaker::UnoType::Sort::UnsignedLong:
1078 if (any) {
1079 code->instrNew("com/sun/star/uno/Any");
1080 code->instrDup();
1081 code->instrGetstatic(
1082 "com/sun/star/uno/Type", "UNSIGNED_LONG",
1083 "Lcom/sun/star/uno/Type;");
1084 code->instrNew("java/lang/Integer");
1085 code->instrDup();
1086 code->loadLocalInteger(*index);
1087 code->instrInvokespecial(
1088 "java/lang/Integer", "<init>", "(I)V");
1089 code->instrInvokespecial(
1090 "com/sun/star/uno/Any", "<init>",
1091 "(Lcom/sun/star/uno/Type;Ljava/lang/Object;)V");
1092 stack = 6;
1093 } else {
1094 code->loadLocalInteger(*index);
1095 stack = 1;
1097 size = 1;
1098 break;
1099 case codemaker::UnoType::Sort::Hyper:
1100 if (any) {
1101 code->instrNew("java/lang/Long");
1102 code->instrDup();
1103 code->loadLocalLong(*index);
1104 code->instrInvokespecial(
1105 "java/lang/Long", "<init>", "(J)V");
1106 stack = 4;
1107 } else {
1108 code->loadLocalLong(*index);
1109 stack = 2;
1111 size = 2;
1112 break;
1113 case codemaker::UnoType::Sort::UnsignedHyper:
1114 if (any) {
1115 code->instrNew("com/sun/star/uno/Any");
1116 code->instrDup();
1117 code->instrGetstatic(
1118 "com/sun/star/uno/Type", "UNSIGNED_HYPER",
1119 "Lcom/sun/star/uno/Type;");
1120 code->instrNew("java/lang/Long");
1121 code->instrDup();
1122 code->loadLocalLong(*index);
1123 code->instrInvokespecial(
1124 "java/lang/Long", "<init>", "(J)V");
1125 code->instrInvokespecial(
1126 "com/sun/star/uno/Any", "<init>",
1127 "(Lcom/sun/star/uno/Type;Ljava/lang/Object;)V");
1128 stack = 7;
1129 } else {
1130 code->loadLocalLong(*index);
1131 stack = 2;
1133 size = 2;
1134 break;
1135 case codemaker::UnoType::Sort::Float:
1136 if (any) {
1137 code->instrNew("java/lang/Float");
1138 code->instrDup();
1139 code->loadLocalFloat(*index);
1140 code->instrInvokespecial(
1141 "java/lang/Float", "<init>", "(F)V");
1142 stack = 3;
1143 } else {
1144 code->loadLocalFloat(*index);
1145 stack = 1;
1147 size = 1;
1148 break;
1149 case codemaker::UnoType::Sort::Double:
1150 if (any) {
1151 code->instrNew("java/lang/Double");
1152 code->instrDup();
1153 code->loadLocalDouble(*index);
1154 code->instrInvokespecial(
1155 "java/lang/Double", "<init>", "(D)V");
1156 stack = 4;
1157 } else {
1158 code->loadLocalDouble(*index);
1159 stack = 2;
1161 size = 2;
1162 break;
1163 case codemaker::UnoType::Sort::Char:
1164 if (any) {
1165 code->instrNew("java/lang/Character");
1166 code->instrDup();
1167 code->loadLocalInteger(*index);
1168 code->instrInvokespecial(
1169 "java/lang/Character", "<init>", "(C)V");
1170 stack = 3;
1171 } else {
1172 code->loadLocalInteger(*index);
1173 stack = 1;
1175 size = 1;
1176 break;
1177 case codemaker::UnoType::Sort::String:
1178 case codemaker::UnoType::Sort::Type:
1179 case codemaker::UnoType::Sort::Any:
1180 code->loadLocalReference(*index);
1181 stack = size = 1;
1182 break;
1183 case codemaker::UnoType::Sort::Enum:
1184 // Assuming that no Java types are derived from Java types that
1185 // are directly derived from com.sun.star.uno.Enum:
1186 code->loadLocalReference(*index);
1187 stack = size = 1;
1188 break;
1189 case codemaker::UnoType::Sort::PlainStruct:
1190 case codemaker::UnoType::Sort::InstantiatedPolymorphicStruct:
1191 if (any) {
1192 code->instrNew("com/sun/star/uno/Any");
1193 code->instrDup();
1194 code->instrNew("com/sun/star/uno/Type");
1195 code->instrDup();
1196 code->loadStringConstant(
1197 codemaker::convertString(
1198 createUnoName(manager, nucleus, rank, args)));
1199 code->instrGetstatic(
1200 "com/sun/star/uno/TypeClass", "STRUCT",
1201 "Lcom/sun/star/uno/TypeClass;");
1202 dependencies->insert("com.sun.star.uno.TypeClass");
1203 code->instrInvokespecial(
1204 "com/sun/star/uno/Type", "<init>",
1205 "(Ljava/lang/String;Lcom/sun/star/uno/TypeClass;)V");
1206 code->loadLocalReference(*index);
1207 code->instrInvokespecial(
1208 "com/sun/star/uno/Any", "<init>",
1209 "(Lcom/sun/star/uno/Type;Ljava/lang/Object;)V");
1210 stack = 6;
1211 } else {
1212 code->loadLocalReference(*index);
1213 stack = 1;
1215 size = 1;
1216 break;
1217 case codemaker::UnoType::Sort::Interface:
1218 if (any && nucleus != "com.sun.star.uno.XInterface") {
1219 code->instrNew("com/sun/star/uno/Any");
1220 code->instrDup();
1221 code->instrNew("com/sun/star/uno/Type");
1222 code->instrDup();
1223 code->loadStringConstant(codemaker::convertString(nucleus));
1224 code->instrGetstatic(
1225 "com/sun/star/uno/TypeClass", "INTERFACE",
1226 "Lcom/sun/star/uno/TypeClass;");
1227 dependencies->insert("com.sun.star.uno.TypeClass");
1228 code->instrInvokespecial(
1229 "com/sun/star/uno/Type", "<init>",
1230 "(Ljava/lang/String;Lcom/sun/star/uno/TypeClass;)V");
1231 code->loadLocalReference(*index);
1232 code->instrInvokespecial(
1233 "com/sun/star/uno/Any", "<init>",
1234 "(Lcom/sun/star/uno/Type;Ljava/lang/Object;)V");
1235 stack = 6;
1236 } else {
1237 code->loadLocalReference(*index);
1238 stack = 1;
1240 size = 1;
1241 break;
1242 case codemaker::UnoType::Sort::Sequence:
1243 case codemaker::UnoType::Sort::Typedef:
1244 for (;;) std::abort(); // this cannot happen
1245 default:
1246 throw CannotDumpException(
1247 "unexpected entity \"" + type
1248 + "\" in call to addLoadLocal");
1250 } else {
1251 bool bWrap = false;
1252 if (any) {
1253 switch (sort) {
1254 case codemaker::UnoType::Sort::Boolean:
1255 case codemaker::UnoType::Sort::Byte:
1256 case codemaker::UnoType::Sort::Short:
1257 case codemaker::UnoType::Sort::Long:
1258 case codemaker::UnoType::Sort::Hyper:
1259 case codemaker::UnoType::Sort::Float:
1260 case codemaker::UnoType::Sort::Double:
1261 case codemaker::UnoType::Sort::Char:
1262 case codemaker::UnoType::Sort::String:
1263 case codemaker::UnoType::Sort::Type:
1264 // assuming that no Java types are derived from
1265 // com.sun.star.uno.Type
1266 case codemaker::UnoType::Sort::Enum:
1267 // assuming that no Java types are derived from Java
1268 // types that are directly derived from
1269 // com.sun.star.uno.Enum
1270 break;
1271 case codemaker::UnoType::Sort::UnsignedShort:
1272 case codemaker::UnoType::Sort::UnsignedLong:
1273 case codemaker::UnoType::Sort::UnsignedHyper:
1274 case codemaker::UnoType::Sort::Any:
1275 case codemaker::UnoType::Sort::PlainStruct:
1276 case codemaker::UnoType::Sort::InstantiatedPolymorphicStruct:
1277 case codemaker::UnoType::Sort::Interface:
1278 bWrap = true;
1279 break;
1280 case codemaker::UnoType::Sort::Sequence:
1281 case codemaker::UnoType::Sort::Typedef:
1282 for (;;) std::abort(); // this cannot happen
1283 default:
1284 throw CannotDumpException(
1285 "unexpected entity \"" + type
1286 + "\" in call to addLoadLocal");
1289 if (bWrap) {
1290 code->instrNew("com/sun/star/uno/Any");
1291 code->instrDup();
1292 code->instrNew("com/sun/star/uno/Type");
1293 code->instrDup();
1294 code->loadStringConstant(
1295 codemaker::convertString(
1296 createUnoName(manager, nucleus, rank, args)));
1297 code->instrInvokespecial(
1298 "com/sun/star/uno/Type", "<init>", "(Ljava/lang/String;)V");
1299 code->loadLocalReference(*index);
1300 code->instrInvokespecial(
1301 "com/sun/star/uno/Any", "<init>",
1302 "(Lcom/sun/star/uno/Type;Ljava/lang/Object;)V");
1303 stack = 5;
1304 } else {
1305 code->loadLocalReference(*index);
1306 stack = 1;
1308 size = 1;
1311 if (*index > SAL_MAX_UINT16 - size) {
1312 throw CannotDumpException(
1313 "Too many local variables for Java class file format");
1315 *index = *index + size;
1316 return stack;
1319 sal_uInt16 addDirectArgument(
1320 rtl::Reference< TypeManager > const & manager, Dependencies * dependencies,
1321 MethodDescriptor * methodDescriptor, ClassFile::Code * code,
1322 sal_uInt16 * index, OString const & className, OString const & fieldName,
1323 bool typeParameter, OUString const & fieldType)
1325 assert(methodDescriptor != nullptr);
1326 assert(code != nullptr);
1327 OString desc;
1328 if (typeParameter) {
1329 methodDescriptor->addTypeParameter(fieldType);
1330 desc = "Ljava/lang/Object;";
1331 } else {
1332 methodDescriptor->addParameter(fieldType, false, true, nullptr);
1333 getFieldDescriptor(manager, dependencies, fieldType, &desc, nullptr, nullptr);
1335 code->loadLocalReference(0);
1336 sal_uInt16 stack = addLoadLocal(
1337 manager, code, index, typeParameter, fieldType, false, dependencies);
1338 code->instrPutfield(className, fieldName, desc);
1339 return stack + 1;
1342 void addPlainStructBaseArguments(
1343 rtl::Reference< TypeManager > const & manager, Dependencies * dependencies,
1344 MethodDescriptor * methodDescriptor, ClassFile::Code * code,
1345 OUString const & base, sal_uInt16 * index)
1347 assert(manager.is());
1348 assert(methodDescriptor != nullptr);
1349 rtl::Reference< unoidl::Entity > ent;
1350 if (manager->getSort(base, &ent)
1351 != codemaker::UnoType::Sort::PlainStruct)
1353 throw CannotDumpException(
1354 "unexpected entity \"" + base
1355 + "\" in call to addPlainStructBaseArguments");
1357 unoidl::PlainStructTypeEntity& ent2(
1358 dynamic_cast<unoidl::PlainStructTypeEntity&>(*ent.get()));
1359 if (!ent2.getDirectBase().isEmpty()) {
1360 addPlainStructBaseArguments(
1361 manager, dependencies, methodDescriptor, code,
1362 ent2.getDirectBase(), index);
1364 for (const unoidl::PlainStructTypeEntity::Member& member : ent2.getDirectMembers())
1366 methodDescriptor->addParameter(member.type, false, true, nullptr);
1367 addLoadLocal(manager, code, index, false, member.type, false, dependencies);
1371 void handlePlainStructType(
1372 const OUString& name,
1373 rtl::Reference< unoidl::PlainStructTypeEntity > const & entity,
1374 rtl::Reference< TypeManager > const & manager, JavaOptions const & options,
1375 Dependencies * dependencies)
1377 assert(entity.is());
1378 assert(dependencies != nullptr);
1379 OString className(codemaker::convertString(name).replace('.', '/'));
1380 OString superClass;
1381 if (entity->getDirectBase().isEmpty()) {
1382 superClass = "java/lang/Object";
1383 } else {
1384 superClass = codemaker::convertString(entity->getDirectBase()).
1385 replace('.', '/');
1386 dependencies->insert(entity->getDirectBase());
1388 std::unique_ptr< ClassFile > cf(
1389 new ClassFile(
1390 static_cast< ClassFile::AccessFlags >(
1391 ClassFile::ACC_PUBLIC | ClassFile::ACC_SUPER),
1392 className, superClass, ""));
1393 std::vector< TypeInfo > typeInfo;
1394 sal_Int32 index = 0;
1395 for (const unoidl::PlainStructTypeEntity::Member& member : entity->getDirectMembers())
1397 addField(
1398 manager, dependencies, cf.get(), &typeInfo, -1, member.type, member.name,
1399 index++);
1401 std::unique_ptr< ClassFile::Code > code(cf->newCode());
1402 code->loadLocalReference(0);
1403 code->instrInvokespecial(superClass, "<init>", "()V");
1404 sal_uInt16 stack = 0;
1405 for (const unoidl::PlainStructTypeEntity::Member& member : entity->getDirectMembers())
1407 stack = std::max(
1408 stack,
1409 addFieldInit(
1410 manager, className, member.name, false, member.type, dependencies,
1411 code.get()));
1413 code->instrReturn();
1414 code->setMaxStackAndLocals(stack + 1, 1);
1415 cf->addMethod(
1416 ClassFile::ACC_PUBLIC, "<init>", "()V", code.get(),
1417 std::vector< OString >(), "");
1418 MethodDescriptor desc(manager, dependencies, "void", nullptr, nullptr);
1419 code.reset(cf->newCode());
1420 code->loadLocalReference(0);
1421 sal_uInt16 index2 = 1;
1422 if (!entity->getDirectBase().isEmpty()) {
1423 addPlainStructBaseArguments(
1424 manager, dependencies, &desc, code.get(), entity->getDirectBase(),
1425 &index2);
1427 code->instrInvokespecial(superClass, "<init>", desc.getDescriptor());
1428 sal_uInt16 maxSize = index2;
1429 for (const unoidl::PlainStructTypeEntity::Member& member : entity->getDirectMembers())
1431 maxSize = std::max(
1432 maxSize,
1433 addDirectArgument(
1434 manager, dependencies, &desc, code.get(), &index2, className,
1435 codemaker::convertString(member.name), false, member.type));
1437 code->instrReturn();
1438 code->setMaxStackAndLocals(maxSize, index2);
1439 cf->addMethod(
1440 ClassFile::ACC_PUBLIC, "<init>", desc.getDescriptor(), code.get(),
1441 std::vector< OString >(), desc.getSignature());
1442 addTypeInfo(className, typeInfo, dependencies, cf.get());
1443 writeClassFile(options, className, *cf.get());
1446 void handlePolyStructType(
1447 const OUString& name,
1448 rtl::Reference< unoidl::PolymorphicStructTypeTemplateEntity > const &
1449 entity,
1450 rtl::Reference< TypeManager > const & manager, JavaOptions const & options,
1451 Dependencies * dependencies)
1453 assert(entity.is());
1454 OString className(codemaker::convertString(name).replace('.', '/'));
1455 std::map< OUString, sal_Int32 > typeParameters;
1456 OStringBuffer sig("<");
1457 sal_Int32 index = 0;
1458 for (const OUString& param : entity->getTypeParameters())
1460 sig.append(codemaker::convertString(param) + ":Ljava/lang/Object;");
1461 if (!typeParameters.insert(
1462 std::map< OUString, sal_Int32 >::value_type(param, index++)).second)
1464 throw CannotDumpException("Bad type information"); //TODO
1467 sig.append(">Ljava/lang/Object;");
1468 std::unique_ptr< ClassFile > cf(
1469 new ClassFile(
1470 static_cast< ClassFile::AccessFlags >(
1471 ClassFile::ACC_PUBLIC | ClassFile::ACC_SUPER),
1472 className, "java/lang/Object", sig.makeStringAndClear()));
1473 std::vector< TypeInfo > typeInfo;
1474 index = 0;
1475 for (const unoidl::PolymorphicStructTypeTemplateEntity::Member& member : entity->getMembers())
1477 sal_Int32 typeParameterIndex;
1478 if (member.parameterized) {
1479 std::map< OUString, sal_Int32 >::iterator it(
1480 typeParameters.find(member.type));
1481 if (it == typeParameters.end()) {
1482 throw CannotDumpException("Bad type information"); //TODO
1484 typeParameterIndex = it->second;
1485 } else {
1486 typeParameterIndex = -1;
1488 addField(
1489 manager, dependencies, cf.get(), &typeInfo, typeParameterIndex,
1490 member.type, member.name, index++);
1492 std::unique_ptr< ClassFile::Code > code(cf->newCode());
1493 code->loadLocalReference(0);
1494 code->instrInvokespecial("java/lang/Object", "<init>", "()V");
1495 sal_uInt16 stack = 0;
1496 for (const unoidl::PolymorphicStructTypeTemplateEntity::Member& member : entity->getMembers())
1498 stack = std::max(
1499 stack,
1500 addFieldInit(
1501 manager, className, member.name, member.parameterized, member.type,
1502 dependencies, code.get()));
1504 code->instrReturn();
1505 code->setMaxStackAndLocals(stack + 1, 1);
1506 cf->addMethod(
1507 ClassFile::ACC_PUBLIC, "<init>", "()V", code.get(),
1508 std::vector< OString >(), "");
1509 MethodDescriptor desc(manager, dependencies, "void", nullptr, nullptr);
1510 code.reset(cf->newCode());
1511 code->loadLocalReference(0);
1512 sal_uInt16 index2 = 1;
1513 code->instrInvokespecial(
1514 "java/lang/Object", "<init>", desc.getDescriptor());
1515 sal_uInt16 maxSize = index2;
1516 for (const unoidl::PolymorphicStructTypeTemplateEntity::Member& member : entity->getMembers())
1518 maxSize = std::max(
1519 maxSize,
1520 addDirectArgument(
1521 manager, dependencies, &desc, code.get(), &index2, className,
1522 codemaker::convertString(member.name), member.parameterized, member.type));
1524 code->instrReturn();
1525 code->setMaxStackAndLocals(maxSize, index2);
1526 cf->addMethod(
1527 ClassFile::ACC_PUBLIC, "<init>", desc.getDescriptor(), code.get(),
1528 std::vector< OString >(), desc.getSignature());
1529 addTypeInfo(className, typeInfo, dependencies, cf.get());
1530 writeClassFile(options, className, *cf.get());
1533 void addExceptionBaseArguments(
1534 rtl::Reference< TypeManager > const & manager, Dependencies * dependencies,
1535 MethodDescriptor * methodDescriptor, ClassFile::Code * code,
1536 OUString const & base, sal_uInt16 * index)
1538 assert(manager.is());
1539 assert(methodDescriptor != nullptr);
1540 rtl::Reference< unoidl::Entity > ent;
1541 if (manager->getSort(base, &ent) != codemaker::UnoType::Sort::Exception)
1543 throw CannotDumpException(
1544 "unexpected entity \"" + base
1545 + "\" in call to addExceptionBaseArguments");
1547 unoidl::ExceptionTypeEntity& ent2(
1548 dynamic_cast<unoidl::ExceptionTypeEntity&>(*ent.get()));
1549 bool baseException = base == "com.sun.star.uno.Exception";
1550 if (!baseException) {
1551 addExceptionBaseArguments(
1552 manager, dependencies, methodDescriptor, code,
1553 ent2.getDirectBase(), index);
1555 for (std::vector< unoidl::ExceptionTypeEntity::Member >::const_iterator i(
1556 ent2.getDirectMembers().begin());
1557 i != ent2.getDirectMembers().end(); ++i)
1559 if (!baseException || i != ent2.getDirectMembers().begin()) {
1560 methodDescriptor->addParameter(i->type, false, true, nullptr);
1561 addLoadLocal(
1562 manager, code, index, false, i->type, false, dependencies);
1567 void handleExceptionType(
1568 const OUString& name, rtl::Reference< unoidl::ExceptionTypeEntity > const & entity,
1569 rtl::Reference< TypeManager > const & manager, JavaOptions const & options,
1570 Dependencies * dependencies)
1572 assert(entity.is());
1573 assert(dependencies != nullptr);
1574 OString className(codemaker::convertString(name).replace('.', '/'));
1575 bool baseException = false;
1576 bool baseRuntimeException = false;
1577 OString superClass;
1578 if (className == "com/sun/star/uno/Exception") {
1579 baseException = true;
1580 superClass = "java/lang/Exception";
1581 } else if (className == "com/sun/star/uno/RuntimeException") {
1582 baseRuntimeException = true;
1583 superClass = "java/lang/RuntimeException";
1584 } else {
1585 if (entity->getDirectBase().isEmpty()) {
1586 throw CannotDumpException(
1587 "Exception type \"" + name + "\" lacks base");
1589 superClass = codemaker::convertString(entity->getDirectBase()).
1590 replace('.', '/');
1591 dependencies->insert(entity->getDirectBase());
1593 std::unique_ptr< ClassFile > cf(
1594 new ClassFile(
1595 static_cast< ClassFile::AccessFlags >(
1596 ClassFile::ACC_PUBLIC | ClassFile::ACC_SUPER),
1597 className, superClass, ""));
1598 std::vector< TypeInfo > typeInfo;
1599 sal_Int32 index = 0;
1600 if (baseRuntimeException) {
1601 addField(
1602 manager, dependencies, cf.get(), &typeInfo, -1,
1603 "com.sun.star.uno.XInterface", "Context", index++);
1605 for (std::vector< unoidl::ExceptionTypeEntity::Member >::const_iterator i(
1606 entity->getDirectMembers().begin());
1607 i != entity->getDirectMembers().end(); ++i)
1609 if (!baseException || i != entity->getDirectMembers().begin()) {
1610 addField(
1611 manager, dependencies, cf.get(), &typeInfo, -1, i->type,
1612 i->name, index++);
1616 // create default constructor
1617 std::unique_ptr< ClassFile::Code > code(cf->newCode());
1618 code->loadLocalReference(0);
1619 code->instrInvokespecial(superClass, "<init>", "()V");
1620 sal_uInt16 stack = 0;
1621 if (baseRuntimeException) {
1622 stack = std::max(
1623 stack,
1624 addFieldInit(
1625 manager, className, "Context", false,
1626 "com.sun.star.uno.XInterface", dependencies, code.get()));
1628 for (std::vector< unoidl::ExceptionTypeEntity::Member >::const_iterator i(
1629 entity->getDirectMembers().begin());
1630 i != entity->getDirectMembers().end(); ++i)
1632 if (!baseException || i != entity->getDirectMembers().begin()) {
1633 stack = std::max(
1634 stack,
1635 addFieldInit(
1636 manager, className, i->name, false, i->type, dependencies,
1637 code.get()));
1640 code->instrReturn();
1641 code->setMaxStackAndLocals(stack + 1, 1);
1642 cf->addMethod(
1643 ClassFile::ACC_PUBLIC, "<init>", "()V", code.get(),
1644 std::vector< OString >(), "");
1647 // create (Throwable Cause) constructor
1648 code.reset(cf->newCode());
1649 code->loadLocalReference(0);
1650 code->loadLocalReference(1);
1651 code->instrInvokespecial(superClass, "<init>", "(Ljava/lang/Throwable;)V");
1652 stack = 0;
1653 if (baseRuntimeException) {
1654 stack = std::max(
1655 stack,
1656 addFieldInit(
1657 manager, className, "Context", false,
1658 "com.sun.star.uno.XInterface", dependencies, code.get()));
1660 for (std::vector< unoidl::ExceptionTypeEntity::Member >::const_iterator i(
1661 entity->getDirectMembers().begin());
1662 i != entity->getDirectMembers().end(); ++i)
1664 if (!baseException || i != entity->getDirectMembers().begin()) {
1665 stack = std::max(
1666 stack,
1667 addFieldInit(
1668 manager, className, i->name, false, i->type, dependencies,
1669 code.get()));
1672 code->instrReturn();
1673 code->setMaxStackAndLocals(stack + 2, 2);
1674 cf->addMethod(
1675 ClassFile::ACC_PUBLIC, "<init>", "(Ljava/lang/Throwable;)V", code.get(),
1676 std::vector< OString >(), "");
1678 // create (Throwable Cause, String Message) constructor
1679 code.reset(cf->newCode());
1680 code->loadLocalReference(0);
1681 if (baseException || baseRuntimeException) {
1682 code->loadLocalReference(2);
1683 code->loadLocalReference(1);
1684 code->instrInvokespecial(superClass, "<init>", "(Ljava/lang/String;Ljava/lang/Throwable;)V");
1685 } else {
1686 code->loadLocalReference(1);
1687 code->loadLocalReference(2);
1688 code->instrInvokespecial(superClass, "<init>", "(Ljava/lang/Throwable;Ljava/lang/String;)V");
1690 stack = 0;
1691 if (baseRuntimeException) {
1692 stack = std::max(
1693 stack,
1694 addFieldInit(
1695 manager, className, "Context", false,
1696 "com.sun.star.uno.XInterface", dependencies, code.get()));
1698 for (std::vector< unoidl::ExceptionTypeEntity::Member >::const_iterator i(
1699 entity->getDirectMembers().begin());
1700 i != entity->getDirectMembers().end(); ++i)
1702 if (!baseException || i != entity->getDirectMembers().begin()) {
1703 stack = std::max(
1704 stack,
1705 addFieldInit(
1706 manager, className, i->name, false, i->type, dependencies,
1707 code.get()));
1710 code->instrReturn();
1711 code->setMaxStackAndLocals(stack + 3, 3);
1712 cf->addMethod(
1713 ClassFile::ACC_PUBLIC, "<init>", "(Ljava/lang/Throwable;Ljava/lang/String;)V", code.get(),
1714 std::vector< OString >(), "");
1716 // create (String Message) constructor
1717 code.reset(cf->newCode());
1718 code->loadLocalReference(0);
1719 code->loadLocalReference(1);
1720 code->instrInvokespecial(superClass, "<init>", "(Ljava/lang/String;)V");
1721 stack = 0;
1722 if (baseRuntimeException) {
1723 stack = std::max(
1724 stack,
1725 addFieldInit(
1726 manager, className, "Context", false,
1727 "com.sun.star.uno.XInterface", dependencies, code.get()));
1729 for (std::vector< unoidl::ExceptionTypeEntity::Member >::const_iterator i(
1730 entity->getDirectMembers().begin());
1731 i != entity->getDirectMembers().end(); ++i)
1733 if (!baseException || i != entity->getDirectMembers().begin()) {
1734 stack = std::max(
1735 stack,
1736 addFieldInit(
1737 manager, className, i->name, false, i->type, dependencies,
1738 code.get()));
1741 code->instrReturn();
1742 code->setMaxStackAndLocals(stack + 2, 2);
1743 cf->addMethod(
1744 ClassFile::ACC_PUBLIC, "<init>", "(Ljava/lang/String;)V", code.get(),
1745 std::vector< OString >(), "");
1748 // create (String Message, Object Context, T1 m1, ..., Tn mn) constructor
1749 MethodDescriptor desc1(manager, dependencies, "void", nullptr, nullptr);
1750 code.reset(cf->newCode());
1751 code->loadLocalReference(0);
1752 sal_uInt16 index2 = 1;
1753 code->loadLocalReference(index2++);
1754 desc1.addParameter("string", false, true, nullptr);
1755 if (!(baseException || baseRuntimeException)) {
1756 addExceptionBaseArguments(
1757 manager, dependencies, &desc1, code.get(), entity->getDirectBase(),
1758 &index2);
1760 code->instrInvokespecial(superClass, "<init>", desc1.getDescriptor());
1761 sal_uInt16 maxSize = index2;
1762 if (baseRuntimeException) {
1763 maxSize = std::max(
1764 maxSize,
1765 addDirectArgument(
1766 manager, dependencies, &desc1, code.get(), &index2, className,
1767 "Context", false, "com.sun.star.uno.XInterface"));
1769 for (std::vector< unoidl::ExceptionTypeEntity::Member >::const_iterator i(
1770 entity->getDirectMembers().begin());
1771 i != entity->getDirectMembers().end(); ++i)
1773 if (!baseException || i != entity->getDirectMembers().begin()) {
1774 maxSize = std::max(
1775 maxSize,
1776 addDirectArgument(
1777 manager, dependencies, &desc1, code.get(), &index2,
1778 className, codemaker::convertString(i->name), false,
1779 i->type));
1782 code->instrReturn();
1783 code->setMaxStackAndLocals(maxSize, index2);
1784 cf->addMethod(
1785 ClassFile::ACC_PUBLIC, "<init>", desc1.getDescriptor(), code.get(),
1786 std::vector< OString >(), desc1.getSignature());
1788 // create (Throwable Cause, String Message, Object Context, T1 m1, ..., Tn mn) constructor
1789 MethodDescriptor desc2(manager, dependencies, "void", nullptr, nullptr);
1790 code.reset(cf->newCode());
1791 code->loadLocalReference(0);
1792 sal_uInt16 index3 = 3;
1793 // Note that we hack in the java.lang.Throwable parameter further down,
1794 // because MethodDescriptor does not know how to handle it.
1795 desc2.addParameter("string", false, true, nullptr);
1796 if (baseException || baseRuntimeException) {
1797 code->loadLocalReference(2);
1798 code->loadLocalReference(1);
1799 code->instrInvokespecial(superClass, "<init>", "(Ljava/lang/String;Ljava/lang/Throwable;)V");
1800 } else {
1801 code->loadLocalReference(1);
1802 code->loadLocalReference(2);
1803 addExceptionBaseArguments(
1804 manager, dependencies, &desc2, code.get(), entity->getDirectBase(),
1805 &index3);
1806 code->instrInvokespecial(superClass, "<init>", "(Ljava/lang/Throwable;" + desc2.getDescriptor().copy(1));
1808 sal_uInt16 maxSize2 = index3;
1809 if (baseRuntimeException) {
1810 maxSize2 = std::max(
1811 maxSize2,
1812 addDirectArgument(
1813 manager, dependencies, &desc2, code.get(), &index3, className,
1814 "Context", false, "com.sun.star.uno.XInterface"));
1816 for (std::vector< unoidl::ExceptionTypeEntity::Member >::const_iterator i(
1817 entity->getDirectMembers().begin());
1818 i != entity->getDirectMembers().end(); ++i)
1820 if (!baseException || i != entity->getDirectMembers().begin()) {
1821 maxSize2 = std::max(
1822 maxSize2,
1823 addDirectArgument(
1824 manager, dependencies, &desc2, code.get(), &index3,
1825 className, codemaker::convertString(i->name), false,
1826 i->type));
1829 code->instrReturn();
1830 code->setMaxStackAndLocals(maxSize2, index3);
1831 cf->addMethod(
1832 ClassFile::ACC_PUBLIC, "<init>", "(Ljava/lang/Throwable;" + desc2.getDescriptor().copy(1), code.get(),
1833 std::vector< OString >(), desc2.getSignature());
1835 addTypeInfo(className, typeInfo, dependencies, cf.get());
1836 writeClassFile(options, className, *cf.get());
1839 void createExceptionsAttribute(
1840 rtl::Reference< TypeManager > const & manager,
1841 std::vector< OUString > const & exceptionTypes,
1842 Dependencies * dependencies, std::vector< OString > * exceptions,
1843 codemaker::ExceptionTree * tree)
1845 assert(dependencies != nullptr);
1846 assert(exceptions != nullptr);
1847 for (const OUString& ex : exceptionTypes)
1849 dependencies->insert(ex);
1850 OString type(codemaker::convertString(ex).replace('.', '/'));
1851 exceptions->push_back(type);
1852 if (tree != nullptr) {
1853 tree->add(type.replace('/', '.'), manager);
1858 void handleInterfaceType(
1859 const OUString& name, rtl::Reference< unoidl::InterfaceTypeEntity > const & entity,
1860 rtl::Reference< TypeManager > const & manager, JavaOptions const & options,
1861 Dependencies * dependencies)
1863 assert(entity.is());
1864 assert(dependencies != nullptr);
1865 OString className(codemaker::convertString(name).replace('.', '/'));
1866 std::unique_ptr< ClassFile > cf(
1867 new ClassFile(
1868 static_cast< ClassFile::AccessFlags >(
1869 ClassFile::ACC_PUBLIC | ClassFile::ACC_INTERFACE
1870 | ClassFile::ACC_ABSTRACT),
1871 className, "java/lang/Object", ""));
1872 for (const unoidl::AnnotatedReference& ar : entity->getDirectMandatoryBases())
1874 dependencies->insert(ar.name);
1875 cf->addInterface(codemaker::convertString(ar.name).replace('.', '/'));
1877 // As a special case, let com.sun.star.lang.XEventListener extend
1878 // java.util.EventListener ("A tagging interface that all event listener
1879 // interfaces must extend"):
1880 if (className == "com/sun/star/lang/XEventListener") {
1881 cf->addInterface("java/util/EventListener");
1883 std::vector< TypeInfo > typeInfo;
1884 if (className != "com/sun/star/uno/XInterface") {
1885 sal_Int32 index = 0;
1886 for (const unoidl::InterfaceTypeEntity::Attribute& attr : entity->getDirectAttributes())
1888 SpecialType specialType;
1889 PolymorphicUnoType polymorphicUnoType;
1890 MethodDescriptor gdesc(
1891 manager, dependencies, attr.type, &specialType,
1892 &polymorphicUnoType);
1893 std::vector< OString > exc;
1894 createExceptionsAttribute(
1895 manager, attr.getExceptions, dependencies, &exc, nullptr);
1896 OString attrName(codemaker::convertString(attr.name));
1897 cf->addMethod(
1898 static_cast< ClassFile::AccessFlags >(
1899 ClassFile::ACC_PUBLIC | ClassFile::ACC_ABSTRACT),
1900 "get" + attrName, gdesc.getDescriptor(), nullptr, exc,
1901 gdesc.getSignature());
1902 if (!attr.readOnly) {
1903 MethodDescriptor sdesc(manager, dependencies, "void", nullptr, nullptr);
1904 sdesc.addParameter(attr.type, false, true, nullptr);
1905 std::vector< OString > exc2;
1906 createExceptionsAttribute(
1907 manager, attr.setExceptions, dependencies, &exc2, nullptr);
1908 cf->addMethod(
1909 static_cast< ClassFile::AccessFlags >(
1910 ClassFile::ACC_PUBLIC | ClassFile::ACC_ABSTRACT),
1911 "set" + attrName, sdesc.getDescriptor(), nullptr, exc2,
1912 sdesc.getSignature());
1914 typeInfo.push_back(
1915 TypeInfo(
1916 TypeInfo::KIND_ATTRIBUTE, attrName, specialType,
1917 static_cast< TypeInfo::Flags >(
1918 (attr.readOnly ? TypeInfo::FLAG_READONLY : 0)
1919 | (attr.bound ? TypeInfo::FLAG_BOUND : 0)),
1920 index, polymorphicUnoType));
1921 index += (attr.readOnly ? 1 : 2);
1923 for (const unoidl::InterfaceTypeEntity::Method& method : entity->getDirectMethods())
1925 OString methodName(codemaker::convertString(method.name));
1926 SpecialType specialReturnType;
1927 PolymorphicUnoType polymorphicUnoReturnType;
1928 MethodDescriptor desc(
1929 manager, dependencies, method.returnType, &specialReturnType,
1930 &polymorphicUnoReturnType);
1931 typeInfo.push_back(
1932 TypeInfo(
1933 TypeInfo::KIND_METHOD, methodName, specialReturnType,
1934 static_cast< TypeInfo::Flags >(0), index++,
1935 polymorphicUnoReturnType));
1936 sal_Int32 paramIndex = 0;
1937 for (const unoidl::InterfaceTypeEntity::Method::Parameter& param : method.parameters)
1939 bool in = param.direction
1940 != (unoidl::InterfaceTypeEntity::Method::Parameter::
1941 DIRECTION_OUT);
1942 bool out = param.direction
1943 != (unoidl::InterfaceTypeEntity::Method::Parameter::
1944 DIRECTION_IN);
1945 PolymorphicUnoType polymorphicUnoType;
1946 SpecialType specialType = desc.addParameter(
1947 param.type, out, true, &polymorphicUnoType);
1948 if (out || isSpecialType(specialType)
1949 || polymorphicUnoType.kind != PolymorphicUnoType::KIND_NONE)
1951 typeInfo.push_back(
1952 TypeInfo(
1953 codemaker::convertString(param.name), specialType, in,
1954 out, methodName, paramIndex, polymorphicUnoType));
1956 ++paramIndex;
1958 std::vector< OString > exc2;
1959 createExceptionsAttribute(
1960 manager, method.exceptions, dependencies, &exc2, nullptr);
1961 cf->addMethod(
1962 static_cast< ClassFile::AccessFlags >(
1963 ClassFile::ACC_PUBLIC | ClassFile::ACC_ABSTRACT),
1964 methodName, desc.getDescriptor(), nullptr, exc2, desc.getSignature());
1967 addTypeInfo(className, typeInfo, dependencies, cf.get());
1968 writeClassFile(options, className, *cf.get());
1971 void handleTypedef(
1972 rtl::Reference< unoidl::TypedefEntity > const & entity,
1973 rtl::Reference< TypeManager > const & manager, Dependencies * dependencies)
1975 assert(entity.is());
1976 assert(manager.is());
1977 assert(dependencies != nullptr);
1978 OUString nucleus;
1979 switch (manager->decompose(entity->getType(), false, &nucleus, nullptr, nullptr, nullptr))
1981 case codemaker::UnoType::Sort::Boolean:
1982 case codemaker::UnoType::Sort::Byte:
1983 case codemaker::UnoType::Sort::Short:
1984 case codemaker::UnoType::Sort::UnsignedShort:
1985 case codemaker::UnoType::Sort::Long:
1986 case codemaker::UnoType::Sort::UnsignedLong:
1987 case codemaker::UnoType::Sort::Hyper:
1988 case codemaker::UnoType::Sort::UnsignedHyper:
1989 case codemaker::UnoType::Sort::Float:
1990 case codemaker::UnoType::Sort::Double:
1991 case codemaker::UnoType::Sort::Char:
1992 case codemaker::UnoType::Sort::String:
1993 case codemaker::UnoType::Sort::Type:
1994 case codemaker::UnoType::Sort::Any:
1995 break;
1996 case codemaker::UnoType::Sort::Enum:
1997 case codemaker::UnoType::Sort::PlainStruct:
1998 case codemaker::UnoType::Sort::Interface:
1999 case codemaker::UnoType::Sort::Typedef:
2000 dependencies->insert(nucleus);
2001 break;
2002 default:
2003 assert(false); // this cannot happen
2007 void handleConstantGroup(
2008 const OUString& name, rtl::Reference< unoidl::ConstantGroupEntity > const & entity,
2009 rtl::Reference< TypeManager > const & manager, JavaOptions const & options,
2010 Dependencies * dependencies)
2012 assert(entity.is());
2013 OString className(codemaker::convertString(name).replace('.', '/'));
2014 std::unique_ptr< ClassFile > cf(
2015 new ClassFile(
2016 static_cast< ClassFile::AccessFlags >(
2017 ClassFile::ACC_PUBLIC | ClassFile::ACC_INTERFACE
2018 | ClassFile::ACC_ABSTRACT),
2019 className, "java/lang/Object", ""));
2020 for (const unoidl::ConstantGroupEntity::Member& member : entity->getMembers())
2022 OUString type;
2023 sal_uInt16 valueIndex = sal_uInt16(); // avoid false warnings
2024 switch (member.value.type) {
2025 case unoidl::ConstantValue::TYPE_BOOLEAN:
2026 type = "boolean";
2027 valueIndex = cf->addIntegerInfo(sal_Int32(member.value.booleanValue));
2028 break;
2029 case unoidl::ConstantValue::TYPE_BYTE:
2030 type = "byte";
2031 valueIndex = cf->addIntegerInfo(member.value.byteValue);
2032 break;
2033 case unoidl::ConstantValue::TYPE_SHORT:
2034 type = "short";
2035 valueIndex = cf->addIntegerInfo(member.value.shortValue);
2036 break;
2037 case unoidl::ConstantValue::TYPE_UNSIGNED_SHORT:
2038 type = "unsigned short";
2039 valueIndex = cf->addIntegerInfo(member.value.unsignedShortValue);
2040 break;
2041 case unoidl::ConstantValue::TYPE_LONG:
2042 type = "long";
2043 valueIndex = cf->addIntegerInfo(member.value.longValue);
2044 break;
2045 case unoidl::ConstantValue::TYPE_UNSIGNED_LONG:
2046 type = "unsigned long";
2047 valueIndex = cf->addIntegerInfo(
2048 static_cast< sal_Int32 >(member.value.unsignedLongValue));
2049 break;
2050 case unoidl::ConstantValue::TYPE_HYPER:
2051 type = "hyper";
2052 valueIndex = cf->addLongInfo(member.value.hyperValue);
2053 break;
2054 case unoidl::ConstantValue::TYPE_UNSIGNED_HYPER:
2055 type = "unsigned hyper";
2056 valueIndex = cf->addLongInfo(
2057 static_cast< sal_Int64 >(member.value.unsignedHyperValue));
2058 break;
2059 case unoidl::ConstantValue::TYPE_FLOAT:
2060 type = "float";
2061 valueIndex = cf->addFloatInfo(member.value.floatValue);
2062 break;
2063 case unoidl::ConstantValue::TYPE_DOUBLE:
2064 type = "double";
2065 valueIndex = cf->addDoubleInfo(member.value.doubleValue);
2066 break;
2068 OString desc;
2069 OString sig;
2070 getFieldDescriptor(manager, dependencies, type, &desc, &sig, nullptr);
2071 cf->addField(
2072 static_cast< ClassFile::AccessFlags >(
2073 ClassFile::ACC_PUBLIC | ClassFile::ACC_STATIC
2074 | ClassFile::ACC_FINAL),
2075 codemaker::convertString(member.name), desc, valueIndex, sig);
2077 writeClassFile(options, className, *cf.get());
2080 void addExceptionHandlers(
2081 codemaker::ExceptionTreeNode const * node,
2082 ClassFile::Code::Position start, ClassFile::Code::Position end,
2083 ClassFile::Code::Position handler, ClassFile::Code * code)
2085 assert(node != nullptr);
2086 assert(code != nullptr);
2087 if (node->present) {
2088 code->addException(start, end, handler, node->name.replace('.', '/'));
2089 } else {
2090 for (std::unique_ptr<codemaker::ExceptionTreeNode> const & p : node->children)
2092 addExceptionHandlers(p.get(), start, end, handler, code);
2097 void addConstructor(
2098 rtl::Reference< TypeManager > const & manager,
2099 OString const & realJavaBaseName, OString const & unoName,
2100 OString const & className,
2101 unoidl::SingleInterfaceBasedServiceEntity::Constructor const & constructor,
2102 OUString const & returnType, Dependencies * dependencies,
2103 ClassFile * classFile)
2105 assert(dependencies != nullptr);
2106 assert(classFile != nullptr);
2107 MethodDescriptor desc(manager, dependencies, returnType, nullptr, nullptr);
2108 desc.addParameter("com.sun.star.uno.XComponentContext", false, false, nullptr);
2109 std::unique_ptr< ClassFile::Code > code(classFile->newCode());
2110 code->loadLocalReference(0);
2111 // stack: context
2112 code->instrInvokeinterface(
2113 "com/sun/star/uno/XComponentContext", "getServiceManager",
2114 "()Lcom/sun/star/lang/XMultiComponentFactory;", 1);
2115 // stack: factory
2116 code->loadStringConstant(unoName);
2117 // stack: factory serviceName
2118 codemaker::ExceptionTree tree;
2119 ClassFile::Code::Position tryStart;
2120 ClassFile::Code::Position tryEnd;
2121 std::vector< OString > exc;
2122 sal_uInt16 stack;
2123 sal_uInt16 localIndex = 1;
2124 ClassFile::AccessFlags access = static_cast< ClassFile::AccessFlags >(
2125 ClassFile::ACC_PUBLIC | ClassFile::ACC_STATIC);
2126 if (constructor.defaultConstructor) {
2127 code->loadLocalReference(0);
2128 // stack: factory serviceName context
2129 tryStart = code->getPosition();
2130 code->instrInvokeinterface(
2131 "com/sun/star/lang/XMultiComponentFactory",
2132 "createInstanceWithContext",
2133 ("(Ljava/lang/String;Lcom/sun/star/uno/XComponentContext;)"
2134 "Ljava/lang/Object;"),
2136 tryEnd = code->getPosition();
2137 // stack: instance
2138 stack = 3;
2139 } else {
2140 if (constructor.parameters.size() == 1
2141 && constructor.parameters[0].rest)
2143 desc.addParameter("any", true, true, nullptr);
2144 code->loadLocalReference(localIndex++);
2145 // stack: factory serviceName args
2146 stack = 4;
2147 access = static_cast< ClassFile::AccessFlags >(
2148 access | ClassFile::ACC_VARARGS);
2149 } else {
2150 code->loadIntegerConstant(constructor.parameters.size());
2151 // stack: factory serviceName N
2152 code->instrAnewarray("java/lang/Object");
2153 // stack: factory serviceName args
2154 stack = 0;
2155 sal_Int32 n = 0;
2156 for (const unoidl::SingleInterfaceBasedServiceEntity::Constructor::Parameter& param :
2157 constructor.parameters)
2159 desc.addParameter(param.type, false, true, nullptr);
2160 code->instrDup();
2161 // stack: factory serviceName args args
2162 code->loadIntegerConstant(n++);
2163 // stack: factory serviceName args args i
2164 stack = std::max(
2165 stack,
2166 addLoadLocal(
2167 manager, code.get(), &localIndex, false, param.type, true,
2168 dependencies));
2169 // stack: factory serviceName args args i any
2170 code->instrAastore();
2171 // stack: factory serviceName args
2173 stack += 5;
2175 code->loadLocalReference(0);
2176 // stack: factory serviceName args context
2177 tryStart = code->getPosition();
2178 code->instrInvokeinterface(
2179 "com/sun/star/lang/XMultiComponentFactory",
2180 "createInstanceWithArgumentsAndContext",
2181 ("(Ljava/lang/String;[Ljava/lang/Object;"
2182 "Lcom/sun/star/uno/XComponentContext;)Ljava/lang/Object;"),
2184 tryEnd = code->getPosition();
2185 // stack: instance
2186 createExceptionsAttribute(
2187 manager, constructor.exceptions, dependencies, &exc, &tree);
2189 code->loadLocalReference(0);
2190 // stack: instance context
2191 code->instrInvokestatic(
2192 className, "$castInstance",
2193 ("(Ljava/lang/Object;Lcom/sun/star/uno/XComponentContext;)"
2194 "Ljava/lang/Object;"));
2195 // stack: instance
2196 code->instrCheckcast(
2197 codemaker::convertString(returnType).replace('.', '/'));
2198 // stack: instance
2199 code->instrAreturn();
2200 if (!tree.getRoot().present) {
2201 ClassFile::Code::Position pos1 = code->getPosition();
2202 // stack: e
2203 code->instrInvokevirtual(
2204 "java/lang/Throwable", "toString", "()Ljava/lang/String;");
2205 // stack: str
2206 localIndex = std::max< sal_uInt16 >(localIndex, 2);
2207 code->storeLocalReference(1);
2208 // stack: -
2209 code->instrNew("com/sun/star/uno/DeploymentException");
2210 // stack: ex
2211 code->instrDup();
2212 // stack: ex ex
2213 code->loadStringConstant(
2214 "component context fails to supply service " + unoName + " of type "
2215 + realJavaBaseName + ": ");
2216 // stack: ex ex "..."
2217 code->loadLocalReference(1);
2218 // stack: ex ex "..." str
2219 code->instrInvokevirtual(
2220 "java/lang/String", "concat",
2221 "(Ljava/lang/String;)Ljava/lang/String;");
2222 // stack: ex ex "..."
2223 code->loadLocalReference(0);
2224 // stack: ex ex "..." context
2225 code->instrInvokespecial(
2226 "com/sun/star/uno/DeploymentException", "<init>",
2227 "(Ljava/lang/String;Ljava/lang/Object;)V");
2228 // stack: ex
2229 ClassFile::Code::Position pos2 = code->getPosition();
2230 code->instrAthrow();
2231 addExceptionHandlers(
2232 &tree.getRoot(), tryStart, tryEnd, pos2, code.get());
2233 code->addException(
2234 tryStart, tryEnd, pos1, "com/sun/star/uno/Exception");
2235 dependencies->insert("com.sun.star.uno.Exception");
2236 stack = std::max< sal_uInt16 >(stack, 4);
2238 code->setMaxStackAndLocals(stack, localIndex);
2239 classFile->addMethod(
2240 access,
2241 codemaker::java::translateUnoToJavaIdentifier(
2242 (constructor.defaultConstructor
2243 ? OString("create") : codemaker::convertString(constructor.name)),
2244 "method"),
2245 desc.getDescriptor(), code.get(), exc, desc.getSignature());
2248 void handleService(
2249 const OUString& name,
2250 rtl::Reference< unoidl::SingleInterfaceBasedServiceEntity > const & entity,
2251 rtl::Reference< TypeManager > const & manager, JavaOptions const & options,
2252 Dependencies * dependencies)
2254 assert(entity.is());
2255 assert(dependencies != nullptr);
2256 OString unoName(codemaker::convertString(name));
2257 OString className(
2258 translateUnoidlEntityNameToJavaFullyQualifiedName(name, "service"));
2259 std::unique_ptr< ClassFile > cf(
2260 new ClassFile(
2261 static_cast< ClassFile::AccessFlags >(
2262 ClassFile::ACC_PUBLIC | ClassFile::ACC_FINAL
2263 | ClassFile::ACC_SUPER),
2264 className, "java/lang/Object", ""));
2265 if (!entity->getConstructors().empty()) {
2266 OString realJavaBaseName(
2267 codemaker::convertString(entity->getBase()));
2268 dependencies->insert(entity->getBase());
2269 dependencies->insert("com.sun.star.lang.XMultiComponentFactory");
2270 dependencies->insert("com.sun.star.uno.DeploymentException");
2271 dependencies->insert("com.sun.star.uno.TypeClass");
2272 dependencies->insert("com.sun.star.uno.XComponentContext");
2273 for (const unoidl::SingleInterfaceBasedServiceEntity::Constructor& cons :
2274 entity->getConstructors())
2276 addConstructor(
2277 manager, realJavaBaseName, unoName, className, cons,
2278 entity->getBase(), dependencies, cf.get());
2280 // Synthetic castInstance method:
2282 std::unique_ptr< ClassFile::Code > code(cf->newCode());
2283 code->instrNew("com/sun/star/uno/Type");
2284 // stack: type
2285 code->instrDup();
2286 // stack: type type
2287 code->loadStringConstant(realJavaBaseName);
2288 // stack: type type "..."
2289 code->instrGetstatic(
2290 "com/sun/star/uno/TypeClass", "INTERFACE",
2291 "Lcom/sun/star/uno/TypeClass;");
2292 // stack: type type "..." INTERFACE
2293 code->instrInvokespecial(
2294 "com/sun/star/uno/Type", "<init>",
2295 "(Ljava/lang/String;Lcom/sun/star/uno/TypeClass;)V");
2296 // stack: type
2297 code->loadLocalReference(0);
2298 // stack: type instance
2299 code->instrInvokestatic(
2300 "com/sun/star/uno/UnoRuntime", "queryInterface",
2301 ("(Lcom/sun/star/uno/Type;Ljava/lang/Object;)"
2302 "Ljava/lang/Object;"));
2303 // stack: instance
2304 code->instrDup();
2305 // stack: instance instance
2306 ClassFile::Code::Branch branch = code->instrIfnull();
2307 // stack: instance
2308 code->instrAreturn();
2309 code->branchHere(branch);
2310 code->instrPop();
2311 // stack: -
2312 code->instrNew("com/sun/star/uno/DeploymentException");
2313 // stack: ex
2314 code->instrDup();
2315 // stack: ex ex
2316 code->loadStringConstant(
2317 "component context fails to supply service " + unoName
2318 + " of type " + realJavaBaseName);
2319 // stack: ex ex "..."
2320 code->loadLocalReference(1);
2321 // stack: ex ex "..." context
2322 code->instrInvokespecial(
2323 "com/sun/star/uno/DeploymentException", "<init>",
2324 "(Ljava/lang/String;Ljava/lang/Object;)V");
2325 // stack: ex
2326 code->instrAthrow();
2327 code->setMaxStackAndLocals(4, 2);
2328 cf->addMethod(
2329 static_cast< ClassFile::AccessFlags >(
2330 ClassFile::ACC_PRIVATE | ClassFile::ACC_STATIC
2331 | ClassFile::ACC_SYNTHETIC),
2332 "$castInstance",
2333 ("(Ljava/lang/Object;Lcom/sun/star/uno/XComponentContext;)"
2334 "Ljava/lang/Object;"),
2335 code.get(), std::vector< OString >(), "");
2338 writeClassFile(options, className, *cf.get());
2341 void handleSingleton(
2342 const OUString& name,
2343 rtl::Reference< unoidl::InterfaceBasedSingletonEntity > const & entity,
2344 rtl::Reference< TypeManager > const & manager, JavaOptions const & options,
2345 Dependencies * dependencies)
2347 assert(entity.is());
2348 assert(dependencies != nullptr);
2349 OString realJavaBaseName(codemaker::convertString(entity->getBase()));
2350 OString base(realJavaBaseName.replace('.', '/'));
2351 dependencies->insert(entity->getBase());
2352 OString unoName(codemaker::convertString(name));
2353 OString className(
2354 translateUnoidlEntityNameToJavaFullyQualifiedName(name, "singleton"));
2355 dependencies->insert("com.sun.star.uno.DeploymentException");
2356 dependencies->insert("com.sun.star.uno.TypeClass");
2357 dependencies->insert("com.sun.star.uno.XComponentContext");
2358 std::unique_ptr< ClassFile > cf(
2359 new ClassFile(
2360 static_cast< ClassFile::AccessFlags >(
2361 ClassFile::ACC_PUBLIC | ClassFile::ACC_FINAL
2362 | ClassFile::ACC_SUPER),
2363 className, "java/lang/Object", ""));
2364 MethodDescriptor desc(manager, dependencies, entity->getBase(), nullptr, nullptr);
2365 desc.addParameter("com.sun.star.uno.XComponentContext", false, false, nullptr);
2366 std::unique_ptr< ClassFile::Code > code(cf->newCode());
2367 code->loadLocalReference(0);
2368 // stack: context
2369 code->loadStringConstant("/singletons/" + unoName);
2370 // stack: context "..."
2371 code->instrInvokeinterface(
2372 "com/sun/star/uno/XComponentContext", "getValueByName",
2373 "(Ljava/lang/String;)Ljava/lang/Object;", 2);
2374 // stack: value
2375 code->instrDup();
2376 // stack: value value
2377 code->instrInstanceof("com/sun/star/uno/Any");
2378 // stack: value 0/1
2379 ClassFile::Code::Branch branch1 = code->instrIfeq();
2380 // stack: value
2381 code->instrCheckcast("com/sun/star/uno/Any");
2382 // stack: value
2383 code->instrDup();
2384 // stack: value value
2385 code->instrInvokevirtual(
2386 "com/sun/star/uno/Any", "getType", "()Lcom/sun/star/uno/Type;");
2387 // stack: value type
2388 code->instrInvokevirtual(
2389 "com/sun/star/uno/Type", "getTypeClass",
2390 "()Lcom/sun/star/uno/TypeClass;");
2391 // stack: value typeClass
2392 code->instrGetstatic(
2393 "com/sun/star/uno/TypeClass", "INTERFACE",
2394 "Lcom/sun/star/uno/TypeClass;");
2395 // stack: value typeClass INTERFACE
2396 ClassFile::Code::Branch branch2 = code->instrIfAcmpne();
2397 // stack: value
2398 code->instrInvokevirtual(
2399 "com/sun/star/uno/Any", "getObject", "()Ljava/lang/Object;");
2400 // stack: value
2401 code->branchHere(branch1);
2402 code->instrNew("com/sun/star/uno/Type");
2403 // stack: value type
2404 code->instrDup();
2405 // stack: value type type
2406 code->loadStringConstant(realJavaBaseName);
2407 // stack: value type type "..."
2408 code->instrGetstatic(
2409 "com/sun/star/uno/TypeClass", "INTERFACE",
2410 "Lcom/sun/star/uno/TypeClass;");
2411 // stack: value type type "..." INTERFACE
2412 code->instrInvokespecial(
2413 "com/sun/star/uno/Type", "<init>",
2414 "(Ljava/lang/String;Lcom/sun/star/uno/TypeClass;)V");
2415 // stack: value type
2416 code->instrSwap();
2417 // stack: type value
2418 code->instrInvokestatic(
2419 "com/sun/star/uno/UnoRuntime", "queryInterface",
2420 "(Lcom/sun/star/uno/Type;Ljava/lang/Object;)Ljava/lang/Object;");
2421 // stack: instance
2422 code->instrDup();
2423 // stack: instance instance
2424 ClassFile::Code::Branch branch3 = code->instrIfnull();
2425 // stack: instance
2426 code->instrCheckcast(base);
2427 // stack: instance
2428 code->instrAreturn();
2429 code->branchHere(branch2);
2430 code->branchHere(branch3);
2431 code->instrPop();
2432 // stack: -
2433 code->instrNew("com/sun/star/uno/DeploymentException");
2434 // stack: ex
2435 code->instrDup();
2436 // stack: ex ex
2437 code->loadStringConstant(
2438 "component context fails to supply singleton " + unoName + " of type "
2439 + realJavaBaseName);
2440 // stack: ex ex "..."
2441 code->loadLocalReference(0);
2442 // stack: ex ex "..." context
2443 code->instrInvokespecial(
2444 "com/sun/star/uno/DeploymentException", "<init>",
2445 "(Ljava/lang/String;Ljava/lang/Object;)V");
2446 // stack: ex
2447 code->instrAthrow();
2448 code->setMaxStackAndLocals(5, 1);
2449 cf->addMethod(
2450 static_cast< ClassFile::AccessFlags >(
2451 ClassFile::ACC_PUBLIC | ClassFile::ACC_STATIC),
2452 "get", desc.getDescriptor(), code.get(), std::vector< OString >(),
2453 desc.getSignature());
2454 writeClassFile(options, className, *cf.get());
2459 void produce(
2460 OUString const & name, rtl::Reference< TypeManager > const & manager,
2461 codemaker::GeneratedTypeSet & generated, JavaOptions const & options)
2463 if (generated.contains(u2b(name))) {
2464 return;
2466 generated.add(u2b(name));
2467 if (!manager->foundAtPrimaryProvider(name)) {
2468 return;
2470 Dependencies deps;
2471 rtl::Reference< unoidl::Entity > ent;
2472 rtl::Reference< unoidl::MapCursor > cur;
2473 switch (manager->getSort(name, &ent, &cur)) {
2474 case codemaker::UnoType::Sort::Module:
2476 OUString prefix;
2477 if (!name.isEmpty()) {
2478 prefix = name + ".";
2480 for (;;) {
2481 OUString mem;
2482 if (!cur->getNext(&mem).is()) {
2483 break;
2485 produce(prefix + mem, manager, generated, options);
2487 return;
2489 case codemaker::UnoType::Sort::Enum:
2490 handleEnumType(
2491 name, dynamic_cast< unoidl::EnumTypeEntity * >(ent.get()), options);
2492 break;
2493 case codemaker::UnoType::Sort::PlainStruct:
2494 handlePlainStructType(
2495 name, dynamic_cast< unoidl::PlainStructTypeEntity * >(ent.get()),
2496 manager, options, &deps);
2497 break;
2498 case codemaker::UnoType::Sort::PolymorphicStructTemplate:
2499 handlePolyStructType(
2500 name,
2501 dynamic_cast< unoidl::PolymorphicStructTypeTemplateEntity * >(
2502 ent.get()),
2503 manager, options, &deps);
2504 break;
2505 case codemaker::UnoType::Sort::Exception:
2506 handleExceptionType(
2507 name, dynamic_cast< unoidl::ExceptionTypeEntity * >(ent.get()),
2508 manager, options, &deps);
2509 break;
2510 case codemaker::UnoType::Sort::Interface:
2511 handleInterfaceType(
2512 name, dynamic_cast< unoidl::InterfaceTypeEntity * >(ent.get()),
2513 manager, options, &deps);
2514 break;
2515 case codemaker::UnoType::Sort::Typedef:
2516 handleTypedef(
2517 dynamic_cast< unoidl::TypedefEntity * >(ent.get()), manager, &deps);
2518 break;
2519 case codemaker::UnoType::Sort::ConstantGroup:
2520 handleConstantGroup(
2521 name, dynamic_cast< unoidl::ConstantGroupEntity * >(ent.get()),
2522 manager, options, &deps);
2523 break;
2524 case codemaker::UnoType::Sort::SingleInterfaceBasedService:
2525 handleService(
2526 name,
2527 dynamic_cast< unoidl::SingleInterfaceBasedServiceEntity * >(
2528 ent.get()),
2529 manager, options, &deps);
2530 break;
2531 case codemaker::UnoType::Sort::InterfaceBasedSingleton:
2532 handleSingleton(
2533 name,
2534 dynamic_cast< unoidl::InterfaceBasedSingletonEntity * >(ent.get()),
2535 manager, options, &deps);
2536 break;
2537 case codemaker::UnoType::Sort::AccumulationBasedService:
2538 case codemaker::UnoType::Sort::ServiceBasedSingleton:
2539 break;
2540 default:
2541 throw CannotDumpException(
2542 "unexpected entity \"" + name + "\" in call to produce");
2544 if (!options.isValid("-nD")) {
2545 for (const OUString& d : deps) {
2546 produce(d, manager, generated, options);
2551 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */