1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
29 #include "osl/thread.hxx"
31 #include "codemaker/commonjava.hxx"
32 #include "codemaker/commoncpp.hxx"
33 #include "codemaker/generatedtypeset.hxx"
35 #include "ostringostreaminserter.hxx"
36 #include "skeletoncommon.hxx"
40 using namespace ::rtl
;
41 using namespace ::codemaker::cpp
;
43 namespace skeletonmaker
{
45 void printLicenseHeader(std::ostream
& o
, rtl::OString
const & filename
)
49 index
= filename
.lastIndexOf('/');
51 index
= filename
.lastIndexOf('\\');
53 OString
shortfilename(filename
);
55 shortfilename
= filename
.copy(index
+1);
57 o
<< "/*************************************************************************\n"
59 " * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.\n"
61 " * Copyright 2000, 2010 Oracle and/or its affiliates.\n"
63 " * OpenOffice.org - a multi-platform office productivity suite\n"
65 " * This file is part of OpenOffice.org.\n"
67 " * OpenOffice.org is free software: you can redistribute it and/or modify\n"
68 " * it under the terms of the GNU Lesser General Public License version 3\n"
69 " * only, as published by the Free Software Foundation.\n"
71 " * OpenOffice.org is distributed in the hope that it will be useful,\n"
72 " * but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
73 " * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
74 " * GNU Lesser General Public License version 3 for more details\n"
75 " * (a copy is included in the LICENSE file that accompanied this code).\n"
77 " * You should have received a copy of the GNU Lesser General Public License\n"
78 " * version 3 along with OpenOffice.org. If not, see\n"
79 " * <http://www.openoffice.org/license.html>\n"
80 " * for a copy of the LGPLv3 License.\n"
82 " ************************************************************************/\n\n";
85 bool getOutputStream(ProgramOptions
const & options
,
86 OString
const & extension
,
87 std::ostream
** ppOutputStream
,
88 OString
& targetSourceFileName
,
89 OString
& tmpSourceFileName
)
91 bool bStandardout
= false;
92 if ( options
.outputpath
.equals("stdout") )
95 *ppOutputStream
= &std::cout
;
99 targetSourceFileName
= createFileNameFromType(
100 options
.outputpath
, options
.implname
.replace('.','/'), extension
);
102 OString tmpDir
= getTempDir(targetSourceFileName
);
104 file
.createTempFile(tmpDir
);
106 if( !file
.isValid() )
108 OString
message("cannot open ");
109 message
+= targetSourceFileName
+ " for writing";
110 throw CannotDumpException(message
);
112 tmpSourceFileName
= file
.getName();
115 *ppOutputStream
= new std::ofstream(tmpSourceFileName
.getStr(),
116 std::ios_base::binary
);
121 codemaker::UnoType::Sort
decomposeResolveAndCheck(
122 TypeManager
const & manager
, OString
const & type
,
123 bool resolveTypedefs
, bool allowVoid
, bool allowExtraEntities
,
124 RTTypeClass
* typeClass
, OString
* name
, sal_Int32
* rank
,
125 std::vector
< OString
> * arguments
)
127 codemaker::UnoType::Sort sort
= codemaker::decomposeAndResolve(
128 manager
, type
, resolveTypedefs
, allowVoid
, allowExtraEntities
,
129 typeClass
, name
, rank
, arguments
);
130 for ( std::vector
< OString
>::iterator
i(arguments
->begin());
131 i
!= arguments
->end(); ++i
)
133 RTTypeClass typeClass2
;
136 std::vector
< OString
> arguments2
;
137 decomposeResolveAndCheck(
138 manager
, *i
, true, false, false, &typeClass2
, &name2
, &rank2
,
144 bool containsAttribute(AttributeInfo
& attributes
, OString
const & attrname
)
146 for ( AttributeInfo::const_iterator
i(attributes
.begin());
147 i
!= attributes
.end(); ++i
) {
148 if ( (*i
).first
== attrname
) {
155 // collect attributes including inherited attributes
156 void checkAttributes(TypeManager
const & manager
,
157 const typereg::Reader
& reader
,
158 AttributeInfo
& attributes
,
159 boost::unordered_set
< OString
, OStringHash
>& propinterfaces
)
161 OString typeName
= codemaker::convertString(reader
.getTypeName());
162 if ( typeName
.equals("com/sun/star/beans/XPropertySet") ||
163 typeName
.equals("com/sun/star/beans/XFastPropertySet") ||
164 // typeName.equals("com/sun/star/beans/XMultiPropertySet") ||
165 typeName
.equals("com/sun/star/beans/XPropertyAccess") )
167 propinterfaces
.insert(typeName
);
170 for ( sal_uInt16 i
= 0; i
< reader
.getSuperTypeCount(); ++i
) {
171 typereg::Reader
supertype(manager
.getTypeReader(
172 codemaker::convertString(
173 reader
.getSuperTypeName(i
))));
174 if ( !supertype
.isValid() ) {
175 throw CannotDumpException(
176 "Bad type library entity "
177 + codemaker::convertString(reader
.getSuperTypeName(i
)));
179 checkAttributes(manager
, supertype
, attributes
, propinterfaces
);
182 for ( sal_uInt16 i
= 0; i
< reader
.getFieldCount(); ++i
) {
184 codemaker::convertString(reader
.getFieldName(i
)).
187 if ( !containsAttribute(attributes
, fieldName
) ) {
189 codemaker::convertString(reader
.getFieldTypeName(i
)).
191 attributes
.push_back(AttributeInfo::value_type(
192 fieldName
, std::pair
<OString
, sal_Int16
>(
193 fieldType
, reader
.getFieldFlags(i
))));
198 void checkType(TypeManager
const & manager
,
199 OString
const & type
,
200 boost::unordered_set
< OString
, OStringHash
>& interfaceTypes
,
201 boost::unordered_set
< OString
, OStringHash
>& serviceTypes
,
202 AttributeInfo
& properties
)
205 OString
binType(type
.replace('.', '/'));
206 typereg::Reader
reader(manager
.getTypeReader(binType
));
207 if ( !reader
.isValid() ) {
208 throw CannotDumpException("Bad type library entity " + binType
);
211 switch ( reader
.getTypeClass() )
213 case RT_TYPE_INTERFACE
:
215 // com/sun/star/lang/XComponent should be also not in the list
216 // but it will be used for checking the impl helper and will be
217 // removed later if necessary.
218 if ( binType
.equals("com/sun/star/lang/XTypeProvider") ||
219 binType
.equals("com/sun/star/uno/XWeak") )
221 if (interfaceTypes
.find(type
) == interfaceTypes
.end()) {
222 interfaceTypes
.insert(type
);
226 case RT_TYPE_SERVICE
:
227 if ( serviceTypes
.find(binType
) == serviceTypes
.end() ) {
228 serviceTypes
.insert(binType
);
230 if ( reader
.getSuperTypeCount() > 0 ) {
231 OString
supername(codemaker::convertString(
232 reader
.getSuperTypeName(0).replace('/', '.')));
233 if ( interfaceTypes
.find(supername
) == interfaceTypes
.end() ) {
234 interfaceTypes
.insert(supername
);
236 typereg::Reader
supertype(manager
.getTypeReader(
237 codemaker::convertString(
238 reader
.getSuperTypeName(0))));
239 if ( !supertype
.isValid() ) {
240 throw CannotDumpException(
241 "Bad type library entity "
242 + codemaker::convertString(reader
.getSuperTypeName(0)));
246 // check if constructors are specified, if yes automatically
247 // support of XInitialization. We will take care of the default
248 // constructor because in this case XInitialization is not called.
249 if ( reader
.getMethodCount() > 1 ||
250 ( reader
.getMethodCount() == 1 &&
251 !reader
.getMethodName(0).isEmpty() ) )
253 OString
s("com.sun.star.lang.XInitialization");
254 if ( interfaceTypes
.find(s
) == interfaceTypes
.end() )
255 interfaceTypes
.insert(s
);
258 for ( sal_uInt16 i
= 0; i
< reader
.getReferenceCount(); ++i
) {
259 OString
referenceType(
260 codemaker::convertString(
261 reader
.getReferenceTypeName(i
)).replace('/', '.'));
263 if ( reader
.getReferenceSort(i
) == RT_REF_SUPPORTS
) {
264 checkType(manager
, referenceType
, interfaceTypes
,
265 serviceTypes
, properties
);
266 } else if ( reader
.getReferenceSort(i
) == RT_REF_EXPORTS
) {
267 checkType(manager
, referenceType
, interfaceTypes
,
268 serviceTypes
, properties
);
272 for ( sal_uInt16 i
= 0; i
< reader
.getFieldCount(); ++i
) {
274 codemaker::convertString(reader
.getFieldName(i
)).
277 codemaker::convertString(reader
.getFieldTypeName(i
)).
280 properties
.push_back(AttributeInfo::value_type(
281 fieldName
, std::pair
<OString
, sal_Int16
>(
282 fieldType
, reader
.getFieldFlags(i
))));
293 void checkDefaultInterfaces(
294 boost::unordered_set
< OString
, OStringHash
>& interfaces
,
295 const boost::unordered_set
< OString
, OStringHash
>& services
,
296 const OString
& propertyhelper
)
298 if ( services
.empty() ) {
299 if (interfaces
.find("com.sun.star.lang.XServiceInfo") != interfaces
.end())
300 interfaces
.erase("com.sun.star.lang.XServiceInfo");
302 if (interfaces
.find("com.sun.star.lang.XServiceInfo") == interfaces
.end())
303 interfaces
.insert("com.sun.star.lang.XServiceInfo");
306 if ( propertyhelper
.equals("_") ) {
307 if (interfaces
.find("com.sun.star.beans.XPropertySet")
309 interfaces
.erase("com.sun.star.beans.XPropertySet");
310 if (interfaces
.find("com.sun.star.beans.XFastPropertySet")
312 interfaces
.erase("com.sun.star.beans.XFastPropertySet");
313 if (interfaces
.find("com.sun.star.beans.XPropertyAccess")
315 interfaces
.erase("com.sun.star.beans.XPropertyAccess");
319 bool checkServiceProperties(TypeManager
const & manager
,
320 const typereg::Reader
& reader
)
322 if ( reader
.getFieldCount() > 0 )
325 if ( reader
.getReferenceCount() > 0 ) {
326 for ( sal_uInt16 i
= 0; i
< reader
.getReferenceCount(); ++i
) {
327 if ( reader
.getReferenceSort(i
) == RT_REF_EXPORTS
) {
328 typereg::Reader
refreader(
329 manager
.getTypeReader(
330 codemaker::convertString(reader
.getReferenceTypeName(i
))));
332 if ( checkServiceProperties(manager
, refreader
) )
341 OString
checkPropertyHelper(
342 ProgramOptions
const & options
,
343 TypeManager
const & manager
,
344 const boost::unordered_set
< OString
, OStringHash
>& services
,
345 const boost::unordered_set
< OString
, OStringHash
>& interfaces
,
346 AttributeInfo
& attributes
,
347 boost::unordered_set
< OString
, OStringHash
>& propinterfaces
)
349 boost::unordered_set
< OString
, OStringHash
>::const_iterator iter
;
350 boost::unordered_set
< OString
, OStringHash
>::const_iterator end
;
352 if ( !services
.empty() ) {
353 iter
= services
.begin();
354 end
= services
.end();
356 iter
= interfaces
.begin();
357 end
= interfaces
.end();
360 bool oldStyleWithProperties
= false;
361 while ( iter
!= end
) {
362 typereg::Reader
reader(manager
.getTypeReader((*iter
).replace('.', '/')));
364 if ( !services
.empty() ) {
365 if ( options
.supportpropertysetmixin
&& reader
.getSuperTypeCount() > 0 )
367 typereg::Reader
supertype(
368 manager
.getTypeReader(
369 codemaker::convertString(
370 reader
.getSuperTypeName(0))));
371 if ( !supertype
.isValid() ) {
372 throw CannotDumpException(
373 "Bad type library entity "
374 + codemaker::convertString(
375 reader
.getSuperTypeName(0)));
378 checkAttributes(manager
, supertype
, attributes
, propinterfaces
);
380 if ( !(attributes
.empty() || propinterfaces
.empty()) ) {
381 return OUStringToOString(
382 supertype
.getTypeName().replace('/', '.'),
383 osl_getThreadTextEncoding());
386 oldStyleWithProperties
= checkServiceProperties(manager
, reader
);
389 checkAttributes(manager
, reader
, attributes
, propinterfaces
);
390 if ( !(attributes
.empty() || propinterfaces
.empty()) ) {
391 return OUStringToOString(
392 reader
.getTypeName().replace('/', '.'),
393 osl_getThreadTextEncoding());
399 return (oldStyleWithProperties
? "_" : "");
402 bool checkXComponentSupport(TypeManager
const & manager
,
403 typereg::Reader
const & reader
)
405 static OUString
s( "com/sun/star/lang/XComponent");
406 if ( reader
.getTypeName().equals(s
) )
409 for ( sal_uInt16 i
= 0; i
< reader
.getSuperTypeCount(); ++i
) {
410 typereg::Reader
super(
411 manager
.getTypeReader(
412 codemaker::convertString(
413 reader
.getSuperTypeName(i
))));
414 if ( !super
.isValid() ) {
415 throw CannotDumpException(
416 "Bad type library entity "
417 + codemaker::convertString(
418 reader
.getSuperTypeName(i
)));
420 if ( checkXComponentSupport(manager
, super
) )
428 // if XComponent is directly specified, return true and remove it from the
429 // supported interfaces list
430 bool checkXComponentSupport(TypeManager
const & manager
,
431 boost::unordered_set
< OString
, OStringHash
>& interfaces
)
433 if ( interfaces
.empty() )
436 boost::unordered_set
< OString
, OStringHash
>::const_iterator iter
=
438 while ( iter
!= interfaces
.end() ) {
439 if ( (*iter
).equals("com.sun.star.lang.XComponent") ) {
440 interfaces
.erase("com.sun.star.lang.XComponent");
443 typereg::Reader
reader(manager
.getTypeReader((*iter
).replace('.', '/')));
444 if ( checkXComponentSupport(manager
, reader
) )
452 sal_uInt16
checkAdditionalPropertyFlags(typereg::Reader
const & reader
,
453 sal_uInt16 field
, sal_uInt16 method
)
455 sal_uInt16 flags
= 0;
456 bool getterSupportsUnknown
= false;
458 OUString
su( "com/sun/star/beans/UnknownPropertyException");
459 if ( method
< reader
.getMethodCount()
460 && reader
.getMethodFlags(method
) == RT_MODE_ATTRIBUTE_GET
461 && reader
.getMethodName(method
) == reader
.getFieldName(field
) )
463 if ( reader
.getMethodExceptionCount(method
) > 0 ) {
464 for ( sal_uInt16 i
= 0; i
< reader
.getMethodExceptionCount(method
);
467 if (su
.equals(reader
.getMethodExceptionTypeName(method
, i
)))
468 getterSupportsUnknown
= true;
473 if ( method
< reader
.getMethodCount()
474 && reader
.getMethodFlags(method
) == RT_MODE_ATTRIBUTE_SET
475 && reader
.getMethodName(method
) == reader
.getFieldName(field
) )
477 if ( reader
.getMethodExceptionCount(method
) > 0 ) {
478 OUString
s( "com/sun/star/beans/PropertyVetoException");
479 for ( sal_uInt16 i
= 0; i
< reader
.getMethodExceptionCount(method
);
482 if ( s
.equals(reader
.getMethodExceptionTypeName(method
, i
)) )
483 flags
|= RT_ACCESS_CONSTRAINED
;
484 if ( getterSupportsUnknown
&&
485 su
.equals(reader
.getMethodExceptionTypeName(method
, i
)) )
486 flags
|= RT_ACCESS_OPTIONAL
;
493 // This function checks if the specified types for parameters and return
494 // types are allowed add-in types, for more info see the com.sun.star.sheet.AddIn
495 // service description
496 bool checkAddinType(TypeManager
const & manager
,
497 OString
const & type
, bool & bLastAny
,
498 bool & bHasXPropertySet
, bool bIsReturn
)
500 RTTypeClass typeClass
;
503 std::vector
< OString
> arguments
;
504 codemaker::UnoType::Sort sort
= codemaker::decomposeAndResolve(
505 manager
, type
, true, true, true, &typeClass
, &name
, &rank
, &arguments
);
507 if ( sort
== codemaker::UnoType::SORT_LONG
||
508 sort
== codemaker::UnoType::SORT_DOUBLE
||
509 sort
== codemaker::UnoType::SORT_STRING
)
511 if ( rank
== 0 || rank
==2 )
514 if ( sort
== codemaker::UnoType::SORT_ANY
)
526 if ( sort
== codemaker::UnoType::SORT_COMPLEX
&&
527 typeClass
== RT_TYPE_INTERFACE
)
529 if ( bIsReturn
&& type
.equals("com/sun/star/sheet/XVolatileResult") )
531 if ( !bIsReturn
&& type
.equals("com/sun/star/table/XCellRange") )
533 if ( !bIsReturn
&& type
.equals("com/sun/star/beans/XPropertySet") )
535 if ( bHasXPropertySet
) {
538 bHasXPropertySet
= true;
546 void checkAddInTypes(TypeManager
const & manager
,
547 typereg::Reader
const & reader
)
549 OString
sType(codemaker::convertString(reader
.getTypeName()).replace('/', '.'));
550 bool bLastAny
= false;
551 bool bHasXPropertySet
= false;
552 for ( sal_uInt16 m
= 0; m
< reader
.getMethodCount(); ++m
) {
553 OString
sMethod(codemaker::convertString(reader
.getMethodName(m
)));
555 OString
sReturnType(codemaker::convertString(
556 reader
.getMethodReturnTypeName(m
)));
557 if ( !checkAddinType(
558 manager
, sReturnType
, bLastAny
, bHasXPropertySet
, true) )
560 OStringBuffer
msg("the return type of the calc add-in function '");
564 msg
.append("' is invalid. Please check your IDL defintion.");
565 throw CannotDumpException(msg
.makeStringAndClear());
568 bHasXPropertySet
= false;
569 for ( sal_uInt16 p
= 0; p
< reader
.getMethodParameterCount(m
); ++p
) {
571 OString
sParamType(codemaker::convertString(
572 reader
.getMethodParameterTypeName(m
, p
)));
573 if ( !checkAddinType(manager
, sParamType
,
574 bLastAny
, bHasXPropertySet
, false) ||
577 OStringBuffer
msg("the type of the ");
578 msg
.append((sal_Int32
)p
+1);
579 msg
.append(". parameter of the calc add-in function '");
583 msg
.append("' is invalid.");
585 msg
.append(" The type 'sequence<any>' is allowed as last "
587 if ( bHasXPropertySet
)
588 msg
.append(" The type 'XPropertySet' is allowed only once.");
590 msg
.append(" Please check your IDL definition.");
591 throw CannotDumpException(msg
.makeStringAndClear());
597 void generateFunctionParamterMap(std::ostream
& o
,
598 ProgramOptions
const & options
,
599 TypeManager
const & manager
,
600 typereg::Reader
const & reader
,
601 ::codemaker::GeneratedTypeSet
& generated
,
604 OString
sType(codemaker::convertString(reader
.getTypeName()));
605 if ( sType
.equals("com/sun/star/uno/XInterface") ||
606 sType
.equals("com/sun/star/lang/XLocalizable") ||
607 sType
.equals("com/sun/star/lang/XServiceInfo") ||
608 // the next three checks becomes obsolete when configuration is used
609 sType
.equals("com/sun/star/sheet/XAddIn") ||
610 sType
.equals("com/sun/star/sheet/XCompatibilityNames") ||
611 sType
.equals("com/sun/star/lang/XServiceName") )
616 // check if the specified add-in functions supports valid types
617 checkAddInTypes(manager
, reader
);
619 for ( sal_uInt16 i
= 0; i
< reader
.getSuperTypeCount(); ++i
) {
620 typereg::Reader
super(
621 manager
.getTypeReader(
622 codemaker::convertString(
623 reader
.getSuperTypeName(i
))));
624 if ( !super
.isValid() ) {
625 throw CannotDumpException(
626 "Bad type library entity "
627 + codemaker::convertString(
628 reader
.getSuperTypeName(i
)));
630 generateFunctionParamterMap(o
, options
, manager
, super
, generated
, bFirst
);
633 OString
type(codemaker::convertString(reader
.getTypeName()));
634 if ( generated
.contains(type
) )
639 for ( sal_uInt16 m
= 0; m
< reader
.getMethodCount(); ++m
) {
640 OString
sMethod(codemaker::convertString(reader
.getMethodName(m
)));
643 if (options
.language
== 2) {
644 o
<< " ParamMap fpm;\n";
648 o
<< " java.util.Hashtable< Integer, String > fpm = "
649 "new java.util.Hashtable< Integer, String >();\n";
651 o
<< " java.util.Hashtable fpm = "
652 "new java.util.Hashtable();\n";
656 if ( options
.language
== 2 ) {
657 o
<< " fpm = ParamMap();\n";
661 o
<< " fpm = new java.util.Hashtable< "
662 "Integer, String >();\n";
664 o
<< " fpm = new java.util.Hashtable();\n";
667 for ( sal_uInt16 p
= 0; p
< reader
.getMethodParameterCount(m
); ++p
) {
668 if ( options
.language
== 2 ) {
670 << "] = ::rtl::OUString(\""
671 << codemaker::convertString(reader
.getMethodParameterName(m
, p
))
676 o
<< " fpm.put(" << p
<< ", \""
677 << codemaker::convertString(
678 reader
.getMethodParameterName(m
, p
))
681 o
<< " fpm.put(new Integer(" << p
<< "), \""
682 << codemaker::convertString(
683 reader
.getMethodParameterName(m
, p
))
688 if ( options
.language
== 2 ) {
689 o
<< " m_functionMap[::rtl::OUString(\""
690 << sMethod
<< "\")] = fpm;\n\n";
693 o
<< " m_functionMap.put(\"" << sMethod
<< "\", fpm);\n\n";
698 void generateFunctionParameterMap(std::ostream
& o
,
699 ProgramOptions
const & options
,
700 TypeManager
const & manager
,
701 const boost::unordered_set
< OString
, OStringHash
>& interfaces
)
703 ::codemaker::GeneratedTypeSet generated
;
705 boost::unordered_set
< OString
, OStringHash
>::const_iterator iter
= interfaces
.begin();
706 while ( iter
!= interfaces
.end() ) {
707 typereg::Reader
reader(manager
.getTypeReader((*iter
).replace('.','/')));
708 if (!reader
.isValid()) {
709 throw CannotDumpException(
710 "Bad type library entity "
711 + codemaker::convertString(
712 reader
.getTypeName()));
715 generateFunctionParamterMap(o
, options
, manager
, reader
, generated
, bFirst
);
722 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */