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: registercomponent.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
37 #include <rtl/strbuf.hxx>
38 #include <rtl/ustrbuf.hxx>
40 #include <cppuhelper/servicefactory.hxx>
41 #include <cppuhelper/shlib.hxx>
43 #include <com/sun/star/container/XSet.hpp>
44 #include <com/sun/star/container/XContentEnumerationAccess.hpp>
45 #include <com/sun/star/registry/XImplementationRegistration2.hpp>
46 #include <com/sun/star/registry/XSimpleRegistry.hpp>
47 #include <com/sun/star/lang/XComponent.hpp>
50 #include <osl/process.h>
51 #include <osl/diagnose.h>
52 #include <osl/thread.h>
53 #include <osl/file.hxx>
58 #define SEPARATOR '\\'
61 using namespace ::rtl
;
62 using namespace ::osl
;
63 using namespace ::cppu
;
64 using namespace ::std
;
65 using namespace ::com::sun::star::uno
;
66 using namespace ::com::sun::star::lang
;
67 using namespace ::com::sun::star::registry
;
68 using com::sun::star::container::XSet
;
69 using com::sun::star::container::XContentEnumerationAccess
;
70 using com::sun::star::container::XEnumeration
;
73 #define putenv _putenv
78 OUString
replacePrefix(OUString
const & url
, OUString
const & prefix
) {
79 sal_Int32 i
= url
.lastIndexOf('/');
80 // Backward compatibility with stoc/source/implementationregistration/
81 // implreg.cxx:1.27 l. 1892:
83 i
= url
.lastIndexOf('\\');
85 return prefix
+ url
.copy(i
+ 1);
90 sal_Bool
isFileUrl(const OUString
& fileName
)
92 if (fileName
.indexOf(OUString::createFromAscii("file://")) == 0 )
97 OUString
convertToFileUrl(const OUString
& fileName
)
99 if ( isFileUrl(fileName
) )
104 OUString uUrlFileName
;
105 if ( fileName
.indexOf('.') == 0 || fileName
.indexOf(SEPARATOR
) < 0 )
107 OUString uWorkingDir
;
108 if (osl_getProcessWorkingDir(&uWorkingDir
.pData
) != osl_Process_E_None
) {
111 if (FileBase::getAbsoluteFileURL(uWorkingDir
, fileName
, uUrlFileName
)
118 if (FileBase::getFileURLFromSystemPath(fileName
, uUrlFileName
)
127 static void usingRegisterImpl()
129 fprintf(stderr
, "usage: regcomp -register|revoke -r registryfile -c locationUrl [-br registryfile] [-l componentLoaderUrl] [-s] [-classpath path]\n");
130 fprintf(stderr
, " Parameters:\n");
131 fprintf(stderr
, " -register\n"
132 " register a new component.\n");
133 fprintf(stderr
, " -revoke\n"
134 " revoke a component.\n");
135 fprintf(stderr
, " -br registryfile\n"
136 " the name of the registry used for bootstrapping\n"
137 " regcomp. The option can be given twice, each\n"
138 " one followed by exactly one registry file.\n"
139 " The registries are used to access both types and\n"
140 " registered components.\n");
141 fprintf(stderr
, " -r registryfile\n"
142 " the name of the target registry (will be created\n"
143 " if it does not exists). The file name may match\n"
144 " with one of the filenames given with the -br option.\n");
145 fprintf(stderr
, " -c locationUrls\n"
146 " the location of a component (a url to a shared\n"
147 " library or a absolute url to a .jar file) or a\n"
148 " list of urls seperated by ';' or ' '. Note if a\n"
149 " list of urls is specified, the components must\n"
150 " all need the same loader (quoting is possible with\n"
152 fprintf(stderr
, " -l componentLoaderUrl\n"
153 " the name of the needed loader. If no loader is\n"
154 " specified and the components have a .jar suffix,\n"
155 " the default is com.sun.star.loader.Java2.\n"
156 " Otherwise, the default is\n"
157 " com.sun.star.loader.SharedLibrary\n"
159 " silent, regcomp prints messages only on error.\n"
161 " register the component name only without path\n"
163 " register the component name with path replaced\n"
166 " sets the java classpath to path (overwriting the\n"
167 " current classpath environment variable). Note that\n"
168 " in case you start regcomp e.g. within an office\n"
169 " environment, the classpath entries in the\n"
170 " configuration still have precedence over this\n"
174 class IllegalArgument
177 IllegalArgument(const OString
& rMessage
)
178 : m_message(rMessage
)
187 : bRegister(sal_False
)
189 , bSilent( sal_False
)
190 , bPrefix( sal_False
)
198 OUString sProgramName
;
199 OUString sBootRegName
;
200 OUString sBootRegName2
;
202 OUString sComponentUrls
;
203 OUString sLoaderName
;
206 sal_Bool
parseOptions(int ac
, char* av
[], Options
& rOptions
, sal_Bool bCmdFile
)
207 throw( IllegalArgument
)
209 sal_Bool ret
= sal_True
;
211 sal_Bool bLoaderExplicitlyGiven
= sal_False
;
213 rOptions
.sProgramName
= OUString::createFromAscii(av
[i
++]);
233 if (strcmp(av
[i
], "-register") == 0)
235 rOptions
.bRegister
= sal_True
;
237 if (strcmp(av
[i
], "-revoke") == 0)
239 rOptions
.bRevoke
= sal_True
;
241 if (av
[i
][2] == '\0')
243 if (i
< ac
- 1 && av
[i
+1][0] != '-')
246 rOptions
.sRegName
= OStringToOUString(av
[i
], osl_getThreadTextEncoding());
249 OString
tmp("'-r', please check");
252 tmp
+= " your input '" + OString(av
[i
+1]) + "'";
254 throw IllegalArgument(tmp
);
258 rOptions
.sRegName
= OStringToOUString(av
[i
]+2, osl_getThreadTextEncoding());
264 OString
tmp("'-b', invalid option!");
265 throw IllegalArgument(tmp
);
267 if (av
[i
][3] == '\0')
269 if (i
< ac
- 1 && av
[i
+1][0] != '-')
272 OUString regName
= OStringToOUString(av
[i
], osl_getThreadTextEncoding());
273 if( ! rOptions
.sBootRegName
.getLength() )
275 rOptions
.sBootRegName
= regName
;
279 rOptions
.sBootRegName2
= regName
;
283 OString
tmp("'-br', please check");
286 tmp
+= " your input '" + OString(av
[i
+1]) + "'";
288 throw IllegalArgument(tmp
);
292 rOptions
.sBootRegName
= OStringToOUString(av
[i
]+3, osl_getThreadTextEncoding());
298 if (av
[i
][2] == '\0')
300 if (i
< ac
- 1 && av
[i
+1][0] != '-')
303 sUrls
= OStringToOUString(av
[i
], osl_getThreadTextEncoding());
306 OString
tmp("'-c', please check");
309 tmp
+= " your input '" + OString(av
[i
+1]) + "'";
311 throw IllegalArgument(tmp
);
314 else if( 0 == strncmp( av
[i
] , "-classpath" ,10 ) )
319 // leak this string as some platforms assume to own
321 sal_Char
* p
= (sal_Char
*) rtl_allocateMemory( 13+ strlen( av
[i
] ) );
323 strcat( p
, "CLASSPATH=" ); // #100211# - checked
324 strcat( p
, av
[i
] ); // #100211# - checked
332 sUrls
= OStringToOUString(av
[i
]+2, osl_getThreadTextEncoding());
335 if (rOptions
.sComponentUrls
.getLength())
337 OUString
tmp(rOptions
.sComponentUrls
+ OUString(";", 1, osl_getThreadTextEncoding()) + sUrls
);
338 rOptions
.sComponentUrls
= tmp
;
341 rOptions
.sComponentUrls
= sUrls
;
347 if (av
[i
][2] == '\0')
349 if (i
< ac
- 1 && av
[i
+1][0] != '-')
352 rOptions
.sLoaderName
= OUString::createFromAscii(av
[i
]);
353 bLoaderExplicitlyGiven
= sal_True
;
356 OString
tmp("'-l', please check");
359 tmp
+= " your input '" + OString(av
[i
+1]) + "'";
361 throw IllegalArgument(tmp
);
365 bLoaderExplicitlyGiven
= sal_True
;
366 rOptions
.sLoaderName
= OUString::createFromAscii(av
[i
]+2);
374 rOptions
.bSilent
= sal_True
;
378 rtl::OStringBuffer buf
;
379 buf
.append( "Unknown error " );
381 throw IllegalArgument( av
[i
] );
387 if( av
[i
][2] == 'n' && av
[i
][3] == 'v' && av
[i
][4] == ':' )
389 // bootstrap variable, ignore it
395 if (strcmp(av
[i
], "-wop") == 0)
397 rOptions
.bPrefix
= sal_True
;
398 rOptions
.sPrefix
= OUString();
399 // in case there are multiple -wops
403 strncmp(av
[i
], "-wop=", RTL_CONSTASCII_LENGTH("-wop="))
406 rOptions
.bPrefix
= sal_True
;
407 rOptions
.sPrefix
= OStringToOUString(
408 av
[i
] + RTL_CONSTASCII_LENGTH("-wop="),
409 osl_getThreadTextEncoding());
415 OString
tmp( "unknown option " );
417 throw IllegalArgument( tmp
);
424 FILE* cmdFile
= fopen(av
[i
]+1, "r");
425 if( cmdFile
== NULL
)
431 fseek( cmdFile
, 0 , SEEK_END
);
432 sal_Int32 nLen
= ftell( cmdFile
);
433 fseek( cmdFile
, 0, SEEK_SET
);
435 // 2 chars per string is a upper limit for the number of
436 // substrings ( at least one separator char needed for fscanf).
437 char ** rargv
= (char **)rtl_allocateMemory( nLen
* sizeof( char* ) /2);
441 buf
.append( "Not enough memory for reading command file " );
442 buf
.append( av
[i
] +1 );
443 buf
.append( " with length " );
446 throw IllegalArgument( buf
.makeStringAndClear() );
448 char *buffer
= ( char * )rtl_allocateMemory( nLen
+1 );
452 buf
.append( "Not enough memory for reading command file " );
453 buf
.append( av
[i
] +1 );
454 buf
.append( " with length " );
457 throw IllegalArgument( buf
.makeStringAndClear() );
460 // we start at one to omit argv[0]
463 while ( fscanf(cmdFile
, "%s", buffer
) != EOF
)
465 rargv
[rargc
]= (char * )rtl_allocateMemory( strlen( buffer
) +1 );
469 buf
.append( "Not enough memory for reading command file " );
470 buf
.append( av
[i
] +1 );
471 buf
.append( " with length " );
474 throw IllegalArgument( buf
.makeStringAndClear() );
476 strcpy( rargv
[rargc
] , buffer
); // #100211# - checked
481 parseOptions(rargc
, rargv
, rOptions
, bCmdFile
);
483 for (long j
=1; j
< rargc
; j
++)
485 rtl_freeMemory(rargv
[j
]);
487 rtl_freeMemory( buffer
);
488 rtl_freeMemory( rargv
);
498 if( ! bLoaderExplicitlyGiven
)
500 if ( rOptions
.sComponentUrls
.getLength() > 4 &&
501 rOptions
.sComponentUrls
.matchAsciiL(
502 ".jar" , 4 , rOptions
.sComponentUrls
.getLength() - 4 ) )
504 if( ! rOptions
.bSilent
)
506 printf( "using loader com.sun.star.loader.Java2\n" );
508 rOptions
.sLoaderName
= OUString(
509 RTL_CONSTASCII_USTRINGPARAM("com.sun.star.loader.Java2"));
513 rOptions
.sLoaderName
= OUString(
514 RTL_CONSTASCII_USTRINGPARAM("com.sun.star.loader.SharedLibrary") );
530 OUString _sLoaderName
;
531 Reference
<XImplementationRegistration2
> _xImplRegistration
;
532 Reference
<XSimpleRegistry
> _xReg
;
533 sal_uInt32
* _exitCode
;
535 DoIt(sal_Bool bRegister
,
539 const OUString
& sPrefix
,
540 const Reference
<XSimpleRegistry
> & xReg
,
541 const OString
& sRegName
,
542 const Reference
<XImplementationRegistration2
> & xImplRegistration
,
543 const OUString
& sLoaderName
,
544 sal_uInt32
* exitCode
)
547 void operator()(const OUString
& url
) throw();
550 DoIt::DoIt(sal_Bool bRegister
,
554 const OUString
& sPrefix
,
555 const Reference
<XSimpleRegistry
> & xReg
,
556 const OString
& sRegName
,
557 const Reference
<XImplementationRegistration2
> & xImplRegistration
,
558 const OUString
& sLoaderName
,
559 sal_uInt32
* exitCode
) throw()
560 : _bRegister(bRegister
),
566 _sLoaderName(sLoaderName
),
567 _xImplRegistration(xImplRegistration
),
572 void DoIt::operator() (const OUString
& url
) throw()
574 OString sUrl
= OUStringToOString(url
, osl_getThreadTextEncoding());
580 Reference
<XImplementationRegistration2
> _xImplRegistration2(_xImplRegistration
, UNO_QUERY
);
582 _xImplRegistration
->registerImplementationWithLocation(
583 _sLoaderName
, url
, replacePrefix(url
, _sPrefix
), _xReg
);
585 _xImplRegistration
->registerImplementation(_sLoaderName
, url
, _xReg
);
590 fprintf(stderr
, "register component '%s' in registry '%s' succesful!\n", sUrl
.getStr(), _sRegName
.getStr());
594 catch(CannotRegisterImplementationException
& cannotRegisterImplementationException
) {
595 OString
aMessage(OUStringToOString(cannotRegisterImplementationException
.Message
, RTL_TEXTENCODING_ASCII_US
));
596 fprintf(stderr
, "register component '%s' in registry '%s' failed!\n", sUrl
.getStr(), _sRegName
.getStr());
597 fprintf(stderr
, "error (CannotRegisterImplementationException): %s\n", aMessage
.getStr());
601 catch( RuntimeException
& e
)
603 OString
aMessage(OUStringToOString(e
.Message
, RTL_TEXTENCODING_ASCII_US
));
604 fprintf(stderr
, "register component '%s' in registry '%s' failed!\n", sUrl
.getStr(), _sRegName
.getStr());
605 fprintf(stderr
, "error (RuntimeException): %s\n", aMessage
.getStr());
614 sal_Bool bRet
= _xImplRegistration
->revokeImplementation(url
, _xReg
);
619 fprintf(stderr
, "revoke component '%s' from registry '%s' succesful!\n", sUrl
.getStr(), _sRegName
.getStr());
623 fprintf(stderr
, "revoke component '%s' from registry '%s' failed!\n", sUrl
.getStr(), _sRegName
.getStr());
627 catch( RuntimeException
& e
)
629 OString
aMessage(OUStringToOString(e
.Message
, RTL_TEXTENCODING_ASCII_US
));
631 "revoke component '%s' from registry '%s' failed!\n",
633 _sRegName
.getStr() );
634 fprintf( stderr
, "RuntimeException: %s\n" , aMessage
.getStr());
640 static bool hasService(
641 const Reference
< XMultiServiceFactory
> &xSMgr
,
642 const sal_Char
* service
)
646 Reference
< XContentEnumerationAccess
> access( xSMgr
, UNO_QUERY
);
649 Reference
< XEnumeration
> enumeration
= access
->createContentEnumeration(
650 OUString::createFromAscii( service
) );
652 if( enumeration
.is() && enumeration
->hasMoreElements() )
660 static void bootstrap(
662 Reference
< XMultiServiceFactory
> &xSMgr
,
663 Reference
< XSimpleRegistry
> & reg
) throw ( Exception
)
665 if( opt
.sRegName
.equals( opt
.sBootRegName2
) )
667 OUString tmp2
= opt
.sBootRegName
;
668 opt
.sBootRegName
= opt
.sBootRegName2
;
669 opt
.sBootRegName2
= tmp2
;
672 if ( opt
.sRegName
.equals(opt
.sBootRegName
) )
674 if( opt
.sBootRegName2
.getLength() )
676 xSMgr
= createRegistryServiceFactory(
677 convertToFileUrl(opt
.sRegName
),
678 convertToFileUrl(opt
.sBootRegName2
),
683 xSMgr
= createRegistryServiceFactory(
684 convertToFileUrl(opt
.sRegName
) , sal_False
);
689 if( opt
.sBootRegName2
.getLength() )
691 xSMgr
= createRegistryServiceFactory(
692 convertToFileUrl( opt
.sBootRegName2
),
693 convertToFileUrl( opt
.sBootRegName
),
696 else if ( opt
.sBootRegName
.getLength() )
698 xSMgr
= createRegistryServiceFactory(
699 convertToFileUrl( opt
.sBootRegName
),
704 xSMgr
= createServiceFactory();
706 reg
= Reference
< XSimpleRegistry
>(
707 xSMgr
->createInstance(
708 rtl::OUString::createFromAscii("com.sun.star.registry.SimpleRegistry")), UNO_QUERY
);
714 reg
->open( convertToFileUrl(opt
.sRegName
), sal_False
, sal_True
);
717 fprintf(stderr
, "ERROR: open|create registry '%s' failed!\n",
718 OUStringToOString(opt
.sRegName
, osl_getThreadTextEncoding() ).getStr());
722 catch( InvalidRegistryException
& e
)
724 OString o
= OUStringToOString( e
.Message
, RTL_TEXTENCODING_ASCII_US
);
726 "ERROR: create registry '%s' failed!\n"
727 "InvalidRegistryException: %s\n",
728 OUStringToOString( opt
.sRegName
, osl_getThreadTextEncoding()).getStr(),
735 if( ! opt
.sLoaderName
.compareToAscii( "com.sun.star.loader.Java2" ) &&
736 ! hasService( xSMgr
, "com.sun.star.loader.Java2" ) )
738 // we know our java loader, so we check, whether a java-loader is
740 Reference
< XInterface
> r
= loadSharedLibComponentFactory(
741 OUString::createFromAscii( "javavm.uno" SAL_DLLEXTENSION
),
743 OUString::createFromAscii( "com.sun.star.comp.stoc.JavaVirtualMachine" ),
745 Reference
< XRegistryKey
> () );
746 Reference
< XInterface
> r2
= loadSharedLibComponentFactory(
747 OUString::createFromAscii( "javaloader.uno" SAL_DLLEXTENSION
),
749 OUString::createFromAscii(( "com.sun.star.comp.stoc.JavaComponentLoader" ) ),
751 Reference
< XRegistryKey
> () );
752 Reference
<XSet
> xSet( xSMgr
, UNO_QUERY
);
753 if( r
.is() && r2
.is() && xSet
.is() )
755 xSet
->insert( makeAny( r
) );
756 xSet
->insert( makeAny( r2
) );
761 SAL_IMPLEMENT_MAIN_WITH_ARGS(argc
, argv
)
763 sal_Bool bRet
= sal_False
;
764 sal_uInt32 exitCode
= 0;
769 if ( !parseOptions(argc
, argv
, aOptions
, sal_False
) )
774 catch ( IllegalArgument
& e
)
776 fprintf(stderr
, "ERROR: %s\n", e
.m_message
.getStr());
780 if( ! aOptions
.sRegName
.getLength() )
782 fprintf( stderr
, "ERROR: target registry missing (-r option)\n" );
785 if ( aOptions
.sComponentUrls
.getLength() == 0 )
787 fprintf(stderr
, "ERROR: no component url is specified!\n");
791 Reference
< XMultiServiceFactory
> xSMgr
;
792 Reference
< XSimpleRegistry
> xReg
;
795 bootstrap( aOptions
, xSMgr
,xReg
);
797 catch( Exception
& e
)
799 fprintf(stderr
, "ERROR: create ServiceManager failed!\n");
800 if ( e
.Message
.getLength() )
802 fprintf(stderr
, "ERROR description: %s\n",
803 OUStringToOString(e
.Message
, osl_getThreadTextEncoding()).getStr());
808 Reference
<XImplementationRegistration2
> xImplRegistration(
809 xSMgr
->createInstance(
810 OUString(RTL_CONSTASCII_USTRINGPARAM(
811 "com.sun.star.registry.ImplementationRegistration"))),
814 if (xImplRegistration
.is())
817 vector
<OUString
> urls
;
819 OUString urlListWithSemikolon
= aOptions
.sComponentUrls
;
821 OUString aToken
= urlListWithSemikolon
.getToken( 0, ';', index
);
822 fprintf(stderr
, "%s\n", OUStringToOString(aToken
, osl_getThreadTextEncoding()).getStr());
823 urls
.push_back(aToken
);
824 } while ( index
>= 0 );
827 OString sRegName
= OUStringToOString( aOptions
.sRegName
, osl_getThreadTextEncoding() );
828 if(aOptions
.bRegister
|| aOptions
.bRevoke
)
830 for_each(urls
.begin(), urls
.end(),
831 DoIt(aOptions
.bRegister
, aOptions
.bRevoke
, aOptions
.bSilent
,
832 aOptions
.bPrefix
, aOptions
.sPrefix
,
833 xReg
, sRegName
, xImplRegistration
,
834 aOptions
.sLoaderName
, &exitCode
));
844 fprintf(stderr
, "Component registration service could not be loaded!\n");
848 if (!bRet
&& xReg
.is() && xReg
->isValid())
851 Reference
< XComponent
> xComponent( xSMgr
, UNO_QUERY
);
852 if ( xComponent
.is() )
853 xComponent
->dispose();