1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: skeletoncommon.cxx,v $
13 * This file is part of OpenOffice.org.
15 * OpenOffice.org is free software: you can redistribute it and/or modify
16 * it under the terms of the GNU Lesser General Public License version 3
17 * only, as published by the Free Software Foundation.
19 * OpenOffice.org is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU Lesser General Public License version 3 for more details
23 * (a copy is included in the LICENSE file that accompanied this code).
25 * You should have received a copy of the GNU Lesser General Public License
26 * version 3 along with OpenOffice.org. If not, see
27 * <http://www.openoffice.org/license.html>
28 * for a copy of the LGPLv3 License.
30 ************************************************************************/
32 #include "osl/thread.hxx"
34 #include "codemaker/commonjava.hxx"
35 #include "codemaker/commoncpp.hxx"
36 #include "codemaker/generatedtypeset.hxx"
38 #include "skeletoncommon.hxx"
42 using namespace ::rtl
;
43 using namespace ::codemaker::cpp
;
45 namespace skeletonmaker
{
47 void printLicenseHeader(std::ostream
& o
, rtl::OString
const & filename
)
51 index
= filename
.lastIndexOf('/');
53 index
= filename
.lastIndexOf('\\');
55 OString
shortfilename(filename
);
57 shortfilename
= filename
.copy(index
+1);
59 o
<< "/*************************************************************************\n"
61 " * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.\n"
63 " * Copyright 2008 by Sun Microsystems, Inc.\n"
65 " * OpenOffice.org - a multi-platform office productivity suite\n"
71 " * $Revision: 1.7 $\n"
73 " * This file is part of OpenOffice.org.\n"
75 " * OpenOffice.org is free software: you can redistribute it and/or modify\n"
76 " * it under the terms of the GNU Lesser General Public License version 3\n"
77 " * only, as published by the Free Software Foundation.\n"
79 " * OpenOffice.org is distributed in the hope that it will be useful,\n"
80 " * but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
81 " * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
82 " * GNU Lesser General Public License version 3 for more details\n"
83 " * (a copy is included in the LICENSE file that accompanied this code).\n"
85 " * You should have received a copy of the GNU Lesser General Public License\n"
86 " * version 3 along with OpenOffice.org. If not, see\n"
87 " * <http://www.openoffice.org/license.html>\n"
88 " * for a copy of the LGPLv3 License.\n"
90 " ************************************************************************/\n\n";
93 bool getOutputStream(ProgramOptions
const & options
,
94 OString
const & extension
,
95 std::ostream
** ppOutputStream
,
96 OString
& targetSourceFileName
,
97 OString
& tmpSourceFileName
)
99 bool bStandardout
= false;
100 if ( options
.outputpath
.equals("stdout") )
103 *ppOutputStream
= &std::cout
;
107 targetSourceFileName
= createFileNameFromType(
108 options
.outputpath
, options
.implname
.replace('.','/'), extension
);
110 OString tmpDir
= getTempDir(targetSourceFileName
);
112 file
.createTempFile(tmpDir
);
114 if( !file
.isValid() )
116 OString
message("cannot open ");
117 message
+= targetSourceFileName
+ " for writing";
118 throw CannotDumpException(message
);
120 tmpSourceFileName
= file
.getName();
123 *ppOutputStream
= new std::ofstream(tmpSourceFileName
.getStr(),
124 std::ios_base::binary
);
129 codemaker::UnoType::Sort
decomposeResolveAndCheck(
130 TypeManager
const & manager
, OString
const & type
,
131 bool resolveTypedefs
, bool allowVoid
, bool allowExtraEntities
,
132 RTTypeClass
* typeClass
, OString
* name
, sal_Int32
* rank
,
133 std::vector
< OString
> * arguments
)
135 codemaker::UnoType::Sort sort
= codemaker::decomposeAndResolve(
136 manager
, type
, resolveTypedefs
, allowVoid
, allowExtraEntities
,
137 typeClass
, name
, rank
, arguments
);
138 for ( std::vector
< OString
>::iterator
i(arguments
->begin());
139 i
!= arguments
->end(); ++i
)
141 RTTypeClass typeClass2
;
144 std::vector
< OString
> arguments2
;
145 decomposeResolveAndCheck(
146 manager
, *i
, true, false, false, &typeClass2
, &name2
, &rank2
,
152 bool containsAttribute(AttributeInfo
& attributes
, OString
const & attrname
)
154 for ( AttributeInfo::const_iterator
i(attributes
.begin());
155 i
!= attributes
.end(); ++i
) {
156 if ( (*i
).first
== attrname
) {
163 // collect attributes including inherited attributes
164 void checkAttributes(TypeManager
const & manager
,
165 const typereg::Reader
& reader
,
166 AttributeInfo
& attributes
,
167 std::hash_set
< OString
, OStringHash
>& propinterfaces
)
169 OString typeName
= codemaker::convertString(reader
.getTypeName());
170 if ( typeName
.equals("com/sun/star/beans/XPropertySet") ||
171 typeName
.equals("com/sun/star/beans/XFastPropertySet") ||
172 // typeName.equals("com/sun/star/beans/XMultiPropertySet") ||
173 typeName
.equals("com/sun/star/beans/XPropertyAccess") )
175 propinterfaces
.insert(typeName
);
178 for ( sal_uInt16 i
= 0; i
< reader
.getSuperTypeCount(); ++i
) {
179 typereg::Reader
supertype(manager
.getTypeReader(
180 codemaker::convertString(
181 reader
.getSuperTypeName(i
))));
182 if ( !supertype
.isValid() ) {
183 throw CannotDumpException(
184 "Bad type library entity "
185 + codemaker::convertString(reader
.getSuperTypeName(i
)));
187 checkAttributes(manager
, supertype
, attributes
, propinterfaces
);
190 for ( sal_uInt16 i
= 0; i
< reader
.getFieldCount(); ++i
) {
192 codemaker::convertString(reader
.getFieldName(i
)).
195 if ( !containsAttribute(attributes
, fieldName
) ) {
197 codemaker::convertString(reader
.getFieldTypeName(i
)).
199 attributes
.push_back(AttributeInfo::value_type(
200 fieldName
, std::pair
<OString
, sal_Int16
>(
201 fieldType
, reader
.getFieldFlags(i
))));
206 void checkType(TypeManager
const & manager
,
207 OString
const & type
,
208 std::hash_set
< OString
, OStringHash
>& interfaceTypes
,
209 std::hash_set
< OString
, OStringHash
>& serviceTypes
,
210 AttributeInfo
& properties
)
213 OString
binType(type
.replace('.', '/'));
214 typereg::Reader
reader(manager
.getTypeReader(binType
));
215 if ( !reader
.isValid() ) {
216 throw CannotDumpException("Bad type library entity " + binType
);
219 switch ( reader
.getTypeClass() )
221 case RT_TYPE_INTERFACE
:
223 // com/sun/star/lang/XComponent should be also not in the list
224 // but it will be used for checking the impl helper and will be
225 // removed later if necessary.
226 if ( binType
.equals("com/sun/star/lang/XTypeProvider") ||
227 binType
.equals("com/sun/star/uno/XWeak") )
229 if (interfaceTypes
.find(type
) == interfaceTypes
.end()) {
230 interfaceTypes
.insert(type
);
234 case RT_TYPE_SERVICE
:
235 if ( serviceTypes
.find(binType
) == serviceTypes
.end() ) {
236 serviceTypes
.insert(binType
);
238 if ( reader
.getSuperTypeCount() > 0 ) {
239 OString
supername(codemaker::convertString(
240 reader
.getSuperTypeName(0).replace('/', '.')));
241 if ( interfaceTypes
.find(supername
) == interfaceTypes
.end() ) {
242 interfaceTypes
.insert(supername
);
244 typereg::Reader
supertype(manager
.getTypeReader(
245 codemaker::convertString(
246 reader
.getSuperTypeName(0))));
247 if ( !supertype
.isValid() ) {
248 throw CannotDumpException(
249 "Bad type library entity "
250 + codemaker::convertString(reader
.getSuperTypeName(0)));
254 // check if constructors are specified, if yes automatically
255 // support of XInitialization. We will take care of the default
256 // constructor because in this case XInitialization is not called.
257 if ( reader
.getMethodCount() > 1 ||
258 ( reader
.getMethodCount() == 1 &&
259 reader
.getMethodName(0).getLength() > 0 ) )
261 OString
s("com.sun.star.lang.XInitialization");
262 if ( interfaceTypes
.find(s
) == interfaceTypes
.end() )
263 interfaceTypes
.insert(s
);
266 for ( sal_uInt16 i
= 0; i
< reader
.getReferenceCount(); ++i
) {
267 OString
referenceType(
268 codemaker::convertString(
269 reader
.getReferenceTypeName(i
)).replace('/', '.'));
271 if ( reader
.getReferenceSort(i
) == RT_REF_SUPPORTS
) {
272 checkType(manager
, referenceType
, interfaceTypes
,
273 serviceTypes
, properties
);
274 } else if ( reader
.getReferenceSort(i
) == RT_REF_EXPORTS
) {
275 checkType(manager
, referenceType
, interfaceTypes
,
276 serviceTypes
, properties
);
280 for ( sal_uInt16 i
= 0; i
< reader
.getFieldCount(); ++i
) {
282 codemaker::convertString(reader
.getFieldName(i
)).
285 codemaker::convertString(reader
.getFieldTypeName(i
)).
288 properties
.push_back(AttributeInfo::value_type(
289 fieldName
, std::pair
<OString
, sal_Int16
>(
290 fieldType
, reader
.getFieldFlags(i
))));
301 void checkDefaultInterfaces(
302 std::hash_set
< OString
, OStringHash
>& interfaces
,
303 const std::hash_set
< OString
, OStringHash
>& services
,
304 const OString
& propertyhelper
)
306 if ( services
.empty() ) {
307 if (interfaces
.find("com.sun.star.lang.XServiceInfo") != interfaces
.end())
308 interfaces
.erase("com.sun.star.lang.XServiceInfo");
310 if (interfaces
.find("com.sun.star.lang.XServiceInfo") == interfaces
.end())
311 interfaces
.insert("com.sun.star.lang.XServiceInfo");
314 if ( propertyhelper
.equals("_") ) {
315 if (interfaces
.find("com.sun.star.beans.XPropertySet")
317 interfaces
.erase("com.sun.star.beans.XPropertySet");
318 if (interfaces
.find("com.sun.star.beans.XFastPropertySet")
320 interfaces
.erase("com.sun.star.beans.XFastPropertySet");
321 if (interfaces
.find("com.sun.star.beans.XPropertyAccess")
323 interfaces
.erase("com.sun.star.beans.XPropertyAccess");
327 bool checkServiceProperties(TypeManager
const & manager
,
328 const typereg::Reader
& reader
)
330 if ( reader
.getFieldCount() > 0 )
333 if ( reader
.getReferenceCount() > 0 ) {
334 for ( sal_uInt16 i
= 0; i
< reader
.getReferenceCount(); ++i
) {
335 if ( reader
.getReferenceSort(i
) == RT_REF_EXPORTS
) {
336 typereg::Reader
refreader(
337 manager
.getTypeReader(
338 codemaker::convertString(reader
.getReferenceTypeName(i
))));
340 if ( checkServiceProperties(manager
, refreader
) )
349 OString
checkPropertyHelper(
350 ProgramOptions
const & options
,
351 TypeManager
const & manager
,
352 const std::hash_set
< OString
, OStringHash
>& services
,
353 const std::hash_set
< OString
, OStringHash
>& interfaces
,
354 AttributeInfo
& attributes
,
355 std::hash_set
< OString
, OStringHash
>& propinterfaces
)
357 std::hash_set
< OString
, OStringHash
>::const_iterator iter
;
358 std::hash_set
< OString
, OStringHash
>::const_iterator end
;
360 if ( !services
.empty() ) {
361 iter
= services
.begin();
362 end
= services
.end();
364 iter
= interfaces
.begin();
365 end
= interfaces
.end();
368 bool oldStyleWithProperties
= false;
369 while ( iter
!= end
) {
370 typereg::Reader
reader(manager
.getTypeReader((*iter
).replace('.', '/')));
372 if ( !services
.empty() ) {
373 if ( options
.supportpropertysetmixin
&& reader
.getSuperTypeCount() > 0 )
375 typereg::Reader
supertype(
376 manager
.getTypeReader(
377 codemaker::convertString(
378 reader
.getSuperTypeName(0))));
379 if ( !supertype
.isValid() ) {
380 throw CannotDumpException(
381 "Bad type library entity "
382 + codemaker::convertString(
383 reader
.getSuperTypeName(0)));
386 checkAttributes(manager
, supertype
, attributes
, propinterfaces
);
388 if ( !(attributes
.empty() || propinterfaces
.empty()) ) {
389 return OUStringToOString(
390 supertype
.getTypeName().replace('/', '.'),
391 osl_getThreadTextEncoding());
394 oldStyleWithProperties
= checkServiceProperties(manager
, reader
);
397 checkAttributes(manager
, reader
, attributes
, propinterfaces
);
398 if ( !(attributes
.empty() || propinterfaces
.empty()) ) {
399 return OUStringToOString(
400 reader
.getTypeName().replace('/', '.'),
401 osl_getThreadTextEncoding());
407 return (oldStyleWithProperties
? "_" : "");
410 bool checkXComponentSupport(TypeManager
const & manager
,
411 typereg::Reader
const & reader
)
413 static OUString
s(RTL_CONSTASCII_USTRINGPARAM(
414 "com/sun/star/lang/XComponent"));
415 if ( reader
.getTypeName().equals(s
) )
418 for ( sal_uInt16 i
= 0; i
< reader
.getSuperTypeCount(); ++i
) {
419 typereg::Reader
super(
420 manager
.getTypeReader(
421 codemaker::convertString(
422 reader
.getSuperTypeName(i
))));
423 if ( !super
.isValid() ) {
424 throw CannotDumpException(
425 "Bad type library entity "
426 + codemaker::convertString(
427 reader
.getSuperTypeName(i
)));
429 if ( checkXComponentSupport(manager
, super
) )
437 // if XComponent is directly specified, return true and remove it from the
438 // supported interfaces list
439 bool checkXComponentSupport(TypeManager
const & manager
,
440 std::hash_set
< OString
, OStringHash
>& interfaces
)
442 if ( interfaces
.empty() )
445 std::hash_set
< OString
, OStringHash
>::const_iterator iter
=
447 while ( iter
!= interfaces
.end() ) {
448 if ( (*iter
).equals("com.sun.star.lang.XComponent") ) {
449 interfaces
.erase("com.sun.star.lang.XComponent");
452 typereg::Reader
reader(manager
.getTypeReader((*iter
).replace('.', '/')));
453 if ( checkXComponentSupport(manager
, reader
) )
461 sal_uInt16
checkAdditionalPropertyFlags(typereg::Reader
const & reader
,
462 sal_uInt16 field
, sal_uInt16 method
)
464 sal_uInt16 flags
= 0;
465 bool getterSupportsUnknown
= false;
467 OUString
su(RTL_CONSTASCII_USTRINGPARAM(
468 "com/sun/star/beans/UnknownPropertyException"));
469 if ( method
< reader
.getMethodCount()
470 && reader
.getMethodFlags(method
) == RT_MODE_ATTRIBUTE_GET
471 && reader
.getMethodName(method
) == reader
.getFieldName(field
) )
473 if ( reader
.getMethodExceptionCount(method
) > 0 ) {
474 for ( sal_uInt16 i
= 0; i
< reader
.getMethodExceptionCount(method
);
477 if (su
.equals(reader
.getMethodExceptionTypeName(method
, i
)))
478 getterSupportsUnknown
= true;
483 if ( method
< reader
.getMethodCount()
484 && reader
.getMethodFlags(method
) == RT_MODE_ATTRIBUTE_SET
485 && reader
.getMethodName(method
) == reader
.getFieldName(field
) )
487 if ( reader
.getMethodExceptionCount(method
) > 0 ) {
488 OUString
s(RTL_CONSTASCII_USTRINGPARAM(
489 "com/sun/star/beans/PropertyVetoException"));
490 for ( sal_uInt16 i
= 0; i
< reader
.getMethodExceptionCount(method
);
493 if ( s
.equals(reader
.getMethodExceptionTypeName(method
, i
)) )
494 flags
|= RT_ACCESS_CONSTRAINED
;
495 if ( getterSupportsUnknown
&&
496 su
.equals(reader
.getMethodExceptionTypeName(method
, i
)) )
497 flags
|= RT_ACCESS_OPTIONAL
;
504 // This function checks if the specified types for paramters and return
505 // types are allowed add-in types, for more info see the com.sun.star.sheet.AddIn
506 // service description
507 bool checkAddinType(TypeManager
const & manager
,
508 OString
const & type
, bool & bLastAny
,
509 bool & bHasXPropertySet
, bool bIsReturn
)
511 RTTypeClass typeClass
;
514 std::vector
< OString
> arguments
;
515 codemaker::UnoType::Sort sort
= codemaker::decomposeAndResolve(
516 manager
, type
, true, true, true, &typeClass
, &name
, &rank
, &arguments
);
518 if ( sort
== codemaker::UnoType::SORT_LONG
||
519 sort
== codemaker::UnoType::SORT_DOUBLE
||
520 sort
== codemaker::UnoType::SORT_STRING
)
522 if ( rank
== 0 || rank
==2 )
525 if ( sort
== codemaker::UnoType::SORT_ANY
)
537 if ( sort
== codemaker::UnoType::SORT_COMPLEX
&&
538 typeClass
== RT_TYPE_INTERFACE
)
540 if ( bIsReturn
&& type
.equals("com/sun/star/sheet/XVolatileResult") )
542 if ( !bIsReturn
&& type
.equals("com/sun/star/table/XCellRange") )
544 if ( !bIsReturn
&& type
.equals("com/sun/star/beans/XPropertySet") )
546 if ( bHasXPropertySet
) {
549 bHasXPropertySet
= true;
557 void checkAddInTypes(TypeManager
const & manager
,
558 typereg::Reader
const & reader
)
560 OString
sType(codemaker::convertString(reader
.getTypeName()).replace('/', '.'));
561 bool bLastAny
= false;
562 bool bHasXPropertySet
= false;
563 for ( sal_uInt16 m
= 0; m
< reader
.getMethodCount(); ++m
) {
564 OString
sMethod(codemaker::convertString(reader
.getMethodName(m
)));
566 OString
sReturnType(codemaker::convertString(
567 reader
.getMethodReturnTypeName(m
)));
568 if ( !checkAddinType(
569 manager
, sReturnType
, bLastAny
, bHasXPropertySet
, true) )
571 OStringBuffer
msg("the return type of the calc add-in function '");
575 msg
.append("' is invalid. Please check your IDL defintion.");
576 throw CannotDumpException(msg
.makeStringAndClear());
579 bHasXPropertySet
= false;
580 for ( sal_uInt16 p
= 0; p
< reader
.getMethodParameterCount(m
); ++p
) {
582 OString
sParamType(codemaker::convertString(
583 reader
.getMethodParameterTypeName(m
, p
)));
584 if ( !checkAddinType(manager
, sParamType
,
585 bLastAny
, bHasXPropertySet
, false) ||
588 OStringBuffer
msg("the type of the ");
589 msg
.append((sal_Int32
)p
+1);
590 msg
.append(". parameter of the calc add-in function '");
594 msg
.append("' is invalid.");
596 msg
.append(" The type 'sequence<any>' is allowed as last "
598 if ( bHasXPropertySet
)
599 msg
.append(" The type 'XPropertySet' is allowed only once.");
601 msg
.append(" Please check your IDL definition.");
602 throw CannotDumpException(msg
.makeStringAndClear());
608 void generateFunctionParamterMap(std::ostream
& o
,
609 ProgramOptions
const & options
,
610 TypeManager
const & manager
,
611 typereg::Reader
const & reader
,
612 ::codemaker::GeneratedTypeSet
& generated
,
615 OString
sType(codemaker::convertString(reader
.getTypeName()));
616 if ( sType
.equals("com/sun/star/uno/XInterface") ||
617 sType
.equals("com/sun/star/lang/XLocalizable") ||
618 sType
.equals("com/sun/star/lang/XServiceInfo") ||
619 // the next three checks becomes obsolete when configuration is used
620 sType
.equals("com/sun/star/sheet/XAddIn") ||
621 sType
.equals("com/sun/star/sheet/XCompatibilityNames") ||
622 sType
.equals("com/sun/star/lang/XServiceName") )
627 // check if the specified add-in functions supports valid types
628 checkAddInTypes(manager
, reader
);
630 for ( sal_uInt16 i
= 0; i
< reader
.getSuperTypeCount(); ++i
) {
631 typereg::Reader
super(
632 manager
.getTypeReader(
633 codemaker::convertString(
634 reader
.getSuperTypeName(i
))));
635 if ( !super
.isValid() ) {
636 throw CannotDumpException(
637 "Bad type library entity "
638 + codemaker::convertString(
639 reader
.getSuperTypeName(i
)));
641 generateFunctionParamterMap(o
, options
, manager
, super
, generated
, bFirst
);
644 OString
type(codemaker::convertString(reader
.getTypeName()));
645 if ( generated
.contains(type
) )
650 for ( sal_uInt16 m
= 0; m
< reader
.getMethodCount(); ++m
) {
651 OString
sMethod(codemaker::convertString(reader
.getMethodName(m
)));
654 if (options
.language
== 2) {
655 o
<< " ParamMap fpm;\n";
659 o
<< " java.util.Hashtable< Integer, String > fpm = "
660 "new java.util.Hashtable< Integer, String >();\n";
662 o
<< " java.util.Hashtable fpm = "
663 "new java.util.Hashtable();\n";
667 if ( options
.language
== 2 ) {
668 o
<< " fpm = ParamMap();\n";
672 o
<< " fpm = new java.util.Hashtable< "
673 "Integer, String >();\n";
675 o
<< " fpm = new java.util.Hashtable();\n";
678 for ( sal_uInt16 p
= 0; p
< reader
.getMethodParameterCount(m
); ++p
) {
679 if ( options
.language
== 2 ) {
681 << "] = ::rtl::OUString::createFromAscii(\""
682 << codemaker::convertString(reader
.getMethodParameterName(m
, p
))
687 o
<< " fpm.put(" << p
<< ", \""
688 << codemaker::convertString(
689 reader
.getMethodParameterName(m
, p
))
692 o
<< " fpm.put(new Integer(" << p
<< "), \""
693 << codemaker::convertString(
694 reader
.getMethodParameterName(m
, p
))
699 if ( options
.language
== 2 ) {
700 o
<< " m_functionMap[::rtl::OUString::createFromAscii(\""
701 << sMethod
<< "\")] = fpm;\n\n";
704 o
<< " m_functionMap.put(\"" << sMethod
<< "\", fpm);\n\n";
709 void generateFunctionParameterMap(std::ostream
& o
,
710 ProgramOptions
const & options
,
711 TypeManager
const & manager
,
712 const std::hash_set
< OString
, OStringHash
>& interfaces
)
714 ::codemaker::GeneratedTypeSet generated
;
716 std::hash_set
< OString
, OStringHash
>::const_iterator iter
= interfaces
.begin();
717 while ( iter
!= interfaces
.end() ) {
718 typereg::Reader
reader(manager
.getTypeReader((*iter
).replace('.','/')));
719 if (!reader
.isValid()) {
720 throw CannotDumpException(
721 "Bad type library entity "
722 + codemaker::convertString(
723 reader
.getTypeName()));
726 generateFunctionParamterMap(o
, options
, manager
, reader
, generated
, bFirst
);