LibreOffice Module desktop (master)  1
dp_sfwk.cxx
Go to the documentation of this file.
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_misc.h>
25 #include <dp_ucb.h>
26 #include "dp_parceldesc.hxx"
27 #include <rtl/uri.hxx>
28 #include <ucbhelper/content.hxx>
29 #include <svl/inettype.hxx>
30 #include <com/sun/star/container/XNameContainer.hpp>
31 #include <com/sun/star/script/provider/theMasterScriptProviderFactory.hpp>
32 #include <com/sun/star/xml/sax/Parser.hpp>
34 
35 
36 using namespace ::dp_misc;
37 using namespace ::com::sun::star;
38 using namespace ::com::sun::star::uno;
39 using namespace ::com::sun::star::ucb;
40 using namespace ::com::sun::star::script;
41 
42 
44 {
45 
46 namespace {
47 
48 class BackendImpl : public ::dp_registry::backend::PackageRegistryBackend
49 {
50  class PackageImpl : public ::dp_registry::backend::Package
51  {
52  BackendImpl * getMyBackend() const;
53 
55  OUString m_descr;
56 
57  void initPackageHandler();
58 
59  // Package
60  virtual beans::Optional< beans::Ambiguous<sal_Bool> > isRegistered_(
61  ::osl::ResettableMutexGuard & guard,
62  ::rtl::Reference<AbortChannel> const & abortChannel,
63  Reference<XCommandEnvironment> const & xCmdEnv ) override;
64  virtual void processPackage_(
65  ::osl::ResettableMutexGuard & guard,
66  bool registerPackage,
67  bool startup,
68  ::rtl::Reference<AbortChannel> const & abortChannel,
69  Reference<XCommandEnvironment> const & xCmdEnv ) override;
70 
71  public:
72  PackageImpl(
73  ::rtl::Reference<BackendImpl> const & myBackend,
74  OUString const & url, OUString const & libType, bool bRemoved,
75  OUString const & identifier);
76  // XPackage
77  virtual OUString SAL_CALL getDescription() override;
78  virtual OUString SAL_CALL getLicenseText() override;
79  };
80  friend class PackageImpl;
81 
82  // PackageRegistryBackend
83  virtual Reference<deployment::XPackage> bindPackage_(
84  OUString const & url, OUString const & mediaType,
85  bool bRemoved, OUString const & identifier,
86  Reference<XCommandEnvironment> const & xCmdEnv ) override;
87 
88  const Reference<deployment::XPackageTypeInfo> m_xTypeInfo;
89 
90 
91 public:
92  BackendImpl(
93  Sequence<Any> const & args,
94  Reference<XComponentContext> const & xComponentContext );
95 
96  // XServiceInfo
97  virtual OUString SAL_CALL getImplementationName() override;
98  virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
99  virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
100 
101  // XPackageRegistry
102  virtual Sequence< Reference<deployment::XPackageTypeInfo> > SAL_CALL
103  getSupportedPackageTypes() override;
104  virtual void SAL_CALL packageRemoved(OUString const & url, OUString const & mediaType) override;
105 };
106 
107 }
108 
109 BackendImpl * BackendImpl::PackageImpl::getMyBackend() const
110 {
111  BackendImpl * pBackend = static_cast<BackendImpl *>(m_myBackend.get());
112  if (nullptr == pBackend)
113  {
114  //May throw a DisposedException
115  check();
116  //We should never get here...
117  throw RuntimeException("Failed to get the BackendImpl",
118  static_cast<OWeakObject*>(const_cast<PackageImpl *>(this)));
119  }
120  return pBackend;
121 }
122 
123 OUString BackendImpl::PackageImpl::getDescription()
124 {
125  if (m_descr.isEmpty())
126  return Package::getDescription();
127  else
128  return m_descr;
129 }
130 
131 OUString BackendImpl::PackageImpl::getLicenseText()
132 {
133  return Package::getDescription();
134 }
135 
136 BackendImpl::PackageImpl::PackageImpl(
137  ::rtl::Reference<BackendImpl> const & myBackend,
138  OUString const & url, OUString const & libType, bool bRemoved,
139  OUString const & identifier)
140  : Package( myBackend, url, OUString(), OUString(),
141  myBackend->m_xTypeInfo, bRemoved, identifier),
142  m_descr(libType)
143 {
144  initPackageHandler();
145 
146  sal_Int32 segmEnd = url.getLength();
147  if ( url.endsWith("/") )
148  --segmEnd;
149  sal_Int32 segmStart = url.lastIndexOf( '/', segmEnd ) + 1;
150  if (segmStart < 0)
151  segmStart = 0;
152  // name and display name default the same:
153  m_displayName = ::rtl::Uri::decode(
154  url.copy( segmStart, segmEnd - segmStart ),
155  rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8 );
156  m_name = m_displayName;
157 
158  dp_misc::TRACE("PackageImpl displayName is " + m_displayName);
159 }
160 
161 
162 BackendImpl::BackendImpl(
163  Sequence<Any> const & args,
164  Reference<XComponentContext> const & xComponentContext )
165  : PackageRegistryBackend( args, xComponentContext ),
166  m_xTypeInfo( new Package::TypeInfo(
167  "application/vnd.sun.star.framework-script",
168  OUString() /* no file filter */,
169  "Scripting Framework Script Library"
170  ) )
171 {
172 }
173 
174 
175 // XServiceInfo
176 OUString BackendImpl::getImplementationName()
177 {
178  return "com.sun.star.comp.deployment.sfwk.PackageRegistryBackend";
179 }
180 
181 sal_Bool BackendImpl::supportsService( const OUString& ServiceName )
182 {
183  return cppu::supportsService(this, ServiceName);
184 }
185 
186 css::uno::Sequence< OUString > BackendImpl::getSupportedServiceNames()
187 {
188  return { BACKEND_SERVICE_NAME };
189 }
190 
191 // XPackageRegistry
192 
193 Sequence< Reference<deployment::XPackageTypeInfo> >
194 BackendImpl::getSupportedPackageTypes()
195 {
196  return Sequence< Reference<deployment::XPackageTypeInfo> >(&m_xTypeInfo, 1);
197 }
198 
199 void BackendImpl::packageRemoved(OUString const & /*url*/, OUString const & /*mediaType*/)
200 {
201 }
202 
203 // PackageRegistryBackend
204 
205 Reference<deployment::XPackage> BackendImpl::bindPackage_(
206  OUString const & url, OUString const & mediaType_, bool bRemoved,
207  OUString const & identifier, Reference<XCommandEnvironment> const & xCmdEnv )
208 {
209  OUString mediaType( mediaType_ );
210  if (mediaType.isEmpty())
211  {
212  // detect media-type:
213  ::ucbhelper::Content ucbContent;
214  if (create_ucb_content( &ucbContent, url, xCmdEnv ) &&
215  ucbContent.isFolder())
216  {
217  // probe for parcel-descriptor.xml:
218  if (create_ucb_content(
219  nullptr, makeURL( url, "parcel-descriptor.xml" ),
220  xCmdEnv, false /* no throw */ ))
221  {
222  mediaType = "application/vnd.sun.star.framework-script";
223  }
224  }
225  if (mediaType.isEmpty())
226  throw lang::IllegalArgumentException(
227  StrCannotDetectMediaType() + url,
228  static_cast<OWeakObject *>(this), static_cast<sal_Int16>(-1) );
229  }
230 
231  OUString type, subType;
233  if (INetContentTypes::parse( mediaType, type, subType, &params ))
234  {
235  if (type.equalsIgnoreAsciiCase("application"))
236  {
237  if (subType.equalsIgnoreAsciiCase("vnd.sun.star.framework-script"))
238  {
239  OUString lang = "Script";
240  OUString sParcelDescURL = makeURL(
241  url, "parcel-descriptor.xml" );
242 
243  ::ucbhelper::Content ucb_content;
244 
245  if (create_ucb_content( &ucb_content, sParcelDescURL,
246  xCmdEnv, false /* no throw */ ))
247  {
249  new ParcelDescDocHandler();
250 
253 
254  Reference< xml::sax::XParser > xParser = xml::sax::Parser::create(xContext);
255 
256  xParser->setDocumentHandler( pHandler );
257  xml::sax::InputSource source;
258  source.aInputStream = ucb_content.openStream();
259  source.sSystemId = ucb_content.getURL();
260  xParser->parseStream( source );
261 
262  if ( pHandler->isParsed() )
263  {
264  lang = pHandler->getParcelLanguage();
265  }
266  }
267 
268  OUString sfwkLibType = DpResId( RID_STR_SFWK_LIB );
269  // replace %MACRONAME placeholder with language name
270  OUString MACRONAME( "%MACROLANG" );
271  sal_Int32 startOfReplace = sfwkLibType.indexOf( MACRONAME );
272  sal_Int32 charsToReplace = MACRONAME.getLength();
273  sfwkLibType = sfwkLibType.replaceAt( startOfReplace, charsToReplace, lang );
274  dp_misc::TRACE("******************************\n");
275  dp_misc::TRACE(" BackEnd detected lang = " + lang + "\n");
276  dp_misc::TRACE(" for url " + sParcelDescURL + "\n");
277  dp_misc::TRACE("******************************\n");
278  return new PackageImpl( this, url, sfwkLibType, bRemoved, identifier);
279  }
280  }
281  }
282  throw lang::IllegalArgumentException(
283  StrUnsupportedMediaType() + mediaType,
284  static_cast<OWeakObject *>(this),
285  static_cast<sal_Int16>(-1) );
286 }
287 
288 
289 void BackendImpl::PackageImpl:: initPackageHandler()
290 {
291  if (m_xNameCntrPkgHandler.is())
292  return;
293 
294  BackendImpl * that = getMyBackend();
295  Any aContext;
296 
297  if ( that->m_eContext == Context::User )
298  {
299  aContext <<= OUString("user");
300  }
301  else if ( that->m_eContext == Context::Shared )
302  {
303  aContext <<= OUString("share");
304  }
305  else if ( that->m_eContext == Context::Bundled )
306  {
307  aContext <<= OUString("bundled");
308  }
309  else
310  {
311  OSL_ASSERT( false );
312  // NOT supported at the moment // TODO
313  }
314 
315  Reference< provider::XScriptProviderFactory > xFac =
316  provider::theMasterScriptProviderFactory::get( that->getComponentContext() );
317 
318  Reference< container::XNameContainer > xName( xFac->createScriptProvider( aContext ), UNO_QUERY );
319  if ( xName.is() )
320  {
321  m_xNameCntrPkgHandler.set( xName );
322  }
323  // TODO what happens if above fails??
324 }
325 
326 // Package
327 
328 beans::Optional< beans::Ambiguous<sal_Bool> >
329 BackendImpl::PackageImpl::isRegistered_(
330  ::osl::ResettableMutexGuard &,
333 {
334  return beans::Optional< beans::Ambiguous<sal_Bool> >(
335  true /* IsPresent */,
336  beans::Ambiguous<sal_Bool>(
337  m_xNameCntrPkgHandler.is() && m_xNameCntrPkgHandler->hasByName(
338  m_url ),
339  false /* IsAmbiguous */ ) );
340 }
341 
342 
343 void BackendImpl::PackageImpl::processPackage_(
344  ::osl::ResettableMutexGuard &,
345  bool doRegisterPackage,
346  bool /* startup */,
349 {
350  if ( !m_xNameCntrPkgHandler.is() )
351  {
352  dp_misc::TRACE("no package handler!!!!\n");
353  throw RuntimeException( "No package Handler " );
354  }
355 
356  if (doRegisterPackage)
357  {
358  // will throw if it fails
359  m_xNameCntrPkgHandler->insertByName( m_url, Any( Reference< XPackage >(this) ) );
360 
361  }
362  else // revokePackage()
363  {
364  m_xNameCntrPkgHandler->removeByName( m_url );
365  }
366 }
367 
368 } // namespace dp_registry::backend::sfwk
369 
370 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
372  css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& args)
373 {
374  return cppu::acquire(new dp_registry::backend::sfwk::BackendImpl(args, context));
375 }
376 
377 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
OUString m_name
css::uno::Sequence< OUString > getSupportedServiceNames()
OUString getImplementationName()
OUString m_descr
Definition: dp_sfwk.cxx:55
OUString makeURL(OUString const &baseURL, OUString const &relPath_)
appends a relative path to a url.
Definition: dp_misc.cxx:250
css::uno::Reference< css::deployment::XPackageRegistry > create(css::uno::Reference< css::deployment::XPackageRegistry > const &xRootRegistry, OUString const &context, OUString const &cachePath, css::uno::Reference< css::uno::XComponentContext > const &xComponentContext)
static bool parse(OUString const &rMediaType, OUString &rType, OUString &rSubType, INetContentTypeParameterList *pParameters=nullptr)
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
def check(model)
Reference< container::XNameContainer > m_xNameCntrPkgHandler
Definition: dp_sfwk.cxx:54
unsigned char sal_Bool
const OUString & getURL() const
const Reference< deployment::XPackageTypeInfo > m_xTypeInfo
Definition: dp_sfwk.cxx:88
Reference< XComponentContext > getComponentContext(Reference< XMultiServiceFactory > const &factory)
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC bool create_ucb_content(::ucbhelper::Content *ucb_content, OUString const &url, css::uno::Reference< css::ucb::XCommandEnvironment > const &xCmdEnv, bool throw_exc=true)
static uno::Reference< css::uno::XComponentContext > xContext
Definition: init.cxx:2429
css::uno::Reference< css::io::XInputStream > openStream()
void TRACE(OUString const &sText)
print the text to the console in a debug build.
Definition: dp_misc.cxx:487
std::unordered_map< OString, INetContentTypeParameter > INetContentTypeParameterList
constexpr OUStringLiteral BACKEND_SERVICE_NAME
Definition: dp_backend.h:40
ResultType type
OUString DpResId(TranslateId aId)
Definition: dp_misc.cxx:554
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)
Definition: dp_sfwk.cxx:371
virtual OUString SAL_CALL getDescription() override
Definition: dp_backend.cxx:480