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 <dp_services.hxx>
23 #include <strings.hrc>
24 #include <dp_backend.h>
25 #include <dp_ucb.h>
26 #include "dp_parceldesc.hxx"
27 #include <rtl/uri.hxx>
28 #include <ucbhelper/content.hxx>
30 #include <svl/inettype.hxx>
31 #include <com/sun/star/container/XNameContainer.hpp>
32 #include <com/sun/star/script/provider/theMasterScriptProviderFactory.hpp>
33 #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  // XPackageRegistry
97  virtual Sequence< Reference<deployment::XPackageTypeInfo> > SAL_CALL
98  getSupportedPackageTypes() override;
99  virtual void SAL_CALL packageRemoved(OUString const & url, OUString const & mediaType) override;
100 };
101 
102 }
103 
104 BackendImpl * BackendImpl::PackageImpl::getMyBackend() const
105 {
106  BackendImpl * pBackend = static_cast<BackendImpl *>(m_myBackend.get());
107  if (nullptr == pBackend)
108  {
109  //May throw a DisposedException
110  check();
111  //We should never get here...
112  throw RuntimeException("Failed to get the BackendImpl",
113  static_cast<OWeakObject*>(const_cast<PackageImpl *>(this)));
114  }
115  return pBackend;
116 }
117 
118 OUString BackendImpl::PackageImpl::getDescription()
119 {
120  if (m_descr.isEmpty())
121  return Package::getDescription();
122  else
123  return m_descr;
124 }
125 
126 OUString BackendImpl::PackageImpl::getLicenseText()
127 {
128  return Package::getDescription();
129 }
130 
131 BackendImpl::PackageImpl::PackageImpl(
132  ::rtl::Reference<BackendImpl> const & myBackend,
133  OUString const & url, OUString const & libType, bool bRemoved,
134  OUString const & identifier)
135  : Package( myBackend.get(), url, OUString(), OUString(),
136  myBackend->m_xTypeInfo, bRemoved, identifier),
137  m_descr(libType)
138 {
139  initPackageHandler();
140 
141  sal_Int32 segmEnd = url.getLength();
142  if ( url.endsWith("/") )
143  --segmEnd;
144  sal_Int32 segmStart = url.lastIndexOf( '/', segmEnd ) + 1;
145  if (segmStart < 0)
146  segmStart = 0;
147  // name and display name default the same:
148  m_displayName = ::rtl::Uri::decode(
149  url.copy( segmStart, segmEnd - segmStart ),
150  rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8 );
151  m_name = m_displayName;
152 
153  dp_misc::TRACE("PackageImpl displayName is " + m_displayName);
154 }
155 
156 
157 BackendImpl::BackendImpl(
158  Sequence<Any> const & args,
159  Reference<XComponentContext> const & xComponentContext )
160  : PackageRegistryBackend( args, xComponentContext ),
161  m_xTypeInfo( new Package::TypeInfo(
162  "application/vnd.sun.star.framework-script",
163  OUString() /* no file filter */,
164  "Scripting Framework Script Library"
165  ) )
166 {
167 }
168 
169 
170 // XPackageRegistry
171 
172 Sequence< Reference<deployment::XPackageTypeInfo> >
173 BackendImpl::getSupportedPackageTypes()
174 {
175  return Sequence< Reference<deployment::XPackageTypeInfo> >(&m_xTypeInfo, 1);
176 }
177 
178 void BackendImpl::packageRemoved(OUString const & /*url*/, OUString const & /*mediaType*/)
179 {
180 }
181 
182 // PackageRegistryBackend
183 
184 Reference<deployment::XPackage> BackendImpl::bindPackage_(
185  OUString const & url, OUString const & mediaType_, bool bRemoved,
186  OUString const & identifier, Reference<XCommandEnvironment> const & xCmdEnv )
187 {
188  OUString mediaType( mediaType_ );
189  if (mediaType.isEmpty())
190  {
191  // detect media-type:
192  ::ucbhelper::Content ucbContent;
193  if (create_ucb_content( &ucbContent, url, xCmdEnv ) &&
194  ucbContent.isFolder())
195  {
196  // probe for parcel-descriptor.xml:
197  if (create_ucb_content(
198  nullptr, makeURL( url, "parcel-descriptor.xml" ),
199  xCmdEnv, false /* no throw */ ))
200  {
201  mediaType = "application/vnd.sun.star.framework-script";
202  }
203  }
204  if (mediaType.isEmpty())
205  throw lang::IllegalArgumentException(
206  StrCannotDetectMediaType() + url,
207  static_cast<OWeakObject *>(this), static_cast<sal_Int16>(-1) );
208  }
209 
210  OUString type, subType;
212  if (INetContentTypes::parse( mediaType, type, subType, &params ))
213  {
214  if (type.equalsIgnoreAsciiCase("application"))
215  {
216  if (subType.equalsIgnoreAsciiCase("vnd.sun.star.framework-script"))
217  {
218  OUString lang = "Script";
219  OUString sParcelDescURL = makeURL(
220  url, "parcel-descriptor.xml" );
221 
222  ::ucbhelper::Content ucb_content;
223 
224  if (create_ucb_content( &ucb_content, sParcelDescURL,
225  xCmdEnv, false /* no throw */ ))
226  {
227  ParcelDescDocHandler* pHandler =
228  new ParcelDescDocHandler();
230  xDocHandler = pHandler;
231 
234 
235  Reference< xml::sax::XParser > xParser = xml::sax::Parser::create(xContext);
236 
237  xParser->setDocumentHandler( xDocHandler );
238  xml::sax::InputSource source;
239  source.aInputStream = ucb_content.openStream();
240  source.sSystemId = ucb_content.getURL();
241  xParser->parseStream( source );
242 
243  if ( pHandler->isParsed() )
244  {
245  lang = pHandler->getParcelLanguage();
246  }
247  }
248 
249  OUString sfwkLibType = DpResId( RID_STR_SFWK_LIB );
250  // replace %MACRONAME placeholder with language name
251  OUString MACRONAME( "%MACROLANG" );
252  sal_Int32 startOfReplace = sfwkLibType.indexOf( MACRONAME );
253  sal_Int32 charsToReplace = MACRONAME.getLength();
254  sfwkLibType = sfwkLibType.replaceAt( startOfReplace, charsToReplace, lang );
255  dp_misc::TRACE("******************************\n");
256  dp_misc::TRACE(" BackEnd detected lang = " + lang + "\n");
257  dp_misc::TRACE(" for url " + sParcelDescURL + "\n");
258  dp_misc::TRACE("******************************\n");
259  return new PackageImpl( this, url, sfwkLibType, bRemoved, identifier);
260  }
261  }
262  }
263  throw lang::IllegalArgumentException(
264  StrUnsupportedMediaType() + mediaType,
265  static_cast<OWeakObject *>(this),
266  static_cast<sal_Int16>(-1) );
267 }
268 
269 
270 void BackendImpl::PackageImpl:: initPackageHandler()
271 {
272  if (m_xNameCntrPkgHandler.is())
273  return;
274 
275  BackendImpl * that = getMyBackend();
276  Any aContext;
277 
278  if ( that->m_eContext == Context::User )
279  {
280  aContext <<= OUString("user");
281  }
282  else if ( that->m_eContext == Context::Shared )
283  {
284  aContext <<= OUString("share");
285  }
286  else if ( that->m_eContext == Context::Bundled )
287  {
288  aContext <<= OUString("bundled");
289  }
290  else
291  {
292  OSL_ASSERT( false );
293  // NOT supported at the moment // TODO
294  }
295 
296  Reference< provider::XScriptProviderFactory > xFac =
297  provider::theMasterScriptProviderFactory::get( that->getComponentContext() );
298 
299  Reference< container::XNameContainer > xName( xFac->createScriptProvider( aContext ), UNO_QUERY );
300  if ( xName.is() )
301  {
302  m_xNameCntrPkgHandler.set( xName );
303  }
304  // TODO what happens if above fails??
305 }
306 
307 // Package
308 
309 beans::Optional< beans::Ambiguous<sal_Bool> >
310 BackendImpl::PackageImpl::isRegistered_(
311  ::osl::ResettableMutexGuard &,
314 {
315  return beans::Optional< beans::Ambiguous<sal_Bool> >(
316  true /* IsPresent */,
317  beans::Ambiguous<sal_Bool>(
318  m_xNameCntrPkgHandler.is() && m_xNameCntrPkgHandler->hasByName(
319  m_url ),
320  false /* IsAmbiguous */ ) );
321 }
322 
323 
324 void BackendImpl::PackageImpl::processPackage_(
325  ::osl::ResettableMutexGuard &,
326  bool doRegisterPackage,
327  bool /* startup */,
330 {
331  if ( !m_xNameCntrPkgHandler.is() )
332  {
333  dp_misc::TRACE("no package handler!!!!\n");
334  throw RuntimeException( "No package Handler " );
335  }
336 
337  if (doRegisterPackage)
338  {
339  // will throw if it fails
340  m_xNameCntrPkgHandler->insertByName( m_url, makeAny( Reference< XPackage >(this) ) );
341 
342  }
343  else // revokePackage()
344  {
345  m_xNameCntrPkgHandler->removeByName( m_url );
346  }
347 }
348 
349 namespace sdecl = comphelper::service_decl;
352  serviceBI,
353  "com.sun.star.comp.deployment.sfwk.PackageRegistryBackend",
355 
356 } // namespace dp_registry::backend::sfwk
357 
358 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
css::uno::Reference< css::linguistic2::XProofreadingIterator > get(css::uno::Reference< css::uno::XComponentContext > const &context)
OUString m_name
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:251
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)
sdecl::class_< BackendImpl, sdecl::with_args< true > > const serviceBI
Definition: dp_sfwk.cxx:350
def check(model)
Reference< container::XNameContainer > m_xNameCntrPkgHandler
Definition: dp_sfwk.cxx:54
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)
#define BACKEND_SERVICE_NAME
Definition: dp_backend.h:41
static uno::Reference< css::uno::XComponentContext > xContext
Definition: init.cxx:2094
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:488
std::unordered_map< OString, INetContentTypeParameter > INetContentTypeParameterList
ResultType type
OUString DpResId(const char *pId)
Definition: dp_shared.hxx:37
sdecl::ServiceDecl const serviceDecl(serviceBI,"com.sun.star.comp.deployment.sfwk.PackageRegistryBackend", BACKEND_SERVICE_NAME)
virtual OUString SAL_CALL getDescription() override
Definition: dp_backend.cxx:479
css::uno::Any SAL_CALL makeAny(const SharedUNOComponent< INTERFACE, COMPONENT > &value)