1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_codemaker.hxx"
26 
27 #include "javatype.hxx"
28 
29 #include "classfile.hxx"
30 #include "javaoptions.hxx"
31 
32 #include "codemaker/exceptiontree.hxx"
33 #include "codemaker/generatedtypeset.hxx"
34 #include "codemaker/global.hxx"
35 #include "codemaker/options.hxx"
36 #include "codemaker/typemanager.hxx"
37 #include "codemaker/unotype.hxx"
38 #include "codemaker/commonjava.hxx"
39 
40 #include "osl/diagnose.h"
41 #include "registry/reader.hxx"
42 #include "registry/refltype.hxx"
43 #include "registry/types.h"
44 #include "rtl/strbuf.hxx"
45 #include "rtl/string.h"
46 #include "rtl/string.hxx"
47 #include "rtl/textcvt.h"
48 #include "rtl/textenc.h"
49 #include "rtl/ustring.h"
50 #include "rtl/ustring.hxx"
51 #include "sal/types.h"
52 
53 #include <algorithm>
54 #include <list>
55 #include <map>
56 #include <memory>
57 #include <set>
58 #include <utility>
59 #include <vector>
60 
61 using codemaker::javamaker::ClassFile;
62 
63 namespace {
64 
checkNoTypeArguments(std::vector<rtl::OString> const & arguments)65 void checkNoTypeArguments(std::vector< rtl::OString > const & arguments) {
66     if (!arguments.empty()) {
67         throw CannotDumpException(
68             rtl::OString(RTL_CONSTASCII_STRINGPARAM("Bad type information")));
69             //TODO
70     }
71 }
72 
73 // helper function for createUnoName
appendUnoName(TypeManager const & manager,rtl::OString const & nucleus,sal_Int32 rank,std::vector<rtl::OString> const & arguments,rtl::OStringBuffer * buffer)74 void appendUnoName(
75     TypeManager const & manager, rtl::OString const & nucleus, sal_Int32 rank,
76     std::vector< rtl::OString > const & arguments, rtl::OStringBuffer * buffer)
77 {
78     OSL_ASSERT(rank >= 0 && buffer != 0);
79     for (sal_Int32 i = 0; i < rank; ++i) {
80         buffer->append(RTL_CONSTASCII_STRINGPARAM("[]"));
81     }
82     buffer->append(nucleus.replace('/', '.'));
83     if (!arguments.empty()) {
84         buffer->append('<');
85         for (std::vector< rtl::OString >::const_iterator i(arguments.begin());
86              i != arguments.end(); ++i)
87         {
88             if (i != arguments.begin()) {
89                 buffer->append(',');
90             }
91             RTTypeClass argTypeClass;
92             rtl::OString argNucleus;
93             sal_Int32 argRank;
94             std::vector< rtl::OString > argArgs;
95             codemaker::decomposeAndResolve(
96                 manager, *i, true, false, false, &argTypeClass, &argNucleus,
97                 &argRank, &argArgs);
98             appendUnoName(manager, argNucleus, argRank, argArgs, buffer);
99         }
100         buffer->append('>');
101     }
102 }
103 
104 // Translate the name of a UNO type registry entity (enum type, plain struct
105 // type, polymorphic struct type template, or interface type, decomposed into
106 // nucleus, rank, and arguments) into a core UNO type name:
createUnoName(TypeManager const & manager,rtl::OString const & nucleus,sal_Int32 rank,std::vector<rtl::OString> const & arguments)107 rtl::OString createUnoName(
108     TypeManager const & manager, rtl::OString const & nucleus, sal_Int32 rank,
109     std::vector< rtl::OString > const & arguments)
110 {
111     rtl::OStringBuffer buf;
112     appendUnoName(manager, nucleus, rank, arguments, &buf);
113     return buf.makeStringAndClear();
114 }
115 
116 /**
117    Set of UTF-8--encoded names of UNO type registry entities a given UNO type
118    registry entity depends on.
119 
120    UNO type registry entities are enum types, plain struct types, polymorphic
121    struct type templates, exception types, interface types, typedefs, modules,
122    constant groupds, single-interface--based services, accumulation-based
123    services, interface-based singletons, and service-based singletons.
124  */
125 typedef std::set< rtl::OString > Dependencies;
126 
127 enum SpecialType {
128     SPECIAL_TYPE_NONE,
129     SPECIAL_TYPE_ANY,
130     SPECIAL_TYPE_UNSIGNED,
131     SPECIAL_TYPE_INTERFACE
132 };
133 
isSpecialType(SpecialType special)134 bool isSpecialType(SpecialType special) {
135     return special >= SPECIAL_TYPE_UNSIGNED;
136 }
137 
translateUnoTypeToJavaFullyQualifiedName(rtl::OString const & type,rtl::OString const & prefix)138 rtl::OString translateUnoTypeToJavaFullyQualifiedName(
139     rtl::OString const & type, rtl::OString const & prefix)
140 {
141     sal_Int32 i = type.lastIndexOf('/') + 1;
142     return type.copy(0, i) +
143         codemaker::java::translateUnoToJavaIdentifier(type.copy(i), prefix);
144 }
145 
146 struct PolymorphicUnoType {
PolymorphicUnoType__anon0dc397770111::PolymorphicUnoType147     PolymorphicUnoType(): kind(KIND_NONE) {}
148 
149     enum Kind { KIND_NONE, KIND_STRUCT, KIND_SEQUENCE };
150     Kind kind;
151     rtl::OString name;
152 };
153 
154 SpecialType translateUnoTypeToDescriptor(
155     TypeManager const & manager, rtl::OString const & type, bool array,
156     bool classType, Dependencies * dependencies,
157     rtl::OStringBuffer * descriptor, rtl::OStringBuffer * signature,
158     bool * needsSignature, PolymorphicUnoType * polymorphicUnoType);
159 
translateUnoTypeToDescriptor(TypeManager const & manager,codemaker::UnoType::Sort sort,RTTypeClass typeClass,rtl::OString const & nucleus,sal_Int32 rank,std::vector<rtl::OString> const & arguments,bool array,bool classType,Dependencies * dependencies,rtl::OStringBuffer * descriptor,rtl::OStringBuffer * signature,bool * needsSignature,PolymorphicUnoType * polymorphicUnoType)160 SpecialType translateUnoTypeToDescriptor(
161     TypeManager const & manager, codemaker::UnoType::Sort sort,
162     RTTypeClass typeClass, rtl::OString const & nucleus, sal_Int32 rank,
163     std::vector< rtl::OString > const & arguments, bool array, bool classType,
164     Dependencies * dependencies, rtl::OStringBuffer * descriptor,
165     rtl::OStringBuffer * signature, bool * needsSignature,
166     PolymorphicUnoType * polymorphicUnoType)
167 {
168     OSL_ASSERT(rank >= 0 && (signature == 0) == (needsSignature == 0));
169     if (rank > 0xFF - (array ? 1 : 0)) {
170         throw CannotDumpException(
171             rtl::OString(
172                 RTL_CONSTASCII_STRINGPARAM(
173                     "Too many array dimensions for Java class file format")));
174     }
175     if (array) {
176         ++rank;
177     }
178     for (sal_Int32 i = 0; i < rank; ++i) {
179         if (descriptor != 0) {
180             descriptor->append('[');
181         }
182         if (signature != 0) {
183             signature->append('[');
184         }
185     }
186     if (sort == codemaker::UnoType::SORT_COMPLEX) {
187         //TODO: check that nucleus is a valid (Java-modified UTF-8) identifier
188         rtl::OString superClass;
189         if (typeClass == RT_TYPE_INTERFACE
190             && (nucleus
191                 == rtl::OString(
192                     RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/XInterface"))))
193         {
194             if (descriptor != 0) {
195                 descriptor->append(
196                     rtl::OString(
197                         RTL_CONSTASCII_STRINGPARAM("Ljava/lang/Object;")));
198             }
199             if (signature != 0) {
200                 signature->append(
201                     rtl::OString(
202                         RTL_CONSTASCII_STRINGPARAM("Ljava/lang/Object;")));
203             }
204             if (polymorphicUnoType != 0) {
205                 polymorphicUnoType->kind = PolymorphicUnoType::KIND_NONE;
206             }
207             return SPECIAL_TYPE_INTERFACE;
208         } else {
209             if (dependencies != 0) {
210                 dependencies->insert(nucleus);
211             }
212             if (descriptor != 0) {
213                 descriptor->append('L');
214                 descriptor->append(nucleus);
215                 descriptor->append(';');
216             }
217             if (signature != 0) {
218                 signature->append('L');
219                 signature->append(nucleus);
220                 if (!arguments.empty()) {
221                     signature->append('<');
222                     for (std::vector< rtl::OString >::const_iterator i(
223                              arguments.begin());
224                          i != arguments.end(); ++i)
225                     {
226                         translateUnoTypeToDescriptor(
227                             manager, *i, false, true, dependencies, 0,
228                             signature, needsSignature, 0);
229                     }
230                     signature->append('>');
231                     *needsSignature = true;
232                 }
233                 signature->append(';');
234             }
235             if (polymorphicUnoType != 0) {
236                 if (arguments.empty()) {
237                     polymorphicUnoType->kind = PolymorphicUnoType::KIND_NONE;
238                 } else {
239                     polymorphicUnoType->kind = rank == 0
240                         ? PolymorphicUnoType::KIND_STRUCT
241                         : PolymorphicUnoType::KIND_SEQUENCE;
242                     polymorphicUnoType->name = createUnoName(
243                         manager, nucleus, rank, arguments);
244                 }
245             }
246             return SPECIAL_TYPE_NONE;
247         }
248     } else {
249         static rtl::OString const
250             simpleTypeDescriptors[codemaker::UnoType::SORT_ANY + 1][2] = {
251                 { rtl::OString(RTL_CONSTASCII_STRINGPARAM("V")),
252                   rtl::OString(RTL_CONSTASCII_STRINGPARAM("Ljava/lang/Void;"))
253                 },
254                 { rtl::OString(RTL_CONSTASCII_STRINGPARAM("Z")),
255                   rtl::OString(
256                       RTL_CONSTASCII_STRINGPARAM("Ljava/lang/Boolean;"))
257                 },
258                 { rtl::OString(RTL_CONSTASCII_STRINGPARAM("B")),
259                   rtl::OString(RTL_CONSTASCII_STRINGPARAM("Ljava/lang/Byte;"))
260                 },
261                 { rtl::OString(RTL_CONSTASCII_STRINGPARAM("S")),
262                   rtl::OString(RTL_CONSTASCII_STRINGPARAM("Ljava/lang/Short;"))
263                 },
264                 { rtl::OString(RTL_CONSTASCII_STRINGPARAM("S")),
265                   rtl::OString(RTL_CONSTASCII_STRINGPARAM("Ljava/lang/Short;"))
266                 },
267                 { rtl::OString(RTL_CONSTASCII_STRINGPARAM("I")),
268                   rtl::OString(
269                       RTL_CONSTASCII_STRINGPARAM("Ljava/lang/Integer;"))
270                 },
271                 { rtl::OString(RTL_CONSTASCII_STRINGPARAM("I")),
272                   rtl::OString(
273                       RTL_CONSTASCII_STRINGPARAM("Ljava/lang/Integer;"))
274                 },
275                 { rtl::OString(RTL_CONSTASCII_STRINGPARAM("J")),
276                   rtl::OString(RTL_CONSTASCII_STRINGPARAM("Ljava/lang/Long;"))
277                 },
278                 { rtl::OString(RTL_CONSTASCII_STRINGPARAM("J")),
279                   rtl::OString(RTL_CONSTASCII_STRINGPARAM("Ljava/lang/Long;"))
280                 },
281                 { rtl::OString(RTL_CONSTASCII_STRINGPARAM("F")),
282                   rtl::OString(RTL_CONSTASCII_STRINGPARAM("Ljava/lang/Float;"))
283                 },
284                 { rtl::OString(RTL_CONSTASCII_STRINGPARAM("D")),
285                   rtl::OString(RTL_CONSTASCII_STRINGPARAM("Ljava/lang/Double;"))
286                 },
287                 { rtl::OString(RTL_CONSTASCII_STRINGPARAM("C")),
288                   rtl::OString(
289                       RTL_CONSTASCII_STRINGPARAM("Ljava/lang/Character;"))
290                 },
291                 { rtl::OString(
292                       RTL_CONSTASCII_STRINGPARAM("Ljava/lang/String;")),
293                   rtl::OString(RTL_CONSTASCII_STRINGPARAM("Ljava/lang/String;"))
294                 },
295                 { rtl::OString(
296                       RTL_CONSTASCII_STRINGPARAM("Lcom/sun/star/uno/Type;")),
297                   rtl::OString(
298                       RTL_CONSTASCII_STRINGPARAM("Lcom/sun/star/uno/Type;"))
299                 },
300                 { rtl::OString(
301                       RTL_CONSTASCII_STRINGPARAM("Ljava/lang/Object;")),
302                   rtl::OString(
303                       RTL_CONSTASCII_STRINGPARAM("Ljava/lang/Object;"))
304                 } };
305         rtl::OString const & s
306             = simpleTypeDescriptors[sort][rank == 0 && classType];
307         if (descriptor != 0) {
308             descriptor->append(s);
309         }
310         if (signature != 0) {
311             signature->append(s);
312         }
313         if (polymorphicUnoType != 0) {
314             polymorphicUnoType->kind = PolymorphicUnoType::KIND_NONE;
315         }
316         static SpecialType const
317             simpleTypeSpecials[codemaker::UnoType::SORT_ANY + 1] = {
318                 SPECIAL_TYPE_NONE, SPECIAL_TYPE_NONE, SPECIAL_TYPE_NONE,
319                 SPECIAL_TYPE_NONE, SPECIAL_TYPE_UNSIGNED, SPECIAL_TYPE_NONE,
320                 SPECIAL_TYPE_UNSIGNED, SPECIAL_TYPE_NONE, SPECIAL_TYPE_UNSIGNED,
321                 SPECIAL_TYPE_NONE, SPECIAL_TYPE_NONE, SPECIAL_TYPE_NONE,
322                 SPECIAL_TYPE_NONE, SPECIAL_TYPE_NONE, SPECIAL_TYPE_ANY };
323         return simpleTypeSpecials[sort];
324     }
325 }
326 
translateUnoTypeToDescriptor(TypeManager const & manager,rtl::OString const & type,bool array,bool classType,Dependencies * dependencies,rtl::OStringBuffer * descriptor,rtl::OStringBuffer * signature,bool * needsSignature,PolymorphicUnoType * polymorphicUnoType)327 SpecialType translateUnoTypeToDescriptor(
328     TypeManager const & manager, rtl::OString const & type, bool array,
329     bool classType, Dependencies * dependencies,
330     rtl::OStringBuffer * descriptor, rtl::OStringBuffer * signature,
331     bool * needsSignature, PolymorphicUnoType * polymorphicUnoType)
332 {
333     RTTypeClass typeClass;
334     rtl::OString nucleus;
335     sal_Int32 rank;
336     std::vector< rtl::OString > args;
337     codemaker::UnoType::Sort sort = codemaker::decomposeAndResolve(
338         manager, type, true, true, false, &typeClass, &nucleus, &rank, &args);
339     OSL_ASSERT(rank < SAL_MAX_INT32);
340     return translateUnoTypeToDescriptor(
341         manager, sort, typeClass, nucleus, rank, args, array, classType,
342         dependencies, descriptor, signature, needsSignature,
343         polymorphicUnoType);
344 }
345 
getFieldDescriptor(TypeManager const & manager,Dependencies * dependencies,rtl::OString const & type,rtl::OString * descriptor,rtl::OString * signature,PolymorphicUnoType * polymorphicUnoType)346 SpecialType getFieldDescriptor(
347     TypeManager const & manager, Dependencies * dependencies,
348     rtl::OString const & type, rtl::OString * descriptor,
349     rtl::OString * signature, PolymorphicUnoType * polymorphicUnoType)
350 {
351     OSL_ASSERT(dependencies != 0 && descriptor != 0);
352     rtl::OStringBuffer desc;
353     rtl::OStringBuffer sig;
354     bool needsSig = false;
355     SpecialType specialType = translateUnoTypeToDescriptor(
356         manager, type, false, false, dependencies, &desc, &sig, &needsSig,
357         polymorphicUnoType);
358     *descriptor = desc.makeStringAndClear();
359     if (signature != 0) {
360         if (needsSig) {
361             *signature = sig.makeStringAndClear();
362         } else {
363             *signature = rtl::OString();
364         }
365     }
366     return specialType;
367 }
368 
369 class MethodDescriptor {
370 public:
371     MethodDescriptor(
372         TypeManager const & manager, Dependencies * dependencies,
373         rtl::OString const & returnType, SpecialType * specialReturnType,
374         PolymorphicUnoType * polymorphicUnoType);
375 
376     SpecialType addParameter(
377         rtl::OString const & type, bool array, bool dependency,
378         PolymorphicUnoType * polymorphicUnoType);
379 
380     void addTypeParameter(rtl::OString const & name);
381 
382     rtl::OString getDescriptor() const;
383 
384     rtl::OString getSignature() const;
385 
386 private:
387     TypeManager const & m_manager;
388     Dependencies * m_dependencies;
389     rtl::OStringBuffer m_descriptorStart;
390     rtl::OString m_descriptorEnd;
391     rtl::OStringBuffer m_signatureStart;
392     rtl::OString m_signatureEnd;
393     bool m_needsSignature;
394 };
395 
MethodDescriptor(TypeManager const & manager,Dependencies * dependencies,rtl::OString const & returnType,SpecialType * specialReturnType,PolymorphicUnoType * polymorphicUnoType)396 MethodDescriptor::MethodDescriptor(
397     TypeManager const & manager, Dependencies * dependencies,
398     rtl::OString const & returnType, SpecialType * specialReturnType,
399     PolymorphicUnoType * polymorphicUnoType):
400     m_manager(manager), m_dependencies(dependencies), m_needsSignature(false)
401 {
402     OSL_ASSERT(dependencies != 0);
403     m_descriptorStart.append('(');
404     m_signatureStart.append('(');
405     rtl::OStringBuffer descEnd;
406     descEnd.append(')');
407     rtl::OStringBuffer sigEnd;
408     sigEnd.append(')');
409     SpecialType special = translateUnoTypeToDescriptor(
410         m_manager, returnType, false, false, m_dependencies, &descEnd, &sigEnd,
411         &m_needsSignature, polymorphicUnoType);
412     m_descriptorEnd = descEnd.makeStringAndClear();
413     m_signatureEnd = sigEnd.makeStringAndClear();
414     if (specialReturnType != 0) {
415         *specialReturnType = special;
416     }
417 }
418 
addParameter(rtl::OString const & type,bool array,bool dependency,PolymorphicUnoType * polymorphicUnoType)419 SpecialType MethodDescriptor::addParameter(
420     rtl::OString const & type, bool array, bool dependency,
421     PolymorphicUnoType * polymorphicUnoType)
422 {
423     return translateUnoTypeToDescriptor(
424         m_manager, type, array, false, dependency ? m_dependencies : 0,
425         &m_descriptorStart, &m_signatureStart, &m_needsSignature,
426         polymorphicUnoType);
427 }
428 
addTypeParameter(rtl::OString const & name)429 void MethodDescriptor::addTypeParameter(rtl::OString const & name) {
430     m_descriptorStart.append(RTL_CONSTASCII_STRINGPARAM("Ljava/lang/Object;"));
431     m_signatureStart.append('T');
432     m_signatureStart.append(name);
433     m_signatureStart.append(';');
434     m_needsSignature = true;
435 }
436 
getDescriptor() const437 rtl::OString MethodDescriptor::getDescriptor() const {
438     rtl::OStringBuffer buf(m_descriptorStart);
439     buf.append(m_descriptorEnd);
440     return buf.makeStringAndClear();
441 }
442 
getSignature() const443 rtl::OString MethodDescriptor::getSignature() const {
444     if (m_needsSignature) {
445         rtl::OStringBuffer buf(m_signatureStart);
446         buf.append(m_signatureEnd);
447         return buf.makeStringAndClear();
448     } else {
449         return rtl::OString();
450     }
451 }
452 
453 class TypeInfo {
454 public:
455     enum Kind { KIND_MEMBER, KIND_ATTRIBUTE, KIND_METHOD, KIND_PARAMETER };
456 
457     // Same values as in com/sun/star/lib/uno/typeinfo/TypeInfo.java:
458     enum Flags {
459         FLAG_READONLY = 0x008, FLAG_BOUND = 0x100, FLAG_ONEWAY = 0x010
460     };
461 
462     // KIND_MEMBER:
463     TypeInfo(
464         rtl::OString const & name, SpecialType specialType, sal_Int32 index,
465         PolymorphicUnoType const & polymorphicUnoType,
466         sal_Int32 typeParameterIndex);
467 
468     // KIND_ATTRIBUTE/METHOD:
469     TypeInfo(
470         Kind kind, rtl::OString const & name, SpecialType specialType,
471         Flags flags, sal_Int32 index,
472         PolymorphicUnoType const & polymorphicUnoType);
473 
474     // KIND_PARAMETER:
475     TypeInfo(
476         rtl::OString const & parameterName, SpecialType specialType,
477         bool inParameter, bool outParameter, rtl::OString const & methodName,
478         sal_Int32 index, PolymorphicUnoType const & polymorphicUnoType);
479 
480     sal_uInt16 generateCode(ClassFile::Code & code, Dependencies * dependencies)
481         const;
482 
483     void generatePolymorphicUnoTypeCode(
484         ClassFile::Code & code, Dependencies * dependencies) const;
485 
486 private:
487     Kind m_kind;
488     rtl::OString m_name;
489     sal_Int32 m_flags;
490     sal_Int32 m_index;
491     rtl::OString m_methodName;
492     PolymorphicUnoType m_polymorphicUnoType;
493     sal_Int32 m_typeParameterIndex;
494 };
495 
translateSpecialTypeFlags(SpecialType specialType,bool inParameter,bool outParameter)496 sal_Int32 translateSpecialTypeFlags(
497     SpecialType specialType, bool inParameter, bool outParameter)
498 {
499     static sal_Int32 const specialTypeFlags[SPECIAL_TYPE_INTERFACE + 1] = {
500         0, 0x0040 /* ANY */, 0x0004 /* UNSIGNED */, 0x0080 /* INTERFACE */ };
501     sal_Int32 flags = specialTypeFlags[specialType];
502     if (inParameter) {
503         flags |= 0x0001; /* IN */
504     }
505     if (outParameter) {
506         flags |= 0x0002; /* OUT */
507     }
508     return flags;
509 }
510 
TypeInfo(rtl::OString const & name,SpecialType specialType,sal_Int32 index,PolymorphicUnoType const & polymorphicUnoType,sal_Int32 typeParameterIndex)511 TypeInfo::TypeInfo(
512     rtl::OString const & name, SpecialType specialType, sal_Int32 index,
513     PolymorphicUnoType const & polymorphicUnoType,
514     sal_Int32 typeParameterIndex):
515     m_kind(KIND_MEMBER), m_name(name),
516     m_flags(translateSpecialTypeFlags(specialType, false, false)),
517     m_index(index), m_polymorphicUnoType(polymorphicUnoType),
518     m_typeParameterIndex(typeParameterIndex)
519 {
520     OSL_ASSERT(
521         polymorphicUnoType.kind == PolymorphicUnoType::KIND_NONE
522         ? typeParameterIndex >= -1 : typeParameterIndex == -1);
523 }
524 
TypeInfo(Kind kind,rtl::OString const & name,SpecialType specialType,Flags flags,sal_Int32 index,PolymorphicUnoType const & polymorphicUnoType)525 TypeInfo::TypeInfo(
526     Kind kind, rtl::OString const & name, SpecialType specialType,
527     Flags flags, sal_Int32 index,
528     PolymorphicUnoType const & polymorphicUnoType):
529     m_kind(kind), m_name(name),
530     m_flags(flags | translateSpecialTypeFlags(specialType, false, false)),
531     m_index(index), m_polymorphicUnoType(polymorphicUnoType)
532 {
533     OSL_ASSERT(kind == KIND_ATTRIBUTE || kind == KIND_METHOD);
534 }
535 
TypeInfo(rtl::OString const & parameterName,SpecialType specialType,bool inParameter,bool outParameter,rtl::OString const & methodName,sal_Int32 index,PolymorphicUnoType const & polymorphicUnoType)536 TypeInfo::TypeInfo(
537     rtl::OString const & parameterName, SpecialType specialType,
538     bool inParameter, bool outParameter, rtl::OString const & methodName,
539     sal_Int32 index, PolymorphicUnoType const & polymorphicUnoType):
540     m_kind(KIND_PARAMETER), m_name(parameterName),
541     m_flags(translateSpecialTypeFlags(specialType, inParameter, outParameter)),
542     m_index(index), m_methodName(methodName),
543     m_polymorphicUnoType(polymorphicUnoType)
544 {}
545 
generateCode(ClassFile::Code & code,Dependencies * dependencies) const546 sal_uInt16 TypeInfo::generateCode(
547     ClassFile::Code & code, Dependencies * dependencies) const
548 {
549     OSL_ASSERT(dependencies != 0);
550     switch (m_kind) {
551     case KIND_MEMBER:
552         code.instrNew(
553             rtl::OString(
554                 RTL_CONSTASCII_STRINGPARAM(
555                     "com/sun/star/lib/uno/typeinfo/MemberTypeInfo")));
556         code.instrDup();
557         code.loadStringConstant(m_name);
558         code.loadIntegerConstant(m_index);
559         code.loadIntegerConstant(m_flags);
560         if (m_polymorphicUnoType.kind != PolymorphicUnoType::KIND_NONE) {
561             generatePolymorphicUnoTypeCode(code, dependencies);
562             code.loadIntegerConstant(m_typeParameterIndex);
563             code.instrInvokespecial(
564                 rtl::OString(
565                     RTL_CONSTASCII_STRINGPARAM(
566                         "com/sun/star/lib/uno/typeinfo/MemberTypeInfo")),
567                 rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")),
568                 rtl::OString(
569                     RTL_CONSTASCII_STRINGPARAM(
570                         "(Ljava/lang/String;IILcom/sun/star/uno/Type;I)V")));
571             return 8;
572         } else if (m_typeParameterIndex >= 0) {
573             code.instrAconstNull();
574             code.loadIntegerConstant(m_typeParameterIndex);
575             code.instrInvokespecial(
576                 rtl::OString(
577                     RTL_CONSTASCII_STRINGPARAM(
578                         "com/sun/star/lib/uno/typeinfo/MemberTypeInfo")),
579                 rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")),
580                 rtl::OString(
581                     RTL_CONSTASCII_STRINGPARAM(
582                         "(Ljava/lang/String;IILcom/sun/star/uno/Type;I)V")));
583             return 6;
584         } else {
585             code.instrInvokespecial(
586                 rtl::OString(
587                     RTL_CONSTASCII_STRINGPARAM(
588                         "com/sun/star/lib/uno/typeinfo/MemberTypeInfo")),
589                 rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")),
590                 rtl::OString(
591                     RTL_CONSTASCII_STRINGPARAM("(Ljava/lang/String;II)V")));
592             return 4;
593         }
594 
595     case KIND_ATTRIBUTE:
596         code.instrNew(
597             rtl::OString(
598                 RTL_CONSTASCII_STRINGPARAM(
599                     "com/sun/star/lib/uno/typeinfo/AttributeTypeInfo")));
600         code.instrDup();
601         code.loadStringConstant(m_name);
602         code.loadIntegerConstant(m_index);
603         code.loadIntegerConstant(m_flags);
604         if (m_polymorphicUnoType.kind != PolymorphicUnoType::KIND_NONE) {
605             generatePolymorphicUnoTypeCode(code, dependencies);
606             code.instrInvokespecial(
607                 rtl::OString(
608                     RTL_CONSTASCII_STRINGPARAM(
609                         "com/sun/star/lib/uno/typeinfo/AttributeTypeInfo")),
610                 rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")),
611                 rtl::OString(
612                     RTL_CONSTASCII_STRINGPARAM(
613                         "(Ljava/lang/String;IILcom/sun/star/uno/Type;)V")));
614             return 8;
615         } else {
616             code.instrInvokespecial(
617                 rtl::OString(
618                     RTL_CONSTASCII_STRINGPARAM(
619                         "com/sun/star/lib/uno/typeinfo/AttributeTypeInfo")),
620                 rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")),
621                 rtl::OString(
622                     RTL_CONSTASCII_STRINGPARAM("(Ljava/lang/String;II)V")));
623             return 4;
624         }
625 
626     case KIND_METHOD:
627         code.instrNew(
628             rtl::OString(
629                 RTL_CONSTASCII_STRINGPARAM(
630                     "com/sun/star/lib/uno/typeinfo/MethodTypeInfo")));
631         code.instrDup();
632         code.loadStringConstant(m_name);
633         code.loadIntegerConstant(m_index);
634         code.loadIntegerConstant(m_flags);
635         if (m_polymorphicUnoType.kind != PolymorphicUnoType::KIND_NONE) {
636             generatePolymorphicUnoTypeCode(code, dependencies);
637             code.instrInvokespecial(
638                 rtl::OString(
639                     RTL_CONSTASCII_STRINGPARAM(
640                         "com/sun/star/lib/uno/typeinfo/MethodTypeInfo")),
641                 rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")),
642                 rtl::OString(
643                     RTL_CONSTASCII_STRINGPARAM(
644                         "(Ljava/lang/String;IILcom/sun/star/uno/Type;)V")));
645             return 8;
646         } else {
647             code.instrInvokespecial(
648                 rtl::OString(
649                     RTL_CONSTASCII_STRINGPARAM(
650                         "com/sun/star/lib/uno/typeinfo/MethodTypeInfo")),
651                 rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")),
652                 rtl::OString(
653                     RTL_CONSTASCII_STRINGPARAM("(Ljava/lang/String;II)V")));
654             return 4;
655         }
656 
657     case KIND_PARAMETER:
658         code.instrNew(
659             rtl::OString(
660                 RTL_CONSTASCII_STRINGPARAM(
661                     "com/sun/star/lib/uno/typeinfo/ParameterTypeInfo")));
662         code.instrDup();
663         code.loadStringConstant(m_name);
664         code.loadStringConstant(m_methodName);
665         code.loadIntegerConstant(m_index);
666         code.loadIntegerConstant(m_flags);
667         if (m_polymorphicUnoType.kind != PolymorphicUnoType::KIND_NONE) {
668             generatePolymorphicUnoTypeCode(code, dependencies);
669             code.instrInvokespecial(
670                 rtl::OString(
671                     RTL_CONSTASCII_STRINGPARAM(
672                         "com/sun/star/lib/uno/typeinfo/ParameterTypeInfo")),
673                 rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")),
674                 rtl::OString(
675                     RTL_CONSTASCII_STRINGPARAM(
676                         "(Ljava/lang/String;Ljava/lang/String;II"
677                         "Lcom/sun/star/uno/Type;)V")));
678             return 9;
679         } else {
680             code.instrInvokespecial(
681                 rtl::OString(
682                     RTL_CONSTASCII_STRINGPARAM(
683                         "com/sun/star/lib/uno/typeinfo/ParameterTypeInfo")),
684                 rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")),
685                 rtl::OString(
686                     RTL_CONSTASCII_STRINGPARAM(
687                         "(Ljava/lang/String;Ljava/lang/String;II)V")));
688             return 5;
689         }
690 
691     default:
692         OSL_ASSERT(false);
693         return 0;
694     }
695 }
696 
generatePolymorphicUnoTypeCode(ClassFile::Code & code,Dependencies * dependencies) const697 void TypeInfo::generatePolymorphicUnoTypeCode(
698     ClassFile::Code & code, Dependencies * dependencies) const
699 {
700     OSL_ASSERT(
701         dependencies != 0
702         && m_polymorphicUnoType.kind != PolymorphicUnoType::KIND_NONE);
703     code.instrNew(
704         rtl::OString(RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/Type")));
705     code.instrDup();
706     code.loadStringConstant(m_polymorphicUnoType.name);
707     if (m_polymorphicUnoType.kind == PolymorphicUnoType::KIND_STRUCT) {
708         code.instrGetstatic(
709             rtl::OString(
710                 RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/TypeClass")),
711             rtl::OString(RTL_CONSTASCII_STRINGPARAM("STRUCT")),
712             rtl::OString(
713                 RTL_CONSTASCII_STRINGPARAM("Lcom/sun/star/uno/TypeClass;")));
714     } else {
715         code.instrGetstatic(
716             rtl::OString(
717                 RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/TypeClass")),
718             rtl::OString(RTL_CONSTASCII_STRINGPARAM("SEQUENCE")),
719             rtl::OString(
720                 RTL_CONSTASCII_STRINGPARAM("Lcom/sun/star/uno/TypeClass;")));
721     }
722     dependencies->insert(
723         rtl::OString(RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/TypeClass")));
724     code.instrInvokespecial(
725         rtl::OString(RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/Type")),
726         rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")),
727         rtl::OString(
728             RTL_CONSTASCII_STRINGPARAM(
729                 "(Ljava/lang/String;Lcom/sun/star/uno/TypeClass;)V")));
730 }
731 
writeClassFile(JavaOptions & options,rtl::OString const & type,ClassFile const & classFile)732 void writeClassFile(
733     JavaOptions /*TODO const*/ & options, rtl::OString const & type,
734     ClassFile const & classFile)
735 {
736     rtl::OString path;
737     if (options.isValid(rtl::OString(RTL_CONSTASCII_STRINGPARAM("-O")))) {
738         path = options.getOption(
739             rtl::OString(RTL_CONSTASCII_STRINGPARAM("-O")));
740     }
741     rtl::OString filename(
742         createFileNameFromType(
743             path, type, rtl::OString(RTL_CONSTASCII_STRINGPARAM(".class"))));
744     bool check = false;
745     if (fileExists(filename)) {
746         if (options.isValid(rtl::OString(RTL_CONSTASCII_STRINGPARAM("-G")))) {
747             return;
748         }
749         check = options.isValid(
750             rtl::OString(RTL_CONSTASCII_STRINGPARAM("-Gc")));
751     }
752     FileStream tempfile;
753     tempfile.createTempFile(getTempDir(filename));
754     if (!tempfile.isValid()) {
755         throw CannotDumpException(
756             rtl::OString(
757                 RTL_CONSTASCII_STRINGPARAM("Cannot create temporary file for "))
758             + filename);
759     }
760     rtl::OString tempname(tempfile.getName());
761     try {
762         classFile.write(tempfile);
763     } catch (...) {
764         // Remove existing file for consistency:
765         if (fileExists(filename)) {
766             removeTypeFile(filename);
767         }
768         tempfile.close();
769         removeTypeFile(tempname);
770         throw;
771     }
772     tempfile.close();
773     if (!makeValidTypeFile(filename, tempname, check)) {
774         rtl::OStringBuffer msg;
775         msg.append(RTL_CONSTASCII_STRINGPARAM("Cannot create "));
776         msg.append(filename);
777         msg.append(RTL_CONSTASCII_STRINGPARAM(" from temporary file "));
778         msg.append(tempname);
779         throw CannotDumpException(msg.makeStringAndClear());
780     }
781 }
782 
addTypeInfo(rtl::OString const & className,std::vector<TypeInfo> const & typeInfo,Dependencies * dependencies,ClassFile * classFile)783 void addTypeInfo(
784     rtl::OString const & className, std::vector< TypeInfo > const & typeInfo,
785     Dependencies * dependencies, ClassFile * classFile)
786 {
787     OSL_ASSERT(dependencies != 0 && classFile != 0);
788     std::vector< TypeInfo >::size_type typeInfos = typeInfo.size();
789     if (typeInfos > SAL_MAX_INT32) {
790         throw CannotDumpException(
791             rtl::OString(
792                 RTL_CONSTASCII_STRINGPARAM(
793                     "UNOTYPEINFO array too big for Java class file format")));
794     }
795     if (typeInfos != 0) {
796         classFile->addField(
797             static_cast< ClassFile::AccessFlags >(
798                 ClassFile::ACC_PUBLIC | ClassFile::ACC_STATIC
799                 | ClassFile::ACC_FINAL),
800             rtl::OString(RTL_CONSTASCII_STRINGPARAM("UNOTYPEINFO")),
801             rtl::OString(
802                 RTL_CONSTASCII_STRINGPARAM(
803                     "[Lcom/sun/star/lib/uno/typeinfo/TypeInfo;")),
804             0, rtl::OString());
805         std::auto_ptr< ClassFile::Code > code(classFile->newCode());
806         code->loadIntegerConstant(static_cast< sal_Int32 >(typeInfos));
807         code->instrAnewarray(
808             rtl::OString(
809                 RTL_CONSTASCII_STRINGPARAM(
810                     "com/sun/star/lib/uno/typeinfo/TypeInfo")));
811         sal_Int32 index = 0;
812         sal_uInt16 stack = 0;
813         for (std::vector< TypeInfo >::const_iterator i(typeInfo.begin());
814              i != typeInfo.end(); ++i)
815         {
816             code->instrDup();
817             code->loadIntegerConstant(index++);
818             stack = std::max(stack, i->generateCode(*code, dependencies));
819             code->instrAastore();
820         }
821         code->instrPutstatic(
822             className, rtl::OString(RTL_CONSTASCII_STRINGPARAM("UNOTYPEINFO")),
823             rtl::OString(
824                 RTL_CONSTASCII_STRINGPARAM(
825                     "[Lcom/sun/star/lib/uno/typeinfo/TypeInfo;")));
826         code->instrReturn();
827         if (stack > SAL_MAX_UINT16 - 4) {
828             throw CannotDumpException(
829                 rtl::OString(
830                     RTL_CONSTASCII_STRINGPARAM(
831                         "Stack too big for Java class file format")));
832         }
833         code->setMaxStackAndLocals(static_cast< sal_uInt16 >(stack + 4), 0);
834         classFile->addMethod(
835             static_cast< ClassFile::AccessFlags >(
836                 ClassFile::ACC_PRIVATE | ClassFile::ACC_STATIC),
837             rtl::OString(RTL_CONSTASCII_STRINGPARAM("<clinit>")),
838             rtl::OString(RTL_CONSTASCII_STRINGPARAM("()V")), code.get(),
839             std::vector< rtl::OString >(), rtl::OString());
840     }
841 }
842 
843 typedef void (* handleUnoTypeRegistryEntityFunction)(
844     TypeManager const & manager, JavaOptions /*TODO const*/ & options,
845     typereg::Reader const & reader, Dependencies * dependencies);
846 
handleEnumType(TypeManager const &,JavaOptions & options,typereg::Reader const & reader,Dependencies *)847 void handleEnumType(
848     TypeManager const &, JavaOptions /*TODO const*/ & options,
849     typereg::Reader const & reader, Dependencies *)
850 {
851     sal_uInt16 fields = reader.getFieldCount();
852     if (fields == 0 || reader.getSuperTypeCount() != 0
853         || reader.getMethodCount() != 0 || reader.getReferenceCount() != 0)
854     {
855         throw CannotDumpException(
856             rtl::OString(RTL_CONSTASCII_STRINGPARAM("Bad type information")));
857             //TODO
858     }
859     rtl::OString className(codemaker::convertString(reader.getTypeName()));
860     std::auto_ptr< ClassFile > cf(
861         new ClassFile(
862             static_cast< ClassFile::AccessFlags >(
863                 ClassFile::ACC_PUBLIC | ClassFile::ACC_FINAL
864                 | ClassFile::ACC_SUPER),
865             className,
866             rtl::OString(RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/Enum")),
867             rtl::OString()));
868     rtl::OStringBuffer buf;
869     buf.append('L');
870     buf.append(className);
871     buf.append(';');
872     rtl::OString classDescriptor(buf.makeStringAndClear());
873     {for (sal_uInt16 i = 0; i < fields; ++i) {
874         RTConstValue fieldValue(reader.getFieldValue(i));
875         if (fieldValue.m_type != RT_TYPE_INT32
876             || reader.getFieldFlags(i) != RT_ACCESS_CONST
877             || !reader.getFieldTypeName(i).isEmpty())
878         {
879             throw CannotDumpException(
880                 rtl::OString(
881                     RTL_CONSTASCII_STRINGPARAM("Bad type information"))); //TODO
882         }
883         rtl::OString fieldName(
884             codemaker::convertString(reader.getFieldName(i)));
885         cf->addField(
886             static_cast< ClassFile::AccessFlags >(
887                 ClassFile::ACC_PUBLIC | ClassFile::ACC_STATIC
888                 | ClassFile::ACC_FINAL),
889             fieldName, classDescriptor, 0, rtl::OString());
890         cf->addField(
891             static_cast< ClassFile::AccessFlags >(
892                 ClassFile::ACC_PUBLIC | ClassFile::ACC_STATIC
893                 | ClassFile::ACC_FINAL),
894             fieldName + rtl::OString(RTL_CONSTASCII_STRINGPARAM("_value")),
895             rtl::OString(RTL_CONSTASCII_STRINGPARAM("I")),
896             cf->addIntegerInfo(fieldValue.m_value.aLong), rtl::OString());
897     }}
898     std::auto_ptr< ClassFile::Code > code(cf->newCode());
899     code->loadLocalReference(0);
900     code->loadLocalInteger(1);
901     code->instrInvokespecial(
902         rtl::OString(RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/Enum")),
903         rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")),
904         rtl::OString(RTL_CONSTASCII_STRINGPARAM("(I)V")));
905     code->instrReturn();
906     code->setMaxStackAndLocals(2, 2);
907     cf->addMethod(
908         ClassFile::ACC_PRIVATE,
909         rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")),
910         rtl::OString(RTL_CONSTASCII_STRINGPARAM("(I)V")), code.get(),
911         std::vector< rtl::OString >(), rtl::OString());
912     code.reset(cf->newCode());
913     code->instrGetstatic(
914         className,
915         codemaker::convertString(reader.getFieldName(0)), classDescriptor);
916     code->instrAreturn();
917     code->setMaxStackAndLocals(1, 0);
918     cf->addMethod(
919         static_cast< ClassFile::AccessFlags >(
920             ClassFile::ACC_PUBLIC | ClassFile::ACC_STATIC),
921         rtl::OString(RTL_CONSTASCII_STRINGPARAM("getDefault")),
922         rtl::OString(RTL_CONSTASCII_STRINGPARAM("()")) + classDescriptor,
923         code.get(), std::vector< rtl::OString >(), rtl::OString());
924     code.reset(cf->newCode());
925     code->loadLocalInteger(0);
926     std::map< sal_Int32, rtl::OString > map;
927     sal_Int32 min = SAL_MAX_INT32;
928     sal_Int32 max = SAL_MIN_INT32;
929     {for (sal_uInt16 i = 0; i < fields; ++i) {
930         sal_Int32 value = reader.getFieldValue(i).m_value.aLong;
931         min = std::min(min, value);
932         max = std::max(max, value);
933         map.insert(
934             std::map< sal_Int32, rtl::OString >::value_type(
935                 value, codemaker::convertString(reader.getFieldName(i))));
936     }}
937     sal_uInt64 size = static_cast< sal_uInt64 >(map.size());
938     if ((static_cast< sal_uInt64 >(max) - static_cast< sal_uInt64 >(min)
939          <= 2 * size)
940         || size > SAL_MAX_INT32)
941     {
942         std::auto_ptr< ClassFile::Code > defCode(cf->newCode());
943         defCode->instrAconstNull();
944         defCode->instrAreturn();
945         std::list< ClassFile::Code * > blocks;
946             //FIXME: pointers contained in blocks may leak
947         sal_Int32 last = SAL_MAX_INT32;
948         for (std::map< sal_Int32, rtl::OString >::iterator i(map.begin());
949              i != map.end(); ++i)
950         {
951             sal_Int32 value = i->first;
952             if (last != SAL_MAX_INT32) {
953                 for (sal_Int32 j = last + 1; j < value; ++j) {
954                     blocks.push_back(0);
955                 }
956             }
957             last = value;
958             std::auto_ptr< ClassFile::Code > blockCode(cf->newCode());
959             blockCode->instrGetstatic(className, i->second, classDescriptor);
960             blockCode->instrAreturn();
961             blocks.push_back(blockCode.get());
962             blockCode.release();
963         }
964         code->instrTableswitch(defCode.get(), min, blocks);
965         {for (std::list< ClassFile::Code * >::iterator i(blocks.begin());
966               i != blocks.end(); ++i)
967         {
968             delete *i;
969         }}
970     } else {
971         std::auto_ptr< ClassFile::Code > defCode(cf->newCode());
972         defCode->instrAconstNull();
973         defCode->instrAreturn();
974         std::list< std::pair< sal_Int32, ClassFile::Code * > > blocks;
975             //FIXME: pointers contained in blocks may leak
976         for (std::map< sal_Int32, rtl::OString >::iterator i(map.begin());
977              i != map.end(); ++i)
978         {
979             std::auto_ptr< ClassFile::Code > blockCode(cf->newCode());
980             blockCode->instrGetstatic(className, i->second, classDescriptor);
981             blockCode->instrAreturn();
982             blocks.push_back(std::make_pair(i->first, blockCode.get()));
983             blockCode.release();
984         }
985         code->instrLookupswitch(defCode.get(), blocks);
986         {for (std::list< std::pair< sal_Int32, ClassFile::Code * > >::iterator
987                   i(blocks.begin());
988               i != blocks.end(); ++i)
989         {
990             delete i->second;
991         }}
992     }
993     code->setMaxStackAndLocals(1, 1);
994     cf->addMethod(
995         static_cast< ClassFile::AccessFlags >(
996             ClassFile::ACC_PUBLIC | ClassFile::ACC_STATIC),
997         rtl::OString(RTL_CONSTASCII_STRINGPARAM("fromInt")),
998         rtl::OString(RTL_CONSTASCII_STRINGPARAM("(I)")) + classDescriptor,
999         code.get(), std::vector< rtl::OString >(), rtl::OString());
1000     code.reset(cf->newCode());
1001     {for (sal_uInt16 i = 0; i < fields; ++i) {
1002         code->instrNew(className);
1003         code->instrDup();
1004         code->loadIntegerConstant(reader.getFieldValue(i).m_value.aLong);
1005         code->instrInvokespecial(
1006             className, rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")),
1007             rtl::OString(RTL_CONSTASCII_STRINGPARAM("(I)V")));
1008         code->instrPutstatic(
1009             className,
1010             codemaker::convertString(reader.getFieldName(i)),
1011             classDescriptor);
1012     }}
1013     code->instrReturn();
1014     code->setMaxStackAndLocals(3, 0);
1015     cf->addMethod(
1016         static_cast< ClassFile::AccessFlags >(
1017             ClassFile::ACC_PRIVATE | ClassFile::ACC_STATIC),
1018         rtl::OString(RTL_CONSTASCII_STRINGPARAM("<clinit>")),
1019         rtl::OString(RTL_CONSTASCII_STRINGPARAM("()V")), code.get(),
1020         std::vector< rtl::OString >(), rtl::OString());
1021     writeClassFile(options, className, *cf.get());
1022 }
1023 
addField(TypeManager const & manager,Dependencies * dependencies,ClassFile * classFile,std::vector<TypeInfo> * typeInfo,sal_Int32 typeParameterIndex,rtl::OString const & type,rtl::OString const & name,sal_Int32 index)1024 void addField(
1025     TypeManager const & manager, Dependencies * dependencies,
1026     ClassFile * classFile, std::vector< TypeInfo > * typeInfo,
1027     sal_Int32 typeParameterIndex, rtl::OString const & type,
1028     rtl::OString const & name, sal_Int32 index)
1029 {
1030     OSL_ASSERT(dependencies != 0 && classFile != 0 && typeInfo != 0);
1031     rtl::OString descriptor;
1032     rtl::OString signature;
1033     SpecialType specialType;
1034     PolymorphicUnoType polymorphicUnoType;
1035     if (typeParameterIndex >= 0) {
1036         descriptor = rtl::OString(
1037             RTL_CONSTASCII_STRINGPARAM("Ljava/lang/Object;"));
1038         rtl::OStringBuffer buf;
1039         buf.append('T');
1040         buf.append(type);
1041         buf.append(';');
1042         signature = buf.makeStringAndClear();
1043         specialType = SPECIAL_TYPE_NONE; //TODO: SPECIAL_TYPE_TYPE_PARAMETER?
1044     } else {
1045         specialType = getFieldDescriptor(
1046             manager, dependencies, type, &descriptor, &signature,
1047             &polymorphicUnoType);
1048     }
1049     classFile->addField(ClassFile::ACC_PUBLIC, name, descriptor, 0, signature);
1050     typeInfo->push_back(
1051         TypeInfo(
1052             name, specialType, index, polymorphicUnoType, typeParameterIndex));
1053 }
1054 
addFieldInit(TypeManager const & manager,rtl::OString const & className,rtl::OString const & fieldName,bool typeParameter,rtl::OString const & fieldType,Dependencies * dependencies,ClassFile::Code * code)1055 sal_uInt16 addFieldInit(
1056     TypeManager const & manager, rtl::OString const & className,
1057     rtl::OString const & fieldName, bool typeParameter,
1058     rtl::OString const & fieldType, Dependencies * dependencies,
1059     ClassFile::Code * code)
1060 {
1061     OSL_ASSERT(dependencies != 0 && code != 0);
1062     if (typeParameter) {
1063         return 0;
1064     } else {
1065         RTTypeClass typeClass;
1066         rtl::OString nucleus;
1067         sal_Int32 rank;
1068         std::vector< rtl::OString > args;
1069         codemaker::UnoType::Sort sort = codemaker::decomposeAndResolve(
1070             manager, fieldType, true, false, false, &typeClass, &nucleus, &rank,
1071             &args);
1072         if (rank == 0) {
1073             switch (sort) {
1074             case codemaker::UnoType::SORT_STRING:
1075                 code->loadLocalReference(0);
1076                 code->loadStringConstant(rtl::OString());
1077                 code->instrPutfield(
1078                     className, fieldName,
1079                     rtl::OString(
1080                         RTL_CONSTASCII_STRINGPARAM("Ljava/lang/String;")));
1081                 return 2;
1082 
1083             case codemaker::UnoType::SORT_TYPE:
1084                 code->loadLocalReference(0);
1085                 code->instrGetstatic(
1086                     rtl::OString(
1087                         RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/Type")),
1088                     rtl::OString(RTL_CONSTASCII_STRINGPARAM("VOID")),
1089                     rtl::OString(
1090                         RTL_CONSTASCII_STRINGPARAM("Lcom/sun/star/uno/Type;")));
1091                 code->instrPutfield(
1092                     className, fieldName,
1093                     rtl::OString(
1094                         RTL_CONSTASCII_STRINGPARAM("Lcom/sun/star/uno/Type;")));
1095                 return 2;
1096 
1097             case codemaker::UnoType::SORT_ANY:
1098                 code->loadLocalReference(0);
1099                 code->instrGetstatic(
1100                     rtl::OString(
1101                         RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/Any")),
1102                     rtl::OString(RTL_CONSTASCII_STRINGPARAM("VOID")),
1103                     rtl::OString(
1104                         RTL_CONSTASCII_STRINGPARAM("Lcom/sun/star/uno/Any;")));
1105                 code->instrPutfield(
1106                     className, fieldName,
1107                     rtl::OString(
1108                         RTL_CONSTASCII_STRINGPARAM("Ljava/lang/Object;")));
1109                 return 2;
1110 
1111             case codemaker::UnoType::SORT_COMPLEX:
1112                 switch (typeClass) {
1113                 case RT_TYPE_ENUM:
1114                     {
1115                         code->loadLocalReference(0);
1116                         typereg::Reader reader(manager.getTypeReader(nucleus));
1117                         if (reader.getFieldCount() == 0) {
1118                             throw CannotDumpException(
1119                                 rtl::OString(
1120                                     RTL_CONSTASCII_STRINGPARAM(
1121                                         "Bad type information"))); //TODO
1122                         }
1123                         rtl::OStringBuffer descBuf;
1124                         translateUnoTypeToDescriptor(
1125                             manager, sort, typeClass, nucleus, 0,
1126                             std::vector< rtl::OString >(), false, false,
1127                             dependencies, &descBuf, 0, 0, 0);
1128                         rtl::OString desc(descBuf.makeStringAndClear());
1129                         code->instrGetstatic(
1130                             nucleus,
1131                             codemaker::convertString(reader.getFieldName(0)),
1132                             desc);
1133                         code->instrPutfield(className, fieldName, desc);
1134                         return 2;
1135                     }
1136 
1137                 case RT_TYPE_STRUCT:
1138                     {
1139                         code->loadLocalReference(0);
1140                         code->instrNew(nucleus);
1141                         code->instrDup();
1142                         code->instrInvokespecial(
1143                             nucleus,
1144                             rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")),
1145                             rtl::OString(RTL_CONSTASCII_STRINGPARAM("()V")));
1146                         rtl::OStringBuffer desc;
1147                         translateUnoTypeToDescriptor(
1148                             manager, sort, typeClass, nucleus, 0,
1149                             std::vector< rtl::OString >(), false, false,
1150                             dependencies, &desc, 0, 0, 0);
1151                         code->instrPutfield(
1152                             className, fieldName, desc.makeStringAndClear());
1153                         return 3;
1154                     }
1155 
1156                 default:
1157                     OSL_ASSERT(typeClass == RT_TYPE_INTERFACE);
1158                     return 0;
1159                 }
1160 
1161             default:
1162                 return 0;
1163             }
1164         } else {
1165             code->loadLocalReference(0);
1166             code->loadIntegerConstant(0);
1167             if (rank == 1) {
1168                 if (sort >= codemaker::UnoType::SORT_BOOLEAN
1169                     && sort <= codemaker::UnoType::SORT_CHAR)
1170                 {
1171                     code->instrNewarray(sort);
1172                 } else {
1173                     code->instrAnewarray(
1174                         codemaker::java::translateUnoToJavaType(sort, typeClass,
1175                                                                 nucleus, 0));
1176                 }
1177             } else {
1178                 rtl::OStringBuffer desc;
1179                 translateUnoTypeToDescriptor(
1180                     manager, sort, typeClass, nucleus, rank - 1,
1181                     std::vector< rtl::OString >(), false, false, dependencies,
1182                     &desc, 0, 0, 0);
1183                 code->instrAnewarray(desc.makeStringAndClear());
1184             }
1185             rtl::OStringBuffer desc;
1186             translateUnoTypeToDescriptor(
1187                 manager, sort, typeClass, nucleus, rank,
1188                 std::vector< rtl::OString >(), false, false, dependencies,
1189                 &desc, 0, 0, 0);
1190             code->instrPutfield(
1191                 className, fieldName, desc.makeStringAndClear());
1192             return 2;
1193         }
1194     }
1195 }
1196 
addLoadLocal(TypeManager const & manager,ClassFile::Code * code,sal_uInt16 * index,bool typeParameter,rtl::OString const & type,bool any,Dependencies * dependencies)1197 sal_uInt16 addLoadLocal(
1198     TypeManager const & manager, ClassFile::Code * code, sal_uInt16 * index,
1199     bool typeParameter, rtl::OString const & type, bool any,
1200     Dependencies * dependencies)
1201 {
1202     OSL_ASSERT(
1203         code != 0 && index != 0 && !(typeParameter && any)
1204         && dependencies != 0);
1205     sal_uInt16 stack = 1;
1206     sal_uInt16 size = 1;
1207     if (typeParameter) {
1208         code->loadLocalReference(*index);
1209         stack = size = 1;
1210     } else {
1211         RTTypeClass typeClass;
1212         rtl::OString nucleus;
1213         sal_Int32 rank;
1214         std::vector< rtl::OString > args;
1215         codemaker::UnoType::Sort sort = codemaker::decomposeAndResolve(
1216             manager, type, true, false, false, &typeClass, &nucleus, &rank, &args);
1217         if (rank == 0) {
1218             switch (sort) {
1219             case codemaker::UnoType::SORT_BOOLEAN:
1220                 if (any) {
1221                     code->instrNew(
1222                         rtl::OString(
1223                             RTL_CONSTASCII_STRINGPARAM("java/lang/Boolean")));
1224                     code->instrDup();
1225                     code->loadLocalInteger(*index);
1226                     code->instrInvokespecial(
1227                         rtl::OString(
1228                             RTL_CONSTASCII_STRINGPARAM("java/lang/Boolean")),
1229                         rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")),
1230                         rtl::OString(RTL_CONSTASCII_STRINGPARAM("(Z)V")));
1231                     stack = 3;
1232                 } else {
1233                     code->loadLocalInteger(*index);
1234                     stack = 1;
1235                 }
1236                 size = 1;
1237                 break;
1238 
1239             case codemaker::UnoType::SORT_BYTE:
1240                 if (any) {
1241                     code->instrNew(
1242                         rtl::OString(
1243                             RTL_CONSTASCII_STRINGPARAM("java/lang/Byte")));
1244                     code->instrDup();
1245                     code->loadLocalInteger(*index);
1246                     code->instrInvokespecial(
1247                         rtl::OString(
1248                             RTL_CONSTASCII_STRINGPARAM("java/lang/Byte")),
1249                         rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")),
1250                         rtl::OString(RTL_CONSTASCII_STRINGPARAM("(B)V")));
1251                     stack = 3;
1252                 } else {
1253                     code->loadLocalInteger(*index);
1254                     stack = 1;
1255                 }
1256                 size = 1;
1257                 break;
1258 
1259             case codemaker::UnoType::SORT_SHORT:
1260                 if (any) {
1261                     code->instrNew(
1262                         rtl::OString(
1263                             RTL_CONSTASCII_STRINGPARAM("java/lang/Short")));
1264                     code->instrDup();
1265                     code->loadLocalInteger(*index);
1266                     code->instrInvokespecial(
1267                         rtl::OString(
1268                             RTL_CONSTASCII_STRINGPARAM("java/lang/Short")),
1269                         rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")),
1270                         rtl::OString(RTL_CONSTASCII_STRINGPARAM("(S)V")));
1271                     stack = 3;
1272                 } else {
1273                     code->loadLocalInteger(*index);
1274                     stack = 1;
1275                 }
1276                 size = 1;
1277                 break;
1278 
1279             case codemaker::UnoType::SORT_UNSIGNED_SHORT:
1280                 if (any) {
1281                     code->instrNew(
1282                         rtl::OString(
1283                             RTL_CONSTASCII_STRINGPARAM(
1284                                 "com/sun/star/uno/Any")));
1285                     code->instrDup();
1286                     code->instrGetstatic(
1287                         rtl::OString(
1288                             RTL_CONSTASCII_STRINGPARAM(
1289                                 "com/sun/star/uno/Type")),
1290                         rtl::OString(
1291                             RTL_CONSTASCII_STRINGPARAM("UNSIGNED_SHORT")),
1292                         rtl::OString(
1293                             RTL_CONSTASCII_STRINGPARAM(
1294                                 "Lcom/sun/star/uno/Type;")));
1295                     code->instrNew(
1296                         rtl::OString(
1297                             RTL_CONSTASCII_STRINGPARAM("java/lang/Short")));
1298                     code->instrDup();
1299                     code->loadLocalInteger(*index);
1300                     code->instrInvokespecial(
1301                         rtl::OString(
1302                             RTL_CONSTASCII_STRINGPARAM("java/lang/Short")),
1303                         rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")),
1304                         rtl::OString(RTL_CONSTASCII_STRINGPARAM("(S)V")));
1305                     code->instrInvokespecial(
1306                         rtl::OString(
1307                             RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/Any")),
1308                         rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")),
1309                         rtl::OString(
1310                             RTL_CONSTASCII_STRINGPARAM(
1311                                 "(Lcom/sun/star/uno/Type;Ljava/lang/Object;)"
1312                                 "V")));
1313                     stack = 6;
1314                 } else {
1315                     code->loadLocalInteger(*index);
1316                     stack = 1;
1317                 }
1318                 size = 1;
1319                 break;
1320 
1321             case codemaker::UnoType::SORT_LONG:
1322                 if (any) {
1323                     code->instrNew(
1324                         rtl::OString(
1325                             RTL_CONSTASCII_STRINGPARAM("java/lang/Integer")));
1326                     code->instrDup();
1327                     code->loadLocalInteger(*index);
1328                     code->instrInvokespecial(
1329                         rtl::OString(
1330                             RTL_CONSTASCII_STRINGPARAM("java/lang/Integer")),
1331                         rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")),
1332                         rtl::OString(RTL_CONSTASCII_STRINGPARAM("(I)V")));
1333                     stack = 3;
1334                 } else {
1335                     code->loadLocalInteger(*index);
1336                     stack = 1;
1337                 }
1338                 size = 1;
1339                 break;
1340 
1341             case codemaker::UnoType::SORT_UNSIGNED_LONG:
1342                 if (any) {
1343                     code->instrNew(
1344                         rtl::OString(
1345                             RTL_CONSTASCII_STRINGPARAM(
1346                                 "com/sun/star/uno/Any")));
1347                     code->instrDup();
1348                     code->instrGetstatic(
1349                         rtl::OString(
1350                             RTL_CONSTASCII_STRINGPARAM(
1351                                 "com/sun/star/uno/Type")),
1352                         rtl::OString(
1353                             RTL_CONSTASCII_STRINGPARAM("UNSIGNED_LONG")),
1354                         rtl::OString(
1355                             RTL_CONSTASCII_STRINGPARAM(
1356                                 "Lcom/sun/star/uno/Type;")));
1357                     code->instrNew(
1358                         rtl::OString(
1359                             RTL_CONSTASCII_STRINGPARAM("java/lang/Integer")));
1360                     code->instrDup();
1361                     code->loadLocalInteger(*index);
1362                     code->instrInvokespecial(
1363                         rtl::OString(
1364                             RTL_CONSTASCII_STRINGPARAM("java/lang/Integer")),
1365                         rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")),
1366                         rtl::OString(RTL_CONSTASCII_STRINGPARAM("(I)V")));
1367                     code->instrInvokespecial(
1368                         rtl::OString(
1369                             RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/Any")),
1370                         rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")),
1371                         rtl::OString(
1372                             RTL_CONSTASCII_STRINGPARAM(
1373                                 "(Lcom/sun/star/uno/Type;Ljava/lang/Object;)"
1374                                 "V")));
1375                     stack = 6;
1376                 } else {
1377                     code->loadLocalInteger(*index);
1378                     stack = 1;
1379                 }
1380                 size = 1;
1381                 break;
1382 
1383             case codemaker::UnoType::SORT_HYPER:
1384                 if (any) {
1385                     code->instrNew(
1386                         rtl::OString(
1387                             RTL_CONSTASCII_STRINGPARAM("java/lang/Long")));
1388                     code->instrDup();
1389                     code->loadLocalLong(*index);
1390                     code->instrInvokespecial(
1391                         rtl::OString(
1392                             RTL_CONSTASCII_STRINGPARAM("java/lang/Long")),
1393                         rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")),
1394                         rtl::OString(RTL_CONSTASCII_STRINGPARAM("(J)V")));
1395                     stack = 4;
1396                 } else {
1397                     code->loadLocalLong(*index);
1398                     stack = 2;
1399                 }
1400                 size = 2;
1401                 break;
1402 
1403             case codemaker::UnoType::SORT_UNSIGNED_HYPER:
1404                 if (any) {
1405                     code->instrNew(
1406                         rtl::OString(
1407                             RTL_CONSTASCII_STRINGPARAM(
1408                                 "com/sun/star/uno/Any")));
1409                     code->instrDup();
1410                     code->instrGetstatic(
1411                         rtl::OString(
1412                             RTL_CONSTASCII_STRINGPARAM(
1413                                 "com/sun/star/uno/Type")),
1414                         rtl::OString(
1415                             RTL_CONSTASCII_STRINGPARAM("UNSIGNED_HYPER")),
1416                         rtl::OString(
1417                             RTL_CONSTASCII_STRINGPARAM(
1418                                 "Lcom/sun/star/uno/Type;")));
1419                     code->instrNew(
1420                         rtl::OString(
1421                             RTL_CONSTASCII_STRINGPARAM("java/lang/Long")));
1422                     code->instrDup();
1423                     code->loadLocalLong(*index);
1424                     code->instrInvokespecial(
1425                         rtl::OString(
1426                             RTL_CONSTASCII_STRINGPARAM("java/lang/Long")),
1427                         rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")),
1428                         rtl::OString(RTL_CONSTASCII_STRINGPARAM("(J)V")));
1429                     code->instrInvokespecial(
1430                         rtl::OString(
1431                             RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/Any")),
1432                         rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")),
1433                         rtl::OString(
1434                             RTL_CONSTASCII_STRINGPARAM(
1435                                 "(Lcom/sun/star/uno/Type;Ljava/lang/Object;)"
1436                                 "V")));
1437                     stack = 7;
1438                 } else {
1439                     code->loadLocalLong(*index);
1440                     stack = 2;
1441                 }
1442                 size = 2;
1443                 break;
1444 
1445             case codemaker::UnoType::SORT_FLOAT:
1446                 if (any) {
1447                     code->instrNew(
1448                         rtl::OString(
1449                             RTL_CONSTASCII_STRINGPARAM("java/lang/Float")));
1450                     code->instrDup();
1451                     code->loadLocalFloat(*index);
1452                     code->instrInvokespecial(
1453                         rtl::OString(
1454                             RTL_CONSTASCII_STRINGPARAM("java/lang/Float")),
1455                         rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")),
1456                         rtl::OString(RTL_CONSTASCII_STRINGPARAM("(F)V")));
1457                     stack = 3;
1458                 } else {
1459                     code->loadLocalFloat(*index);
1460                     stack = 1;
1461                 }
1462                 size = 1;
1463                 break;
1464 
1465             case codemaker::UnoType::SORT_DOUBLE:
1466                 if (any) {
1467                     code->instrNew(
1468                         rtl::OString(
1469                             RTL_CONSTASCII_STRINGPARAM("java/lang/Double")));
1470                     code->instrDup();
1471                     code->loadLocalDouble(*index);
1472                     code->instrInvokespecial(
1473                         rtl::OString(
1474                             RTL_CONSTASCII_STRINGPARAM("java/lang/Double")),
1475                         rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")),
1476                         rtl::OString(RTL_CONSTASCII_STRINGPARAM("(D)V")));
1477                     stack = 4;
1478                 } else {
1479                     code->loadLocalDouble(*index);
1480                     stack = 2;
1481                 }
1482                 size = 2;
1483                 break;
1484 
1485             case codemaker::UnoType::SORT_CHAR:
1486                 if (any) {
1487                     code->instrNew(
1488                         rtl::OString(
1489                             RTL_CONSTASCII_STRINGPARAM("java/lang/Character")));
1490                     code->instrDup();
1491                     code->loadLocalInteger(*index);
1492                     code->instrInvokespecial(
1493                         rtl::OString(
1494                             RTL_CONSTASCII_STRINGPARAM("java/lang/Character")),
1495                         rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")),
1496                         rtl::OString(RTL_CONSTASCII_STRINGPARAM("(C)V")));
1497                     stack = 3;
1498                 } else {
1499                     code->loadLocalInteger(*index);
1500                     stack = 1;
1501                 }
1502                 size = 1;
1503                 break;
1504 
1505             case codemaker::UnoType::SORT_STRING:
1506             case codemaker::UnoType::SORT_TYPE:
1507             case codemaker::UnoType::SORT_ANY:
1508                 code->loadLocalReference(*index);
1509                 stack = size = 1;
1510                 break;
1511 
1512             case codemaker::UnoType::SORT_COMPLEX:
1513                 switch (typeClass) {
1514                 case RT_TYPE_ENUM:
1515                     // Assuming that no Java types are derived from Java types
1516                     // that are directly derived from com.sun.star.uno.Enum:
1517                     code->loadLocalReference(*index);
1518                     stack = size = 1;
1519                     break;
1520 
1521                 case RT_TYPE_STRUCT:
1522                     if (any) {
1523                         code->instrNew(
1524                             rtl::OString(
1525                                 RTL_CONSTASCII_STRINGPARAM(
1526                                     "com/sun/star/uno/Any")));
1527                         code->instrDup();
1528                         code->instrNew(
1529                             rtl::OString(
1530                                 RTL_CONSTASCII_STRINGPARAM(
1531                                     "com/sun/star/uno/Type")));
1532                         code->instrDup();
1533                         code->loadStringConstant(
1534                             createUnoName(manager, nucleus, rank, args));
1535                         code->instrGetstatic(
1536                             rtl::OString(
1537                                 RTL_CONSTASCII_STRINGPARAM(
1538                                     "com/sun/star/uno/TypeClass")),
1539                             rtl::OString(RTL_CONSTASCII_STRINGPARAM("STRUCT")),
1540                             rtl::OString(
1541                                 RTL_CONSTASCII_STRINGPARAM(
1542                                     "Lcom/sun/star/uno/TypeClass;")));
1543                         dependencies->insert(
1544                             rtl::OString(
1545                                 RTL_CONSTASCII_STRINGPARAM(
1546                                     "com/sun/star/uno/TypeClass")));
1547                         code->instrInvokespecial(
1548                             rtl::OString(
1549                                 RTL_CONSTASCII_STRINGPARAM(
1550                                     "com/sun/star/uno/Type")),
1551                             rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")),
1552                             rtl::OString(
1553                                 RTL_CONSTASCII_STRINGPARAM(
1554                                     "(Ljava/lang/String;"
1555                                     "Lcom/sun/star/uno/TypeClass;)V")));
1556                         code->loadLocalReference(*index);
1557                         code->instrInvokespecial(
1558                             rtl::OString(
1559                                 RTL_CONSTASCII_STRINGPARAM(
1560                                     "com/sun/star/uno/Any")),
1561                             rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")),
1562                             rtl::OString(
1563                                 RTL_CONSTASCII_STRINGPARAM(
1564                                     "(Lcom/sun/star/uno/Type;"
1565                                     "Ljava/lang/Object;)V")));
1566                         stack = 6;
1567                     } else {
1568                         code->loadLocalReference(*index);
1569                         stack = 1;
1570                     }
1571                     size = 1;
1572                     break;
1573 
1574                 case RT_TYPE_INTERFACE:
1575                     if (any
1576                         && (nucleus
1577                             != rtl::OString(
1578                                 RTL_CONSTASCII_STRINGPARAM(
1579                                     "com/sun/star/uno/XInterface"))))
1580                     {
1581                         code->instrNew(
1582                             rtl::OString(
1583                                 RTL_CONSTASCII_STRINGPARAM(
1584                                     "com/sun/star/uno/Any")));
1585                         code->instrDup();
1586                         code->instrNew(
1587                             rtl::OString(
1588                                 RTL_CONSTASCII_STRINGPARAM(
1589                                     "com/sun/star/uno/Type")));
1590                         code->instrDup();
1591                         code->loadStringConstant(nucleus.replace('/', '.'));
1592                         code->instrGetstatic(
1593                             rtl::OString(
1594                                 RTL_CONSTASCII_STRINGPARAM(
1595                                     "com/sun/star/uno/TypeClass")),
1596                             rtl::OString(
1597                                 RTL_CONSTASCII_STRINGPARAM("INTERFACE")),
1598                             rtl::OString(
1599                                 RTL_CONSTASCII_STRINGPARAM(
1600                                     "Lcom/sun/star/uno/TypeClass;")));
1601                         dependencies->insert(
1602                             rtl::OString(
1603                                 RTL_CONSTASCII_STRINGPARAM(
1604                                     "com/sun/star/uno/TypeClass")));
1605                         code->instrInvokespecial(
1606                             rtl::OString(
1607                                 RTL_CONSTASCII_STRINGPARAM(
1608                                     "com/sun/star/uno/Type")),
1609                             rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")),
1610                             rtl::OString(
1611                                 RTL_CONSTASCII_STRINGPARAM(
1612                                     "(Ljava/lang/String;"
1613                                     "Lcom/sun/star/uno/TypeClass;)V")));
1614                         code->loadLocalReference(*index);
1615                         code->instrInvokespecial(
1616                             rtl::OString(
1617                                 RTL_CONSTASCII_STRINGPARAM(
1618                                     "com/sun/star/uno/Any")),
1619                             rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")),
1620                             rtl::OString(
1621                                 RTL_CONSTASCII_STRINGPARAM(
1622                                     "(Lcom/sun/star/uno/Type;"
1623                                     "Ljava/lang/Object;)V")));
1624                         stack = 6;
1625                     } else {
1626                         code->loadLocalReference(*index);
1627                         stack = 1;
1628                     }
1629                     size = 1;
1630                     break;
1631 
1632                 default:
1633                     OSL_ASSERT(false);
1634                     break;
1635                 }
1636                 break;
1637 
1638             default:
1639                 OSL_ASSERT(false);
1640                 break;
1641             }
1642         } else {
1643             bool wrap = false;
1644             if (any) {
1645                 switch (sort) {
1646                 case codemaker::UnoType::SORT_BOOLEAN:
1647                 case codemaker::UnoType::SORT_BYTE:
1648                 case codemaker::UnoType::SORT_SHORT:
1649                 case codemaker::UnoType::SORT_LONG:
1650                 case codemaker::UnoType::SORT_HYPER:
1651                 case codemaker::UnoType::SORT_FLOAT:
1652                 case codemaker::UnoType::SORT_DOUBLE:
1653                 case codemaker::UnoType::SORT_CHAR:
1654                 case codemaker::UnoType::SORT_STRING:
1655                 case codemaker::UnoType::SORT_TYPE:
1656                         // assuming that no Java types are derived from
1657                         // com.sun.star.uno.Type
1658                     break;
1659 
1660                 case codemaker::UnoType::SORT_UNSIGNED_SHORT:
1661                 case codemaker::UnoType::SORT_UNSIGNED_LONG:
1662                 case codemaker::UnoType::SORT_UNSIGNED_HYPER:
1663                 case codemaker::UnoType::SORT_ANY:
1664                     wrap = true;
1665                     break;
1666 
1667                 case codemaker::UnoType::SORT_COMPLEX:
1668                     switch (typeClass) {
1669                     case RT_TYPE_ENUM:
1670                             // assuming that no Java types are derived from Java
1671                             // types that are directly derived from
1672                             // com.sun.star.uno.Enum
1673                         break;
1674 
1675                     case RT_TYPE_STRUCT:
1676                     case RT_TYPE_INTERFACE:
1677                         wrap = true;
1678                         break;
1679 
1680                     default:
1681                         OSL_ASSERT(false);
1682                         break;
1683                     }
1684                     break;
1685 
1686                 default:
1687                     OSL_ASSERT(false);
1688                     break;
1689                 }
1690             }
1691             if (wrap) {
1692                 code->instrNew(
1693                     rtl::OString(
1694                         RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/Any")));
1695                 code->instrDup();
1696                 code->instrNew(
1697                     rtl::OString(
1698                         RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/Type")));
1699                 code->instrDup();
1700                 code->loadStringConstant(
1701                     createUnoName(manager, nucleus, rank, args));
1702                 code->instrInvokespecial(
1703                     rtl::OString(
1704                         RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/Type")),
1705                     rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")),
1706                     rtl::OString(
1707                         RTL_CONSTASCII_STRINGPARAM("(Ljava/lang/String;)V")));
1708                 code->loadLocalReference(*index);
1709                 code->instrInvokespecial(
1710                     rtl::OString(
1711                         RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/Any")),
1712                     rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")),
1713                     rtl::OString(
1714                         RTL_CONSTASCII_STRINGPARAM(
1715                             "(Lcom/sun/star/uno/Type;Ljava/lang/Object;)V")));
1716                 stack = 5;
1717             } else {
1718                 code->loadLocalReference(*index);
1719                 stack = 1;
1720             }
1721             size = 1;
1722         }
1723     }
1724     if (*index > SAL_MAX_UINT16 - size) {
1725         throw CannotDumpException(
1726             rtl::OString(
1727                 RTL_CONSTASCII_STRINGPARAM(
1728                     "Too many local variables for Java class file format")));
1729     }
1730     *index = *index + size;
1731     return stack;
1732 }
1733 
addBaseArguments(TypeManager const & manager,Dependencies * dependencies,MethodDescriptor * methodDescriptor,ClassFile::Code * code,RTTypeClass typeClass,rtl::OString const & type,sal_uInt16 * index)1734 void addBaseArguments(
1735     TypeManager const & manager, Dependencies * dependencies,
1736     MethodDescriptor * methodDescriptor, ClassFile::Code * code,
1737     RTTypeClass typeClass, rtl::OString const & type, sal_uInt16 * index)
1738 {
1739     OSL_ASSERT(
1740         dependencies != 0 && methodDescriptor != 0 && code != 0 && index != 0);
1741     typereg::Reader reader(manager.getTypeReader(type));
1742     if (!reader.isValid() || reader.getTypeClass() != typeClass
1743         || codemaker::convertString(reader.getTypeName()) != type
1744         || reader.getMethodCount() != 0 || reader.getReferenceCount() != 0)
1745     {
1746         throw CannotDumpException(
1747             rtl::OString(RTL_CONSTASCII_STRINGPARAM("Bad type information")));
1748             //TODO
1749     }
1750     sal_uInt16 superTypes = reader.getSuperTypeCount();
1751     sal_uInt16 fields = reader.getFieldCount();
1752     sal_uInt16 firstField = 0;
1753     if (type
1754         == rtl::OString(
1755             RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/Exception")))
1756     {
1757         if (typeClass != RT_TYPE_EXCEPTION || superTypes != 0 || fields != 2) {
1758             throw CannotDumpException(
1759                 rtl::OString(
1760                     RTL_CONSTASCII_STRINGPARAM("Bad type information"))); //TODO
1761         }
1762         firstField = 1;
1763     } else {
1764         if (
1765             (typeClass == RT_TYPE_STRUCT && (superTypes > 1 || fields == 0)) ||
1766             (typeClass == RT_TYPE_EXCEPTION && superTypes != 1)
1767            )
1768         {
1769             throw CannotDumpException(
1770                 rtl::OString(
1771                     RTL_CONSTASCII_STRINGPARAM("Bad type information"))); //TODO
1772         }
1773         if (superTypes == 1) {
1774             addBaseArguments(
1775                 manager, dependencies, methodDescriptor, code, typeClass,
1776                 codemaker::convertString(reader.getSuperTypeName(0)), index);
1777         }
1778     }
1779     for (sal_uInt16 i = firstField; i < fields; ++i) {
1780         if (reader.getFieldFlags(i) != RT_ACCESS_READWRITE
1781             || reader.getFieldValue(i).m_type != RT_TYPE_NONE)
1782         {
1783             throw CannotDumpException(
1784                 rtl::OString(
1785                     RTL_CONSTASCII_STRINGPARAM("Bad type information"))); //TODO
1786         }
1787         rtl::OString fieldType(
1788             codemaker::convertString(reader.getFieldTypeName(i)));
1789         methodDescriptor->addParameter(fieldType, false, true, 0);
1790         addLoadLocal(
1791             manager, code, index, false, fieldType, false, dependencies);
1792     }
1793 }
1794 
addDirectArgument(TypeManager const & manager,Dependencies * dependencies,MethodDescriptor * methodDescriptor,ClassFile::Code * code,sal_uInt16 * index,rtl::OString const & className,rtl::OString const & fieldName,bool typeParameter,rtl::OString const & fieldType)1795 sal_uInt16 addDirectArgument(
1796     TypeManager const & manager, Dependencies * dependencies,
1797     MethodDescriptor * methodDescriptor, ClassFile::Code * code,
1798     sal_uInt16 * index, rtl::OString const & className,
1799     rtl::OString const & fieldName, bool typeParameter,
1800     rtl::OString const & fieldType)
1801 {
1802     OSL_ASSERT(
1803         dependencies != 0 && methodDescriptor != 0 && code != 0 && index != 0);
1804     rtl::OString desc;
1805     if (typeParameter) {
1806         methodDescriptor->addTypeParameter(fieldType);
1807         desc = rtl::OString(RTL_CONSTASCII_STRINGPARAM("Ljava/lang/Object;"));
1808     } else {
1809         methodDescriptor->addParameter(fieldType, false, true, 0);
1810         getFieldDescriptor(manager, dependencies, fieldType, &desc, 0, 0);
1811     }
1812     code->loadLocalReference(0);
1813     sal_uInt16 stack = addLoadLocal(
1814         manager, code, index, typeParameter, fieldType, false, dependencies);
1815     code->instrPutfield(className, fieldName, desc);
1816     return stack + 1;
1817 }
1818 
handleAggregatingType(TypeManager const & manager,JavaOptions & options,typereg::Reader const & reader,Dependencies * dependencies)1819 void handleAggregatingType(
1820     TypeManager const & manager, JavaOptions /*TODO const*/ & options,
1821     typereg::Reader const & reader, Dependencies * dependencies)
1822 {
1823     OSL_ASSERT(dependencies != 0);
1824     if (reader.getMethodCount() != 0)
1825     {
1826         throw CannotDumpException(
1827             rtl::OString(RTL_CONSTASCII_STRINGPARAM("Bad type information")));
1828             //TODO
1829     }
1830     RTTypeClass typeClass = reader.getTypeClass();
1831     rtl::OString className(codemaker::convertString(reader.getTypeName()));
1832     sal_uInt16 superTypes = reader.getSuperTypeCount();
1833     sal_uInt16 fields = reader.getFieldCount();
1834     sal_uInt16 firstField = 0;
1835     sal_uInt16 references = reader.getReferenceCount();
1836     bool runtimeException = false;
1837     rtl::OString superClass;
1838     if (className
1839         == rtl::OString(
1840             RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/Exception")))
1841     {
1842         if (typeClass != RT_TYPE_EXCEPTION || superTypes != 0 || fields != 2
1843             || references != 0)
1844         {
1845             throw CannotDumpException(
1846                 rtl::OString(
1847                     RTL_CONSTASCII_STRINGPARAM("Bad type information"))); //TODO
1848         }
1849         firstField = 1;
1850         superClass = rtl::OString(
1851             RTL_CONSTASCII_STRINGPARAM("java/lang/Exception"));
1852     } else if (className
1853                == rtl::OString(
1854                    RTL_CONSTASCII_STRINGPARAM(
1855                        "com/sun/star/uno/RuntimeException")))
1856     {
1857         if (typeClass != RT_TYPE_EXCEPTION || superTypes != 1 || fields != 0
1858             || references != 0)
1859         {
1860             throw CannotDumpException(
1861                 rtl::OString(
1862                     RTL_CONSTASCII_STRINGPARAM("Bad type information"))); //TODO
1863         }
1864         superTypes = 0;
1865         superClass = rtl::OString(
1866             RTL_CONSTASCII_STRINGPARAM("java/lang/RuntimeException"));
1867         runtimeException = true;
1868     } else {
1869         if (
1870              (
1871               typeClass == RT_TYPE_STRUCT &&
1872               (
1873                fields == 0 ||
1874                (references == 0 ? superTypes > 1 : superTypes != 0)
1875               )
1876              ) ||
1877              (typeClass == RT_TYPE_EXCEPTION && superTypes != 1)
1878            )
1879         {
1880             throw CannotDumpException(
1881                 rtl::OString(
1882                     RTL_CONSTASCII_STRINGPARAM("Bad type information"))); //TODO
1883         }
1884         if (superTypes == 0) {
1885             superClass = rtl::OString(
1886                 RTL_CONSTASCII_STRINGPARAM("java/lang/Object"));
1887         } else {
1888             superClass = codemaker::convertString(reader.getSuperTypeName(0));
1889             dependencies->insert(superClass);
1890         }
1891     }
1892     rtl::OString sig;
1893     std::map< rtl::OString, sal_Int32 > typeParameters;
1894     if (references != 0) {
1895         rtl::OStringBuffer buf;
1896         buf.append('<');
1897         for (sal_uInt16 i = 0; i < references; ++i) {
1898             if (reader.getReferenceFlags(i) != RT_ACCESS_INVALID
1899                 || reader.getReferenceSort(i) != RT_REF_TYPE_PARAMETER)
1900             {
1901                 throw CannotDumpException(
1902                     rtl::OString(
1903                         RTL_CONSTASCII_STRINGPARAM("Bad type information")));
1904                     //TODO
1905             }
1906             rtl::OString name(
1907                 codemaker::convertString(reader.getReferenceTypeName(i)));
1908             buf.append(name);
1909             buf.append(RTL_CONSTASCII_STRINGPARAM(":Ljava/lang/Object;"));
1910             if (!typeParameters.insert(
1911                     std::map< rtl::OString, sal_Int32 >::value_type(name, i)).
1912                 second)
1913             {
1914                 throw CannotDumpException(
1915                     rtl::OString(
1916                         RTL_CONSTASCII_STRINGPARAM("Bad type information")));
1917                     //TODO
1918             }
1919         }
1920         buf.append(RTL_CONSTASCII_STRINGPARAM(">Ljava/lang/Object;"));
1921         sig = buf.makeStringAndClear();
1922     }
1923     std::auto_ptr< ClassFile > cf(
1924         new ClassFile(
1925             static_cast< ClassFile::AccessFlags >(
1926                 ClassFile::ACC_PUBLIC | ClassFile::ACC_SUPER),
1927             className, superClass, sig));
1928     std::vector< TypeInfo > typeInfo;
1929     {for (sal_uInt16 i = firstField; i < fields; ++i) {
1930         RTFieldAccess flags = reader.getFieldFlags(i);
1931         if ((flags != RT_ACCESS_READWRITE
1932              && flags != (RT_ACCESS_READWRITE | RT_ACCESS_PARAMETERIZED_TYPE))
1933             || ((flags & RT_ACCESS_PARAMETERIZED_TYPE) != 0 && references == 0)
1934             || reader.getFieldValue(i).m_type != RT_TYPE_NONE)
1935         {
1936             throw CannotDumpException(
1937                 rtl::OString(
1938                     RTL_CONSTASCII_STRINGPARAM("Bad type information"))); //TODO
1939         }
1940         rtl::OString type(
1941             codemaker::convertString(reader.getFieldTypeName(i)));
1942         sal_Int32 typeParameterIndex;
1943         if ((flags & RT_ACCESS_PARAMETERIZED_TYPE) == 0) {
1944             typeParameterIndex = -1;
1945         } else {
1946             std::map< rtl::OString, sal_Int32 >::iterator it(
1947                 typeParameters.find(type));
1948             if (it == typeParameters.end()) {
1949                 throw CannotDumpException(
1950                     rtl::OString(
1951                         RTL_CONSTASCII_STRINGPARAM("Bad type information")));
1952                     //TODO
1953             }
1954             typeParameterIndex = it->second;
1955         }
1956         addField(
1957             manager, dependencies, cf.get(), &typeInfo, typeParameterIndex,
1958             type, codemaker::convertString(reader.getFieldName(i)), i - firstField);
1959     }}
1960     if (runtimeException) {
1961         addField(
1962             manager, dependencies, cf.get(), &typeInfo, -1,
1963             rtl::OString(
1964                 RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/XInterface")),
1965             rtl::OString(RTL_CONSTASCII_STRINGPARAM("Context")), 0);
1966     }
1967     std::auto_ptr< ClassFile::Code > code(cf->newCode());
1968     code->loadLocalReference(0);
1969     code->instrInvokespecial(
1970         superClass, rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")),
1971         rtl::OString(RTL_CONSTASCII_STRINGPARAM("()V")));
1972     sal_uInt16 stack = 0;
1973     {for (sal_uInt16 i = firstField; i < fields; ++i) {
1974         stack = std::max(
1975             stack,
1976             addFieldInit(
1977                 manager, className,
1978                 codemaker::convertString(reader.getFieldName(i)),
1979                 (reader.getFieldFlags(i) & RT_ACCESS_PARAMETERIZED_TYPE) != 0,
1980                 codemaker::convertString(reader.getFieldTypeName(i)),
1981                 dependencies, code.get()));
1982     }}
1983     if (runtimeException) {
1984         stack = std::max(
1985             stack,
1986             addFieldInit(
1987                 manager, className,
1988                 rtl::OString(RTL_CONSTASCII_STRINGPARAM("Context")), false,
1989                 rtl::OString(
1990                     RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/XInterface")),
1991                 dependencies, code.get()));
1992     }
1993     code->instrReturn();
1994     code->setMaxStackAndLocals(stack + 1, 1);
1995     cf->addMethod(
1996         ClassFile::ACC_PUBLIC,
1997         rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")),
1998         rtl::OString(RTL_CONSTASCII_STRINGPARAM("()V")), code.get(),
1999         std::vector< rtl::OString >(), rtl::OString());
2000     if (typeClass == RT_TYPE_EXCEPTION) {
2001         code.reset(cf->newCode());
2002         code->loadLocalReference(0);
2003         code->loadLocalReference(1);
2004         code->instrInvokespecial(
2005             superClass, rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")),
2006             rtl::OString(RTL_CONSTASCII_STRINGPARAM("(Ljava/lang/String;)V")));
2007         stack = 0;
2008         for (sal_uInt16 i = firstField; i < fields; ++i) {
2009             stack = std::max(
2010                 stack,
2011                 addFieldInit(
2012                     manager, className,
2013                     codemaker::convertString(reader.getFieldName(i)),
2014                     ((reader.getFieldFlags(i) & RT_ACCESS_PARAMETERIZED_TYPE)
2015                      != 0),
2016                     codemaker::convertString(reader.getFieldTypeName(i)),
2017                     dependencies, code.get()));
2018         }
2019         if (runtimeException) {
2020             stack = std::max(
2021                 stack,
2022                 addFieldInit(
2023                     manager, className,
2024                     rtl::OString(RTL_CONSTASCII_STRINGPARAM("Context")), false,
2025                     rtl::OString(
2026                         RTL_CONSTASCII_STRINGPARAM(
2027                             "com/sun/star/uno/XInterface")),
2028                     dependencies, code.get()));
2029         }
2030         code->instrReturn();
2031         code->setMaxStackAndLocals(stack + 2, 2);
2032         cf->addMethod(
2033             ClassFile::ACC_PUBLIC,
2034             rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")),
2035             rtl::OString(RTL_CONSTASCII_STRINGPARAM("(Ljava/lang/String;)V")),
2036             code.get(), std::vector< rtl::OString >(), rtl::OString());
2037     }
2038     MethodDescriptor desc(
2039         manager, dependencies, rtl::OString(RTL_CONSTASCII_STRINGPARAM("void")),
2040         0, 0);
2041     code.reset(cf->newCode());
2042     code->loadLocalReference(0);
2043     sal_uInt16 index = 1;
2044     if (typeClass == RT_TYPE_EXCEPTION) {
2045         desc.addParameter(
2046             rtl::OString(RTL_CONSTASCII_STRINGPARAM("string")), false, true, 0);
2047         code->loadLocalReference(index++);
2048     }
2049     if (superTypes != 0) {
2050         addBaseArguments(
2051             manager, dependencies, &desc, code.get(), typeClass, superClass,
2052             &index);
2053     }
2054     code->instrInvokespecial(
2055         superClass, rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")),
2056         desc.getDescriptor());
2057     sal_uInt16 maxSize = index;
2058     {for (sal_uInt16 i = firstField; i < fields; ++i) {
2059         maxSize = std::max(
2060             maxSize,
2061             addDirectArgument(
2062                 manager, dependencies, &desc, code.get(), &index, className,
2063                 codemaker::convertString(reader.getFieldName(i)),
2064                 (reader.getFieldFlags(i) & RT_ACCESS_PARAMETERIZED_TYPE) != 0,
2065                 codemaker::convertString(reader.getFieldTypeName(i))));
2066     }}
2067     if (runtimeException) {
2068         maxSize = std::max(
2069             maxSize,
2070             addDirectArgument(
2071                 manager, dependencies, &desc, code.get(), &index, className,
2072                 rtl::OString(RTL_CONSTASCII_STRINGPARAM("Context")), false,
2073                 rtl::OString(
2074                     RTL_CONSTASCII_STRINGPARAM(
2075                         "com/sun/star/uno/XInterface"))));
2076     }
2077     code->instrReturn();
2078     code->setMaxStackAndLocals(maxSize, index);
2079     cf->addMethod(
2080         ClassFile::ACC_PUBLIC,
2081         rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")),
2082         desc.getDescriptor(), code.get(), std::vector< rtl::OString >(),
2083         desc.getSignature());
2084     addTypeInfo(className, typeInfo, dependencies, cf.get());
2085     writeClassFile(options, className, *cf.get());
2086 }
2087 
createExceptionsAttribute(TypeManager const & manager,typereg::Reader const & reader,sal_uInt16 methodIndex,Dependencies * dependencies,std::vector<rtl::OString> * exceptions,codemaker::ExceptionTree * tree)2088 void createExceptionsAttribute(
2089     TypeManager const & manager, typereg::Reader const & reader,
2090     sal_uInt16 methodIndex, Dependencies * dependencies,
2091     std::vector< rtl::OString > * exceptions, codemaker::ExceptionTree * tree)
2092 {
2093     OSL_ASSERT(dependencies != 0 && exceptions != 0);
2094     sal_uInt16 n = reader.getMethodExceptionCount(methodIndex);
2095     for (sal_uInt16 i = 0; i < n; ++i) {
2096         rtl::OString type(
2097             codemaker::convertString(
2098                 reader.getMethodExceptionTypeName(methodIndex, i)));
2099         dependencies->insert(type);
2100         exceptions->push_back(type);
2101         if (tree != 0) {
2102             tree->add(type, manager);
2103         }
2104     }
2105 }
2106 
handleInterfaceType(TypeManager const & manager,JavaOptions & options,typereg::Reader const & reader,Dependencies * dependencies)2107 void handleInterfaceType(
2108     TypeManager const & manager, JavaOptions /*TODO const*/ & options,
2109     typereg::Reader const & reader, Dependencies * dependencies)
2110 {
2111     OSL_ASSERT(dependencies != 0);
2112 
2113     rtl::OString className(codemaker::convertString(reader.getTypeName()));
2114     sal_uInt16 superTypes = reader.getSuperTypeCount();
2115     sal_uInt16 fields = reader.getFieldCount();
2116     sal_uInt16 methods = reader.getMethodCount();
2117     if (className
2118         == rtl::OString(
2119             RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/XInterface")))
2120     {
2121         if (superTypes != 0 || fields != 0 || methods != 3) {
2122             throw CannotDumpException(
2123                 rtl::OString(
2124                     RTL_CONSTASCII_STRINGPARAM("Bad type information"))); //TODO
2125         }
2126         methods = 0;
2127     } else if (superTypes == 0) {
2128         throw CannotDumpException(
2129             rtl::OString(RTL_CONSTASCII_STRINGPARAM("Bad type information")));
2130             //TODO
2131     }
2132     std::auto_ptr< ClassFile > cf(
2133         new ClassFile(
2134             static_cast< ClassFile::AccessFlags >(
2135                 ClassFile::ACC_PUBLIC | ClassFile::ACC_INTERFACE
2136                 | ClassFile::ACC_ABSTRACT),
2137             className,
2138             rtl::OString(RTL_CONSTASCII_STRINGPARAM("java/lang/Object")),
2139             rtl::OString()));
2140     {for (sal_uInt16 i = 0; i < superTypes; ++i) {
2141         rtl::OString t(codemaker::convertString(reader.getSuperTypeName(i)));
2142         dependencies->insert(t);
2143         cf->addInterface(t);
2144     }}
2145     // As a special case, let com.sun.star.lang.XEventListener extend
2146     // java.util.EventListener ("A tagging interface that all event listener
2147     // interfaces must extend"):
2148     if (className ==
2149         rtl::OString(
2150             RTL_CONSTASCII_STRINGPARAM("com/sun/star/lang/XEventListener")))
2151     {
2152         cf->addInterface(
2153             rtl::OString(
2154                 RTL_CONSTASCII_STRINGPARAM("java/util/EventListener")));
2155     }
2156     std::vector< TypeInfo > typeInfo;
2157     sal_Int32 index = 0;
2158     {for (sal_uInt16 i = 0; i < fields; ++i) {
2159         RTFieldAccess flags = reader.getFieldFlags(i);
2160         //TODO: ok if both READONLY and BOUND?
2161         if (((((flags & RT_ACCESS_READWRITE) != 0)
2162               ^ ((flags & RT_ACCESS_READONLY) != 0))
2163              == 0)
2164             || ((flags
2165                  & ~(RT_ACCESS_READWRITE | RT_ACCESS_READONLY
2166                      | RT_ACCESS_BOUND))
2167                 != 0)
2168             || reader.getFieldValue(i).m_type != RT_TYPE_NONE)
2169         {
2170             throw CannotDumpException(
2171                 rtl::OString(
2172                     RTL_CONSTASCII_STRINGPARAM("Bad type information"))); //TODO
2173         }
2174         //TODO: exploit the fact that attribute getter/setter methods precede
2175         // real methods
2176         rtl::OUString attrNameUtf16(reader.getFieldName(i));
2177         sal_uInt16 getter = SAL_MAX_UINT16;
2178         sal_uInt16 setter = SAL_MAX_UINT16;
2179         for (sal_uInt16 j = 0; j < methods; ++j) {
2180             RTMethodMode mflags = reader.getMethodFlags(j);
2181             if ((mflags == RT_MODE_ATTRIBUTE_GET
2182                  || mflags == RT_MODE_ATTRIBUTE_SET)
2183                 && reader.getMethodName(j) == attrNameUtf16)
2184             {
2185                 if (!reader.getMethodReturnTypeName(j).equalsAsciiL(
2186                         RTL_CONSTASCII_STRINGPARAM("void"))
2187                     || reader.getMethodParameterCount(j) != 0
2188                     || (mflags == RT_MODE_ATTRIBUTE_GET
2189                         ? getter != SAL_MAX_UINT16
2190                         : (setter != SAL_MAX_UINT16
2191                            || (flags & RT_ACCESS_READONLY) != 0)))
2192                 {
2193                     throw CannotDumpException(
2194                         rtl::OString(
2195                             RTL_CONSTASCII_STRINGPARAM(
2196                                 "Bad type information"))); //TODO
2197                 }
2198                 OSL_ASSERT(j != SAL_MAX_UINT16);
2199                 (mflags == RT_MODE_ATTRIBUTE_GET ? getter : setter) = j;
2200             }
2201         }
2202         rtl::OString fieldType(
2203             codemaker::convertString(reader.getFieldTypeName(i)));
2204         SpecialType specialType;
2205         PolymorphicUnoType polymorphicUnoType;
2206         MethodDescriptor gdesc(
2207             manager, dependencies, fieldType, &specialType,
2208             &polymorphicUnoType);
2209         std::vector< rtl::OString > exc;
2210         if (getter != SAL_MAX_UINT16) {
2211             createExceptionsAttribute(
2212                 manager, reader, getter, dependencies, &exc, 0);
2213         }
2214         rtl::OString attrName(codemaker::convertString(attrNameUtf16));
2215         cf->addMethod(
2216             static_cast< ClassFile::AccessFlags >(
2217                 ClassFile::ACC_PUBLIC | ClassFile::ACC_ABSTRACT),
2218             rtl::OString(RTL_CONSTASCII_STRINGPARAM("get")) + attrName,
2219             gdesc.getDescriptor(), 0, exc, gdesc.getSignature());
2220         if ((flags & RT_ACCESS_READONLY) == 0) {
2221             MethodDescriptor sdesc(
2222                 manager, dependencies,
2223                 rtl::OString(RTL_CONSTASCII_STRINGPARAM("void")), 0, 0);
2224             sdesc.addParameter(fieldType, false, true, 0);
2225             std::vector< rtl::OString > exc2;
2226             if (setter != SAL_MAX_UINT16) {
2227                 createExceptionsAttribute(
2228                     manager, reader, setter, dependencies, &exc2, 0);
2229             }
2230             cf->addMethod(
2231                 static_cast< ClassFile::AccessFlags >(
2232                     ClassFile::ACC_PUBLIC | ClassFile::ACC_ABSTRACT),
2233                 rtl::OString(RTL_CONSTASCII_STRINGPARAM("set")) + attrName,
2234                 sdesc.getDescriptor(), 0, exc2, sdesc.getSignature());
2235         }
2236         typeInfo.push_back(
2237             TypeInfo(
2238                 TypeInfo::KIND_ATTRIBUTE, attrName, specialType,
2239                 static_cast< TypeInfo::Flags >(
2240                     ((flags & RT_ACCESS_READONLY) == 0
2241                      ? 0 : TypeInfo::FLAG_READONLY)
2242                     | ((flags & RT_ACCESS_BOUND) == 0
2243                        ? 0 : TypeInfo::FLAG_BOUND)),
2244                 index, polymorphicUnoType));
2245         index += ((flags & RT_ACCESS_READONLY) == 0 ? 2 : 1);
2246     }}
2247     {for (sal_uInt16 i = 0; i < methods; ++i) {
2248         RTMethodMode flags = reader.getMethodFlags(i);
2249         switch (flags) {
2250         case RT_MODE_ONEWAY:
2251         case RT_MODE_TWOWAY:
2252             {
2253                 rtl::OString methodName(
2254                     codemaker::convertString(reader.getMethodName(i)));
2255                 SpecialType specialReturnType;
2256                 PolymorphicUnoType polymorphicUnoReturnType;
2257                 MethodDescriptor desc(
2258                     manager, dependencies,
2259                     codemaker::convertString(
2260                         reader.getMethodReturnTypeName(i)),
2261                     &specialReturnType, &polymorphicUnoReturnType);
2262                 typeInfo.push_back(
2263                     TypeInfo(
2264                         TypeInfo::KIND_METHOD, methodName, specialReturnType,
2265                         static_cast< TypeInfo::Flags >(
2266                             flags == RT_MODE_ONEWAY
2267                             ? TypeInfo::FLAG_ONEWAY : 0),
2268                         index++, polymorphicUnoReturnType));
2269                 for (sal_uInt16 j = 0; j < reader.getMethodParameterCount(i);
2270                      ++j)
2271                 {
2272                     bool in;
2273                     bool out;
2274                     switch (reader.getMethodParameterFlags(i, j)) {
2275                     case RT_PARAM_IN:
2276                         in = true;
2277                         out = false;
2278                         break;
2279 
2280                     case RT_PARAM_OUT:
2281                         in = false;
2282                         out = true;
2283                         break;
2284 
2285                     case RT_PARAM_INOUT:
2286                         in = true;
2287                         out = true;
2288                         break;
2289 
2290                     default:
2291                         throw CannotDumpException(
2292                             rtl::OString(
2293                                 RTL_CONSTASCII_STRINGPARAM(
2294                                     "Bad type information"))); //TODO
2295                     }
2296                     PolymorphicUnoType polymorphicUnoType;
2297                     SpecialType specialType = desc.addParameter(
2298                         codemaker::convertString(
2299                             reader.getMethodParameterTypeName(i, j)),
2300                         out, true, &polymorphicUnoType);
2301                     if (out || isSpecialType(specialType)
2302                         || (polymorphicUnoType.kind
2303                             != PolymorphicUnoType::KIND_NONE))
2304                     {
2305                         typeInfo.push_back(
2306                             TypeInfo(
2307                                 codemaker::convertString(
2308                                     reader.getMethodParameterName(i, j)),
2309                                 specialType, in, out, methodName, j,
2310                                 polymorphicUnoType));
2311                     }
2312                 }
2313                 std::vector< rtl::OString > exc2;
2314                 createExceptionsAttribute(
2315                     manager, reader, i, dependencies, &exc2, 0);
2316                 cf->addMethod(
2317                     static_cast< ClassFile::AccessFlags >(
2318                         ClassFile::ACC_PUBLIC | ClassFile::ACC_ABSTRACT),
2319                     methodName, desc.getDescriptor(), 0, exc2,
2320                     desc.getSignature());
2321                 break;
2322             }
2323 
2324         case RT_MODE_ATTRIBUTE_GET:
2325         case RT_MODE_ATTRIBUTE_SET:
2326             {
2327                 //TODO: exploit the fact that attribute getter/setter methods
2328                 // are ordered the same way as the attribute fields themselves
2329                 rtl::OUString methodNameUtf16(reader.getMethodName(i));
2330                 bool found = false;
2331                 for (sal_uInt16 j = 0; j < fields; ++j) {
2332                     if (reader.getFieldName(j) == methodNameUtf16) {
2333                         found = true;
2334                         break;
2335                     }
2336                 }
2337                 if (found) {
2338                     break;
2339                 }
2340             }
2341         default:
2342             throw CannotDumpException(
2343                 rtl::OString(
2344                     RTL_CONSTASCII_STRINGPARAM("Bad type information"))); //TODO
2345         }
2346     }}
2347     addTypeInfo(className, typeInfo, dependencies, cf.get());
2348     writeClassFile(options, className, *cf.get());
2349 }
2350 
handleTypedef(TypeManager const & manager,JavaOptions &,typereg::Reader const & reader,Dependencies * dependencies)2351 void handleTypedef(
2352     TypeManager const & manager, JavaOptions /*TODO const*/ &,
2353     typereg::Reader const & reader, Dependencies * dependencies)
2354 {
2355     OSL_ASSERT(dependencies != 0);
2356     if (reader.getSuperTypeCount() != 1 || reader.getFieldCount() != 0
2357         || reader.getMethodCount() != 0 || reader.getReferenceCount() != 0)
2358     {
2359         throw CannotDumpException(
2360             rtl::OString(RTL_CONSTASCII_STRINGPARAM("Bad type information")));
2361             //TODO
2362     }
2363     RTTypeClass typeClass;
2364     rtl::OString nucleus;
2365     sal_Int32 rank;
2366     std::vector< rtl::OString > args;
2367     if (codemaker::decomposeAndResolve(
2368             manager, codemaker::convertString(reader.getSuperTypeName(0)),
2369             false, false, false, &typeClass, &nucleus, &rank, &args)
2370         == codemaker::UnoType::SORT_COMPLEX)
2371     {
2372         switch (typeClass) {
2373         case RT_TYPE_STRUCT:
2374             if (!args.empty()) {
2375                 throw CannotDumpException(
2376                     rtl::OString(
2377                         RTL_CONSTASCII_STRINGPARAM("Bad type information")));
2378                     //TODO
2379             }
2380         case RT_TYPE_ENUM:
2381         case RT_TYPE_INTERFACE:
2382         case RT_TYPE_TYPEDEF:
2383             dependencies->insert(nucleus);
2384             break;
2385 
2386         default:
2387             OSL_ASSERT(false);
2388             break;
2389         }
2390     }
2391 }
2392 
addConstant(TypeManager const & manager,typereg::Reader const & reader,bool publishable,sal_uInt16 index,Dependencies * dependencies,ClassFile * classFile)2393 void addConstant(
2394     TypeManager const & manager, typereg::Reader const & reader,
2395     bool publishable, sal_uInt16 index, Dependencies * dependencies,
2396     ClassFile * classFile)
2397 {
2398     OSL_ASSERT(dependencies != 0 && classFile != 0);
2399     RTFieldAccess flags = reader.getFieldFlags(index);
2400     if (flags != RT_ACCESS_CONST
2401         && (!publishable || flags != (RT_ACCESS_CONST | RT_ACCESS_PUBLISHED)))
2402     {
2403         throw CannotDumpException(
2404             rtl::OString(RTL_CONSTASCII_STRINGPARAM("Bad type information")));
2405             //TODO
2406     }
2407     RTConstValue fieldValue(reader.getFieldValue(index));
2408     sal_uInt16 valueIndex;
2409     RTTypeClass typeClass;
2410     rtl::OString nucleus;
2411     sal_Int32 rank;
2412     std::vector< rtl::OString > args;
2413     switch (codemaker::decomposeAndResolve(
2414                 manager,
2415                 codemaker::convertString(reader.getFieldTypeName(index)),
2416                 true, false, false, &typeClass, &nucleus, &rank, &args))
2417     {
2418     case codemaker::UnoType::SORT_BOOLEAN:
2419         if (fieldValue.m_type != RT_TYPE_BOOL) {
2420             throw CannotDumpException(
2421                 rtl::OString(
2422                     RTL_CONSTASCII_STRINGPARAM("Bad type information"))); //TODO
2423         }
2424         valueIndex = classFile->addIntegerInfo(fieldValue.m_value.aBool);
2425         break;
2426 
2427     case codemaker::UnoType::SORT_BYTE:
2428         if (fieldValue.m_type != RT_TYPE_BYTE) {
2429             throw CannotDumpException(
2430                 rtl::OString(
2431                     RTL_CONSTASCII_STRINGPARAM("Bad type information"))); //TODO
2432         }
2433         valueIndex = classFile->addIntegerInfo(fieldValue.m_value.aByte);
2434         break;
2435 
2436     case codemaker::UnoType::SORT_SHORT:
2437         if (fieldValue.m_type != RT_TYPE_INT16) {
2438             throw CannotDumpException(
2439                 rtl::OString(
2440                     RTL_CONSTASCII_STRINGPARAM("Bad type information"))); //TODO
2441         }
2442         valueIndex = classFile->addIntegerInfo(fieldValue.m_value.aShort);
2443         break;
2444 
2445     case codemaker::UnoType::SORT_UNSIGNED_SHORT:
2446     case codemaker::UnoType::SORT_CHAR:
2447         if (fieldValue.m_type != RT_TYPE_UINT16) {
2448             throw CannotDumpException(
2449                 rtl::OString(
2450                     RTL_CONSTASCII_STRINGPARAM("Bad type information"))); //TODO
2451         }
2452         valueIndex = classFile->addIntegerInfo(fieldValue.m_value.aUShort);
2453         break;
2454 
2455     case codemaker::UnoType::SORT_LONG:
2456         if (fieldValue.m_type != RT_TYPE_INT32) {
2457             throw CannotDumpException(
2458                 rtl::OString(
2459                     RTL_CONSTASCII_STRINGPARAM("Bad type information"))); //TODO
2460         }
2461         valueIndex = classFile->addIntegerInfo(fieldValue.m_value.aLong);
2462         break;
2463 
2464     case codemaker::UnoType::SORT_UNSIGNED_LONG:
2465         if (fieldValue.m_type != RT_TYPE_UINT32) {
2466             throw CannotDumpException(
2467                 rtl::OString(
2468                     RTL_CONSTASCII_STRINGPARAM("Bad type information"))); //TODO
2469         }
2470         valueIndex = classFile->addIntegerInfo(
2471             static_cast< sal_Int32 >(fieldValue.m_value.aULong));
2472         break;
2473 
2474     case codemaker::UnoType::SORT_HYPER:
2475         if (fieldValue.m_type != RT_TYPE_INT64) {
2476             throw CannotDumpException(
2477                 rtl::OString(
2478                     RTL_CONSTASCII_STRINGPARAM("Bad type information"))); //TODO
2479         }
2480         valueIndex = classFile->addLongInfo(fieldValue.m_value.aHyper);
2481         break;
2482 
2483     case codemaker::UnoType::SORT_UNSIGNED_HYPER:
2484         if (fieldValue.m_type != RT_TYPE_UINT64) {
2485             throw CannotDumpException(
2486                 rtl::OString(
2487                     RTL_CONSTASCII_STRINGPARAM("Bad type information"))); //TODO
2488         }
2489         valueIndex = classFile->addLongInfo(
2490             static_cast< sal_Int64 >(fieldValue.m_value.aUHyper));
2491         break;
2492 
2493     case codemaker::UnoType::SORT_FLOAT:
2494         if (fieldValue.m_type != RT_TYPE_FLOAT) {
2495             throw CannotDumpException(
2496                 rtl::OString(
2497                     RTL_CONSTASCII_STRINGPARAM("Bad type information"))); //TODO
2498         }
2499         valueIndex = classFile->addFloatInfo(fieldValue.m_value.aFloat);
2500         break;
2501 
2502     case codemaker::UnoType::SORT_DOUBLE:
2503         if (fieldValue.m_type != RT_TYPE_DOUBLE) {
2504             throw CannotDumpException(
2505                 rtl::OString(
2506                     RTL_CONSTASCII_STRINGPARAM("Bad type information"))); //TODO
2507         }
2508         valueIndex = classFile->addDoubleInfo(fieldValue.m_value.aDouble);
2509         break;
2510 
2511     default:
2512         throw CannotDumpException(
2513             rtl::OString(RTL_CONSTASCII_STRINGPARAM("Bad type information")));
2514             //TODO
2515     }
2516     rtl::OString desc;
2517     rtl::OString sig;
2518     getFieldDescriptor(
2519         manager, dependencies,
2520         codemaker::convertString(reader.getFieldTypeName(index)),
2521         &desc, &sig, 0);
2522     classFile->addField(
2523         static_cast< ClassFile::AccessFlags >(
2524             ClassFile::ACC_PUBLIC | ClassFile::ACC_STATIC
2525             | ClassFile::ACC_FINAL),
2526         codemaker::convertString(reader.getFieldName(index)),
2527         desc, valueIndex, sig);
2528 }
2529 
handleConstantGroup(TypeManager const & manager,JavaOptions & options,typereg::Reader const & reader,Dependencies * dependencies)2530 void handleConstantGroup(
2531     TypeManager const & manager, JavaOptions /*TODO const*/ & options,
2532     typereg::Reader const & reader, Dependencies * dependencies)
2533 {
2534     OSL_ASSERT(dependencies != 0);
2535     if (reader.getSuperTypeCount() != 0 || reader.getMethodCount() != 0
2536         || reader.getReferenceCount() != 0)
2537     {
2538         throw CannotDumpException(
2539             rtl::OString(RTL_CONSTASCII_STRINGPARAM("Bad type information")));
2540             //TODO
2541     }
2542     rtl::OString className(codemaker::convertString(reader.getTypeName()));
2543     std::auto_ptr< ClassFile > cf(
2544         new ClassFile(
2545             static_cast< ClassFile::AccessFlags >(
2546                 ClassFile::ACC_PUBLIC | ClassFile::ACC_INTERFACE
2547                 | ClassFile::ACC_ABSTRACT),
2548             className,
2549             rtl::OString(RTL_CONSTASCII_STRINGPARAM("java/lang/Object")),
2550             rtl::OString()));
2551     sal_uInt16 fields = reader.getFieldCount();
2552     for (sal_uInt16 i = 0; i < fields; ++i) {
2553         addConstant(manager, reader, false, i, dependencies, cf.get());
2554     }
2555     writeClassFile(options, className, *cf.get());
2556 }
2557 
handleModule(TypeManager const & manager,JavaOptions & options,typereg::Reader const & reader,Dependencies * dependencies)2558 void handleModule(
2559     TypeManager const & manager, JavaOptions /*TODO const*/ & options,
2560     typereg::Reader const & reader, Dependencies * dependencies)
2561 {
2562     OSL_ASSERT(dependencies != 0);
2563     if (reader.getSuperTypeCount() != 0 || reader.getMethodCount() != 0
2564         || reader.getReferenceCount() != 0)
2565     {
2566         throw CannotDumpException(
2567             rtl::OString(RTL_CONSTASCII_STRINGPARAM("Bad type information")));
2568             //TODO
2569     }
2570     rtl::OStringBuffer buf(codemaker::convertString(reader.getTypeName()));
2571     buf.append('/');
2572     rtl::OString prefix(buf.makeStringAndClear());
2573     sal_uInt16 fields = reader.getFieldCount();
2574     for (sal_uInt16 i = 0; i < fields; ++i) {
2575         rtl::OString className(
2576             prefix + codemaker::convertString(reader.getFieldName(i)));
2577         std::auto_ptr< ClassFile > cf(
2578             new ClassFile(
2579                 static_cast< ClassFile::AccessFlags >(
2580                     ClassFile::ACC_PUBLIC | ClassFile::ACC_INTERFACE
2581                     | ClassFile::ACC_ABSTRACT),
2582                 className,
2583                 rtl::OString(RTL_CONSTASCII_STRINGPARAM("java/lang/Object")),
2584                 rtl::OString()));
2585         addConstant(manager, reader, true, i, dependencies, cf.get());
2586         writeClassFile(options, className, *cf.get());
2587     }
2588 }
2589 
addExceptionHandlers(codemaker::ExceptionTreeNode const * node,ClassFile::Code::Position start,ClassFile::Code::Position end,ClassFile::Code::Position handler,ClassFile::Code * code)2590 void addExceptionHandlers(
2591     codemaker::ExceptionTreeNode const * node,
2592     ClassFile::Code::Position start, ClassFile::Code::Position end,
2593     ClassFile::Code::Position handler, ClassFile::Code * code)
2594 {
2595     OSL_ASSERT(node != 0 && code != 0);
2596     if (node->present) {
2597         code->addException(start, end, handler, node->name);
2598     } else {
2599         for (codemaker::ExceptionTreeNode::Children::const_iterator i(
2600                  node->children.begin());
2601              i != node->children.end(); ++i)
2602         {
2603             addExceptionHandlers(*i, start, end, handler, code);
2604         }
2605     }
2606 }
2607 
addConstructor(TypeManager const & manager,rtl::OString const & realJavaBaseName,rtl::OString const & unoName,rtl::OString const & className,typereg::Reader const & reader,sal_uInt16 methodIndex,rtl::OString const & methodName,rtl::OString const & returnType,bool defaultConstructor,Dependencies * dependencies,ClassFile * classFile)2608 void addConstructor(
2609     TypeManager const & manager, rtl::OString const & realJavaBaseName,
2610     rtl::OString const & unoName, rtl::OString const & className,
2611     typereg::Reader const & reader, sal_uInt16 methodIndex,
2612     rtl::OString const & methodName, rtl::OString const & returnType,
2613     bool defaultConstructor, Dependencies * dependencies, ClassFile * classFile)
2614 {
2615     OSL_ASSERT(dependencies != 0 && classFile != 0);
2616     MethodDescriptor desc(manager, dependencies, returnType, 0, 0);
2617     desc.addParameter(
2618         rtl::OString(
2619             RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/XComponentContext")),
2620         false, false, 0);
2621     std::auto_ptr< ClassFile::Code > code(classFile->newCode());
2622     code->loadLocalReference(0);
2623     // stack: context
2624     code->instrInvokestatic(
2625         className, rtl::OString(RTL_CONSTASCII_STRINGPARAM("$getFactory")),
2626         rtl::OString(
2627             RTL_CONSTASCII_STRINGPARAM(
2628                 "(Lcom/sun/star/uno/XComponentContext;)"
2629                 "Lcom/sun/star/lang/XMultiComponentFactory;")));
2630     // stack: factory
2631     code->loadStringConstant(unoName);
2632     // stack: factory serviceName
2633     codemaker::ExceptionTree tree;
2634     ClassFile::Code::Position tryStart;
2635     ClassFile::Code::Position tryEnd;
2636     std::vector< rtl::OString > exc;
2637     sal_uInt16 stack;
2638     sal_uInt16 localIndex = 1;
2639     ClassFile::AccessFlags access = static_cast< ClassFile::AccessFlags >(
2640         ClassFile::ACC_PUBLIC | ClassFile::ACC_STATIC);
2641     if (defaultConstructor) {
2642         code->loadLocalReference(0);
2643         // stack: factory serviceName context
2644         tryStart = code->getPosition();
2645         code->instrInvokeinterface(
2646             rtl::OString(
2647                 RTL_CONSTASCII_STRINGPARAM(
2648                     "com/sun/star/lang/XMultiComponentFactory")),
2649             rtl::OString(
2650                 RTL_CONSTASCII_STRINGPARAM(
2651                     "createInstanceWithContext")),
2652             rtl::OString(
2653                 RTL_CONSTASCII_STRINGPARAM(
2654                     "(Ljava/lang/String;Lcom/sun/star/uno/XComponentContext;)"
2655                     "Ljava/lang/Object;")),
2656             3);
2657         tryEnd = code->getPosition();
2658         // stack: instance
2659         stack = 3;
2660     } else {
2661         sal_uInt16 parameters = reader.getMethodParameterCount(methodIndex);
2662         if (parameters == 1
2663             && (reader.getMethodParameterFlags(methodIndex, 0)
2664                 == (RT_PARAM_IN | RT_PARAM_REST))
2665             && (reader.getMethodParameterTypeName(methodIndex, 0)
2666                 == rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("any"))))
2667         {
2668             desc.addParameter(
2669                 rtl::OString(RTL_CONSTASCII_STRINGPARAM("any")), true, true, 0);
2670             code->loadLocalReference(localIndex++);
2671             // stack: factory serviceName args
2672             stack = 4;
2673             access = static_cast< ClassFile::AccessFlags >(
2674                 access | ClassFile::ACC_VARARGS);
2675         } else {
2676             code->loadIntegerConstant(parameters);
2677             // stack: factory serviceName N
2678             code->instrAnewarray(
2679                 rtl::OString(RTL_CONSTASCII_STRINGPARAM("java/lang/Object")));
2680             // stack: factory serviceName args
2681             stack = 0;
2682             for (sal_uInt16 i = 0; i < parameters; ++i) {
2683                 RTParamMode flags = reader.getMethodParameterFlags(
2684                     methodIndex, i);
2685                 rtl::OString paramType(
2686                     codemaker::convertString(
2687                         reader.getMethodParameterTypeName(methodIndex, i)));
2688                 if ((flags != RT_PARAM_IN
2689                      && flags != (RT_PARAM_IN | RT_PARAM_REST))
2690                     || ((flags & RT_PARAM_REST) != 0
2691                         && (parameters != 1
2692                             || (paramType
2693                                 != rtl::OString(
2694                                     RTL_CONSTASCII_STRINGPARAM("any"))))))
2695                 {
2696                     throw CannotDumpException(
2697                         rtl::OString(
2698                             RTL_CONSTASCII_STRINGPARAM(
2699                                 "Bad type information"))); //TODO
2700                 }
2701                 desc.addParameter(paramType, false, true, 0);
2702                 code->instrDup();
2703                 // stack: factory serviceName args args
2704                 code->loadIntegerConstant(i);
2705                 // stack: factory serviceName args args i
2706                 stack = std::max(
2707                     stack,
2708                     addLoadLocal(
2709                         manager, code.get(), &localIndex, false, paramType,
2710                         true, dependencies));
2711                 // stack: factory serviceName args args i any
2712                 code->instrAastore();
2713                 // stack: factory serviceName args
2714             }
2715             stack += 5;
2716         }
2717         code->loadLocalReference(0);
2718         // stack: factory serviceName args context
2719         tryStart = code->getPosition();
2720         code->instrInvokeinterface(
2721             rtl::OString(
2722                 RTL_CONSTASCII_STRINGPARAM(
2723                     "com/sun/star/lang/XMultiComponentFactory")),
2724             rtl::OString(
2725                 RTL_CONSTASCII_STRINGPARAM(
2726                     "createInstanceWithArgumentsAndContext")),
2727             rtl::OString(
2728                 RTL_CONSTASCII_STRINGPARAM(
2729                     "(Ljava/lang/String;[Ljava/lang/Object;"
2730                     "Lcom/sun/star/uno/XComponentContext;)Ljava/lang/Object;")),
2731             4);
2732         tryEnd = code->getPosition();
2733         // stack: instance
2734         createExceptionsAttribute(
2735             manager, reader, methodIndex, dependencies, &exc, &tree);
2736     }
2737     code->loadLocalReference(0);
2738     // stack: instance context
2739     code->instrInvokestatic(
2740         className, rtl::OString(RTL_CONSTASCII_STRINGPARAM("$castInstance")),
2741         rtl::OString(
2742             RTL_CONSTASCII_STRINGPARAM(
2743                 "(Ljava/lang/Object;Lcom/sun/star/uno/XComponentContext;)"
2744                 "Ljava/lang/Object;")));
2745     // stack: instance
2746     code->instrCheckcast(returnType);
2747     // stack: instance
2748     code->instrAreturn();
2749     if (!tree.getRoot()->present) {
2750         ClassFile::Code::Position pos1 = code->getPosition();
2751         // stack: e
2752         code->instrInvokevirtual(
2753             rtl::OString(RTL_CONSTASCII_STRINGPARAM("java/lang/Throwable")),
2754             rtl::OString(RTL_CONSTASCII_STRINGPARAM("toString")),
2755             rtl::OString(RTL_CONSTASCII_STRINGPARAM("()Ljava/lang/String;")));
2756         // stack: str
2757         localIndex = std::max< sal_uInt16 >(localIndex, 2);
2758         code->storeLocalReference(1);
2759         // stack: -
2760         code->instrNew(
2761             rtl::OString(
2762                 RTL_CONSTASCII_STRINGPARAM(
2763                     "com/sun/star/uno/DeploymentException")));
2764         // stack: ex
2765         code->instrDup();
2766         // stack: ex ex
2767         rtl::OStringBuffer msg;
2768         msg.append(
2769             RTL_CONSTASCII_STRINGPARAM(
2770                 "component context fails to supply service "));
2771         msg.append(unoName);
2772         msg.append(RTL_CONSTASCII_STRINGPARAM(" of type "));
2773         msg.append(realJavaBaseName);
2774         msg.append(RTL_CONSTASCII_STRINGPARAM(": "));
2775         code->loadStringConstant(msg.makeStringAndClear());
2776         // stack: ex ex "..."
2777         code->loadLocalReference(1);
2778         // stack: ex ex "..." str
2779         code->instrInvokevirtual(
2780             rtl::OString(RTL_CONSTASCII_STRINGPARAM("java/lang/String")),
2781             rtl::OString(RTL_CONSTASCII_STRINGPARAM("concat")),
2782             rtl::OString(
2783                 RTL_CONSTASCII_STRINGPARAM(
2784                     "(Ljava/lang/String;)Ljava/lang/String;")));
2785         // stack: ex ex "..."
2786         code->loadLocalReference(0);
2787         // stack: ex ex "..." context
2788         code->instrInvokespecial(
2789             rtl::OString(
2790                 RTL_CONSTASCII_STRINGPARAM(
2791                     "com/sun/star/uno/DeploymentException")),
2792             rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")),
2793             rtl::OString(
2794                 RTL_CONSTASCII_STRINGPARAM(
2795                     "(Ljava/lang/String;Ljava/lang/Object;)V")));
2796         // stack: ex
2797         ClassFile::Code::Position pos2 = code->getPosition();
2798         code->instrAthrow();
2799         addExceptionHandlers(
2800             tree.getRoot(), tryStart, tryEnd, pos2, code.get());
2801         code->addException(
2802             tryStart, tryEnd, pos1,
2803             rtl::OString(
2804                 RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/Exception")));
2805         dependencies->insert(
2806             rtl::OString(
2807                 RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/Exception")));
2808         stack = std::max< sal_uInt16 >(stack, 4);
2809     }
2810     code->setMaxStackAndLocals(stack, localIndex);
2811     classFile->addMethod(
2812         access, methodName, desc.getDescriptor(), code.get(), exc,
2813         desc.getSignature());
2814 }
2815 
handleService(TypeManager const & manager,JavaOptions & options,typereg::Reader const & reader,Dependencies * dependencies)2816 void handleService(
2817     TypeManager const & manager, JavaOptions /*TODO const*/ & options,
2818     typereg::Reader const & reader, Dependencies * dependencies)
2819 {
2820     OSL_ASSERT(dependencies != 0);
2821     sal_uInt16 superTypes = reader.getSuperTypeCount();
2822     sal_uInt16 methods = reader.getMethodCount();
2823     if (superTypes == 0
2824         ? methods != 0
2825         : (superTypes != 1 || reader.getFieldCount() != 0
2826            || reader.getReferenceCount() != 0))
2827     {
2828         throw CannotDumpException(
2829             rtl::OString(RTL_CONSTASCII_STRINGPARAM("Bad type information")));
2830             //TODO
2831     }
2832     if (superTypes == 0) {
2833         return;
2834     }
2835     rtl::OString unoName(codemaker::convertString(reader.getTypeName()));
2836     rtl::OString className(
2837         translateUnoTypeToJavaFullyQualifiedName(
2838             unoName, rtl::OString(RTL_CONSTASCII_STRINGPARAM("service"))));
2839     unoName = unoName.replace('/', '.');
2840     std::auto_ptr< ClassFile > cf(
2841         new ClassFile(
2842             static_cast< ClassFile::AccessFlags >(
2843                 ClassFile::ACC_PUBLIC | ClassFile::ACC_FINAL
2844                 | ClassFile::ACC_SUPER),
2845             className,
2846             rtl::OString(RTL_CONSTASCII_STRINGPARAM("java/lang/Object")),
2847             rtl::OString()));
2848     if (methods > 0) {
2849         rtl::OString base(codemaker::convertString(
2850                               reader.getSuperTypeName(0)));
2851         rtl::OString realJavaBaseName(base.replace('/', '.'));
2852         dependencies->insert(base);
2853         dependencies->insert(
2854             rtl::OString(
2855                 RTL_CONSTASCII_STRINGPARAM(
2856                     "com/sun/star/lang/XMultiComponentFactory")));
2857         dependencies->insert(
2858             rtl::OString(
2859                 RTL_CONSTASCII_STRINGPARAM(
2860                     "com/sun/star/uno/DeploymentException")));
2861         dependencies->insert(
2862             rtl::OString(
2863                 RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/TypeClass")));
2864         dependencies->insert(
2865             rtl::OString(
2866                 RTL_CONSTASCII_STRINGPARAM(
2867                     "com/sun/star/uno/XComponentContext")));
2868         for (sal_uInt16 i = 0; i < methods; ++i) {
2869             rtl::OString name(codemaker::convertString(
2870                                   reader.getMethodName(i)));
2871             bool defaultCtor = name.isEmpty();
2872             if (reader.getMethodFlags(i) != RT_MODE_TWOWAY
2873                 || (!reader.getMethodReturnTypeName(i).equalsAsciiL(
2874                         RTL_CONSTASCII_STRINGPARAM("void")))
2875                 || (defaultCtor
2876                     && (methods != 1 || reader.getMethodParameterCount(i) != 0
2877                         || reader.getMethodExceptionCount(i) != 0)))
2878             {
2879                 throw CannotDumpException(
2880                     rtl::OString(
2881                         RTL_CONSTASCII_STRINGPARAM("Bad type information")));
2882                     //TODO
2883             }
2884             if (defaultCtor) {
2885                 name = rtl::OString(RTL_CONSTASCII_STRINGPARAM("create"));
2886             } else {
2887                 name = codemaker::java::translateUnoToJavaIdentifier(
2888                     name, rtl::OString(RTL_CONSTASCII_STRINGPARAM("method")));
2889             }
2890             addConstructor(
2891                 manager, realJavaBaseName, unoName, className, reader, i, name,
2892                 base, defaultCtor, dependencies, cf.get());
2893         }
2894         // Synthetic getFactory method:
2895         {
2896             std::auto_ptr< ClassFile::Code > code(cf->newCode());
2897             code->loadLocalReference(0);
2898             // stack: context
2899             code->instrInvokeinterface(
2900                 rtl::OString(
2901                     RTL_CONSTASCII_STRINGPARAM(
2902                         "com/sun/star/uno/XComponentContext")),
2903                 rtl::OString(RTL_CONSTASCII_STRINGPARAM("getServiceManager")),
2904                 rtl::OString(
2905                     RTL_CONSTASCII_STRINGPARAM(
2906                         "()Lcom/sun/star/lang/XMultiComponentFactory;")),
2907                 1);
2908             // stack: factory
2909             code->instrDup();
2910             // stack: factory factory
2911             ClassFile::Code::Branch branch = code->instrIfnull();
2912             // stack: factory
2913             code->instrAreturn();
2914             code->branchHere(branch);
2915             code->instrPop();
2916             // stack: -
2917             code->instrNew(
2918                 rtl::OString(
2919                     RTL_CONSTASCII_STRINGPARAM(
2920                         "com/sun/star/uno/DeploymentException")));
2921             // stack: ex
2922             code->instrDup();
2923             // stack: ex ex
2924             code->loadStringConstant(
2925                 rtl::OString(
2926                     RTL_CONSTASCII_STRINGPARAM(
2927                         "component context fails to supply service manager")));
2928             // stack: ex ex "..."
2929             code->loadLocalReference(0);
2930             // stack: ex ex "..." context
2931             code->instrInvokespecial(
2932                 rtl::OString(
2933                     RTL_CONSTASCII_STRINGPARAM(
2934                         "com/sun/star/uno/DeploymentException")),
2935                 rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")),
2936                 rtl::OString(
2937                     RTL_CONSTASCII_STRINGPARAM(
2938                         "(Ljava/lang/String;Ljava/lang/Object;)V")));
2939             // stack: ex
2940             code->instrAthrow();
2941             code->setMaxStackAndLocals(4, 1);
2942             cf->addMethod(
2943                 static_cast< ClassFile::AccessFlags >(
2944                     ClassFile::ACC_PRIVATE | ClassFile::ACC_STATIC
2945                     | ClassFile::ACC_SYNTHETIC),
2946                 rtl::OString(RTL_CONSTASCII_STRINGPARAM("$getFactory")),
2947                 rtl::OString(
2948                     RTL_CONSTASCII_STRINGPARAM(
2949                         "(Lcom/sun/star/uno/XComponentContext;)"
2950                         "Lcom/sun/star/lang/XMultiComponentFactory;")),
2951                 code.get(), std::vector< rtl::OString >(), rtl::OString());
2952         }
2953         // Synthetic castInstance method:
2954         {
2955             std::auto_ptr< ClassFile::Code > code(cf->newCode());
2956             code->instrNew(
2957                 rtl::OString(
2958                     RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/Type")));
2959             // stack: type
2960             code->instrDup();
2961             // stack: type type
2962             code->loadStringConstant(realJavaBaseName);
2963             // stack: type type "..."
2964             code->instrGetstatic(
2965                 rtl::OString(
2966                     RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/TypeClass")),
2967                 rtl::OString(RTL_CONSTASCII_STRINGPARAM("INTERFACE")),
2968                 rtl::OString(
2969                     RTL_CONSTASCII_STRINGPARAM(
2970                         "Lcom/sun/star/uno/TypeClass;")));
2971             // stack: type type "..." INTERFACE
2972             code->instrInvokespecial(
2973                 rtl::OString(
2974                     RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/Type")),
2975                 rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")),
2976                 rtl::OString(
2977                     RTL_CONSTASCII_STRINGPARAM(
2978                         "(Ljava/lang/String;Lcom/sun/star/uno/TypeClass;)V")));
2979             // stack: type
2980             code->loadLocalReference(0);
2981             // stack: type instance
2982             code->instrInvokestatic(
2983                 rtl::OString(
2984                     RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/UnoRuntime")),
2985                 rtl::OString(RTL_CONSTASCII_STRINGPARAM("queryInterface")),
2986                 rtl::OString(
2987                     RTL_CONSTASCII_STRINGPARAM(
2988                         "(Lcom/sun/star/uno/Type;Ljava/lang/Object;)"
2989                         "Ljava/lang/Object;")));
2990             // stack: instance
2991             code->instrDup();
2992             // stack: instance instance
2993             ClassFile::Code::Branch branch = code->instrIfnull();
2994             // stack: instance
2995             code->instrAreturn();
2996             code->branchHere(branch);
2997             code->instrPop();
2998             // stack: -
2999             code->instrNew(
3000                 rtl::OString(
3001                     RTL_CONSTASCII_STRINGPARAM(
3002                         "com/sun/star/uno/DeploymentException")));
3003             // stack: ex
3004             code->instrDup();
3005             // stack: ex ex
3006             rtl::OStringBuffer msg;
3007             msg.append(
3008                 RTL_CONSTASCII_STRINGPARAM(
3009                     "component context fails to supply service "));
3010             msg.append(unoName);
3011             msg.append(RTL_CONSTASCII_STRINGPARAM(" of type "));
3012             msg.append(realJavaBaseName);
3013             code->loadStringConstant(msg.makeStringAndClear());
3014             // stack: ex ex "..."
3015             code->loadLocalReference(1);
3016             // stack: ex ex "..." context
3017             code->instrInvokespecial(
3018                 rtl::OString(
3019                     RTL_CONSTASCII_STRINGPARAM(
3020                         "com/sun/star/uno/DeploymentException")),
3021                 rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")),
3022                 rtl::OString(
3023                     RTL_CONSTASCII_STRINGPARAM(
3024                         "(Ljava/lang/String;Ljava/lang/Object;)V")));
3025             // stack: ex
3026             code->instrAthrow();
3027             code->setMaxStackAndLocals(4, 2);
3028             cf->addMethod(
3029                 static_cast< ClassFile::AccessFlags >(
3030                     ClassFile::ACC_PRIVATE | ClassFile::ACC_STATIC
3031                     | ClassFile::ACC_SYNTHETIC),
3032                 rtl::OString(RTL_CONSTASCII_STRINGPARAM("$castInstance")),
3033                 rtl::OString(
3034                     RTL_CONSTASCII_STRINGPARAM(
3035                         "(Ljava/lang/Object;Lcom/sun/star/uno/"
3036                         "XComponentContext;)Ljava/lang/Object;")),
3037                 code.get(), std::vector< rtl::OString >(), rtl::OString());
3038         }
3039     }
3040     writeClassFile(options, className, *cf.get());
3041 }
3042 
handleSingleton(TypeManager const & manager,JavaOptions & options,typereg::Reader const & reader,Dependencies * dependencies)3043 void handleSingleton(
3044     TypeManager const & manager, JavaOptions /*TODO const*/ & options,
3045     typereg::Reader const & reader, Dependencies * dependencies)
3046 {
3047     OSL_ASSERT(dependencies != 0);
3048     if (reader.getSuperTypeCount() != 1 || reader.getFieldCount() != 0
3049         || reader.getMethodCount() != 0 || reader.getReferenceCount() != 0)
3050     {
3051         throw CannotDumpException(
3052             rtl::OString(RTL_CONSTASCII_STRINGPARAM("Bad type information")));
3053             //TODO
3054     }
3055     rtl::OString base(codemaker::convertString(reader.getSuperTypeName(0)));
3056     rtl::OString realJavaBaseName(base.replace('/', '.'));
3057     switch (manager.getTypeReader(base).getTypeClass()) {
3058     case RT_TYPE_INTERFACE:
3059         break;
3060 
3061     case RT_TYPE_SERVICE:
3062         return;
3063 
3064     default:
3065         throw CannotDumpException(
3066             rtl::OString(RTL_CONSTASCII_STRINGPARAM("Bad type information")));
3067             //TODO
3068     }
3069     dependencies->insert(base);
3070     rtl::OString unoName(codemaker::convertString(reader.getTypeName()));
3071     rtl::OString className(
3072         translateUnoTypeToJavaFullyQualifiedName(
3073             unoName, rtl::OString(RTL_CONSTASCII_STRINGPARAM("singleton"))));
3074     unoName = unoName.replace('/', '.');
3075     dependencies->insert(
3076         rtl::OString(
3077             RTL_CONSTASCII_STRINGPARAM(
3078                 "com/sun/star/uno/DeploymentException")));
3079     dependencies->insert(
3080         rtl::OString(RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/TypeClass")));
3081     dependencies->insert(
3082         rtl::OString(
3083             RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/XComponentContext")));
3084     std::auto_ptr< ClassFile > cf(
3085         new ClassFile(
3086             static_cast< ClassFile::AccessFlags >(
3087                 ClassFile::ACC_PUBLIC | ClassFile::ACC_FINAL
3088                 | ClassFile::ACC_SUPER),
3089             className,
3090             rtl::OString(RTL_CONSTASCII_STRINGPARAM("java/lang/Object")),
3091             rtl::OString()));
3092     MethodDescriptor desc(manager, dependencies, base, 0, 0);
3093     desc.addParameter(
3094         rtl::OString(
3095             RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/XComponentContext")),
3096         false, false, 0);
3097     std::auto_ptr< ClassFile::Code > code(cf->newCode());
3098     code->loadLocalReference(0);
3099     // stack: context
3100     code->loadStringConstant(
3101         rtl::OString(RTL_CONSTASCII_STRINGPARAM("/singletons/")) + unoName);
3102     // stack: context "..."
3103     code->instrInvokeinterface(
3104         rtl::OString(
3105             RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/XComponentContext")),
3106         rtl::OString(RTL_CONSTASCII_STRINGPARAM("getValueByName")),
3107         rtl::OString(
3108             RTL_CONSTASCII_STRINGPARAM(
3109                 "(Ljava/lang/String;)Ljava/lang/Object;")),
3110         2);
3111     // stack: value
3112     code->instrDup();
3113     // stack: value value
3114     code->instrInstanceof(
3115         rtl::OString(RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/Any")));
3116     // stack: value 0/1
3117     ClassFile::Code::Branch branch1 = code->instrIfeq();
3118     // stack: value
3119     code->instrCheckcast(
3120         rtl::OString(RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/Any")));
3121     // stack: value
3122     code->instrDup();
3123     // stack: value value
3124     code->instrInvokevirtual(
3125         rtl::OString(RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/Any")),
3126         rtl::OString(RTL_CONSTASCII_STRINGPARAM("getType")),
3127         rtl::OString(RTL_CONSTASCII_STRINGPARAM("()Lcom/sun/star/uno/Type;")));
3128     // stack: value type
3129     code->instrInvokevirtual(
3130         rtl::OString(RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/Type")),
3131         rtl::OString(RTL_CONSTASCII_STRINGPARAM("getTypeClass")),
3132         rtl::OString(
3133             RTL_CONSTASCII_STRINGPARAM("()Lcom/sun/star/uno/TypeClass;")));
3134     // stack: value typeClass
3135     code->instrGetstatic(
3136         rtl::OString(RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/TypeClass")),
3137         rtl::OString(RTL_CONSTASCII_STRINGPARAM("INTERFACE")),
3138         rtl::OString(
3139             RTL_CONSTASCII_STRINGPARAM("Lcom/sun/star/uno/TypeClass;")));
3140     // stack: value typeClass INTERFACE
3141     ClassFile::Code::Branch branch2 = code->instrIfAcmpne();
3142     // stack: value
3143     code->instrInvokevirtual(
3144         rtl::OString(RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/Any")),
3145         rtl::OString(RTL_CONSTASCII_STRINGPARAM("getObject")),
3146         rtl::OString(RTL_CONSTASCII_STRINGPARAM("()Ljava/lang/Object;")));
3147     // stack: value
3148     code->branchHere(branch1);
3149     code->instrNew(
3150         rtl::OString(RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/Type")));
3151     // stack: value type
3152     code->instrDup();
3153     // stack: value type type
3154     code->loadStringConstant(realJavaBaseName);
3155     // stack: value type type "..."
3156     code->instrGetstatic(
3157         rtl::OString(RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/TypeClass")),
3158         rtl::OString(RTL_CONSTASCII_STRINGPARAM("INTERFACE")),
3159         rtl::OString(
3160             RTL_CONSTASCII_STRINGPARAM("Lcom/sun/star/uno/TypeClass;")));
3161     // stack: value type type "..." INTERFACE
3162     code->instrInvokespecial(
3163         rtl::OString(RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/Type")),
3164         rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")),
3165         rtl::OString(
3166             RTL_CONSTASCII_STRINGPARAM(
3167                 "(Ljava/lang/String;Lcom/sun/star/uno/TypeClass;)V")));
3168     // stack: value type
3169     code->instrSwap();
3170     // stack: type value
3171     code->instrInvokestatic(
3172         rtl::OString(RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/UnoRuntime")),
3173         rtl::OString(RTL_CONSTASCII_STRINGPARAM("queryInterface")),
3174         rtl::OString(
3175             RTL_CONSTASCII_STRINGPARAM(
3176                 "(Lcom/sun/star/uno/Type;Ljava/lang/Object;)"
3177                 "Ljava/lang/Object;")));
3178     // stack: instance
3179     code->instrDup();
3180     // stack: instance instance
3181     ClassFile::Code::Branch branch3 = code->instrIfnull();
3182     // stack: instance
3183     code->instrCheckcast(base);
3184     // stack: instance
3185     code->instrAreturn();
3186     code->branchHere(branch2);
3187     code->branchHere(branch3);
3188     code->instrPop();
3189     // stack: -
3190     code->instrNew(
3191         rtl::OString(
3192             RTL_CONSTASCII_STRINGPARAM(
3193                 "com/sun/star/uno/DeploymentException")));
3194     // stack: ex
3195     code->instrDup();
3196     // stack: ex ex
3197     rtl::OStringBuffer msg;
3198     msg.append(
3199         RTL_CONSTASCII_STRINGPARAM(
3200             "component context fails to supply singleton "));
3201     msg.append(unoName);
3202     msg.append(RTL_CONSTASCII_STRINGPARAM(" of type "));
3203     msg.append(realJavaBaseName);
3204     code->loadStringConstant(msg.makeStringAndClear());
3205     // stack: ex ex "..."
3206     code->loadLocalReference(0);
3207     // stack: ex ex "..." context
3208     code->instrInvokespecial(
3209         rtl::OString(
3210             RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/DeploymentException")),
3211         rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")),
3212         rtl::OString(
3213             RTL_CONSTASCII_STRINGPARAM(
3214                 "(Ljava/lang/String;Ljava/lang/Object;)V")));
3215     // stack: ex
3216     code->instrAthrow();
3217     code->setMaxStackAndLocals(5, 1);
3218     cf->addMethod(
3219         static_cast< ClassFile::AccessFlags >(
3220             ClassFile::ACC_PUBLIC | ClassFile::ACC_STATIC),
3221         rtl::OString(RTL_CONSTASCII_STRINGPARAM("get")), desc.getDescriptor(),
3222         code.get(), std::vector< rtl::OString >(), desc.getSignature());
3223     writeClassFile(options, className, *cf.get());
3224 }
3225 
3226 }
3227 
produceType(rtl::OString const & type,TypeManager const & manager,codemaker::GeneratedTypeSet & generated,JavaOptions * options)3228 bool produceType(
3229     rtl::OString const & type, TypeManager const & manager,
3230     codemaker::GeneratedTypeSet & generated, JavaOptions * options)
3231 {
3232     OSL_ASSERT(options != 0);
3233     if (type.equals("/")
3234         || type.equals(manager.getBase())
3235         || generated.contains(type))
3236     {
3237         return true;
3238     }
3239     sal_Bool extra = sal_False;
3240     typereg::Reader reader(manager.getTypeReader(type, &extra));
3241     if (extra) {
3242         generated.add(type);
3243         return true;
3244     }
3245     if (!reader.isValid()) {
3246         return false;
3247     }
3248 
3249     handleUnoTypeRegistryEntityFunction handler;
3250     switch (reader.getTypeClass()) {
3251     case RT_TYPE_ENUM:
3252         handler = handleEnumType;
3253         break;
3254 
3255     case RT_TYPE_STRUCT:
3256     case RT_TYPE_EXCEPTION:
3257         handler = handleAggregatingType;
3258         break;
3259 
3260     case RT_TYPE_INTERFACE:
3261         handler = handleInterfaceType;
3262         break;
3263 
3264     case RT_TYPE_TYPEDEF:
3265         handler = handleTypedef;
3266         break;
3267 
3268     case RT_TYPE_CONSTANTS:
3269         handler = handleConstantGroup;
3270         break;
3271 
3272     case RT_TYPE_MODULE:
3273         handler = handleModule;
3274         break;
3275 
3276     case RT_TYPE_SERVICE:
3277         handler = handleService;
3278         break;
3279 
3280     case RT_TYPE_SINGLETON:
3281         handler = handleSingleton;
3282         break;
3283 
3284     default:
3285         return false;
3286     }
3287     Dependencies deps;
3288     handler(manager, *options, reader, &deps);
3289     generated.add(type);
3290     if (!options->isValid(rtl::OString(RTL_CONSTASCII_STRINGPARAM("-nD")))) {
3291         for (Dependencies::iterator i(deps.begin()); i != deps.end(); ++i) {
3292             if (!produceType(*i, manager, generated, options)) {
3293                 return false;
3294             }
3295         }
3296     }
3297     return true;
3298 }
3299 
produceType(RegistryKey & rTypeKey,bool bIsExtraType,TypeManager const & manager,codemaker::GeneratedTypeSet & generated,JavaOptions * options)3300 bool produceType(
3301     RegistryKey & rTypeKey, bool bIsExtraType, TypeManager const & manager,
3302     codemaker::GeneratedTypeSet & generated, JavaOptions * options)
3303 {
3304     ::rtl::OString typeName = manager.getTypeName(rTypeKey);
3305 
3306     OSL_ASSERT(options != 0);
3307     if (typeName.equals("/")
3308         || typeName.equals(manager.getBase())
3309         || generated.contains(typeName))
3310     {
3311         return true;
3312     }
3313     typereg::Reader reader(manager.getTypeReader(rTypeKey));
3314     if (bIsExtraType) {
3315         generated.add(typeName);
3316         return true;
3317     }
3318     if (!reader.isValid()) {
3319         return false;
3320     }
3321     handleUnoTypeRegistryEntityFunction handler;
3322     switch (reader.getTypeClass()) {
3323     case RT_TYPE_ENUM:
3324         handler = handleEnumType;
3325         break;
3326 
3327     case RT_TYPE_STRUCT:
3328     case RT_TYPE_EXCEPTION:
3329         handler = handleAggregatingType;
3330         break;
3331 
3332     case RT_TYPE_INTERFACE:
3333         handler = handleInterfaceType;
3334         break;
3335 
3336     case RT_TYPE_TYPEDEF:
3337         handler = handleTypedef;
3338         break;
3339 
3340     case RT_TYPE_CONSTANTS:
3341         handler = handleConstantGroup;
3342         break;
3343 
3344     case RT_TYPE_MODULE:
3345         handler = handleModule;
3346         break;
3347 
3348     case RT_TYPE_SERVICE:
3349         handler = handleService;
3350         break;
3351 
3352     case RT_TYPE_SINGLETON:
3353         handler = handleSingleton;
3354         break;
3355 
3356     default:
3357         return false;
3358     }
3359     Dependencies deps;
3360     handler(manager, *options, reader, &deps);
3361     generated.add(typeName);
3362     if (!options->isValid(rtl::OString(RTL_CONSTASCII_STRINGPARAM("-nD")))) {
3363         for (Dependencies::iterator i(deps.begin()); i != deps.end(); ++i) {
3364             if (!produceType(*i, manager, generated, options)) {
3365                 return false;
3366             }
3367         }
3368     }
3369     return true;
3370 }
3371