1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20 #include <sal/config.h>
21
22 #include <strings.hrc>
23 #include <dp_backend.h>
24 #include <dp_ucb.h>
25 #include "dp_parceldesc.hxx"
26 #include <rtl/uri.hxx>
27 #include <ucbhelper/content.hxx>
28 #include <svl/inettype.hxx>
29 #include <com/sun/star/container/XNameContainer.hpp>
30 #include <com/sun/star/script/provider/theMasterScriptProviderFactory.hpp>
31 #include <com/sun/star/xml/sax/Parser.hpp>
32 #include <cppuhelper/supportsservice.hxx>
33
34
35 using namespace ::dp_misc;
36 using namespace ::com::sun::star;
37 using namespace ::com::sun::star::uno;
38 using namespace ::com::sun::star::ucb;
39 using namespace ::com::sun::star::script;
40
41
42 namespace dp_registry::backend::sfwk
43 {
44
45 namespace {
46
47 class BackendImpl : public ::dp_registry::backend::PackageRegistryBackend
48 {
49 class PackageImpl : public ::dp_registry::backend::Package
50 {
51 BackendImpl * getMyBackend() const;
52
53 Reference< container::XNameContainer > m_xNameCntrPkgHandler;
54 OUString m_descr;
55
56 void initPackageHandler();
57
58 // Package
59 virtual beans::Optional< beans::Ambiguous<sal_Bool> > isRegistered_(
60 ::osl::ResettableMutexGuard & guard,
61 ::rtl::Reference<AbortChannel> const & abortChannel,
62 Reference<XCommandEnvironment> const & xCmdEnv ) override;
63 virtual void processPackage_(
64 ::osl::ResettableMutexGuard & guard,
65 bool registerPackage,
66 bool startup,
67 ::rtl::Reference<AbortChannel> const & abortChannel,
68 Reference<XCommandEnvironment> const & xCmdEnv ) override;
69
70 public:
71 PackageImpl(
72 ::rtl::Reference<BackendImpl> const & myBackend,
73 OUString const & url, OUString const & libType, bool bRemoved,
74 OUString const & identifier);
75 // XPackage
76 virtual OUString SAL_CALL getDescription() override;
77 virtual OUString SAL_CALL getLicenseText() override;
78 };
79 friend class PackageImpl;
80
81 // PackageRegistryBackend
82 virtual Reference<deployment::XPackage> bindPackage_(
83 OUString const & url, OUString const & mediaType,
84 bool bRemoved, OUString const & identifier,
85 Reference<XCommandEnvironment> const & xCmdEnv ) override;
86
87 const Reference<deployment::XPackageTypeInfo> m_xTypeInfo;
88
89
90 public:
91 BackendImpl(
92 Sequence<Any> const & args,
93 Reference<XComponentContext> const & xComponentContext );
94
95 // XServiceInfo
96 virtual OUString SAL_CALL getImplementationName() override;
97 virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
98 virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
99
100 // XPackageRegistry
101 virtual Sequence< Reference<deployment::XPackageTypeInfo> > SAL_CALL
102 getSupportedPackageTypes() override;
103 virtual void SAL_CALL packageRemoved(OUString const & url, OUString const & mediaType) override;
104 };
105
106 }
107
getMyBackend() const108 BackendImpl * BackendImpl::PackageImpl::getMyBackend() const
109 {
110 BackendImpl * pBackend = static_cast<BackendImpl *>(m_myBackend.get());
111 if (nullptr == pBackend)
112 {
113 //May throw a DisposedException
114 check();
115 //We should never get here...
116 throw RuntimeException("Failed to get the BackendImpl",
117 static_cast<OWeakObject*>(const_cast<PackageImpl *>(this)));
118 }
119 return pBackend;
120 }
121
getDescription()122 OUString BackendImpl::PackageImpl::getDescription()
123 {
124 if (m_descr.isEmpty())
125 return Package::getDescription();
126 else
127 return m_descr;
128 }
129
getLicenseText()130 OUString BackendImpl::PackageImpl::getLicenseText()
131 {
132 return Package::getDescription();
133 }
134
PackageImpl(::rtl::Reference<BackendImpl> const & myBackend,OUString const & url,OUString const & libType,bool bRemoved,OUString const & identifier)135 BackendImpl::PackageImpl::PackageImpl(
136 ::rtl::Reference<BackendImpl> const & myBackend,
137 OUString const & url, OUString const & libType, bool bRemoved,
138 OUString const & identifier)
139 : Package( myBackend, url, OUString(), OUString(),
140 myBackend->m_xTypeInfo, bRemoved, identifier),
141 m_descr(libType)
142 {
143 initPackageHandler();
144
145 sal_Int32 segmEnd = url.getLength();
146 if ( url.endsWith("/") )
147 --segmEnd;
148 sal_Int32 segmStart = url.lastIndexOf( '/', segmEnd ) + 1;
149 if (segmStart < 0)
150 segmStart = 0;
151 // name and display name default the same:
152 m_displayName = ::rtl::Uri::decode(
153 url.copy( segmStart, segmEnd - segmStart ),
154 rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8 );
155 m_name = m_displayName;
156
157 dp_misc::TRACE("PackageImpl displayName is " + m_displayName);
158 }
159
160
BackendImpl(Sequence<Any> const & args,Reference<XComponentContext> const & xComponentContext)161 BackendImpl::BackendImpl(
162 Sequence<Any> const & args,
163 Reference<XComponentContext> const & xComponentContext )
164 : PackageRegistryBackend( args, xComponentContext ),
165 m_xTypeInfo( new Package::TypeInfo(
166 "application/vnd.sun.star.framework-script",
167 OUString() /* no file filter */,
168 "Scripting Framework Script Library"
169 ) )
170 {
171 }
172
173
174 // XServiceInfo
getImplementationName()175 OUString BackendImpl::getImplementationName()
176 {
177 return "com.sun.star.comp.deployment.sfwk.PackageRegistryBackend";
178 }
179
supportsService(const OUString & ServiceName)180 sal_Bool BackendImpl::supportsService( const OUString& ServiceName )
181 {
182 return cppu::supportsService(this, ServiceName);
183 }
184
getSupportedServiceNames()185 css::uno::Sequence< OUString > BackendImpl::getSupportedServiceNames()
186 {
187 return { BACKEND_SERVICE_NAME };
188 }
189
190 // XPackageRegistry
191
192 Sequence< Reference<deployment::XPackageTypeInfo> >
getSupportedPackageTypes()193 BackendImpl::getSupportedPackageTypes()
194 {
195 return Sequence< Reference<deployment::XPackageTypeInfo> >(&m_xTypeInfo, 1);
196 }
197
packageRemoved(OUString const &,OUString const &)198 void BackendImpl::packageRemoved(OUString const & /*url*/, OUString const & /*mediaType*/)
199 {
200 }
201
202 // PackageRegistryBackend
203
bindPackage_(OUString const & url,OUString const & mediaType_,bool bRemoved,OUString const & identifier,Reference<XCommandEnvironment> const & xCmdEnv)204 Reference<deployment::XPackage> BackendImpl::bindPackage_(
205 OUString const & url, OUString const & mediaType_, bool bRemoved,
206 OUString const & identifier, Reference<XCommandEnvironment> const & xCmdEnv )
207 {
208 OUString mediaType( mediaType_ );
209 if (mediaType.isEmpty())
210 {
211 // detect media-type:
212 ::ucbhelper::Content ucbContent;
213 if (create_ucb_content( &ucbContent, url, xCmdEnv ) &&
214 ucbContent.isFolder())
215 {
216 // probe for parcel-descriptor.xml:
217 if (create_ucb_content(
218 nullptr, makeURL( url, "parcel-descriptor.xml" ),
219 xCmdEnv, false /* no throw */ ))
220 {
221 mediaType = "application/vnd.sun.star.framework-script";
222 }
223 }
224 if (mediaType.isEmpty())
225 throw lang::IllegalArgumentException(
226 StrCannotDetectMediaType() + url,
227 static_cast<OWeakObject *>(this), static_cast<sal_Int16>(-1) );
228 }
229
230 OUString type, subType;
231 INetContentTypeParameterList params;
232 if (INetContentTypes::parse( mediaType, type, subType, ¶ms ))
233 {
234 if (type.equalsIgnoreAsciiCase("application"))
235 {
236 if (subType.equalsIgnoreAsciiCase("vnd.sun.star.framework-script"))
237 {
238 OUString lang = "Script";
239 OUString sParcelDescURL = makeURL(
240 url, "parcel-descriptor.xml" );
241
242 ::ucbhelper::Content ucb_content;
243
244 if (create_ucb_content( &ucb_content, sParcelDescURL,
245 xCmdEnv, false /* no throw */ ))
246 {
247 rtl::Reference<ParcelDescDocHandler> pHandler =
248 new ParcelDescDocHandler();
249
250 Reference<XComponentContext>
251 xContext( getComponentContext() );
252
253 Reference< xml::sax::XParser > xParser = xml::sax::Parser::create(xContext);
254
255 xParser->setDocumentHandler( pHandler );
256 xml::sax::InputSource source;
257 source.aInputStream = ucb_content.openStream();
258 source.sSystemId = ucb_content.getURL();
259 xParser->parseStream( source );
260
261 if ( pHandler->isParsed() )
262 {
263 lang = pHandler->getParcelLanguage();
264 }
265 }
266
267 OUString sfwkLibType = DpResId( RID_STR_SFWK_LIB );
268 // replace %MACRONAME placeholder with language name
269 OUString MACRONAME( "%MACROLANG" );
270 sal_Int32 startOfReplace = sfwkLibType.indexOf( MACRONAME );
271 sal_Int32 charsToReplace = MACRONAME.getLength();
272 sfwkLibType = sfwkLibType.replaceAt( startOfReplace, charsToReplace, lang );
273 dp_misc::TRACE("******************************\n");
274 dp_misc::TRACE(" BackEnd detected lang = " + lang + "\n");
275 dp_misc::TRACE(" for url " + sParcelDescURL + "\n");
276 dp_misc::TRACE("******************************\n");
277 return new PackageImpl( this, url, sfwkLibType, bRemoved, identifier);
278 }
279 }
280 }
281 throw lang::IllegalArgumentException(
282 StrUnsupportedMediaType() + mediaType,
283 static_cast<OWeakObject *>(this),
284 static_cast<sal_Int16>(-1) );
285 }
286
287
initPackageHandler()288 void BackendImpl::PackageImpl:: initPackageHandler()
289 {
290 if (m_xNameCntrPkgHandler.is())
291 return;
292
293 BackendImpl * that = getMyBackend();
294 Any aContext;
295
296 if ( that->m_eContext == Context::User )
297 {
298 aContext <<= OUString("user");
299 }
300 else if ( that->m_eContext == Context::Shared )
301 {
302 aContext <<= OUString("share");
303 }
304 else if ( that->m_eContext == Context::Bundled )
305 {
306 aContext <<= OUString("bundled");
307 }
308 else
309 {
310 OSL_ASSERT( false );
311 // NOT supported at the moment // TODO
312 }
313
314 Reference< provider::XScriptProviderFactory > xFac =
315 provider::theMasterScriptProviderFactory::get( that->getComponentContext() );
316
317 Reference< container::XNameContainer > xName( xFac->createScriptProvider( aContext ), UNO_QUERY );
318 if ( xName.is() )
319 {
320 m_xNameCntrPkgHandler.set( xName );
321 }
322 // TODO what happens if above fails??
323 }
324
325 // Package
326
327 beans::Optional< beans::Ambiguous<sal_Bool> >
isRegistered_(::osl::ResettableMutexGuard &,::rtl::Reference<AbortChannel> const &,Reference<XCommandEnvironment> const &)328 BackendImpl::PackageImpl::isRegistered_(
329 ::osl::ResettableMutexGuard &,
330 ::rtl::Reference<AbortChannel> const &,
331 Reference<XCommandEnvironment> const & )
332 {
333 return beans::Optional< beans::Ambiguous<sal_Bool> >(
334 true /* IsPresent */,
335 beans::Ambiguous<sal_Bool>(
336 m_xNameCntrPkgHandler.is() && m_xNameCntrPkgHandler->hasByName(
337 m_url ),
338 false /* IsAmbiguous */ ) );
339 }
340
341
processPackage_(::osl::ResettableMutexGuard &,bool doRegisterPackage,bool,::rtl::Reference<AbortChannel> const &,Reference<XCommandEnvironment> const &)342 void BackendImpl::PackageImpl::processPackage_(
343 ::osl::ResettableMutexGuard &,
344 bool doRegisterPackage,
345 bool /* startup */,
346 ::rtl::Reference<AbortChannel> const &,
347 Reference<XCommandEnvironment> const & )
348 {
349 if ( !m_xNameCntrPkgHandler.is() )
350 {
351 dp_misc::TRACE("no package handler!!!!\n");
352 throw RuntimeException( "No package Handler " );
353 }
354
355 if (doRegisterPackage)
356 {
357 // will throw if it fails
358 m_xNameCntrPkgHandler->insertByName( m_url, makeAny( Reference< XPackage >(this) ) );
359
360 }
361 else // revokePackage()
362 {
363 m_xNameCntrPkgHandler->removeByName( m_url );
364 }
365 }
366
367 } // namespace dp_registry::backend::sfwk
368
369 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
com_sun_star_comp_deployment_sfwk_PackageRegistryBackend_get_implementation(css::uno::XComponentContext * context,css::uno::Sequence<css::uno::Any> const & args)370 com_sun_star_comp_deployment_sfwk_PackageRegistryBackend_get_implementation(
371 css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& args)
372 {
373 return cppu::acquire(new dp_registry::backend::sfwk::BackendImpl(args, context));
374 }
375
376 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
377