| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_codemaker.hxx" |
| |
| #include "javatype.hxx" |
| |
| #include "classfile.hxx" |
| #include "javaoptions.hxx" |
| |
| #include "codemaker/exceptiontree.hxx" |
| #include "codemaker/generatedtypeset.hxx" |
| #include "codemaker/global.hxx" |
| #include "codemaker/options.hxx" |
| #include "codemaker/typemanager.hxx" |
| #include "codemaker/unotype.hxx" |
| #include "codemaker/commonjava.hxx" |
| |
| #include "osl/diagnose.h" |
| #include "registry/reader.hxx" |
| #include "registry/refltype.hxx" |
| #include "registry/types.h" |
| #include "rtl/strbuf.hxx" |
| #include "rtl/string.h" |
| #include "rtl/string.hxx" |
| #include "rtl/textcvt.h" |
| #include "rtl/textenc.h" |
| #include "rtl/ustring.h" |
| #include "rtl/ustring.hxx" |
| #include "sal/types.h" |
| |
| #include <algorithm> |
| #include <list> |
| #include <map> |
| #include <memory> |
| #include <set> |
| #include <utility> |
| #include <vector> |
| |
| using codemaker::javamaker::ClassFile; |
| |
| namespace { |
| |
| void checkNoTypeArguments(std::vector< rtl::OString > const & arguments) { |
| if (!arguments.empty()) { |
| throw CannotDumpException( |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("Bad type information"))); |
| //TODO |
| } |
| } |
| |
| // helper function for createUnoName |
| void appendUnoName( |
| TypeManager const & manager, rtl::OString const & nucleus, sal_Int32 rank, |
| std::vector< rtl::OString > const & arguments, rtl::OStringBuffer * buffer) |
| { |
| OSL_ASSERT(rank >= 0 && buffer != 0); |
| for (sal_Int32 i = 0; i < rank; ++i) { |
| buffer->append(RTL_CONSTASCII_STRINGPARAM("[]")); |
| } |
| buffer->append(nucleus.replace('/', '.')); |
| if (!arguments.empty()) { |
| buffer->append('<'); |
| for (std::vector< rtl::OString >::const_iterator i(arguments.begin()); |
| i != arguments.end(); ++i) |
| { |
| if (i != arguments.begin()) { |
| buffer->append(','); |
| } |
| RTTypeClass argTypeClass; |
| rtl::OString argNucleus; |
| sal_Int32 argRank; |
| std::vector< rtl::OString > argArgs; |
| codemaker::decomposeAndResolve( |
| manager, *i, true, false, false, &argTypeClass, &argNucleus, |
| &argRank, &argArgs); |
| appendUnoName(manager, argNucleus, argRank, argArgs, buffer); |
| } |
| buffer->append('>'); |
| } |
| } |
| |
| // Translate the name of a UNO type registry entity (enum type, plain struct |
| // type, polymorphic struct type template, or interface type, decomposed into |
| // nucleus, rank, and arguments) into a core UNO type name: |
| rtl::OString createUnoName( |
| TypeManager const & manager, rtl::OString const & nucleus, sal_Int32 rank, |
| std::vector< rtl::OString > const & arguments) |
| { |
| rtl::OStringBuffer buf; |
| appendUnoName(manager, nucleus, rank, arguments, &buf); |
| return buf.makeStringAndClear(); |
| } |
| |
| /** |
| Set of UTF-8--encoded names of UNO type registry entities a given UNO type |
| registry entity depends on. |
| |
| UNO type registry entities are enum types, plain struct types, polymorphic |
| struct type templates, exception types, interface types, typedefs, modules, |
| constant groupds, single-interface--based services, accumulation-based |
| services, interface-based singletons, and service-based singletons. |
| */ |
| typedef std::set< rtl::OString > Dependencies; |
| |
| enum SpecialType { |
| SPECIAL_TYPE_NONE, |
| SPECIAL_TYPE_ANY, |
| SPECIAL_TYPE_UNSIGNED, |
| SPECIAL_TYPE_INTERFACE |
| }; |
| |
| bool isSpecialType(SpecialType special) { |
| return special >= SPECIAL_TYPE_UNSIGNED; |
| } |
| |
| rtl::OString translateUnoTypeToJavaFullyQualifiedName( |
| rtl::OString const & type, rtl::OString const & prefix) |
| { |
| sal_Int32 i = type.lastIndexOf('/') + 1; |
| return type.copy(0, i) + |
| codemaker::java::translateUnoToJavaIdentifier(type.copy(i), prefix); |
| } |
| |
| struct PolymorphicUnoType { |
| PolymorphicUnoType(): kind(KIND_NONE) {} |
| |
| enum Kind { KIND_NONE, KIND_STRUCT, KIND_SEQUENCE }; |
| Kind kind; |
| rtl::OString name; |
| }; |
| |
| SpecialType translateUnoTypeToDescriptor( |
| TypeManager const & manager, rtl::OString const & type, bool array, |
| bool classType, Dependencies * dependencies, |
| rtl::OStringBuffer * descriptor, rtl::OStringBuffer * signature, |
| bool * needsSignature, PolymorphicUnoType * polymorphicUnoType); |
| |
| SpecialType 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) |
| { |
| OSL_ASSERT(rank >= 0 && (signature == 0) == (needsSignature == 0)); |
| if (rank > 0xFF - (array ? 1 : 0)) { |
| throw CannotDumpException( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "Too many array dimensions for Java class file format"))); |
| } |
| if (array) { |
| ++rank; |
| } |
| for (sal_Int32 i = 0; i < rank; ++i) { |
| if (descriptor != 0) { |
| descriptor->append('['); |
| } |
| if (signature != 0) { |
| signature->append('['); |
| } |
| } |
| if (sort == codemaker::UnoType::SORT_COMPLEX) { |
| //TODO: check that nucleus is a valid (Java-modified UTF-8) identifier |
| rtl::OString superClass; |
| if (typeClass == RT_TYPE_INTERFACE |
| && (nucleus |
| == rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/XInterface")))) |
| { |
| if (descriptor != 0) { |
| descriptor->append( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("Ljava/lang/Object;"))); |
| } |
| if (signature != 0) { |
| signature->append( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("Ljava/lang/Object;"))); |
| } |
| if (polymorphicUnoType != 0) { |
| polymorphicUnoType->kind = PolymorphicUnoType::KIND_NONE; |
| } |
| return SPECIAL_TYPE_INTERFACE; |
| } else { |
| if (dependencies != 0) { |
| dependencies->insert(nucleus); |
| } |
| if (descriptor != 0) { |
| descriptor->append('L'); |
| descriptor->append(nucleus); |
| descriptor->append(';'); |
| } |
| if (signature != 0) { |
| signature->append('L'); |
| signature->append(nucleus); |
| if (!arguments.empty()) { |
| signature->append('<'); |
| for (std::vector< rtl::OString >::const_iterator i( |
| arguments.begin()); |
| i != arguments.end(); ++i) |
| { |
| translateUnoTypeToDescriptor( |
| manager, *i, false, true, dependencies, 0, |
| signature, needsSignature, 0); |
| } |
| signature->append('>'); |
| *needsSignature = true; |
| } |
| signature->append(';'); |
| } |
| if (polymorphicUnoType != 0) { |
| if (arguments.empty()) { |
| polymorphicUnoType->kind = PolymorphicUnoType::KIND_NONE; |
| } else { |
| polymorphicUnoType->kind = rank == 0 |
| ? PolymorphicUnoType::KIND_STRUCT |
| : PolymorphicUnoType::KIND_SEQUENCE; |
| polymorphicUnoType->name = createUnoName( |
| manager, nucleus, rank, arguments); |
| } |
| } |
| return SPECIAL_TYPE_NONE; |
| } |
| } else { |
| static rtl::OString const |
| simpleTypeDescriptors[codemaker::UnoType::SORT_ANY + 1][2] = { |
| { rtl::OString(RTL_CONSTASCII_STRINGPARAM("V")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("Ljava/lang/Void;")) |
| }, |
| { rtl::OString(RTL_CONSTASCII_STRINGPARAM("Z")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("Ljava/lang/Boolean;")) |
| }, |
| { rtl::OString(RTL_CONSTASCII_STRINGPARAM("B")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("Ljava/lang/Byte;")) |
| }, |
| { rtl::OString(RTL_CONSTASCII_STRINGPARAM("S")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("Ljava/lang/Short;")) |
| }, |
| { rtl::OString(RTL_CONSTASCII_STRINGPARAM("S")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("Ljava/lang/Short;")) |
| }, |
| { rtl::OString(RTL_CONSTASCII_STRINGPARAM("I")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("Ljava/lang/Integer;")) |
| }, |
| { rtl::OString(RTL_CONSTASCII_STRINGPARAM("I")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("Ljava/lang/Integer;")) |
| }, |
| { rtl::OString(RTL_CONSTASCII_STRINGPARAM("J")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("Ljava/lang/Long;")) |
| }, |
| { rtl::OString(RTL_CONSTASCII_STRINGPARAM("J")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("Ljava/lang/Long;")) |
| }, |
| { rtl::OString(RTL_CONSTASCII_STRINGPARAM("F")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("Ljava/lang/Float;")) |
| }, |
| { rtl::OString(RTL_CONSTASCII_STRINGPARAM("D")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("Ljava/lang/Double;")) |
| }, |
| { rtl::OString(RTL_CONSTASCII_STRINGPARAM("C")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("Ljava/lang/Character;")) |
| }, |
| { rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("Ljava/lang/String;")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("Ljava/lang/String;")) |
| }, |
| { rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("Lcom/sun/star/uno/Type;")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("Lcom/sun/star/uno/Type;")) |
| }, |
| { rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("Ljava/lang/Object;")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("Ljava/lang/Object;")) |
| } }; |
| rtl::OString const & s |
| = simpleTypeDescriptors[sort][rank == 0 && classType]; |
| if (descriptor != 0) { |
| descriptor->append(s); |
| } |
| if (signature != 0) { |
| signature->append(s); |
| } |
| if (polymorphicUnoType != 0) { |
| polymorphicUnoType->kind = PolymorphicUnoType::KIND_NONE; |
| } |
| static SpecialType const |
| simpleTypeSpecials[codemaker::UnoType::SORT_ANY + 1] = { |
| SPECIAL_TYPE_NONE, SPECIAL_TYPE_NONE, SPECIAL_TYPE_NONE, |
| SPECIAL_TYPE_NONE, SPECIAL_TYPE_UNSIGNED, SPECIAL_TYPE_NONE, |
| SPECIAL_TYPE_UNSIGNED, SPECIAL_TYPE_NONE, SPECIAL_TYPE_UNSIGNED, |
| SPECIAL_TYPE_NONE, SPECIAL_TYPE_NONE, SPECIAL_TYPE_NONE, |
| SPECIAL_TYPE_NONE, SPECIAL_TYPE_NONE, SPECIAL_TYPE_ANY }; |
| return simpleTypeSpecials[sort]; |
| } |
| } |
| |
| SpecialType translateUnoTypeToDescriptor( |
| TypeManager const & manager, rtl::OString const & type, bool array, |
| bool classType, Dependencies * dependencies, |
| rtl::OStringBuffer * descriptor, rtl::OStringBuffer * signature, |
| bool * needsSignature, PolymorphicUnoType * polymorphicUnoType) |
| { |
| RTTypeClass typeClass; |
| rtl::OString nucleus; |
| sal_Int32 rank; |
| std::vector< rtl::OString > args; |
| codemaker::UnoType::Sort sort = codemaker::decomposeAndResolve( |
| manager, type, true, true, false, &typeClass, &nucleus, &rank, &args); |
| OSL_ASSERT(rank < SAL_MAX_INT32); |
| return translateUnoTypeToDescriptor( |
| manager, sort, typeClass, nucleus, rank, args, array, classType, |
| dependencies, descriptor, signature, needsSignature, |
| polymorphicUnoType); |
| } |
| |
| SpecialType getFieldDescriptor( |
| TypeManager const & manager, Dependencies * dependencies, |
| rtl::OString const & type, rtl::OString * descriptor, |
| rtl::OString * signature, PolymorphicUnoType * polymorphicUnoType) |
| { |
| OSL_ASSERT(dependencies != 0 && descriptor != 0); |
| rtl::OStringBuffer desc; |
| rtl::OStringBuffer sig; |
| bool needsSig = false; |
| SpecialType specialType = translateUnoTypeToDescriptor( |
| manager, type, false, false, dependencies, &desc, &sig, &needsSig, |
| polymorphicUnoType); |
| *descriptor = desc.makeStringAndClear(); |
| if (signature != 0) { |
| if (needsSig) { |
| *signature = sig.makeStringAndClear(); |
| } else { |
| *signature = rtl::OString(); |
| } |
| } |
| return specialType; |
| } |
| |
| class MethodDescriptor { |
| public: |
| MethodDescriptor( |
| TypeManager const & manager, Dependencies * dependencies, |
| rtl::OString const & returnType, SpecialType * specialReturnType, |
| PolymorphicUnoType * polymorphicUnoType); |
| |
| SpecialType addParameter( |
| rtl::OString const & type, bool array, bool dependency, |
| PolymorphicUnoType * polymorphicUnoType); |
| |
| void addTypeParameter(rtl::OString const & name); |
| |
| rtl::OString getDescriptor() const; |
| |
| rtl::OString getSignature() const; |
| |
| private: |
| TypeManager const & m_manager; |
| Dependencies * m_dependencies; |
| rtl::OStringBuffer m_descriptorStart; |
| rtl::OString m_descriptorEnd; |
| rtl::OStringBuffer m_signatureStart; |
| rtl::OString m_signatureEnd; |
| bool m_needsSignature; |
| }; |
| |
| MethodDescriptor::MethodDescriptor( |
| TypeManager const & manager, Dependencies * dependencies, |
| rtl::OString const & returnType, SpecialType * specialReturnType, |
| PolymorphicUnoType * polymorphicUnoType): |
| m_manager(manager), m_dependencies(dependencies), m_needsSignature(false) |
| { |
| OSL_ASSERT(dependencies != 0); |
| m_descriptorStart.append('('); |
| m_signatureStart.append('('); |
| rtl::OStringBuffer descEnd; |
| descEnd.append(')'); |
| rtl::OStringBuffer sigEnd; |
| sigEnd.append(')'); |
| SpecialType special = translateUnoTypeToDescriptor( |
| m_manager, returnType, false, false, m_dependencies, &descEnd, &sigEnd, |
| &m_needsSignature, polymorphicUnoType); |
| m_descriptorEnd = descEnd.makeStringAndClear(); |
| m_signatureEnd = sigEnd.makeStringAndClear(); |
| if (specialReturnType != 0) { |
| *specialReturnType = special; |
| } |
| } |
| |
| SpecialType MethodDescriptor::addParameter( |
| rtl::OString const & type, bool array, bool dependency, |
| PolymorphicUnoType * polymorphicUnoType) |
| { |
| return translateUnoTypeToDescriptor( |
| m_manager, type, array, false, dependency ? m_dependencies : 0, |
| &m_descriptorStart, &m_signatureStart, &m_needsSignature, |
| polymorphicUnoType); |
| } |
| |
| void MethodDescriptor::addTypeParameter(rtl::OString const & name) { |
| m_descriptorStart.append(RTL_CONSTASCII_STRINGPARAM("Ljava/lang/Object;")); |
| m_signatureStart.append('T'); |
| m_signatureStart.append(name); |
| m_signatureStart.append(';'); |
| m_needsSignature = true; |
| } |
| |
| rtl::OString MethodDescriptor::getDescriptor() const { |
| rtl::OStringBuffer buf(m_descriptorStart); |
| buf.append(m_descriptorEnd); |
| return buf.makeStringAndClear(); |
| } |
| |
| rtl::OString MethodDescriptor::getSignature() const { |
| if (m_needsSignature) { |
| rtl::OStringBuffer buf(m_signatureStart); |
| buf.append(m_signatureEnd); |
| return buf.makeStringAndClear(); |
| } else { |
| return rtl::OString(); |
| } |
| } |
| |
| class TypeInfo { |
| public: |
| enum Kind { KIND_MEMBER, KIND_ATTRIBUTE, KIND_METHOD, KIND_PARAMETER }; |
| |
| // Same values as in com/sun/star/lib/uno/typeinfo/TypeInfo.java: |
| enum Flags { |
| FLAG_READONLY = 0x008, FLAG_BOUND = 0x100, FLAG_ONEWAY = 0x010 |
| }; |
| |
| // KIND_MEMBER: |
| TypeInfo( |
| rtl::OString const & name, SpecialType specialType, sal_Int32 index, |
| PolymorphicUnoType const & polymorphicUnoType, |
| sal_Int32 typeParameterIndex); |
| |
| // KIND_ATTRIBUTE/METHOD: |
| TypeInfo( |
| Kind kind, rtl::OString const & name, SpecialType specialType, |
| Flags flags, sal_Int32 index, |
| PolymorphicUnoType const & polymorphicUnoType); |
| |
| // KIND_PARAMETER: |
| TypeInfo( |
| rtl::OString const & parameterName, SpecialType specialType, |
| bool inParameter, bool outParameter, rtl::OString const & methodName, |
| sal_Int32 index, PolymorphicUnoType const & polymorphicUnoType); |
| |
| sal_uInt16 generateCode(ClassFile::Code & code, Dependencies * dependencies) |
| const; |
| |
| void generatePolymorphicUnoTypeCode( |
| ClassFile::Code & code, Dependencies * dependencies) const; |
| |
| private: |
| Kind m_kind; |
| rtl::OString m_name; |
| sal_Int32 m_flags; |
| sal_Int32 m_index; |
| rtl::OString m_methodName; |
| PolymorphicUnoType m_polymorphicUnoType; |
| sal_Int32 m_typeParameterIndex; |
| }; |
| |
| sal_Int32 translateSpecialTypeFlags( |
| SpecialType specialType, bool inParameter, bool outParameter) |
| { |
| static sal_Int32 const specialTypeFlags[SPECIAL_TYPE_INTERFACE + 1] = { |
| 0, 0x0040 /* ANY */, 0x0004 /* UNSIGNED */, 0x0080 /* INTERFACE */ }; |
| sal_Int32 flags = specialTypeFlags[specialType]; |
| if (inParameter) { |
| flags |= 0x0001; /* IN */ |
| } |
| if (outParameter) { |
| flags |= 0x0002; /* OUT */ |
| } |
| return flags; |
| } |
| |
| TypeInfo::TypeInfo( |
| rtl::OString const & name, SpecialType specialType, sal_Int32 index, |
| PolymorphicUnoType const & polymorphicUnoType, |
| sal_Int32 typeParameterIndex): |
| m_kind(KIND_MEMBER), m_name(name), |
| m_flags(translateSpecialTypeFlags(specialType, false, false)), |
| m_index(index), m_polymorphicUnoType(polymorphicUnoType), |
| m_typeParameterIndex(typeParameterIndex) |
| { |
| OSL_ASSERT( |
| polymorphicUnoType.kind == PolymorphicUnoType::KIND_NONE |
| ? typeParameterIndex >= -1 : typeParameterIndex == -1); |
| } |
| |
| TypeInfo::TypeInfo( |
| Kind kind, rtl::OString const & name, SpecialType specialType, |
| Flags flags, sal_Int32 index, |
| PolymorphicUnoType const & polymorphicUnoType): |
| m_kind(kind), m_name(name), |
| m_flags(flags | translateSpecialTypeFlags(specialType, false, false)), |
| m_index(index), m_polymorphicUnoType(polymorphicUnoType) |
| { |
| OSL_ASSERT(kind == KIND_ATTRIBUTE || kind == KIND_METHOD); |
| } |
| |
| TypeInfo::TypeInfo( |
| rtl::OString const & parameterName, SpecialType specialType, |
| bool inParameter, bool outParameter, rtl::OString const & methodName, |
| sal_Int32 index, PolymorphicUnoType const & polymorphicUnoType): |
| m_kind(KIND_PARAMETER), m_name(parameterName), |
| m_flags(translateSpecialTypeFlags(specialType, inParameter, outParameter)), |
| m_index(index), m_methodName(methodName), |
| m_polymorphicUnoType(polymorphicUnoType) |
| {} |
| |
| sal_uInt16 TypeInfo::generateCode( |
| ClassFile::Code & code, Dependencies * dependencies) const |
| { |
| OSL_ASSERT(dependencies != 0); |
| switch (m_kind) { |
| case KIND_MEMBER: |
| code.instrNew( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "com/sun/star/lib/uno/typeinfo/MemberTypeInfo"))); |
| code.instrDup(); |
| code.loadStringConstant(m_name); |
| code.loadIntegerConstant(m_index); |
| code.loadIntegerConstant(m_flags); |
| if (m_polymorphicUnoType.kind != PolymorphicUnoType::KIND_NONE) { |
| generatePolymorphicUnoTypeCode(code, dependencies); |
| code.loadIntegerConstant(m_typeParameterIndex); |
| code.instrInvokespecial( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "com/sun/star/lib/uno/typeinfo/MemberTypeInfo")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "(Ljava/lang/String;IILcom/sun/star/uno/Type;I)V"))); |
| return 8; |
| } else if (m_typeParameterIndex >= 0) { |
| code.instrAconstNull(); |
| code.loadIntegerConstant(m_typeParameterIndex); |
| code.instrInvokespecial( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "com/sun/star/lib/uno/typeinfo/MemberTypeInfo")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "(Ljava/lang/String;IILcom/sun/star/uno/Type;I)V"))); |
| return 6; |
| } else { |
| code.instrInvokespecial( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "com/sun/star/lib/uno/typeinfo/MemberTypeInfo")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("(Ljava/lang/String;II)V"))); |
| return 4; |
| } |
| |
| case KIND_ATTRIBUTE: |
| code.instrNew( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "com/sun/star/lib/uno/typeinfo/AttributeTypeInfo"))); |
| code.instrDup(); |
| code.loadStringConstant(m_name); |
| code.loadIntegerConstant(m_index); |
| code.loadIntegerConstant(m_flags); |
| if (m_polymorphicUnoType.kind != PolymorphicUnoType::KIND_NONE) { |
| generatePolymorphicUnoTypeCode(code, dependencies); |
| code.instrInvokespecial( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "com/sun/star/lib/uno/typeinfo/AttributeTypeInfo")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "(Ljava/lang/String;IILcom/sun/star/uno/Type;)V"))); |
| return 8; |
| } else { |
| code.instrInvokespecial( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "com/sun/star/lib/uno/typeinfo/AttributeTypeInfo")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("(Ljava/lang/String;II)V"))); |
| return 4; |
| } |
| |
| case KIND_METHOD: |
| code.instrNew( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "com/sun/star/lib/uno/typeinfo/MethodTypeInfo"))); |
| code.instrDup(); |
| code.loadStringConstant(m_name); |
| code.loadIntegerConstant(m_index); |
| code.loadIntegerConstant(m_flags); |
| if (m_polymorphicUnoType.kind != PolymorphicUnoType::KIND_NONE) { |
| generatePolymorphicUnoTypeCode(code, dependencies); |
| code.instrInvokespecial( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "com/sun/star/lib/uno/typeinfo/MethodTypeInfo")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "(Ljava/lang/String;IILcom/sun/star/uno/Type;)V"))); |
| return 8; |
| } else { |
| code.instrInvokespecial( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "com/sun/star/lib/uno/typeinfo/MethodTypeInfo")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("(Ljava/lang/String;II)V"))); |
| return 4; |
| } |
| |
| case KIND_PARAMETER: |
| code.instrNew( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "com/sun/star/lib/uno/typeinfo/ParameterTypeInfo"))); |
| code.instrDup(); |
| code.loadStringConstant(m_name); |
| code.loadStringConstant(m_methodName); |
| code.loadIntegerConstant(m_index); |
| code.loadIntegerConstant(m_flags); |
| if (m_polymorphicUnoType.kind != PolymorphicUnoType::KIND_NONE) { |
| generatePolymorphicUnoTypeCode(code, dependencies); |
| code.instrInvokespecial( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "com/sun/star/lib/uno/typeinfo/ParameterTypeInfo")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "(Ljava/lang/String;Ljava/lang/String;II" |
| "Lcom/sun/star/uno/Type;)V"))); |
| return 9; |
| } else { |
| code.instrInvokespecial( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "com/sun/star/lib/uno/typeinfo/ParameterTypeInfo")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "(Ljava/lang/String;Ljava/lang/String;II)V"))); |
| return 5; |
| } |
| |
| default: |
| OSL_ASSERT(false); |
| return 0; |
| } |
| } |
| |
| void TypeInfo::generatePolymorphicUnoTypeCode( |
| ClassFile::Code & code, Dependencies * dependencies) const |
| { |
| OSL_ASSERT( |
| dependencies != 0 |
| && m_polymorphicUnoType.kind != PolymorphicUnoType::KIND_NONE); |
| code.instrNew( |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/Type"))); |
| code.instrDup(); |
| code.loadStringConstant(m_polymorphicUnoType.name); |
| if (m_polymorphicUnoType.kind == PolymorphicUnoType::KIND_STRUCT) { |
| code.instrGetstatic( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/TypeClass")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("STRUCT")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("Lcom/sun/star/uno/TypeClass;"))); |
| } else { |
| code.instrGetstatic( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/TypeClass")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("SEQUENCE")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("Lcom/sun/star/uno/TypeClass;"))); |
| } |
| dependencies->insert( |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/TypeClass"))); |
| code.instrInvokespecial( |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/Type")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "(Ljava/lang/String;Lcom/sun/star/uno/TypeClass;)V"))); |
| } |
| |
| void writeClassFile( |
| JavaOptions /*TODO const*/ & options, rtl::OString const & type, |
| ClassFile const & classFile) |
| { |
| rtl::OString path; |
| if (options.isValid(rtl::OString(RTL_CONSTASCII_STRINGPARAM("-O")))) { |
| path = options.getOption( |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("-O"))); |
| } |
| rtl::OString filename( |
| createFileNameFromType( |
| path, type, rtl::OString(RTL_CONSTASCII_STRINGPARAM(".class")))); |
| bool check = false; |
| if (fileExists(filename)) { |
| if (options.isValid(rtl::OString(RTL_CONSTASCII_STRINGPARAM("-G")))) { |
| return; |
| } |
| check = options.isValid( |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("-Gc"))); |
| } |
| FileStream tempfile; |
| tempfile.createTempFile(getTempDir(filename)); |
| if (!tempfile.isValid()) { |
| throw CannotDumpException( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("Cannot create temporary file for ")) |
| + filename); |
| } |
| rtl::OString tempname(tempfile.getName()); |
| try { |
| classFile.write(tempfile); |
| } catch (...) { |
| // Remove existing file for consistency: |
| if (fileExists(filename)) { |
| removeTypeFile(filename); |
| } |
| tempfile.close(); |
| removeTypeFile(tempname); |
| throw; |
| } |
| tempfile.close(); |
| if (!makeValidTypeFile(filename, tempname, check)) { |
| rtl::OStringBuffer msg; |
| msg.append(RTL_CONSTASCII_STRINGPARAM("Cannot create ")); |
| msg.append(filename); |
| msg.append(RTL_CONSTASCII_STRINGPARAM(" from temporary file ")); |
| msg.append(tempname); |
| throw CannotDumpException(msg.makeStringAndClear()); |
| } |
| } |
| |
| void addTypeInfo( |
| rtl::OString const & className, std::vector< TypeInfo > const & typeInfo, |
| Dependencies * dependencies, ClassFile * classFile) |
| { |
| OSL_ASSERT(dependencies != 0 && classFile != 0); |
| std::vector< TypeInfo >::size_type typeInfos = typeInfo.size(); |
| if (typeInfos > SAL_MAX_INT32) { |
| throw CannotDumpException( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "UNOTYPEINFO array too big for Java class file format"))); |
| } |
| if (typeInfos != 0) { |
| classFile->addField( |
| static_cast< ClassFile::AccessFlags >( |
| ClassFile::ACC_PUBLIC | ClassFile::ACC_STATIC |
| | ClassFile::ACC_FINAL), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("UNOTYPEINFO")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "[Lcom/sun/star/lib/uno/typeinfo/TypeInfo;")), |
| 0, rtl::OString()); |
| std::auto_ptr< ClassFile::Code > code(classFile->newCode()); |
| code->loadIntegerConstant(static_cast< sal_Int32 >(typeInfos)); |
| code->instrAnewarray( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "com/sun/star/lib/uno/typeinfo/TypeInfo"))); |
| sal_Int32 index = 0; |
| sal_uInt16 stack = 0; |
| for (std::vector< TypeInfo >::const_iterator i(typeInfo.begin()); |
| i != typeInfo.end(); ++i) |
| { |
| code->instrDup(); |
| code->loadIntegerConstant(index++); |
| stack = std::max(stack, i->generateCode(*code, dependencies)); |
| code->instrAastore(); |
| } |
| code->instrPutstatic( |
| className, rtl::OString(RTL_CONSTASCII_STRINGPARAM("UNOTYPEINFO")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "[Lcom/sun/star/lib/uno/typeinfo/TypeInfo;"))); |
| code->instrReturn(); |
| if (stack > SAL_MAX_UINT16 - 4) { |
| throw CannotDumpException( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "Stack too big for Java class file format"))); |
| } |
| code->setMaxStackAndLocals(static_cast< sal_uInt16 >(stack + 4), 0); |
| classFile->addMethod( |
| static_cast< ClassFile::AccessFlags >( |
| ClassFile::ACC_PRIVATE | ClassFile::ACC_STATIC), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("<clinit>")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("()V")), code.get(), |
| std::vector< rtl::OString >(), rtl::OString()); |
| } |
| } |
| |
| typedef void (* handleUnoTypeRegistryEntityFunction)( |
| TypeManager const & manager, JavaOptions /*TODO const*/ & options, |
| typereg::Reader const & reader, Dependencies * dependencies); |
| |
| void handleEnumType( |
| TypeManager const &, JavaOptions /*TODO const*/ & options, |
| typereg::Reader const & reader, Dependencies *) |
| { |
| sal_uInt16 fields = reader.getFieldCount(); |
| if (fields == 0 || reader.getSuperTypeCount() != 0 |
| || reader.getMethodCount() != 0 || reader.getReferenceCount() != 0) |
| { |
| throw CannotDumpException( |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("Bad type information"))); |
| //TODO |
| } |
| rtl::OString className(codemaker::convertString(reader.getTypeName())); |
| std::auto_ptr< ClassFile > cf( |
| new ClassFile( |
| static_cast< ClassFile::AccessFlags >( |
| ClassFile::ACC_PUBLIC | ClassFile::ACC_FINAL |
| | ClassFile::ACC_SUPER), |
| className, |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/Enum")), |
| rtl::OString())); |
| rtl::OStringBuffer buf; |
| buf.append('L'); |
| buf.append(className); |
| buf.append(';'); |
| rtl::OString classDescriptor(buf.makeStringAndClear()); |
| {for (sal_uInt16 i = 0; i < fields; ++i) { |
| RTConstValue fieldValue(reader.getFieldValue(i)); |
| if (fieldValue.m_type != RT_TYPE_INT32 |
| || reader.getFieldFlags(i) != RT_ACCESS_CONST |
| || !reader.getFieldTypeName(i).isEmpty()) |
| { |
| throw CannotDumpException( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("Bad type information"))); //TODO |
| } |
| rtl::OString fieldName( |
| codemaker::convertString(reader.getFieldName(i))); |
| cf->addField( |
| static_cast< ClassFile::AccessFlags >( |
| ClassFile::ACC_PUBLIC | ClassFile::ACC_STATIC |
| | ClassFile::ACC_FINAL), |
| fieldName, classDescriptor, 0, rtl::OString()); |
| cf->addField( |
| static_cast< ClassFile::AccessFlags >( |
| ClassFile::ACC_PUBLIC | ClassFile::ACC_STATIC |
| | ClassFile::ACC_FINAL), |
| fieldName + rtl::OString(RTL_CONSTASCII_STRINGPARAM("_value")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("I")), |
| cf->addIntegerInfo(fieldValue.m_value.aLong), rtl::OString()); |
| }} |
| std::auto_ptr< ClassFile::Code > code(cf->newCode()); |
| code->loadLocalReference(0); |
| code->loadLocalInteger(1); |
| code->instrInvokespecial( |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/Enum")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("(I)V"))); |
| code->instrReturn(); |
| code->setMaxStackAndLocals(2, 2); |
| cf->addMethod( |
| ClassFile::ACC_PRIVATE, |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("(I)V")), code.get(), |
| std::vector< rtl::OString >(), rtl::OString()); |
| code.reset(cf->newCode()); |
| code->instrGetstatic( |
| className, |
| codemaker::convertString(reader.getFieldName(0)), classDescriptor); |
| code->instrAreturn(); |
| code->setMaxStackAndLocals(1, 0); |
| cf->addMethod( |
| static_cast< ClassFile::AccessFlags >( |
| ClassFile::ACC_PUBLIC | ClassFile::ACC_STATIC), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("getDefault")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("()")) + classDescriptor, |
| code.get(), std::vector< rtl::OString >(), rtl::OString()); |
| code.reset(cf->newCode()); |
| code->loadLocalInteger(0); |
| std::map< sal_Int32, rtl::OString > map; |
| sal_Int32 min = SAL_MAX_INT32; |
| sal_Int32 max = SAL_MIN_INT32; |
| {for (sal_uInt16 i = 0; i < fields; ++i) { |
| sal_Int32 value = reader.getFieldValue(i).m_value.aLong; |
| min = std::min(min, value); |
| max = std::max(max, value); |
| map.insert( |
| std::map< sal_Int32, rtl::OString >::value_type( |
| value, codemaker::convertString(reader.getFieldName(i)))); |
| }} |
| sal_uInt64 size = static_cast< sal_uInt64 >(map.size()); |
| if ((static_cast< sal_uInt64 >(max) - static_cast< sal_uInt64 >(min) |
| <= 2 * size) |
| || size > SAL_MAX_INT32) |
| { |
| std::auto_ptr< ClassFile::Code > defCode(cf->newCode()); |
| defCode->instrAconstNull(); |
| defCode->instrAreturn(); |
| std::list< ClassFile::Code * > blocks; |
| //FIXME: pointers contained in blocks may leak |
| sal_Int32 last = SAL_MAX_INT32; |
| for (std::map< sal_Int32, rtl::OString >::iterator i(map.begin()); |
| i != map.end(); ++i) |
| { |
| sal_Int32 value = i->first; |
| if (last != SAL_MAX_INT32) { |
| for (sal_Int32 j = last + 1; j < value; ++j) { |
| blocks.push_back(0); |
| } |
| } |
| last = value; |
| std::auto_ptr< ClassFile::Code > blockCode(cf->newCode()); |
| blockCode->instrGetstatic(className, i->second, classDescriptor); |
| blockCode->instrAreturn(); |
| blocks.push_back(blockCode.get()); |
| blockCode.release(); |
| } |
| code->instrTableswitch(defCode.get(), min, blocks); |
| {for (std::list< ClassFile::Code * >::iterator i(blocks.begin()); |
| i != blocks.end(); ++i) |
| { |
| delete *i; |
| }} |
| } else { |
| std::auto_ptr< ClassFile::Code > defCode(cf->newCode()); |
| defCode->instrAconstNull(); |
| defCode->instrAreturn(); |
| std::list< std::pair< sal_Int32, ClassFile::Code * > > blocks; |
| //FIXME: pointers contained in blocks may leak |
| for (std::map< sal_Int32, rtl::OString >::iterator i(map.begin()); |
| i != map.end(); ++i) |
| { |
| std::auto_ptr< ClassFile::Code > blockCode(cf->newCode()); |
| blockCode->instrGetstatic(className, i->second, classDescriptor); |
| blockCode->instrAreturn(); |
| blocks.push_back(std::make_pair(i->first, blockCode.get())); |
| blockCode.release(); |
| } |
| code->instrLookupswitch(defCode.get(), blocks); |
| {for (std::list< std::pair< sal_Int32, ClassFile::Code * > >::iterator |
| i(blocks.begin()); |
| i != blocks.end(); ++i) |
| { |
| delete i->second; |
| }} |
| } |
| code->setMaxStackAndLocals(1, 1); |
| cf->addMethod( |
| static_cast< ClassFile::AccessFlags >( |
| ClassFile::ACC_PUBLIC | ClassFile::ACC_STATIC), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("fromInt")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("(I)")) + classDescriptor, |
| code.get(), std::vector< rtl::OString >(), rtl::OString()); |
| code.reset(cf->newCode()); |
| {for (sal_uInt16 i = 0; i < fields; ++i) { |
| code->instrNew(className); |
| code->instrDup(); |
| code->loadIntegerConstant(reader.getFieldValue(i).m_value.aLong); |
| code->instrInvokespecial( |
| className, rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("(I)V"))); |
| code->instrPutstatic( |
| className, |
| codemaker::convertString(reader.getFieldName(i)), |
| classDescriptor); |
| }} |
| code->instrReturn(); |
| code->setMaxStackAndLocals(3, 0); |
| cf->addMethod( |
| static_cast< ClassFile::AccessFlags >( |
| ClassFile::ACC_PRIVATE | ClassFile::ACC_STATIC), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("<clinit>")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("()V")), code.get(), |
| std::vector< rtl::OString >(), rtl::OString()); |
| writeClassFile(options, className, *cf.get()); |
| } |
| |
| void 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) |
| { |
| OSL_ASSERT(dependencies != 0 && classFile != 0 && typeInfo != 0); |
| rtl::OString descriptor; |
| rtl::OString signature; |
| SpecialType specialType; |
| PolymorphicUnoType polymorphicUnoType; |
| if (typeParameterIndex >= 0) { |
| descriptor = rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("Ljava/lang/Object;")); |
| rtl::OStringBuffer buf; |
| buf.append('T'); |
| buf.append(type); |
| buf.append(';'); |
| signature = buf.makeStringAndClear(); |
| specialType = SPECIAL_TYPE_NONE; //TODO: SPECIAL_TYPE_TYPE_PARAMETER? |
| } else { |
| specialType = getFieldDescriptor( |
| manager, dependencies, type, &descriptor, &signature, |
| &polymorphicUnoType); |
| } |
| classFile->addField(ClassFile::ACC_PUBLIC, name, descriptor, 0, signature); |
| typeInfo->push_back( |
| TypeInfo( |
| name, specialType, index, polymorphicUnoType, typeParameterIndex)); |
| } |
| |
| sal_uInt16 addFieldInit( |
| TypeManager const & manager, rtl::OString const & className, |
| rtl::OString const & fieldName, bool typeParameter, |
| rtl::OString const & fieldType, Dependencies * dependencies, |
| ClassFile::Code * code) |
| { |
| OSL_ASSERT(dependencies != 0 && code != 0); |
| if (typeParameter) { |
| return 0; |
| } else { |
| RTTypeClass typeClass; |
| rtl::OString nucleus; |
| sal_Int32 rank; |
| std::vector< rtl::OString > args; |
| codemaker::UnoType::Sort sort = codemaker::decomposeAndResolve( |
| manager, fieldType, true, false, false, &typeClass, &nucleus, &rank, |
| &args); |
| if (rank == 0) { |
| switch (sort) { |
| case codemaker::UnoType::SORT_STRING: |
| code->loadLocalReference(0); |
| code->loadStringConstant(rtl::OString()); |
| code->instrPutfield( |
| className, fieldName, |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("Ljava/lang/String;"))); |
| return 2; |
| |
| case codemaker::UnoType::SORT_TYPE: |
| code->loadLocalReference(0); |
| code->instrGetstatic( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/Type")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("VOID")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("Lcom/sun/star/uno/Type;"))); |
| code->instrPutfield( |
| className, fieldName, |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("Lcom/sun/star/uno/Type;"))); |
| return 2; |
| |
| case codemaker::UnoType::SORT_ANY: |
| code->loadLocalReference(0); |
| code->instrGetstatic( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/Any")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("VOID")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("Lcom/sun/star/uno/Any;"))); |
| code->instrPutfield( |
| className, fieldName, |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("Ljava/lang/Object;"))); |
| return 2; |
| |
| case codemaker::UnoType::SORT_COMPLEX: |
| switch (typeClass) { |
| case RT_TYPE_ENUM: |
| { |
| code->loadLocalReference(0); |
| typereg::Reader reader(manager.getTypeReader(nucleus)); |
| if (reader.getFieldCount() == 0) { |
| throw CannotDumpException( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "Bad type information"))); //TODO |
| } |
| rtl::OStringBuffer descBuf; |
| translateUnoTypeToDescriptor( |
| manager, sort, typeClass, nucleus, 0, |
| std::vector< rtl::OString >(), false, false, |
| dependencies, &descBuf, 0, 0, 0); |
| rtl::OString desc(descBuf.makeStringAndClear()); |
| code->instrGetstatic( |
| nucleus, |
| codemaker::convertString(reader.getFieldName(0)), |
| desc); |
| code->instrPutfield(className, fieldName, desc); |
| return 2; |
| } |
| |
| case RT_TYPE_STRUCT: |
| { |
| code->loadLocalReference(0); |
| code->instrNew(nucleus); |
| code->instrDup(); |
| code->instrInvokespecial( |
| nucleus, |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("()V"))); |
| rtl::OStringBuffer desc; |
| translateUnoTypeToDescriptor( |
| manager, sort, typeClass, nucleus, 0, |
| std::vector< rtl::OString >(), false, false, |
| dependencies, &desc, 0, 0, 0); |
| code->instrPutfield( |
| className, fieldName, desc.makeStringAndClear()); |
| return 3; |
| } |
| |
| default: |
| OSL_ASSERT(typeClass == RT_TYPE_INTERFACE); |
| return 0; |
| } |
| |
| default: |
| return 0; |
| } |
| } else { |
| code->loadLocalReference(0); |
| code->loadIntegerConstant(0); |
| if (rank == 1) { |
| if (sort >= codemaker::UnoType::SORT_BOOLEAN |
| && sort <= codemaker::UnoType::SORT_CHAR) |
| { |
| code->instrNewarray(sort); |
| } else { |
| code->instrAnewarray( |
| codemaker::java::translateUnoToJavaType(sort, typeClass, |
| nucleus, 0)); |
| } |
| } else { |
| rtl::OStringBuffer desc; |
| translateUnoTypeToDescriptor( |
| manager, sort, typeClass, nucleus, rank - 1, |
| std::vector< rtl::OString >(), false, false, dependencies, |
| &desc, 0, 0, 0); |
| code->instrAnewarray(desc.makeStringAndClear()); |
| } |
| rtl::OStringBuffer desc; |
| translateUnoTypeToDescriptor( |
| manager, sort, typeClass, nucleus, rank, |
| std::vector< rtl::OString >(), false, false, dependencies, |
| &desc, 0, 0, 0); |
| code->instrPutfield( |
| className, fieldName, desc.makeStringAndClear()); |
| return 2; |
| } |
| } |
| } |
| |
| sal_uInt16 addLoadLocal( |
| TypeManager const & manager, ClassFile::Code * code, sal_uInt16 * index, |
| bool typeParameter, rtl::OString const & type, bool any, |
| Dependencies * dependencies) |
| { |
| OSL_ASSERT( |
| code != 0 && index != 0 && !(typeParameter && any) |
| && dependencies != 0); |
| sal_uInt16 stack = 1; |
| sal_uInt16 size = 1; |
| if (typeParameter) { |
| code->loadLocalReference(*index); |
| stack = size = 1; |
| } else { |
| RTTypeClass typeClass; |
| rtl::OString nucleus; |
| sal_Int32 rank; |
| std::vector< rtl::OString > args; |
| codemaker::UnoType::Sort sort = codemaker::decomposeAndResolve( |
| manager, type, true, false, false, &typeClass, &nucleus, &rank, &args); |
| if (rank == 0) { |
| switch (sort) { |
| case codemaker::UnoType::SORT_BOOLEAN: |
| if (any) { |
| code->instrNew( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("java/lang/Boolean"))); |
| code->instrDup(); |
| code->loadLocalInteger(*index); |
| code->instrInvokespecial( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("java/lang/Boolean")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("(Z)V"))); |
| stack = 3; |
| } else { |
| code->loadLocalInteger(*index); |
| stack = 1; |
| } |
| size = 1; |
| break; |
| |
| case codemaker::UnoType::SORT_BYTE: |
| if (any) { |
| code->instrNew( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("java/lang/Byte"))); |
| code->instrDup(); |
| code->loadLocalInteger(*index); |
| code->instrInvokespecial( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("java/lang/Byte")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("(B)V"))); |
| stack = 3; |
| } else { |
| code->loadLocalInteger(*index); |
| stack = 1; |
| } |
| size = 1; |
| break; |
| |
| case codemaker::UnoType::SORT_SHORT: |
| if (any) { |
| code->instrNew( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("java/lang/Short"))); |
| code->instrDup(); |
| code->loadLocalInteger(*index); |
| code->instrInvokespecial( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("java/lang/Short")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("(S)V"))); |
| stack = 3; |
| } else { |
| code->loadLocalInteger(*index); |
| stack = 1; |
| } |
| size = 1; |
| break; |
| |
| case codemaker::UnoType::SORT_UNSIGNED_SHORT: |
| if (any) { |
| code->instrNew( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "com/sun/star/uno/Any"))); |
| code->instrDup(); |
| code->instrGetstatic( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "com/sun/star/uno/Type")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("UNSIGNED_SHORT")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "Lcom/sun/star/uno/Type;"))); |
| code->instrNew( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("java/lang/Short"))); |
| code->instrDup(); |
| code->loadLocalInteger(*index); |
| code->instrInvokespecial( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("java/lang/Short")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("(S)V"))); |
| code->instrInvokespecial( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/Any")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "(Lcom/sun/star/uno/Type;Ljava/lang/Object;)" |
| "V"))); |
| stack = 6; |
| } else { |
| code->loadLocalInteger(*index); |
| stack = 1; |
| } |
| size = 1; |
| break; |
| |
| case codemaker::UnoType::SORT_LONG: |
| if (any) { |
| code->instrNew( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("java/lang/Integer"))); |
| code->instrDup(); |
| code->loadLocalInteger(*index); |
| code->instrInvokespecial( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("java/lang/Integer")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("(I)V"))); |
| stack = 3; |
| } else { |
| code->loadLocalInteger(*index); |
| stack = 1; |
| } |
| size = 1; |
| break; |
| |
| case codemaker::UnoType::SORT_UNSIGNED_LONG: |
| if (any) { |
| code->instrNew( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "com/sun/star/uno/Any"))); |
| code->instrDup(); |
| code->instrGetstatic( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "com/sun/star/uno/Type")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("UNSIGNED_LONG")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "Lcom/sun/star/uno/Type;"))); |
| code->instrNew( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("java/lang/Integer"))); |
| code->instrDup(); |
| code->loadLocalInteger(*index); |
| code->instrInvokespecial( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("java/lang/Integer")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("(I)V"))); |
| code->instrInvokespecial( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/Any")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "(Lcom/sun/star/uno/Type;Ljava/lang/Object;)" |
| "V"))); |
| stack = 6; |
| } else { |
| code->loadLocalInteger(*index); |
| stack = 1; |
| } |
| size = 1; |
| break; |
| |
| case codemaker::UnoType::SORT_HYPER: |
| if (any) { |
| code->instrNew( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("java/lang/Long"))); |
| code->instrDup(); |
| code->loadLocalLong(*index); |
| code->instrInvokespecial( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("java/lang/Long")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("(J)V"))); |
| stack = 4; |
| } else { |
| code->loadLocalLong(*index); |
| stack = 2; |
| } |
| size = 2; |
| break; |
| |
| case codemaker::UnoType::SORT_UNSIGNED_HYPER: |
| if (any) { |
| code->instrNew( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "com/sun/star/uno/Any"))); |
| code->instrDup(); |
| code->instrGetstatic( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "com/sun/star/uno/Type")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("UNSIGNED_HYPER")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "Lcom/sun/star/uno/Type;"))); |
| code->instrNew( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("java/lang/Long"))); |
| code->instrDup(); |
| code->loadLocalLong(*index); |
| code->instrInvokespecial( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("java/lang/Long")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("(J)V"))); |
| code->instrInvokespecial( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/Any")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "(Lcom/sun/star/uno/Type;Ljava/lang/Object;)" |
| "V"))); |
| stack = 7; |
| } else { |
| code->loadLocalLong(*index); |
| stack = 2; |
| } |
| size = 2; |
| break; |
| |
| case codemaker::UnoType::SORT_FLOAT: |
| if (any) { |
| code->instrNew( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("java/lang/Float"))); |
| code->instrDup(); |
| code->loadLocalFloat(*index); |
| code->instrInvokespecial( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("java/lang/Float")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("(F)V"))); |
| stack = 3; |
| } else { |
| code->loadLocalFloat(*index); |
| stack = 1; |
| } |
| size = 1; |
| break; |
| |
| case codemaker::UnoType::SORT_DOUBLE: |
| if (any) { |
| code->instrNew( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("java/lang/Double"))); |
| code->instrDup(); |
| code->loadLocalDouble(*index); |
| code->instrInvokespecial( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("java/lang/Double")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("(D)V"))); |
| stack = 4; |
| } else { |
| code->loadLocalDouble(*index); |
| stack = 2; |
| } |
| size = 2; |
| break; |
| |
| case codemaker::UnoType::SORT_CHAR: |
| if (any) { |
| code->instrNew( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("java/lang/Character"))); |
| code->instrDup(); |
| code->loadLocalInteger(*index); |
| code->instrInvokespecial( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("java/lang/Character")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("(C)V"))); |
| stack = 3; |
| } else { |
| code->loadLocalInteger(*index); |
| stack = 1; |
| } |
| size = 1; |
| break; |
| |
| case codemaker::UnoType::SORT_STRING: |
| case codemaker::UnoType::SORT_TYPE: |
| case codemaker::UnoType::SORT_ANY: |
| code->loadLocalReference(*index); |
| stack = size = 1; |
| break; |
| |
| case codemaker::UnoType::SORT_COMPLEX: |
| switch (typeClass) { |
| case RT_TYPE_ENUM: |
| // Assuming that no Java types are derived from Java types |
| // that are directly derived from com.sun.star.uno.Enum: |
| code->loadLocalReference(*index); |
| stack = size = 1; |
| break; |
| |
| case RT_TYPE_STRUCT: |
| if (any) { |
| code->instrNew( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "com/sun/star/uno/Any"))); |
| code->instrDup(); |
| code->instrNew( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "com/sun/star/uno/Type"))); |
| code->instrDup(); |
| code->loadStringConstant( |
| createUnoName(manager, nucleus, rank, args)); |
| code->instrGetstatic( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "com/sun/star/uno/TypeClass")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("STRUCT")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "Lcom/sun/star/uno/TypeClass;"))); |
| dependencies->insert( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "com/sun/star/uno/TypeClass"))); |
| code->instrInvokespecial( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "com/sun/star/uno/Type")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "(Ljava/lang/String;" |
| "Lcom/sun/star/uno/TypeClass;)V"))); |
| code->loadLocalReference(*index); |
| code->instrInvokespecial( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "com/sun/star/uno/Any")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "(Lcom/sun/star/uno/Type;" |
| "Ljava/lang/Object;)V"))); |
| stack = 6; |
| } else { |
| code->loadLocalReference(*index); |
| stack = 1; |
| } |
| size = 1; |
| break; |
| |
| case RT_TYPE_INTERFACE: |
| if (any |
| && (nucleus |
| != rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "com/sun/star/uno/XInterface")))) |
| { |
| code->instrNew( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "com/sun/star/uno/Any"))); |
| code->instrDup(); |
| code->instrNew( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "com/sun/star/uno/Type"))); |
| code->instrDup(); |
| code->loadStringConstant(nucleus.replace('/', '.')); |
| code->instrGetstatic( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "com/sun/star/uno/TypeClass")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("INTERFACE")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "Lcom/sun/star/uno/TypeClass;"))); |
| dependencies->insert( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "com/sun/star/uno/TypeClass"))); |
| code->instrInvokespecial( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "com/sun/star/uno/Type")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "(Ljava/lang/String;" |
| "Lcom/sun/star/uno/TypeClass;)V"))); |
| code->loadLocalReference(*index); |
| code->instrInvokespecial( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "com/sun/star/uno/Any")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "(Lcom/sun/star/uno/Type;" |
| "Ljava/lang/Object;)V"))); |
| stack = 6; |
| } else { |
| code->loadLocalReference(*index); |
| stack = 1; |
| } |
| size = 1; |
| break; |
| |
| default: |
| OSL_ASSERT(false); |
| break; |
| } |
| break; |
| |
| default: |
| OSL_ASSERT(false); |
| break; |
| } |
| } else { |
| bool wrap = false; |
| if (any) { |
| switch (sort) { |
| case codemaker::UnoType::SORT_BOOLEAN: |
| case codemaker::UnoType::SORT_BYTE: |
| case codemaker::UnoType::SORT_SHORT: |
| case codemaker::UnoType::SORT_LONG: |
| case codemaker::UnoType::SORT_HYPER: |
| case codemaker::UnoType::SORT_FLOAT: |
| case codemaker::UnoType::SORT_DOUBLE: |
| case codemaker::UnoType::SORT_CHAR: |
| case codemaker::UnoType::SORT_STRING: |
| case codemaker::UnoType::SORT_TYPE: |
| // assuming that no Java types are derived from |
| // com.sun.star.uno.Type |
| break; |
| |
| case codemaker::UnoType::SORT_UNSIGNED_SHORT: |
| case codemaker::UnoType::SORT_UNSIGNED_LONG: |
| case codemaker::UnoType::SORT_UNSIGNED_HYPER: |
| case codemaker::UnoType::SORT_ANY: |
| wrap = true; |
| break; |
| |
| case codemaker::UnoType::SORT_COMPLEX: |
| switch (typeClass) { |
| case RT_TYPE_ENUM: |
| // assuming that no Java types are derived from Java |
| // types that are directly derived from |
| // com.sun.star.uno.Enum |
| break; |
| |
| case RT_TYPE_STRUCT: |
| case RT_TYPE_INTERFACE: |
| wrap = true; |
| break; |
| |
| default: |
| OSL_ASSERT(false); |
| break; |
| } |
| break; |
| |
| default: |
| OSL_ASSERT(false); |
| break; |
| } |
| } |
| if (wrap) { |
| code->instrNew( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/Any"))); |
| code->instrDup(); |
| code->instrNew( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/Type"))); |
| code->instrDup(); |
| code->loadStringConstant( |
| createUnoName(manager, nucleus, rank, args)); |
| code->instrInvokespecial( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/Type")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("(Ljava/lang/String;)V"))); |
| code->loadLocalReference(*index); |
| code->instrInvokespecial( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/Any")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "(Lcom/sun/star/uno/Type;Ljava/lang/Object;)V"))); |
| stack = 5; |
| } else { |
| code->loadLocalReference(*index); |
| stack = 1; |
| } |
| size = 1; |
| } |
| } |
| if (*index > SAL_MAX_UINT16 - size) { |
| throw CannotDumpException( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "Too many local variables for Java class file format"))); |
| } |
| *index = *index + size; |
| return stack; |
| } |
| |
| void addBaseArguments( |
| TypeManager const & manager, Dependencies * dependencies, |
| MethodDescriptor * methodDescriptor, ClassFile::Code * code, |
| RTTypeClass typeClass, rtl::OString const & type, sal_uInt16 * index) |
| { |
| OSL_ASSERT( |
| dependencies != 0 && methodDescriptor != 0 && code != 0 && index != 0); |
| typereg::Reader reader(manager.getTypeReader(type)); |
| if (!reader.isValid() || reader.getTypeClass() != typeClass |
| || codemaker::convertString(reader.getTypeName()) != type |
| || reader.getMethodCount() != 0 || reader.getReferenceCount() != 0) |
| { |
| throw CannotDumpException( |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("Bad type information"))); |
| //TODO |
| } |
| sal_uInt16 superTypes = reader.getSuperTypeCount(); |
| sal_uInt16 fields = reader.getFieldCount(); |
| sal_uInt16 firstField = 0; |
| if (type |
| == rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/Exception"))) |
| { |
| if (typeClass != RT_TYPE_EXCEPTION || superTypes != 0 || fields != 2) { |
| throw CannotDumpException( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("Bad type information"))); //TODO |
| } |
| firstField = 1; |
| } else { |
| if ( |
| (typeClass == RT_TYPE_STRUCT && (superTypes > 1 || fields == 0)) || |
| (typeClass == RT_TYPE_EXCEPTION && superTypes != 1) |
| ) |
| { |
| throw CannotDumpException( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("Bad type information"))); //TODO |
| } |
| if (superTypes == 1) { |
| addBaseArguments( |
| manager, dependencies, methodDescriptor, code, typeClass, |
| codemaker::convertString(reader.getSuperTypeName(0)), index); |
| } |
| } |
| for (sal_uInt16 i = firstField; i < fields; ++i) { |
| if (reader.getFieldFlags(i) != RT_ACCESS_READWRITE |
| || reader.getFieldValue(i).m_type != RT_TYPE_NONE) |
| { |
| throw CannotDumpException( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("Bad type information"))); //TODO |
| } |
| rtl::OString fieldType( |
| codemaker::convertString(reader.getFieldTypeName(i))); |
| methodDescriptor->addParameter(fieldType, false, true, 0); |
| addLoadLocal( |
| manager, code, index, false, fieldType, false, dependencies); |
| } |
| } |
| |
| sal_uInt16 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) |
| { |
| OSL_ASSERT( |
| dependencies != 0 && methodDescriptor != 0 && code != 0 && index != 0); |
| rtl::OString desc; |
| if (typeParameter) { |
| methodDescriptor->addTypeParameter(fieldType); |
| desc = rtl::OString(RTL_CONSTASCII_STRINGPARAM("Ljava/lang/Object;")); |
| } else { |
| methodDescriptor->addParameter(fieldType, false, true, 0); |
| getFieldDescriptor(manager, dependencies, fieldType, &desc, 0, 0); |
| } |
| code->loadLocalReference(0); |
| sal_uInt16 stack = addLoadLocal( |
| manager, code, index, typeParameter, fieldType, false, dependencies); |
| code->instrPutfield(className, fieldName, desc); |
| return stack + 1; |
| } |
| |
| void handleAggregatingType( |
| TypeManager const & manager, JavaOptions /*TODO const*/ & options, |
| typereg::Reader const & reader, Dependencies * dependencies) |
| { |
| OSL_ASSERT(dependencies != 0); |
| if (reader.getMethodCount() != 0) |
| { |
| throw CannotDumpException( |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("Bad type information"))); |
| //TODO |
| } |
| RTTypeClass typeClass = reader.getTypeClass(); |
| rtl::OString className(codemaker::convertString(reader.getTypeName())); |
| sal_uInt16 superTypes = reader.getSuperTypeCount(); |
| sal_uInt16 fields = reader.getFieldCount(); |
| sal_uInt16 firstField = 0; |
| sal_uInt16 references = reader.getReferenceCount(); |
| bool runtimeException = false; |
| rtl::OString superClass; |
| if (className |
| == rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/Exception"))) |
| { |
| if (typeClass != RT_TYPE_EXCEPTION || superTypes != 0 || fields != 2 |
| || references != 0) |
| { |
| throw CannotDumpException( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("Bad type information"))); //TODO |
| } |
| firstField = 1; |
| superClass = rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("java/lang/Exception")); |
| } else if (className |
| == rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "com/sun/star/uno/RuntimeException"))) |
| { |
| if (typeClass != RT_TYPE_EXCEPTION || superTypes != 1 || fields != 0 |
| || references != 0) |
| { |
| throw CannotDumpException( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("Bad type information"))); //TODO |
| } |
| superTypes = 0; |
| superClass = rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("java/lang/RuntimeException")); |
| runtimeException = true; |
| } else { |
| if ( |
| ( |
| typeClass == RT_TYPE_STRUCT && |
| ( |
| fields == 0 || |
| (references == 0 ? superTypes > 1 : superTypes != 0) |
| ) |
| ) || |
| (typeClass == RT_TYPE_EXCEPTION && superTypes != 1) |
| ) |
| { |
| throw CannotDumpException( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("Bad type information"))); //TODO |
| } |
| if (superTypes == 0) { |
| superClass = rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("java/lang/Object")); |
| } else { |
| superClass = codemaker::convertString(reader.getSuperTypeName(0)); |
| dependencies->insert(superClass); |
| } |
| } |
| rtl::OString sig; |
| std::map< rtl::OString, sal_Int32 > typeParameters; |
| if (references != 0) { |
| rtl::OStringBuffer buf; |
| buf.append('<'); |
| for (sal_uInt16 i = 0; i < references; ++i) { |
| if (reader.getReferenceFlags(i) != RT_ACCESS_INVALID |
| || reader.getReferenceSort(i) != RT_REF_TYPE_PARAMETER) |
| { |
| throw CannotDumpException( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("Bad type information"))); |
| //TODO |
| } |
| rtl::OString name( |
| codemaker::convertString(reader.getReferenceTypeName(i))); |
| buf.append(name); |
| buf.append(RTL_CONSTASCII_STRINGPARAM(":Ljava/lang/Object;")); |
| if (!typeParameters.insert( |
| std::map< rtl::OString, sal_Int32 >::value_type(name, i)). |
| second) |
| { |
| throw CannotDumpException( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("Bad type information"))); |
| //TODO |
| } |
| } |
| buf.append(RTL_CONSTASCII_STRINGPARAM(">Ljava/lang/Object;")); |
| sig = buf.makeStringAndClear(); |
| } |
| std::auto_ptr< ClassFile > cf( |
| new ClassFile( |
| static_cast< ClassFile::AccessFlags >( |
| ClassFile::ACC_PUBLIC | ClassFile::ACC_SUPER), |
| className, superClass, sig)); |
| std::vector< TypeInfo > typeInfo; |
| {for (sal_uInt16 i = firstField; i < fields; ++i) { |
| RTFieldAccess flags = reader.getFieldFlags(i); |
| if ((flags != RT_ACCESS_READWRITE |
| && flags != (RT_ACCESS_READWRITE | RT_ACCESS_PARAMETERIZED_TYPE)) |
| || ((flags & RT_ACCESS_PARAMETERIZED_TYPE) != 0 && references == 0) |
| || reader.getFieldValue(i).m_type != RT_TYPE_NONE) |
| { |
| throw CannotDumpException( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("Bad type information"))); //TODO |
| } |
| rtl::OString type( |
| codemaker::convertString(reader.getFieldTypeName(i))); |
| sal_Int32 typeParameterIndex; |
| if ((flags & RT_ACCESS_PARAMETERIZED_TYPE) == 0) { |
| typeParameterIndex = -1; |
| } else { |
| std::map< rtl::OString, sal_Int32 >::iterator it( |
| typeParameters.find(type)); |
| if (it == typeParameters.end()) { |
| throw CannotDumpException( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("Bad type information"))); |
| //TODO |
| } |
| typeParameterIndex = it->second; |
| } |
| addField( |
| manager, dependencies, cf.get(), &typeInfo, typeParameterIndex, |
| type, codemaker::convertString(reader.getFieldName(i)), i - firstField); |
| }} |
| if (runtimeException) { |
| addField( |
| manager, dependencies, cf.get(), &typeInfo, -1, |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/XInterface")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("Context")), 0); |
| } |
| std::auto_ptr< ClassFile::Code > code(cf->newCode()); |
| code->loadLocalReference(0); |
| code->instrInvokespecial( |
| superClass, rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("()V"))); |
| sal_uInt16 stack = 0; |
| {for (sal_uInt16 i = firstField; i < fields; ++i) { |
| stack = std::max( |
| stack, |
| addFieldInit( |
| manager, className, |
| codemaker::convertString(reader.getFieldName(i)), |
| (reader.getFieldFlags(i) & RT_ACCESS_PARAMETERIZED_TYPE) != 0, |
| codemaker::convertString(reader.getFieldTypeName(i)), |
| dependencies, code.get())); |
| }} |
| if (runtimeException) { |
| stack = std::max( |
| stack, |
| addFieldInit( |
| manager, className, |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("Context")), false, |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/XInterface")), |
| dependencies, code.get())); |
| } |
| code->instrReturn(); |
| code->setMaxStackAndLocals(stack + 1, 1); |
| cf->addMethod( |
| ClassFile::ACC_PUBLIC, |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("()V")), code.get(), |
| std::vector< rtl::OString >(), rtl::OString()); |
| if (typeClass == RT_TYPE_EXCEPTION) { |
| code.reset(cf->newCode()); |
| code->loadLocalReference(0); |
| code->loadLocalReference(1); |
| code->instrInvokespecial( |
| superClass, rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("(Ljava/lang/String;)V"))); |
| stack = 0; |
| for (sal_uInt16 i = firstField; i < fields; ++i) { |
| stack = std::max( |
| stack, |
| addFieldInit( |
| manager, className, |
| codemaker::convertString(reader.getFieldName(i)), |
| ((reader.getFieldFlags(i) & RT_ACCESS_PARAMETERIZED_TYPE) |
| != 0), |
| codemaker::convertString(reader.getFieldTypeName(i)), |
| dependencies, code.get())); |
| } |
| if (runtimeException) { |
| stack = std::max( |
| stack, |
| addFieldInit( |
| manager, className, |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("Context")), false, |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "com/sun/star/uno/XInterface")), |
| dependencies, code.get())); |
| } |
| code->instrReturn(); |
| code->setMaxStackAndLocals(stack + 2, 2); |
| cf->addMethod( |
| ClassFile::ACC_PUBLIC, |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("(Ljava/lang/String;)V")), |
| code.get(), std::vector< rtl::OString >(), rtl::OString()); |
| } |
| MethodDescriptor desc( |
| manager, dependencies, rtl::OString(RTL_CONSTASCII_STRINGPARAM("void")), |
| 0, 0); |
| code.reset(cf->newCode()); |
| code->loadLocalReference(0); |
| sal_uInt16 index = 1; |
| if (typeClass == RT_TYPE_EXCEPTION) { |
| desc.addParameter( |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("string")), false, true, 0); |
| code->loadLocalReference(index++); |
| } |
| if (superTypes != 0) { |
| addBaseArguments( |
| manager, dependencies, &desc, code.get(), typeClass, superClass, |
| &index); |
| } |
| code->instrInvokespecial( |
| superClass, rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")), |
| desc.getDescriptor()); |
| sal_uInt16 maxSize = index; |
| {for (sal_uInt16 i = firstField; i < fields; ++i) { |
| maxSize = std::max( |
| maxSize, |
| addDirectArgument( |
| manager, dependencies, &desc, code.get(), &index, className, |
| codemaker::convertString(reader.getFieldName(i)), |
| (reader.getFieldFlags(i) & RT_ACCESS_PARAMETERIZED_TYPE) != 0, |
| codemaker::convertString(reader.getFieldTypeName(i)))); |
| }} |
| if (runtimeException) { |
| maxSize = std::max( |
| maxSize, |
| addDirectArgument( |
| manager, dependencies, &desc, code.get(), &index, className, |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("Context")), false, |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "com/sun/star/uno/XInterface")))); |
| } |
| code->instrReturn(); |
| code->setMaxStackAndLocals(maxSize, index); |
| cf->addMethod( |
| ClassFile::ACC_PUBLIC, |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")), |
| desc.getDescriptor(), code.get(), std::vector< rtl::OString >(), |
| desc.getSignature()); |
| addTypeInfo(className, typeInfo, dependencies, cf.get()); |
| writeClassFile(options, className, *cf.get()); |
| } |
| |
| void createExceptionsAttribute( |
| TypeManager const & manager, typereg::Reader const & reader, |
| sal_uInt16 methodIndex, Dependencies * dependencies, |
| std::vector< rtl::OString > * exceptions, codemaker::ExceptionTree * tree) |
| { |
| OSL_ASSERT(dependencies != 0 && exceptions != 0); |
| sal_uInt16 n = reader.getMethodExceptionCount(methodIndex); |
| for (sal_uInt16 i = 0; i < n; ++i) { |
| rtl::OString type( |
| codemaker::convertString( |
| reader.getMethodExceptionTypeName(methodIndex, i))); |
| dependencies->insert(type); |
| exceptions->push_back(type); |
| if (tree != 0) { |
| tree->add(type, manager); |
| } |
| } |
| } |
| |
| void handleInterfaceType( |
| TypeManager const & manager, JavaOptions /*TODO const*/ & options, |
| typereg::Reader const & reader, Dependencies * dependencies) |
| { |
| OSL_ASSERT(dependencies != 0); |
| |
| rtl::OString className(codemaker::convertString(reader.getTypeName())); |
| sal_uInt16 superTypes = reader.getSuperTypeCount(); |
| sal_uInt16 fields = reader.getFieldCount(); |
| sal_uInt16 methods = reader.getMethodCount(); |
| if (className |
| == rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/XInterface"))) |
| { |
| if (superTypes != 0 || fields != 0 || methods != 3) { |
| throw CannotDumpException( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("Bad type information"))); //TODO |
| } |
| methods = 0; |
| } else if (superTypes == 0) { |
| throw CannotDumpException( |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("Bad type information"))); |
| //TODO |
| } |
| std::auto_ptr< ClassFile > cf( |
| new ClassFile( |
| static_cast< ClassFile::AccessFlags >( |
| ClassFile::ACC_PUBLIC | ClassFile::ACC_INTERFACE |
| | ClassFile::ACC_ABSTRACT), |
| className, |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("java/lang/Object")), |
| rtl::OString())); |
| {for (sal_uInt16 i = 0; i < superTypes; ++i) { |
| rtl::OString t(codemaker::convertString(reader.getSuperTypeName(i))); |
| dependencies->insert(t); |
| cf->addInterface(t); |
| }} |
| // As a special case, let com.sun.star.lang.XEventListener extend |
| // java.util.EventListener ("A tagging interface that all event listener |
| // interfaces must extend"): |
| if (className == |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("com/sun/star/lang/XEventListener"))) |
| { |
| cf->addInterface( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("java/util/EventListener"))); |
| } |
| std::vector< TypeInfo > typeInfo; |
| sal_Int32 index = 0; |
| {for (sal_uInt16 i = 0; i < fields; ++i) { |
| RTFieldAccess flags = reader.getFieldFlags(i); |
| //TODO: ok if both READONLY and BOUND? |
| if (((((flags & RT_ACCESS_READWRITE) != 0) |
| ^ ((flags & RT_ACCESS_READONLY) != 0)) |
| == 0) |
| || ((flags |
| & ~(RT_ACCESS_READWRITE | RT_ACCESS_READONLY |
| | RT_ACCESS_BOUND)) |
| != 0) |
| || reader.getFieldValue(i).m_type != RT_TYPE_NONE) |
| { |
| throw CannotDumpException( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("Bad type information"))); //TODO |
| } |
| //TODO: exploit the fact that attribute getter/setter methods precede |
| // real methods |
| rtl::OUString attrNameUtf16(reader.getFieldName(i)); |
| sal_uInt16 getter = SAL_MAX_UINT16; |
| sal_uInt16 setter = SAL_MAX_UINT16; |
| for (sal_uInt16 j = 0; j < methods; ++j) { |
| RTMethodMode mflags = reader.getMethodFlags(j); |
| if ((mflags == RT_MODE_ATTRIBUTE_GET |
| || mflags == RT_MODE_ATTRIBUTE_SET) |
| && reader.getMethodName(j) == attrNameUtf16) |
| { |
| if (!reader.getMethodReturnTypeName(j).equalsAsciiL( |
| RTL_CONSTASCII_STRINGPARAM("void")) |
| || reader.getMethodParameterCount(j) != 0 |
| || (mflags == RT_MODE_ATTRIBUTE_GET |
| ? getter != SAL_MAX_UINT16 |
| : (setter != SAL_MAX_UINT16 |
| || (flags & RT_ACCESS_READONLY) != 0))) |
| { |
| throw CannotDumpException( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "Bad type information"))); //TODO |
| } |
| OSL_ASSERT(j != SAL_MAX_UINT16); |
| (mflags == RT_MODE_ATTRIBUTE_GET ? getter : setter) = j; |
| } |
| } |
| rtl::OString fieldType( |
| codemaker::convertString(reader.getFieldTypeName(i))); |
| SpecialType specialType; |
| PolymorphicUnoType polymorphicUnoType; |
| MethodDescriptor gdesc( |
| manager, dependencies, fieldType, &specialType, |
| &polymorphicUnoType); |
| std::vector< rtl::OString > exc; |
| if (getter != SAL_MAX_UINT16) { |
| createExceptionsAttribute( |
| manager, reader, getter, dependencies, &exc, 0); |
| } |
| rtl::OString attrName(codemaker::convertString(attrNameUtf16)); |
| cf->addMethod( |
| static_cast< ClassFile::AccessFlags >( |
| ClassFile::ACC_PUBLIC | ClassFile::ACC_ABSTRACT), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("get")) + attrName, |
| gdesc.getDescriptor(), 0, exc, gdesc.getSignature()); |
| if ((flags & RT_ACCESS_READONLY) == 0) { |
| MethodDescriptor sdesc( |
| manager, dependencies, |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("void")), 0, 0); |
| sdesc.addParameter(fieldType, false, true, 0); |
| std::vector< rtl::OString > exc2; |
| if (setter != SAL_MAX_UINT16) { |
| createExceptionsAttribute( |
| manager, reader, setter, dependencies, &exc2, 0); |
| } |
| cf->addMethod( |
| static_cast< ClassFile::AccessFlags >( |
| ClassFile::ACC_PUBLIC | ClassFile::ACC_ABSTRACT), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("set")) + attrName, |
| sdesc.getDescriptor(), 0, exc2, sdesc.getSignature()); |
| } |
| typeInfo.push_back( |
| TypeInfo( |
| TypeInfo::KIND_ATTRIBUTE, attrName, specialType, |
| static_cast< TypeInfo::Flags >( |
| ((flags & RT_ACCESS_READONLY) == 0 |
| ? 0 : TypeInfo::FLAG_READONLY) |
| | ((flags & RT_ACCESS_BOUND) == 0 |
| ? 0 : TypeInfo::FLAG_BOUND)), |
| index, polymorphicUnoType)); |
| index += ((flags & RT_ACCESS_READONLY) == 0 ? 2 : 1); |
| }} |
| {for (sal_uInt16 i = 0; i < methods; ++i) { |
| RTMethodMode flags = reader.getMethodFlags(i); |
| switch (flags) { |
| case RT_MODE_ONEWAY: |
| case RT_MODE_TWOWAY: |
| { |
| rtl::OString methodName( |
| codemaker::convertString(reader.getMethodName(i))); |
| SpecialType specialReturnType; |
| PolymorphicUnoType polymorphicUnoReturnType; |
| MethodDescriptor desc( |
| manager, dependencies, |
| codemaker::convertString( |
| reader.getMethodReturnTypeName(i)), |
| &specialReturnType, &polymorphicUnoReturnType); |
| typeInfo.push_back( |
| TypeInfo( |
| TypeInfo::KIND_METHOD, methodName, specialReturnType, |
| static_cast< TypeInfo::Flags >( |
| flags == RT_MODE_ONEWAY |
| ? TypeInfo::FLAG_ONEWAY : 0), |
| index++, polymorphicUnoReturnType)); |
| for (sal_uInt16 j = 0; j < reader.getMethodParameterCount(i); |
| ++j) |
| { |
| bool in; |
| bool out; |
| switch (reader.getMethodParameterFlags(i, j)) { |
| case RT_PARAM_IN: |
| in = true; |
| out = false; |
| break; |
| |
| case RT_PARAM_OUT: |
| in = false; |
| out = true; |
| break; |
| |
| case RT_PARAM_INOUT: |
| in = true; |
| out = true; |
| break; |
| |
| default: |
| throw CannotDumpException( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "Bad type information"))); //TODO |
| } |
| PolymorphicUnoType polymorphicUnoType; |
| SpecialType specialType = desc.addParameter( |
| codemaker::convertString( |
| reader.getMethodParameterTypeName(i, j)), |
| out, true, &polymorphicUnoType); |
| if (out || isSpecialType(specialType) |
| || (polymorphicUnoType.kind |
| != PolymorphicUnoType::KIND_NONE)) |
| { |
| typeInfo.push_back( |
| TypeInfo( |
| codemaker::convertString( |
| reader.getMethodParameterName(i, j)), |
| specialType, in, out, methodName, j, |
| polymorphicUnoType)); |
| } |
| } |
| std::vector< rtl::OString > exc2; |
| createExceptionsAttribute( |
| manager, reader, i, dependencies, &exc2, 0); |
| cf->addMethod( |
| static_cast< ClassFile::AccessFlags >( |
| ClassFile::ACC_PUBLIC | ClassFile::ACC_ABSTRACT), |
| methodName, desc.getDescriptor(), 0, exc2, |
| desc.getSignature()); |
| break; |
| } |
| |
| case RT_MODE_ATTRIBUTE_GET: |
| case RT_MODE_ATTRIBUTE_SET: |
| { |
| //TODO: exploit the fact that attribute getter/setter methods |
| // are ordered the same way as the attribute fields themselves |
| rtl::OUString methodNameUtf16(reader.getMethodName(i)); |
| bool found = false; |
| for (sal_uInt16 j = 0; j < fields; ++j) { |
| if (reader.getFieldName(j) == methodNameUtf16) { |
| found = true; |
| break; |
| } |
| } |
| if (found) { |
| break; |
| } |
| } |
| default: |
| throw CannotDumpException( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("Bad type information"))); //TODO |
| } |
| }} |
| addTypeInfo(className, typeInfo, dependencies, cf.get()); |
| writeClassFile(options, className, *cf.get()); |
| } |
| |
| void handleTypedef( |
| TypeManager const & manager, JavaOptions /*TODO const*/ &, |
| typereg::Reader const & reader, Dependencies * dependencies) |
| { |
| OSL_ASSERT(dependencies != 0); |
| if (reader.getSuperTypeCount() != 1 || reader.getFieldCount() != 0 |
| || reader.getMethodCount() != 0 || reader.getReferenceCount() != 0) |
| { |
| throw CannotDumpException( |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("Bad type information"))); |
| //TODO |
| } |
| RTTypeClass typeClass; |
| rtl::OString nucleus; |
| sal_Int32 rank; |
| std::vector< rtl::OString > args; |
| if (codemaker::decomposeAndResolve( |
| manager, codemaker::convertString(reader.getSuperTypeName(0)), |
| false, false, false, &typeClass, &nucleus, &rank, &args) |
| == codemaker::UnoType::SORT_COMPLEX) |
| { |
| switch (typeClass) { |
| case RT_TYPE_STRUCT: |
| if (!args.empty()) { |
| throw CannotDumpException( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("Bad type information"))); |
| //TODO |
| } |
| case RT_TYPE_ENUM: |
| case RT_TYPE_INTERFACE: |
| case RT_TYPE_TYPEDEF: |
| dependencies->insert(nucleus); |
| break; |
| |
| default: |
| OSL_ASSERT(false); |
| break; |
| } |
| } |
| } |
| |
| void addConstant( |
| TypeManager const & manager, typereg::Reader const & reader, |
| bool publishable, sal_uInt16 index, Dependencies * dependencies, |
| ClassFile * classFile) |
| { |
| OSL_ASSERT(dependencies != 0 && classFile != 0); |
| RTFieldAccess flags = reader.getFieldFlags(index); |
| if (flags != RT_ACCESS_CONST |
| && (!publishable || flags != (RT_ACCESS_CONST | RT_ACCESS_PUBLISHED))) |
| { |
| throw CannotDumpException( |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("Bad type information"))); |
| //TODO |
| } |
| RTConstValue fieldValue(reader.getFieldValue(index)); |
| sal_uInt16 valueIndex; |
| RTTypeClass typeClass; |
| rtl::OString nucleus; |
| sal_Int32 rank; |
| std::vector< rtl::OString > args; |
| switch (codemaker::decomposeAndResolve( |
| manager, |
| codemaker::convertString(reader.getFieldTypeName(index)), |
| true, false, false, &typeClass, &nucleus, &rank, &args)) |
| { |
| case codemaker::UnoType::SORT_BOOLEAN: |
| if (fieldValue.m_type != RT_TYPE_BOOL) { |
| throw CannotDumpException( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("Bad type information"))); //TODO |
| } |
| valueIndex = classFile->addIntegerInfo(fieldValue.m_value.aBool); |
| break; |
| |
| case codemaker::UnoType::SORT_BYTE: |
| if (fieldValue.m_type != RT_TYPE_BYTE) { |
| throw CannotDumpException( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("Bad type information"))); //TODO |
| } |
| valueIndex = classFile->addIntegerInfo(fieldValue.m_value.aByte); |
| break; |
| |
| case codemaker::UnoType::SORT_SHORT: |
| if (fieldValue.m_type != RT_TYPE_INT16) { |
| throw CannotDumpException( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("Bad type information"))); //TODO |
| } |
| valueIndex = classFile->addIntegerInfo(fieldValue.m_value.aShort); |
| break; |
| |
| case codemaker::UnoType::SORT_UNSIGNED_SHORT: |
| case codemaker::UnoType::SORT_CHAR: |
| if (fieldValue.m_type != RT_TYPE_UINT16) { |
| throw CannotDumpException( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("Bad type information"))); //TODO |
| } |
| valueIndex = classFile->addIntegerInfo(fieldValue.m_value.aUShort); |
| break; |
| |
| case codemaker::UnoType::SORT_LONG: |
| if (fieldValue.m_type != RT_TYPE_INT32) { |
| throw CannotDumpException( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("Bad type information"))); //TODO |
| } |
| valueIndex = classFile->addIntegerInfo(fieldValue.m_value.aLong); |
| break; |
| |
| case codemaker::UnoType::SORT_UNSIGNED_LONG: |
| if (fieldValue.m_type != RT_TYPE_UINT32) { |
| throw CannotDumpException( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("Bad type information"))); //TODO |
| } |
| valueIndex = classFile->addIntegerInfo( |
| static_cast< sal_Int32 >(fieldValue.m_value.aULong)); |
| break; |
| |
| case codemaker::UnoType::SORT_HYPER: |
| if (fieldValue.m_type != RT_TYPE_INT64) { |
| throw CannotDumpException( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("Bad type information"))); //TODO |
| } |
| valueIndex = classFile->addLongInfo(fieldValue.m_value.aHyper); |
| break; |
| |
| case codemaker::UnoType::SORT_UNSIGNED_HYPER: |
| if (fieldValue.m_type != RT_TYPE_UINT64) { |
| throw CannotDumpException( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("Bad type information"))); //TODO |
| } |
| valueIndex = classFile->addLongInfo( |
| static_cast< sal_Int64 >(fieldValue.m_value.aUHyper)); |
| break; |
| |
| case codemaker::UnoType::SORT_FLOAT: |
| if (fieldValue.m_type != RT_TYPE_FLOAT) { |
| throw CannotDumpException( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("Bad type information"))); //TODO |
| } |
| valueIndex = classFile->addFloatInfo(fieldValue.m_value.aFloat); |
| break; |
| |
| case codemaker::UnoType::SORT_DOUBLE: |
| if (fieldValue.m_type != RT_TYPE_DOUBLE) { |
| throw CannotDumpException( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("Bad type information"))); //TODO |
| } |
| valueIndex = classFile->addDoubleInfo(fieldValue.m_value.aDouble); |
| break; |
| |
| default: |
| throw CannotDumpException( |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("Bad type information"))); |
| //TODO |
| } |
| rtl::OString desc; |
| rtl::OString sig; |
| getFieldDescriptor( |
| manager, dependencies, |
| codemaker::convertString(reader.getFieldTypeName(index)), |
| &desc, &sig, 0); |
| classFile->addField( |
| static_cast< ClassFile::AccessFlags >( |
| ClassFile::ACC_PUBLIC | ClassFile::ACC_STATIC |
| | ClassFile::ACC_FINAL), |
| codemaker::convertString(reader.getFieldName(index)), |
| desc, valueIndex, sig); |
| } |
| |
| void handleConstantGroup( |
| TypeManager const & manager, JavaOptions /*TODO const*/ & options, |
| typereg::Reader const & reader, Dependencies * dependencies) |
| { |
| OSL_ASSERT(dependencies != 0); |
| if (reader.getSuperTypeCount() != 0 || reader.getMethodCount() != 0 |
| || reader.getReferenceCount() != 0) |
| { |
| throw CannotDumpException( |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("Bad type information"))); |
| //TODO |
| } |
| rtl::OString className(codemaker::convertString(reader.getTypeName())); |
| std::auto_ptr< ClassFile > cf( |
| new ClassFile( |
| static_cast< ClassFile::AccessFlags >( |
| ClassFile::ACC_PUBLIC | ClassFile::ACC_INTERFACE |
| | ClassFile::ACC_ABSTRACT), |
| className, |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("java/lang/Object")), |
| rtl::OString())); |
| sal_uInt16 fields = reader.getFieldCount(); |
| for (sal_uInt16 i = 0; i < fields; ++i) { |
| addConstant(manager, reader, false, i, dependencies, cf.get()); |
| } |
| writeClassFile(options, className, *cf.get()); |
| } |
| |
| void handleModule( |
| TypeManager const & manager, JavaOptions /*TODO const*/ & options, |
| typereg::Reader const & reader, Dependencies * dependencies) |
| { |
| OSL_ASSERT(dependencies != 0); |
| if (reader.getSuperTypeCount() != 0 || reader.getMethodCount() != 0 |
| || reader.getReferenceCount() != 0) |
| { |
| throw CannotDumpException( |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("Bad type information"))); |
| //TODO |
| } |
| rtl::OStringBuffer buf(codemaker::convertString(reader.getTypeName())); |
| buf.append('/'); |
| rtl::OString prefix(buf.makeStringAndClear()); |
| sal_uInt16 fields = reader.getFieldCount(); |
| for (sal_uInt16 i = 0; i < fields; ++i) { |
| rtl::OString className( |
| prefix + codemaker::convertString(reader.getFieldName(i))); |
| std::auto_ptr< ClassFile > cf( |
| new ClassFile( |
| static_cast< ClassFile::AccessFlags >( |
| ClassFile::ACC_PUBLIC | ClassFile::ACC_INTERFACE |
| | ClassFile::ACC_ABSTRACT), |
| className, |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("java/lang/Object")), |
| rtl::OString())); |
| addConstant(manager, reader, true, i, dependencies, cf.get()); |
| writeClassFile(options, className, *cf.get()); |
| } |
| } |
| |
| void addExceptionHandlers( |
| codemaker::ExceptionTreeNode const * node, |
| ClassFile::Code::Position start, ClassFile::Code::Position end, |
| ClassFile::Code::Position handler, ClassFile::Code * code) |
| { |
| OSL_ASSERT(node != 0 && code != 0); |
| if (node->present) { |
| code->addException(start, end, handler, node->name); |
| } else { |
| for (codemaker::ExceptionTreeNode::Children::const_iterator i( |
| node->children.begin()); |
| i != node->children.end(); ++i) |
| { |
| addExceptionHandlers(*i, start, end, handler, code); |
| } |
| } |
| } |
| |
| void 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) |
| { |
| OSL_ASSERT(dependencies != 0 && classFile != 0); |
| MethodDescriptor desc(manager, dependencies, returnType, 0, 0); |
| desc.addParameter( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/XComponentContext")), |
| false, false, 0); |
| std::auto_ptr< ClassFile::Code > code(classFile->newCode()); |
| code->loadLocalReference(0); |
| // stack: context |
| code->instrInvokestatic( |
| className, rtl::OString(RTL_CONSTASCII_STRINGPARAM("$getFactory")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "(Lcom/sun/star/uno/XComponentContext;)" |
| "Lcom/sun/star/lang/XMultiComponentFactory;"))); |
| // stack: factory |
| code->loadStringConstant(unoName); |
| // stack: factory serviceName |
| codemaker::ExceptionTree tree; |
| ClassFile::Code::Position tryStart; |
| ClassFile::Code::Position tryEnd; |
| std::vector< rtl::OString > exc; |
| sal_uInt16 stack; |
| sal_uInt16 localIndex = 1; |
| ClassFile::AccessFlags access = static_cast< ClassFile::AccessFlags >( |
| ClassFile::ACC_PUBLIC | ClassFile::ACC_STATIC); |
| if (defaultConstructor) { |
| code->loadLocalReference(0); |
| // stack: factory serviceName context |
| tryStart = code->getPosition(); |
| code->instrInvokeinterface( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "com/sun/star/lang/XMultiComponentFactory")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "createInstanceWithContext")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "(Ljava/lang/String;Lcom/sun/star/uno/XComponentContext;)" |
| "Ljava/lang/Object;")), |
| 3); |
| tryEnd = code->getPosition(); |
| // stack: instance |
| stack = 3; |
| } else { |
| sal_uInt16 parameters = reader.getMethodParameterCount(methodIndex); |
| if (parameters == 1 |
| && (reader.getMethodParameterFlags(methodIndex, 0) |
| == (RT_PARAM_IN | RT_PARAM_REST)) |
| && (reader.getMethodParameterTypeName(methodIndex, 0) |
| == rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("any")))) |
| { |
| desc.addParameter( |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("any")), true, true, 0); |
| code->loadLocalReference(localIndex++); |
| // stack: factory serviceName args |
| stack = 4; |
| access = static_cast< ClassFile::AccessFlags >( |
| access | ClassFile::ACC_VARARGS); |
| } else { |
| code->loadIntegerConstant(parameters); |
| // stack: factory serviceName N |
| code->instrAnewarray( |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("java/lang/Object"))); |
| // stack: factory serviceName args |
| stack = 0; |
| for (sal_uInt16 i = 0; i < parameters; ++i) { |
| RTParamMode flags = reader.getMethodParameterFlags( |
| methodIndex, i); |
| rtl::OString paramType( |
| codemaker::convertString( |
| reader.getMethodParameterTypeName(methodIndex, i))); |
| if ((flags != RT_PARAM_IN |
| && flags != (RT_PARAM_IN | RT_PARAM_REST)) |
| || ((flags & RT_PARAM_REST) != 0 |
| && (parameters != 1 |
| || (paramType |
| != rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("any")))))) |
| { |
| throw CannotDumpException( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "Bad type information"))); //TODO |
| } |
| desc.addParameter(paramType, false, true, 0); |
| code->instrDup(); |
| // stack: factory serviceName args args |
| code->loadIntegerConstant(i); |
| // stack: factory serviceName args args i |
| stack = std::max( |
| stack, |
| addLoadLocal( |
| manager, code.get(), &localIndex, false, paramType, |
| true, dependencies)); |
| // stack: factory serviceName args args i any |
| code->instrAastore(); |
| // stack: factory serviceName args |
| } |
| stack += 5; |
| } |
| code->loadLocalReference(0); |
| // stack: factory serviceName args context |
| tryStart = code->getPosition(); |
| code->instrInvokeinterface( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "com/sun/star/lang/XMultiComponentFactory")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "createInstanceWithArgumentsAndContext")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "(Ljava/lang/String;[Ljava/lang/Object;" |
| "Lcom/sun/star/uno/XComponentContext;)Ljava/lang/Object;")), |
| 4); |
| tryEnd = code->getPosition(); |
| // stack: instance |
| createExceptionsAttribute( |
| manager, reader, methodIndex, dependencies, &exc, &tree); |
| } |
| code->loadLocalReference(0); |
| // stack: instance context |
| code->instrInvokestatic( |
| className, rtl::OString(RTL_CONSTASCII_STRINGPARAM("$castInstance")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "(Ljava/lang/Object;Lcom/sun/star/uno/XComponentContext;)" |
| "Ljava/lang/Object;"))); |
| // stack: instance |
| code->instrCheckcast(returnType); |
| // stack: instance |
| code->instrAreturn(); |
| if (!tree.getRoot()->present) { |
| ClassFile::Code::Position pos1 = code->getPosition(); |
| // stack: e |
| code->instrInvokevirtual( |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("java/lang/Throwable")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("toString")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("()Ljava/lang/String;"))); |
| // stack: str |
| localIndex = std::max< sal_uInt16 >(localIndex, 2); |
| code->storeLocalReference(1); |
| // stack: - |
| code->instrNew( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "com/sun/star/uno/DeploymentException"))); |
| // stack: ex |
| code->instrDup(); |
| // stack: ex ex |
| rtl::OStringBuffer msg; |
| msg.append( |
| RTL_CONSTASCII_STRINGPARAM( |
| "component context fails to supply service ")); |
| msg.append(unoName); |
| msg.append(RTL_CONSTASCII_STRINGPARAM(" of type ")); |
| msg.append(realJavaBaseName); |
| msg.append(RTL_CONSTASCII_STRINGPARAM(": ")); |
| code->loadStringConstant(msg.makeStringAndClear()); |
| // stack: ex ex "..." |
| code->loadLocalReference(1); |
| // stack: ex ex "..." str |
| code->instrInvokevirtual( |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("java/lang/String")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("concat")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "(Ljava/lang/String;)Ljava/lang/String;"))); |
| // stack: ex ex "..." |
| code->loadLocalReference(0); |
| // stack: ex ex "..." context |
| code->instrInvokespecial( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "com/sun/star/uno/DeploymentException")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "(Ljava/lang/String;Ljava/lang/Object;)V"))); |
| // stack: ex |
| ClassFile::Code::Position pos2 = code->getPosition(); |
| code->instrAthrow(); |
| addExceptionHandlers( |
| tree.getRoot(), tryStart, tryEnd, pos2, code.get()); |
| code->addException( |
| tryStart, tryEnd, pos1, |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/Exception"))); |
| dependencies->insert( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/Exception"))); |
| stack = std::max< sal_uInt16 >(stack, 4); |
| } |
| code->setMaxStackAndLocals(stack, localIndex); |
| classFile->addMethod( |
| access, methodName, desc.getDescriptor(), code.get(), exc, |
| desc.getSignature()); |
| } |
| |
| void handleService( |
| TypeManager const & manager, JavaOptions /*TODO const*/ & options, |
| typereg::Reader const & reader, Dependencies * dependencies) |
| { |
| OSL_ASSERT(dependencies != 0); |
| sal_uInt16 superTypes = reader.getSuperTypeCount(); |
| sal_uInt16 methods = reader.getMethodCount(); |
| if (superTypes == 0 |
| ? methods != 0 |
| : (superTypes != 1 || reader.getFieldCount() != 0 |
| || reader.getReferenceCount() != 0)) |
| { |
| throw CannotDumpException( |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("Bad type information"))); |
| //TODO |
| } |
| if (superTypes == 0) { |
| return; |
| } |
| rtl::OString unoName(codemaker::convertString(reader.getTypeName())); |
| rtl::OString className( |
| translateUnoTypeToJavaFullyQualifiedName( |
| unoName, rtl::OString(RTL_CONSTASCII_STRINGPARAM("service")))); |
| unoName = unoName.replace('/', '.'); |
| std::auto_ptr< ClassFile > cf( |
| new ClassFile( |
| static_cast< ClassFile::AccessFlags >( |
| ClassFile::ACC_PUBLIC | ClassFile::ACC_FINAL |
| | ClassFile::ACC_SUPER), |
| className, |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("java/lang/Object")), |
| rtl::OString())); |
| if (methods > 0) { |
| rtl::OString base(codemaker::convertString( |
| reader.getSuperTypeName(0))); |
| rtl::OString realJavaBaseName(base.replace('/', '.')); |
| dependencies->insert(base); |
| dependencies->insert( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "com/sun/star/lang/XMultiComponentFactory"))); |
| dependencies->insert( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "com/sun/star/uno/DeploymentException"))); |
| dependencies->insert( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/TypeClass"))); |
| dependencies->insert( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "com/sun/star/uno/XComponentContext"))); |
| for (sal_uInt16 i = 0; i < methods; ++i) { |
| rtl::OString name(codemaker::convertString( |
| reader.getMethodName(i))); |
| bool defaultCtor = name.isEmpty(); |
| if (reader.getMethodFlags(i) != RT_MODE_TWOWAY |
| || (!reader.getMethodReturnTypeName(i).equalsAsciiL( |
| RTL_CONSTASCII_STRINGPARAM("void"))) |
| || (defaultCtor |
| && (methods != 1 || reader.getMethodParameterCount(i) != 0 |
| || reader.getMethodExceptionCount(i) != 0))) |
| { |
| throw CannotDumpException( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("Bad type information"))); |
| //TODO |
| } |
| if (defaultCtor) { |
| name = rtl::OString(RTL_CONSTASCII_STRINGPARAM("create")); |
| } else { |
| name = codemaker::java::translateUnoToJavaIdentifier( |
| name, rtl::OString(RTL_CONSTASCII_STRINGPARAM("method"))); |
| } |
| addConstructor( |
| manager, realJavaBaseName, unoName, className, reader, i, name, |
| base, defaultCtor, dependencies, cf.get()); |
| } |
| // Synthetic getFactory method: |
| { |
| std::auto_ptr< ClassFile::Code > code(cf->newCode()); |
| code->loadLocalReference(0); |
| // stack: context |
| code->instrInvokeinterface( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "com/sun/star/uno/XComponentContext")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("getServiceManager")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "()Lcom/sun/star/lang/XMultiComponentFactory;")), |
| 1); |
| // stack: factory |
| code->instrDup(); |
| // stack: factory factory |
| ClassFile::Code::Branch branch = code->instrIfnull(); |
| // stack: factory |
| code->instrAreturn(); |
| code->branchHere(branch); |
| code->instrPop(); |
| // stack: - |
| code->instrNew( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "com/sun/star/uno/DeploymentException"))); |
| // stack: ex |
| code->instrDup(); |
| // stack: ex ex |
| code->loadStringConstant( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "component context fails to supply service manager"))); |
| // stack: ex ex "..." |
| code->loadLocalReference(0); |
| // stack: ex ex "..." context |
| code->instrInvokespecial( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "com/sun/star/uno/DeploymentException")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "(Ljava/lang/String;Ljava/lang/Object;)V"))); |
| // stack: ex |
| code->instrAthrow(); |
| code->setMaxStackAndLocals(4, 1); |
| cf->addMethod( |
| static_cast< ClassFile::AccessFlags >( |
| ClassFile::ACC_PRIVATE | ClassFile::ACC_STATIC |
| | ClassFile::ACC_SYNTHETIC), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("$getFactory")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "(Lcom/sun/star/uno/XComponentContext;)" |
| "Lcom/sun/star/lang/XMultiComponentFactory;")), |
| code.get(), std::vector< rtl::OString >(), rtl::OString()); |
| } |
| // Synthetic castInstance method: |
| { |
| std::auto_ptr< ClassFile::Code > code(cf->newCode()); |
| code->instrNew( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/Type"))); |
| // stack: type |
| code->instrDup(); |
| // stack: type type |
| code->loadStringConstant(realJavaBaseName); |
| // stack: type type "..." |
| code->instrGetstatic( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/TypeClass")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("INTERFACE")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "Lcom/sun/star/uno/TypeClass;"))); |
| // stack: type type "..." INTERFACE |
| code->instrInvokespecial( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/Type")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "(Ljava/lang/String;Lcom/sun/star/uno/TypeClass;)V"))); |
| // stack: type |
| code->loadLocalReference(0); |
| // stack: type instance |
| code->instrInvokestatic( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/UnoRuntime")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("queryInterface")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "(Lcom/sun/star/uno/Type;Ljava/lang/Object;)" |
| "Ljava/lang/Object;"))); |
| // stack: instance |
| code->instrDup(); |
| // stack: instance instance |
| ClassFile::Code::Branch branch = code->instrIfnull(); |
| // stack: instance |
| code->instrAreturn(); |
| code->branchHere(branch); |
| code->instrPop(); |
| // stack: - |
| code->instrNew( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "com/sun/star/uno/DeploymentException"))); |
| // stack: ex |
| code->instrDup(); |
| // stack: ex ex |
| rtl::OStringBuffer msg; |
| msg.append( |
| RTL_CONSTASCII_STRINGPARAM( |
| "component context fails to supply service ")); |
| msg.append(unoName); |
| msg.append(RTL_CONSTASCII_STRINGPARAM(" of type ")); |
| msg.append(realJavaBaseName); |
| code->loadStringConstant(msg.makeStringAndClear()); |
| // stack: ex ex "..." |
| code->loadLocalReference(1); |
| // stack: ex ex "..." context |
| code->instrInvokespecial( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "com/sun/star/uno/DeploymentException")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "(Ljava/lang/String;Ljava/lang/Object;)V"))); |
| // stack: ex |
| code->instrAthrow(); |
| code->setMaxStackAndLocals(4, 2); |
| cf->addMethod( |
| static_cast< ClassFile::AccessFlags >( |
| ClassFile::ACC_PRIVATE | ClassFile::ACC_STATIC |
| | ClassFile::ACC_SYNTHETIC), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("$castInstance")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "(Ljava/lang/Object;Lcom/sun/star/uno/" |
| "XComponentContext;)Ljava/lang/Object;")), |
| code.get(), std::vector< rtl::OString >(), rtl::OString()); |
| } |
| } |
| writeClassFile(options, className, *cf.get()); |
| } |
| |
| void handleSingleton( |
| TypeManager const & manager, JavaOptions /*TODO const*/ & options, |
| typereg::Reader const & reader, Dependencies * dependencies) |
| { |
| OSL_ASSERT(dependencies != 0); |
| if (reader.getSuperTypeCount() != 1 || reader.getFieldCount() != 0 |
| || reader.getMethodCount() != 0 || reader.getReferenceCount() != 0) |
| { |
| throw CannotDumpException( |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("Bad type information"))); |
| //TODO |
| } |
| rtl::OString base(codemaker::convertString(reader.getSuperTypeName(0))); |
| rtl::OString realJavaBaseName(base.replace('/', '.')); |
| switch (manager.getTypeReader(base).getTypeClass()) { |
| case RT_TYPE_INTERFACE: |
| break; |
| |
| case RT_TYPE_SERVICE: |
| return; |
| |
| default: |
| throw CannotDumpException( |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("Bad type information"))); |
| //TODO |
| } |
| dependencies->insert(base); |
| rtl::OString unoName(codemaker::convertString(reader.getTypeName())); |
| rtl::OString className( |
| translateUnoTypeToJavaFullyQualifiedName( |
| unoName, rtl::OString(RTL_CONSTASCII_STRINGPARAM("singleton")))); |
| unoName = unoName.replace('/', '.'); |
| dependencies->insert( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "com/sun/star/uno/DeploymentException"))); |
| dependencies->insert( |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/TypeClass"))); |
| dependencies->insert( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/XComponentContext"))); |
| std::auto_ptr< ClassFile > cf( |
| new ClassFile( |
| static_cast< ClassFile::AccessFlags >( |
| ClassFile::ACC_PUBLIC | ClassFile::ACC_FINAL |
| | ClassFile::ACC_SUPER), |
| className, |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("java/lang/Object")), |
| rtl::OString())); |
| MethodDescriptor desc(manager, dependencies, base, 0, 0); |
| desc.addParameter( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/XComponentContext")), |
| false, false, 0); |
| std::auto_ptr< ClassFile::Code > code(cf->newCode()); |
| code->loadLocalReference(0); |
| // stack: context |
| code->loadStringConstant( |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("/singletons/")) + unoName); |
| // stack: context "..." |
| code->instrInvokeinterface( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/XComponentContext")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("getValueByName")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "(Ljava/lang/String;)Ljava/lang/Object;")), |
| 2); |
| // stack: value |
| code->instrDup(); |
| // stack: value value |
| code->instrInstanceof( |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/Any"))); |
| // stack: value 0/1 |
| ClassFile::Code::Branch branch1 = code->instrIfeq(); |
| // stack: value |
| code->instrCheckcast( |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/Any"))); |
| // stack: value |
| code->instrDup(); |
| // stack: value value |
| code->instrInvokevirtual( |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/Any")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("getType")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("()Lcom/sun/star/uno/Type;"))); |
| // stack: value type |
| code->instrInvokevirtual( |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/Type")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("getTypeClass")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("()Lcom/sun/star/uno/TypeClass;"))); |
| // stack: value typeClass |
| code->instrGetstatic( |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/TypeClass")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("INTERFACE")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("Lcom/sun/star/uno/TypeClass;"))); |
| // stack: value typeClass INTERFACE |
| ClassFile::Code::Branch branch2 = code->instrIfAcmpne(); |
| // stack: value |
| code->instrInvokevirtual( |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/Any")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("getObject")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("()Ljava/lang/Object;"))); |
| // stack: value |
| code->branchHere(branch1); |
| code->instrNew( |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/Type"))); |
| // stack: value type |
| code->instrDup(); |
| // stack: value type type |
| code->loadStringConstant(realJavaBaseName); |
| // stack: value type type "..." |
| code->instrGetstatic( |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/TypeClass")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("INTERFACE")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("Lcom/sun/star/uno/TypeClass;"))); |
| // stack: value type type "..." INTERFACE |
| code->instrInvokespecial( |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/Type")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "(Ljava/lang/String;Lcom/sun/star/uno/TypeClass;)V"))); |
| // stack: value type |
| code->instrSwap(); |
| // stack: type value |
| code->instrInvokestatic( |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/UnoRuntime")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("queryInterface")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "(Lcom/sun/star/uno/Type;Ljava/lang/Object;)" |
| "Ljava/lang/Object;"))); |
| // stack: instance |
| code->instrDup(); |
| // stack: instance instance |
| ClassFile::Code::Branch branch3 = code->instrIfnull(); |
| // stack: instance |
| code->instrCheckcast(base); |
| // stack: instance |
| code->instrAreturn(); |
| code->branchHere(branch2); |
| code->branchHere(branch3); |
| code->instrPop(); |
| // stack: - |
| code->instrNew( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "com/sun/star/uno/DeploymentException"))); |
| // stack: ex |
| code->instrDup(); |
| // stack: ex ex |
| rtl::OStringBuffer msg; |
| msg.append( |
| RTL_CONSTASCII_STRINGPARAM( |
| "component context fails to supply singleton ")); |
| msg.append(unoName); |
| msg.append(RTL_CONSTASCII_STRINGPARAM(" of type ")); |
| msg.append(realJavaBaseName); |
| code->loadStringConstant(msg.makeStringAndClear()); |
| // stack: ex ex "..." |
| code->loadLocalReference(0); |
| // stack: ex ex "..." context |
| code->instrInvokespecial( |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM("com/sun/star/uno/DeploymentException")), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("<init>")), |
| rtl::OString( |
| RTL_CONSTASCII_STRINGPARAM( |
| "(Ljava/lang/String;Ljava/lang/Object;)V"))); |
| // stack: ex |
| code->instrAthrow(); |
| code->setMaxStackAndLocals(5, 1); |
| cf->addMethod( |
| static_cast< ClassFile::AccessFlags >( |
| ClassFile::ACC_PUBLIC | ClassFile::ACC_STATIC), |
| rtl::OString(RTL_CONSTASCII_STRINGPARAM("get")), desc.getDescriptor(), |
| code.get(), std::vector< rtl::OString >(), desc.getSignature()); |
| writeClassFile(options, className, *cf.get()); |
| } |
| |
| } |
| |
| bool produceType( |
| rtl::OString const & type, TypeManager const & manager, |
| codemaker::GeneratedTypeSet & generated, JavaOptions * options) |
| { |
| OSL_ASSERT(options != 0); |
| if (type.equals("/") |
| || type.equals(manager.getBase()) |
| || generated.contains(type)) |
| { |
| return true; |
| } |
| sal_Bool extra = sal_False; |
| typereg::Reader reader(manager.getTypeReader(type, &extra)); |
| if (extra) { |
| generated.add(type); |
| return true; |
| } |
| if (!reader.isValid()) { |
| return false; |
| } |
| |
| handleUnoTypeRegistryEntityFunction handler; |
| switch (reader.getTypeClass()) { |
| case RT_TYPE_ENUM: |
| handler = handleEnumType; |
| break; |
| |
| case RT_TYPE_STRUCT: |
| case RT_TYPE_EXCEPTION: |
| handler = handleAggregatingType; |
| break; |
| |
| case RT_TYPE_INTERFACE: |
| handler = handleInterfaceType; |
| break; |
| |
| case RT_TYPE_TYPEDEF: |
| handler = handleTypedef; |
| break; |
| |
| case RT_TYPE_CONSTANTS: |
| handler = handleConstantGroup; |
| break; |
| |
| case RT_TYPE_MODULE: |
| handler = handleModule; |
| break; |
| |
| case RT_TYPE_SERVICE: |
| handler = handleService; |
| break; |
| |
| case RT_TYPE_SINGLETON: |
| handler = handleSingleton; |
| break; |
| |
| default: |
| return false; |
| } |
| Dependencies deps; |
| handler(manager, *options, reader, &deps); |
| generated.add(type); |
| if (!options->isValid(rtl::OString(RTL_CONSTASCII_STRINGPARAM("-nD")))) { |
| for (Dependencies::iterator i(deps.begin()); i != deps.end(); ++i) { |
| if (!produceType(*i, manager, generated, options)) { |
| return false; |
| } |
| } |
| } |
| return true; |
| } |
| |
| bool produceType( |
| RegistryKey & rTypeKey, bool bIsExtraType, TypeManager const & manager, |
| codemaker::GeneratedTypeSet & generated, JavaOptions * options) |
| { |
| ::rtl::OString typeName = manager.getTypeName(rTypeKey); |
| |
| OSL_ASSERT(options != 0); |
| if (typeName.equals("/") |
| || typeName.equals(manager.getBase()) |
| || generated.contains(typeName)) |
| { |
| return true; |
| } |
| typereg::Reader reader(manager.getTypeReader(rTypeKey)); |
| if (bIsExtraType) { |
| generated.add(typeName); |
| return true; |
| } |
| if (!reader.isValid()) { |
| return false; |
| } |
| handleUnoTypeRegistryEntityFunction handler; |
| switch (reader.getTypeClass()) { |
| case RT_TYPE_ENUM: |
| handler = handleEnumType; |
| break; |
| |
| case RT_TYPE_STRUCT: |
| case RT_TYPE_EXCEPTION: |
| handler = handleAggregatingType; |
| break; |
| |
| case RT_TYPE_INTERFACE: |
| handler = handleInterfaceType; |
| break; |
| |
| case RT_TYPE_TYPEDEF: |
| handler = handleTypedef; |
| break; |
| |
| case RT_TYPE_CONSTANTS: |
| handler = handleConstantGroup; |
| break; |
| |
| case RT_TYPE_MODULE: |
| handler = handleModule; |
| break; |
| |
| case RT_TYPE_SERVICE: |
| handler = handleService; |
| break; |
| |
| case RT_TYPE_SINGLETON: |
| handler = handleSingleton; |
| break; |
| |
| default: |
| return false; |
| } |
| Dependencies deps; |
| handler(manager, *options, reader, &deps); |
| generated.add(typeName); |
| if (!options->isValid(rtl::OString(RTL_CONSTASCII_STRINGPARAM("-nD")))) { |
| for (Dependencies::iterator i(deps.begin()); i != deps.end(); ++i) { |
| if (!produceType(*i, manager, generated, options)) { |
| return false; |
| } |
| } |
| } |
| return true; |
| } |