1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_desktop.hxx"
30 #include "dp_sfwk.hrc"
31 #include "dp_backend.h"
32 #include "dp_ucb.h"
33 #include "dp_parceldesc.hxx"
34 #include "rtl/uri.hxx"
35 #include "ucbhelper/content.hxx"
36 #include "cppuhelper/exc_hlp.hxx"
37 #include "comphelper/servicedecl.hxx"
38 #include "svl/inettype.hxx"
39 #include <com/sun/star/container/XNameContainer.hpp>
40 #include <com/sun/star/script/provider/XScriptProviderFactory.hpp>
41 #include <memory>
42 
43 
44 using namespace ::dp_misc;
45 using namespace ::com::sun::star;
46 using namespace ::com::sun::star::uno;
47 using namespace ::com::sun::star::ucb;
48 using namespace ::com::sun::star::script;
49 
50 using ::rtl::OUString;
51 namespace css = ::com::sun::star;
52 
53 namespace dp_registry
54 {
55 namespace backend
56 {
57 namespace sfwk
58 {
59 
60 //==============================================================================
61 class BackendImpl : public ::dp_registry::backend::PackageRegistryBackend
62 {
63     class PackageImpl : public ::dp_registry::backend::Package
64     {
65         BackendImpl * getMyBackend() const;
66 
67         Reference< container::XNameContainer > m_xNameCntrPkgHandler;
68         OUString m_descr;
69 
70         void initPackageHandler();
71 
72         // Package
73         virtual beans::Optional< beans::Ambiguous<sal_Bool> > isRegistered_(
74             ::osl::ResettableMutexGuard & guard,
75             ::rtl::Reference<AbortChannel> const & abortChannel,
76             Reference<XCommandEnvironment> const & xCmdEnv );
77         virtual void processPackage_(
78             ::osl::ResettableMutexGuard & guard,
79             bool registerPackage,
80             bool startup,
81             ::rtl::Reference<AbortChannel> const & abortChannel,
82             Reference<XCommandEnvironment> const & xCmdEnv );
83 
84     public:
85         PackageImpl(
86             ::rtl::Reference<BackendImpl> const & myBackend,
87             OUString const & url, OUString const & libType, bool bRemoved,
88             OUString const & identifier);
89         // XPackage
90         virtual OUString SAL_CALL getDescription() throw (RuntimeException);
91         virtual OUString SAL_CALL getLicenseText() throw (RuntimeException);
92     };
93     friend class PackageImpl;
94 
95     // PackageRegistryBackend
96     virtual Reference<deployment::XPackage> bindPackage_(
97         OUString const & url, OUString const & mediaType,
98         sal_Bool bRemoved, OUString const & identifier,
99         Reference<XCommandEnvironment> const & xCmdEnv );
100 
101     const Reference<deployment::XPackageTypeInfo> m_xTypeInfo;
102 
103 
104 public:
105     BackendImpl(
106         Sequence<Any> const & args,
107         Reference<XComponentContext> const & xComponentContext );
108 
109     // XPackageRegistry
110     virtual Sequence< Reference<deployment::XPackageTypeInfo> > SAL_CALL
111     getSupportedPackageTypes() throw (RuntimeException);
112     virtual void SAL_CALL packageRemoved(OUString const & url, OUString const & mediaType)
113         throw (deployment::DeploymentException,
114                uno::RuntimeException);
115 };
116 
117 BackendImpl * BackendImpl::PackageImpl::getMyBackend() const
118 {
119     BackendImpl * pBackend = static_cast<BackendImpl *>(m_myBackend.get());
120     if (NULL == pBackend)
121     {
122         //May throw a DisposedException
123         check();
124         //We should never get here...
125         throw RuntimeException(
126             OUSTR("Failed to get the BackendImpl"),
127             static_cast<OWeakObject*>(const_cast<PackageImpl *>(this)));
128     }
129     return pBackend;
130 }
131 //______________________________________________________________________________
132 OUString BackendImpl::PackageImpl::getDescription() throw (RuntimeException)
133 {
134     if (m_descr.getLength() == 0)
135         return Package::getDescription();
136     else
137         return m_descr;
138 }
139 
140 //______________________________________________________________________________
141 OUString BackendImpl::PackageImpl::getLicenseText() throw (RuntimeException)
142 {
143     return Package::getDescription();
144 }
145 
146 //______________________________________________________________________________
147 BackendImpl::PackageImpl::PackageImpl(
148     ::rtl::Reference<BackendImpl> const & myBackend,
149     OUString const & url, OUString const & libType, bool bRemoved,
150     OUString const & identifier)
151     : Package( myBackend.get(), url, OUString(), OUString(),
152                myBackend->m_xTypeInfo, bRemoved, identifier),
153       m_descr(libType)
154 {
155     initPackageHandler();
156 
157     sal_Int32 segmEnd = url.getLength();
158     if (url.getLength() > 0 && url[ url.getLength() - 1 ] == '/')
159         --segmEnd;
160     sal_Int32 segmStart = (url.lastIndexOf( '/', segmEnd ) + 1);
161     if (segmStart < 0)
162         segmStart = 0;
163     // name and display name default the same:
164     m_displayName = ::rtl::Uri::decode(
165         url.copy( segmStart, segmEnd - segmStart ),
166         rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8 );
167     m_name = m_displayName;
168 
169     dp_misc::TRACE(OUSTR("PakageImpl displayName is ") + m_displayName);
170 }
171 
172 //______________________________________________________________________________
173 BackendImpl::BackendImpl(
174     Sequence<Any> const & args,
175     Reference<XComponentContext> const & xComponentContext )
176     : PackageRegistryBackend( args, xComponentContext ),
177       m_xTypeInfo( new Package::TypeInfo(
178                        OUSTR("application/vnd.sun.star.framework-script"),
179                        OUString() /* no file filter */,
180                        OUSTR("Scripting Framework Script Library"),
181                        RID_IMG_SCRIPTLIB, RID_IMG_SCRIPTLIB_HC ) )
182 {
183     if (! transientMode())
184     {
185 /*
186         if (office_is_running())
187         {
188             Reference<XComponentContext> xContext( getComponentContext() );
189             m_xScriptLibs.set(
190                 xContext->getServiceManager()->createInstanceWithContext(
191                     OUSTR("com.sun.star."
192                           "script.ApplicationScriptLibraryContainer"),
193                     xContext ), UNO_QUERY_THROW );
194             m_xDialogLibs.set(
195                 xContext->getServiceManager()->createInstanceWithContext(
196                     OUSTR("com.sun.star."
197                           "script.ApplicationDialogLibraryContainer"),
198                     xContext ), UNO_QUERY_THROW );
199         }
200         else
201         {
202             OUString basic_path(
203                 m_eContext == CONTEXT_USER
204                 ? OUSTR("vnd.sun.star.expand:${$BRAND_BASE_DIR/program/"
205                         SAL_CONFIGFILE("bootstrap")
206                         ":UserInstallation}/user/basic")
207                 : OUSTR("vnd.sun.star.expand:${$BRAND_BASE_DIR/program/"
208                         SAL_CONFIGFILE("bootstrap")
209                         ":BaseInstallation}/share/basic") );
210             m_basic_script_libs.reset(
211                 new LibraryContainer(
212                     makeURL( basic_path, OUSTR("script.xlc") ),
213                     getMutex(),
214                     getComponentContext() ) );
215             m_dialog_libs.reset(
216                 new LibraryContainer(
217                     makeURL( basic_path, OUSTR("dialog.xlc") ),
218                     getMutex(),
219                     getComponentContext() ) );
220         }
221 */
222     }
223 }
224 
225 
226 
227 // XPackageRegistry
228 //______________________________________________________________________________
229 Sequence< Reference<deployment::XPackageTypeInfo> >
230 BackendImpl::getSupportedPackageTypes() throw (RuntimeException)
231 {
232     return Sequence< Reference<deployment::XPackageTypeInfo> >(&m_xTypeInfo, 1);
233 }
234 
235 void BackendImpl::packageRemoved(OUString const & /*url*/, OUString const & /*mediaType*/)
236         throw (deployment::DeploymentException,
237                uno::RuntimeException)
238 {
239 }
240 
241 // PackageRegistryBackend
242 //______________________________________________________________________________
243 Reference<deployment::XPackage> BackendImpl::bindPackage_(
244     OUString const & url, OUString const & mediaType_, sal_Bool bRemoved,
245     OUString const & identifier, Reference<XCommandEnvironment> const & xCmdEnv )
246 {
247     OUString mediaType( mediaType_ );
248     if (mediaType.getLength() == 0)
249     {
250         // detect media-type:
251         ::ucbhelper::Content ucbContent;
252         if (create_ucb_content( &ucbContent, url, xCmdEnv ) &&
253             ucbContent.isFolder())
254         {
255             // probe for parcel-descriptor.xml:
256             if (create_ucb_content(
257                     0, makeURL( url, OUSTR("parcel-descriptor.xml") ),
258                     xCmdEnv, false /* no throw */ ))
259             {
260                 mediaType = OUSTR("application/vnd.sun.star.framework-script");
261             }
262         }
263         if (mediaType.getLength() == 0)
264             throw lang::IllegalArgumentException(
265                 StrCannotDetectMediaType::get() + url,
266                 static_cast<OWeakObject *>(this), static_cast<sal_Int16>(-1) );
267     }
268 
269     String type, subType;
270     INetContentTypeParameterList params;
271     if (INetContentTypes::parse( mediaType, type, subType, &params ))
272     {
273         if (type.EqualsIgnoreCaseAscii("application"))
274         {
275             if (subType.EqualsIgnoreCaseAscii("vnd.sun.star.framework-script"))
276             {
277                 OUString lang = OUString::createFromAscii("Script");
278                 OUString sParcelDescURL = makeURL(
279                     url, OUSTR("parcel-descriptor.xml") );
280 
281                 ::ucbhelper::Content ucb_content;
282 
283                 if (create_ucb_content( &ucb_content, sParcelDescURL,
284                         xCmdEnv, false /* no throw */ ))
285                 {
286                     ParcelDescDocHandler* pHandler =
287                         new ParcelDescDocHandler();
288                     Reference< xml::sax::XDocumentHandler >
289                         xDocHandler = pHandler;
290 
291                     Reference<XComponentContext>
292                         xContext( getComponentContext() );
293 
294                     Reference< xml::sax::XParser > xParser(
295                       xContext->getServiceManager()->createInstanceWithContext(
296                             OUSTR("com.sun.star.xml.sax.Parser"), xContext ),
297                                 UNO_QUERY_THROW );
298 
299                     xParser->setDocumentHandler( xDocHandler );
300                     xml::sax::InputSource source;
301                     source.aInputStream = ucb_content.openStream();
302                     source.sSystemId = ucb_content.getURL();
303                     xParser->parseStream( source );
304 
305                     if ( pHandler->isParsed() )
306                     {
307                         lang = pHandler->getParcelLanguage();
308                     }
309                 }
310 
311                 OUString sfwkLibType = getResourceString( RID_STR_SFWK_LIB );
312                 // replace %MACRONAME placeholder with language name
313                 OUString MACRONAME( OUSTR("%MACROLANG" ) );
314                 sal_Int32 startOfReplace = sfwkLibType.indexOf( MACRONAME );
315                 sal_Int32 charsToReplace = MACRONAME.getLength();
316                 sfwkLibType = sfwkLibType.replaceAt( startOfReplace, charsToReplace, lang );
317                 dp_misc::TRACE("******************************\n");
318                 dp_misc::TRACE(OUSTR(" BackEnd detected lang = ") + lang + OUSTR("\n"));
319                 dp_misc::TRACE(OUSTR(" for url ") + sParcelDescURL + OUSTR("\n") );
320                 dp_misc::TRACE("******************************\n");
321                 return new PackageImpl( this, url, sfwkLibType, bRemoved, identifier);
322             }
323         }
324     }
325     throw lang::IllegalArgumentException(
326         StrUnsupportedMediaType::get() + mediaType,
327         static_cast<OWeakObject *>(this),
328         static_cast<sal_Int16>(-1) );
329 }
330 
331 //##############################################################################
332 
333 void BackendImpl::PackageImpl:: initPackageHandler()
334 {
335     if (m_xNameCntrPkgHandler.is())
336         return;
337 
338     BackendImpl * that = getMyBackend();
339     Any aContext;
340 
341     if ( that->m_eContext == CONTEXT_USER )
342     {
343         aContext  <<= OUSTR("user");
344     }
345     else if ( that->m_eContext == CONTEXT_SHARED )
346     {
347         aContext  <<= OUSTR("share");
348     }
349     else if ( that->m_eContext == CONTEXT_BUNDLED )
350     {
351         aContext  <<= OUSTR("bundled");
352     }
353     else if ( that->m_eContext == CONTEXT_BUNDLED_PREREG )
354     {
355         aContext  <<= OUSTR("bundled_prereg");
356     }
357 
358     else
359     {
360         OSL_ASSERT( 0 );
361         // NOT supported at the momemtn // TODO
362     }
363 
364     Reference< provider::XScriptProviderFactory > xFac(
365         that->getComponentContext()->getValueByName(
366             OUSTR( "/singletons/com.sun.star.script.provider.theMasterScriptProviderFactory") ), UNO_QUERY );
367 
368     if ( xFac.is() )
369     {
370         Reference< container::XNameContainer > xName( xFac->createScriptProvider( aContext ), UNO_QUERY );
371         if ( xName.is() )
372         {
373             m_xNameCntrPkgHandler.set( xName );
374         }
375     }
376     // TODO what happens if above fails??
377 }
378 
379 // Package
380 //______________________________________________________________________________
381 beans::Optional< beans::Ambiguous<sal_Bool> >
382 BackendImpl::PackageImpl::isRegistered_(
383     ::osl::ResettableMutexGuard &,
384     ::rtl::Reference<AbortChannel> const &,
385     Reference<XCommandEnvironment> const & )
386 {
387     return beans::Optional< beans::Ambiguous<sal_Bool> >(
388         true /* IsPresent */,
389         beans::Ambiguous<sal_Bool>(
390             m_xNameCntrPkgHandler.is() && m_xNameCntrPkgHandler->hasByName(
391                 m_url ),
392             false /* IsAmbiguous */ ) );
393 }
394 
395 //______________________________________________________________________________
396 void BackendImpl::PackageImpl::processPackage_(
397     ::osl::ResettableMutexGuard &,
398     bool doRegisterPackage,
399     bool /* startup */,
400     ::rtl::Reference<AbortChannel> const &,
401     Reference<XCommandEnvironment> const & )
402 {
403     if ( !m_xNameCntrPkgHandler.is() )
404     {
405         dp_misc::TRACE("no package handler!!!!\n");
406         throw RuntimeException( OUSTR("No package Handler " ),
407             Reference< XInterface >() );
408     }
409 
410     if (doRegisterPackage)
411     {
412         // will throw if it fails
413         m_xNameCntrPkgHandler->insertByName( m_url, makeAny( Reference< XPackage >(this) ) );
414 
415     }
416     else // revokePackage()
417     {
418         m_xNameCntrPkgHandler->removeByName( m_url );
419     }
420 }
421 
422 namespace sdecl = comphelper::service_decl;
423 sdecl::class_<BackendImpl, sdecl::with_args<true> > serviceBI;
424 extern sdecl::ServiceDecl const serviceDecl(
425     serviceBI,
426     "com.sun.star.comp.deployment.sfwk.PackageRegistryBackend",
427     BACKEND_SERVICE_NAME );
428 
429 } // namespace sfwk
430 } // namespace backend
431 } // namespace dp_registry
432 
433