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