LCOV - code coverage report
Current view: top level - writerperfect/source/impress - KeynoteImportFilter.cxx (source / functions) Hit Total Coverage
Test: commit e02a6cb2c3e2b23b203b422e4e0680877f232636 Lines: 0 169 0.0 %
Date: 2014-04-14 Functions: 0 16 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /* KeynoteImportFilter: Sets up the filter, and calls OdpExporter
       3             :  * to do the actual filtering
       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             : 
      10             : #include <boost/shared_ptr.hpp>
      11             : #include <com/sun/star/beans/NamedValue.hpp>
      12             : #include <com/sun/star/container/XChild.hpp>
      13             : #include <com/sun/star/io/XInputStream.hpp>
      14             : #include <com/sun/star/ucb/XCommandEnvironment.hpp>
      15             : #include <com/sun/star/ucb/XContent.hpp>
      16             : #include <com/sun/star/xml/sax/XAttributeList.hpp>
      17             : #include <com/sun/star/xml/sax/XDocumentHandler.hpp>
      18             : #include <com/sun/star/xml/sax/InputSource.hpp>
      19             : #include <com/sun/star/xml/sax/XParser.hpp>
      20             : #include <com/sun/star/io/XSeekable.hpp>
      21             : #include <com/sun/star/uno/Reference.h>
      22             : #include <comphelper/processfactory.hxx>
      23             : #include <comphelper/types.hxx>
      24             : #include <cppuhelper/supportsservice.hxx>
      25             : #include <iostream>
      26             : #include <libetonyek/libetonyek.h>
      27             : #include <libodfgen/libodfgen.hxx>
      28             : #include <osl/diagnose.h>
      29             : #include <rtl/tencinfo.h>
      30             : #include <ucbhelper/content.hxx>
      31             : #include <xmloff/attrlist.hxx>
      32             : 
      33             : #include "common/DirectoryStream.hxx"
      34             : #include "common/DocumentHandler.hxx"
      35             : #include "common/WPXSvStream.hxx"
      36             : #include "KeynoteImportFilter.hxx"
      37             : 
      38             : using boost::shared_ptr;
      39             : 
      40             : using namespace ::com::sun::star::uno;
      41             : using com::sun::star::uno::Reference;
      42             : using com::sun::star::io::XInputStream;
      43             : using com::sun::star::io::XSeekable;
      44             : using com::sun::star::uno::Sequence;
      45             : using com::sun::star::uno::Any;
      46             : using com::sun::star::uno::UNO_QUERY;
      47             : using com::sun::star::uno::XInterface;
      48             : using com::sun::star::uno::Exception;
      49             : using com::sun::star::uno::RuntimeException;
      50             : using com::sun::star::beans::PropertyValue;
      51             : using com::sun::star::document::XFilter;
      52             : using com::sun::star::document::XExtendedFilterDetection;
      53             : using com::sun::star::document::XImporter;
      54             : using com::sun::star::xml::sax::InputSource;
      55             : using com::sun::star::xml::sax::XAttributeList;
      56             : using com::sun::star::xml::sax::XDocumentHandler;
      57             : using com::sun::star::xml::sax::XParser;
      58             : 
      59             : namespace beans = com::sun::star::beans;
      60             : namespace container = com::sun::star::container;
      61             : namespace ucb = com::sun::star::ucb;
      62             : 
      63             : namespace
      64             : {
      65             : 
      66             : template<class T>
      67           0 : sal_Bool lcl_queryIsPackage( const Sequence<T> &lComponentData )
      68             : {
      69           0 :     sal_Bool bIsPackage = sal_False;
      70             : 
      71           0 :     const sal_Int32 nLength = lComponentData.getLength();
      72           0 :     const T *pValue = lComponentData.getConstArray();
      73           0 :     for ( sal_Int32 i = 0; i < nLength; ++i)
      74             :     {
      75           0 :         if ( pValue[i].Name == "IsPackage" )
      76             :         {
      77           0 :             pValue[i].Value >>= bIsPackage;
      78           0 :             break;
      79             :         }
      80             :     }
      81             : 
      82           0 :     return bIsPackage;
      83             : }
      84             : 
      85           0 : sal_Bool lcl_isPackage( const Any &rComponentData )
      86             : {
      87           0 :     Sequence < beans::NamedValue > lComponentDataNV;
      88           0 :     Sequence < beans::PropertyValue > lComponentDataPV;
      89             : 
      90           0 :     if ( rComponentData >>= lComponentDataNV )
      91           0 :         return lcl_queryIsPackage( lComponentDataNV );
      92           0 :     else if ( rComponentData >>= lComponentDataPV )
      93           0 :         return lcl_queryIsPackage( lComponentDataPV );
      94             : 
      95           0 :     return false;
      96             : }
      97             : }
      98             : 
      99           0 : sal_Bool SAL_CALL KeynoteImportFilter::filter( const Sequence< ::com::sun::star::beans::PropertyValue >& aDescriptor )
     100             : throw (RuntimeException, std::exception)
     101             : {
     102             :     SAL_INFO("writerperfect", "KeynoteImportFilter::filter");
     103           0 :     sal_Int32 nLength = aDescriptor.getLength();
     104           0 :     const PropertyValue *pValue = aDescriptor.getConstArray();
     105           0 :     Reference < XInputStream > xInputStream;
     106           0 :     Reference < ucb::XContent > xContent;
     107           0 :     sal_Bool bIsPackage = sal_False;
     108           0 :     for ( sal_Int32 i = 0 ; i < nLength; i++)
     109             :     {
     110           0 :         if ( pValue[i].Name == "ComponentData" )
     111           0 :             bIsPackage = lcl_isPackage( pValue[i].Value );
     112           0 :         else if ( pValue[i].Name == "InputStream" )
     113           0 :             pValue[i].Value >>= xInputStream;
     114           0 :         else if ( pValue[i].Name == "UCBContent" )
     115           0 :             pValue[i].Value >>= xContent;
     116             :     }
     117           0 :     if ( !xInputStream.is() )
     118             :     {
     119             :         OSL_ASSERT( false );
     120           0 :         return sal_False;
     121             :     }
     122             : 
     123           0 :     if ( bIsPackage && !xContent.is() )
     124             :     {
     125             :         SAL_WARN("writerperfect", "the input claims to be a package, but does not have UCBContent");
     126           0 :         bIsPackage = false;
     127             :     }
     128             : 
     129             :     // An XML import service: what we push sax messages to..
     130             :     Reference < XDocumentHandler > xInternalHandler(
     131           0 :         mxContext->getServiceManager()->createInstanceWithContext(
     132           0 :             "com.sun.star.comp.Draw.XMLOasisImporter", mxContext),
     133           0 :         css::uno::UNO_QUERY_THROW);
     134             : 
     135             :     // The XImporter sets up an empty target document for XDocumentHandler to write to..
     136           0 :     Reference < XImporter > xImporter(xInternalHandler, UNO_QUERY);
     137           0 :     xImporter->setTargetDocument( mxDoc );
     138             : 
     139             :     // OO Graphics Handler: abstract class to handle document SAX messages, concrete implementation here
     140             :     // writes to in-memory target doc
     141           0 :     DocumentHandler xHandler(xInternalHandler);
     142             : 
     143           0 :     shared_ptr< WPXInputStream > input;
     144           0 :     if ( bIsPackage )
     145           0 :         input.reset( new writerperfect::DirectoryStream( xContent ) );
     146             :     else
     147           0 :         input.reset( new WPXSvInputStream( xInputStream ) );
     148             : 
     149           0 :     OdpGenerator exporter(&xHandler, ODF_FLAT_XML);
     150           0 :     bool tmpParseResult = libetonyek::KEYDocument::parse(input.get(), &exporter);
     151           0 :     return tmpParseResult;
     152             : }
     153             : 
     154           0 : void SAL_CALL KeynoteImportFilter::cancel(  )
     155             : throw (RuntimeException, std::exception)
     156             : {
     157             :     SAL_INFO("writerperfect", "KeynoteImportFilter::cancel");
     158           0 : }
     159             : 
     160             : // XImporter
     161           0 : void SAL_CALL KeynoteImportFilter::setTargetDocument( const Reference< ::com::sun::star::lang::XComponent >& xDoc )
     162             : throw (::com::sun::star::lang::IllegalArgumentException, RuntimeException, std::exception)
     163             : {
     164             :     SAL_INFO("writerperfect", "KeynoteImportFilter::setTargetDocument");
     165           0 :     mxDoc = xDoc;
     166           0 : }
     167             : 
     168             : // XExtendedFilterDetection
     169           0 : OUString SAL_CALL KeynoteImportFilter::detect( com::sun::star::uno::Sequence< PropertyValue >& Descriptor )
     170             : throw( com::sun::star::uno::RuntimeException, std::exception )
     171             : {
     172             :     SAL_INFO("writerperfect", "KeynoteImportFilter::detect");
     173             : 
     174           0 :     sal_Int32 nLength = Descriptor.getLength();
     175           0 :     sal_Int32 nNewLength = nLength + 2;
     176           0 :     sal_Int32 nComponentDataLocation = -1;
     177           0 :     sal_Int32 nTypeNameLocation = -1;
     178           0 :     sal_Int32 nUCBContentLocation = -1;
     179           0 :     bool bIsPackage = false;
     180           0 :     bool bUCBContentChanged = false;
     181           0 :     const PropertyValue *pValue = Descriptor.getConstArray();
     182           0 :     Reference < XInputStream > xInputStream;
     183           0 :     Reference < ucb::XContent > xContent;
     184           0 :     Sequence < beans::NamedValue > lComponentDataNV;
     185           0 :     Sequence < beans::PropertyValue > lComponentDataPV;
     186           0 :     bool bComponentDataNV = true;
     187             : 
     188           0 :     for ( sal_Int32 i = 0 ; i < nLength; i++)
     189             :     {
     190           0 :         if ( pValue[i].Name == "TypeName" )
     191             :         {
     192           0 :             nTypeNameLocation = i;
     193           0 :             --nNewLength;
     194             :         }
     195           0 :         if ( pValue[i].Name == "ComponentData" )
     196             :         {
     197           0 :             bComponentDataNV = pValue[i].Value >>= lComponentDataNV;
     198           0 :             if (!bComponentDataNV)
     199           0 :                 pValue[i].Value >>= lComponentDataPV;
     200           0 :             nComponentDataLocation = i;
     201           0 :             --nNewLength;
     202             :         }
     203           0 :         else if ( pValue[i].Name == "InputStream" )
     204             :         {
     205           0 :             pValue[i].Value >>= xInputStream;
     206             :         }
     207           0 :         else if ( pValue[i].Name == "UCBContent" )
     208             :         {
     209           0 :             pValue[i].Value >>= xContent;
     210           0 :             nUCBContentLocation = i;
     211             :         }
     212             :     }
     213             : 
     214             :     assert(nNewLength >= nLength);
     215             : 
     216           0 :     if (!xInputStream.is())
     217           0 :         return OUString();
     218             : 
     219           0 :     shared_ptr< WPXInputStream > input( new WPXSvInputStream( xInputStream ) );
     220             : 
     221             :     /* Apple Keynote documents come in two variants:
     222             :      * * actual files (zip), only produced by Keynote 5 (at least with
     223             :      *   default settings)
     224             :      * * packages (IOW, directories), produced by Keynote 1-4 and again
     225             :      *   starting with 6.
     226             :      * But since the libetonyek import only works with a stream, we need
     227             :      * to pass it one for the whole package. Here we determine if that
     228             :      * is needed.
     229             :      *
     230             :      * Note: for convenience, we also recognize that the main XML file
     231             :      * from a package was passed and pass the whole package to the
     232             :      * filter instead.
     233             :      */
     234           0 :     if ( xContent.is() )
     235             :     {
     236           0 :         ucbhelper::Content aContent( xContent, Reference< ucb::XCommandEnvironment >(), comphelper::getProcessComponentContext() );
     237             :         try
     238             :         {
     239           0 :             if ( aContent.isFolder() )
     240             :             {
     241           0 :                 input.reset( new writerperfect::DirectoryStream( xContent ) );
     242           0 :                 bIsPackage = true;
     243             :             }
     244             :         }
     245           0 :         catch (...)
     246             :         {
     247           0 :             return OUString();
     248             :         }
     249             : 
     250           0 :         libetonyek::KEYDocumentType type = libetonyek::KEY_DOCUMENT_TYPE_UNKNOWN;
     251           0 :         if ( !libetonyek::KEYDocument::isSupported( input.get(), &type ) )
     252           0 :             return OUString();
     253             : 
     254           0 :         if ( type == libetonyek::KEY_DOCUMENT_TYPE_APXL_FILE )
     255             :         {
     256             :             assert( !bIsPackage );
     257             : 
     258           0 :             const Reference < container::XChild > xChild( xContent, UNO_QUERY );
     259           0 :             if ( xChild.is() )
     260             :             {
     261           0 :                 const Reference < ucb::XContent > xPackageContent( xChild->getParent(), UNO_QUERY );
     262           0 :                 if ( xPackageContent.is() )
     263             :                 {
     264           0 :                     input.reset( new writerperfect::DirectoryStream( xPackageContent ) );
     265           0 :                     if ( libetonyek::KEYDocument::isSupported( input.get() ) )
     266             :                     {
     267           0 :                         xContent = xPackageContent;
     268           0 :                         bUCBContentChanged = true;
     269           0 :                         bIsPackage = true;
     270             :                     }
     271           0 :                 }
     272           0 :             }
     273           0 :         }
     274             :     }
     275             : 
     276             :     // we do not need to insert ComponentData if this is not a package
     277           0 :     if ( !bIsPackage && ( nComponentDataLocation == -1 ) )
     278           0 :         --nNewLength;
     279             : 
     280           0 :     if ( nNewLength > nLength )
     281           0 :         Descriptor.realloc( nNewLength );
     282             : 
     283           0 :     if ( nTypeNameLocation == -1 )
     284             :     {
     285             :         assert( nLength < nNewLength );
     286           0 :         nTypeNameLocation = nLength++;
     287           0 :         Descriptor[nTypeNameLocation].Name = "TypeName";
     288             :     }
     289             : 
     290           0 :     if ( bIsPackage && ( nComponentDataLocation == -1 ) )
     291             :     {
     292             :         assert( nLength < nNewLength );
     293           0 :         nComponentDataLocation = nLength++;
     294           0 :         Descriptor[nComponentDataLocation].Name = "ComponentData";
     295             :     }
     296             : 
     297           0 :     if ( bIsPackage )
     298             :     {
     299           0 :         if (bComponentDataNV)
     300             :         {
     301           0 :             const sal_Int32 nCDSize = lComponentDataNV.getLength();
     302           0 :             lComponentDataNV.realloc( nCDSize + 1 );
     303           0 :             beans::NamedValue aValue;
     304           0 :             aValue.Name = "IsPackage";
     305           0 :             aValue.Value = comphelper::makeBoolAny(true);
     306           0 :             lComponentDataNV[nCDSize] = aValue;
     307           0 :             Descriptor[nComponentDataLocation].Value <<= lComponentDataNV;
     308             :         }
     309             :         else
     310             :         {
     311           0 :             const sal_Int32 nCDSize = lComponentDataPV.getLength();
     312           0 :             lComponentDataPV.realloc( nCDSize + 1 );
     313           0 :             beans::PropertyValue aProp;
     314           0 :             aProp.Name = "IsPackage";
     315           0 :             aProp.Value = comphelper::makeBoolAny(true);
     316           0 :             aProp.Handle = -1;
     317           0 :             aProp.State = beans::PropertyState_DIRECT_VALUE;
     318           0 :             lComponentDataPV[nCDSize] = aProp;
     319           0 :             Descriptor[nComponentDataLocation].Value <<= lComponentDataPV;
     320             :         }
     321             :     }
     322             : 
     323           0 :     if ( bUCBContentChanged )
     324           0 :         Descriptor[nUCBContentLocation].Value <<= xContent;
     325             : 
     326           0 :     const OUString sTypeName("impress_AppleKeynote");
     327           0 :     Descriptor[nTypeNameLocation].Value <<= sTypeName;
     328             : 
     329           0 :     return sTypeName;
     330             : }
     331             : 
     332             : // XInitialization
     333           0 : void SAL_CALL KeynoteImportFilter::initialize( const Sequence< Any >& aArguments )
     334             : throw (Exception, RuntimeException, std::exception)
     335             : {
     336             :     SAL_INFO("writerperfect", "KeynoteImportFilter::initialize");
     337           0 :     Sequence < PropertyValue > aAnySeq;
     338           0 :     sal_Int32 nLength = aArguments.getLength();
     339           0 :     if ( nLength && ( aArguments[0] >>= aAnySeq ) )
     340             :     {
     341           0 :         const PropertyValue *pValue = aAnySeq.getConstArray();
     342           0 :         nLength = aAnySeq.getLength();
     343           0 :         for ( sal_Int32 i = 0 ; i < nLength; i++)
     344             :         {
     345           0 :             if ( pValue[i].Name == "Type" )
     346             :             {
     347           0 :                 pValue[i].Value >>= msFilterName;
     348           0 :                 break;
     349             :             }
     350             :         }
     351           0 :     }
     352           0 : }
     353             : 
     354           0 : OUString KeynoteImportFilter_getImplementationName ()
     355             : throw (RuntimeException)
     356             : {
     357             :     SAL_INFO("writerperfect", "KeynoteImportFilter_getImplementationName");
     358           0 :     return OUString ( "org.libreoffice.comp.Impress.KeynoteImportFilter" );
     359             : }
     360             : 
     361             : #define SERVICE_NAME1 "com.sun.star.document.ImportFilter"
     362             : #define SERVICE_NAME2 "com.sun.star.document.ExtendedTypeDetection"
     363             : 
     364           0 : Sequence< OUString > SAL_CALL KeynoteImportFilter_getSupportedServiceNames(  )
     365             : throw (RuntimeException)
     366             : {
     367             :     SAL_INFO("writerperfect", "KeynoteImportFilter_getSupportedServiceNames");
     368           0 :     Sequence < OUString > aRet(2);
     369           0 :     OUString *pArray = aRet.getArray();
     370           0 :     pArray[0] =  OUString ( SERVICE_NAME1 );
     371           0 :     pArray[1] =  OUString ( SERVICE_NAME2 );
     372           0 :     return aRet;
     373             : }
     374             : 
     375             : #undef SERVICE_NAME2
     376             : #undef SERVICE_NAME1
     377             : 
     378           0 : Reference< XInterface > SAL_CALL KeynoteImportFilter_createInstance( const Reference< XComponentContext > & rContext)
     379             : throw( Exception )
     380             : {
     381             :     SAL_INFO("writerperfect", "KeynoteImportFilter_createInstance");
     382           0 :     return (cppu::OWeakObject *) new KeynoteImportFilter( rContext );
     383             : }
     384             : 
     385             : // XServiceInfo
     386           0 : OUString SAL_CALL KeynoteImportFilter::getImplementationName(  )
     387             : throw (RuntimeException, std::exception)
     388             : {
     389             :     SAL_INFO("writerperfect", "KeynoteImportFilter::getImplementationName");
     390           0 :     return KeynoteImportFilter_getImplementationName();
     391             : }
     392             : 
     393           0 : sal_Bool SAL_CALL KeynoteImportFilter::supportsService( const OUString &rServiceName )
     394             : throw (RuntimeException, std::exception)
     395             : {
     396             :     SAL_INFO("writerperfect", "KeynoteImportFilter::supportsService");
     397           0 :     return cppu::supportsService(this, rServiceName);
     398             : }
     399             : 
     400           0 : Sequence< OUString > SAL_CALL KeynoteImportFilter::getSupportedServiceNames(  )
     401             : throw (RuntimeException, std::exception)
     402             : {
     403             :     SAL_INFO("writerperfect", "KeynoteImportFilter::getSupportedServiceNames");
     404           0 :     return KeynoteImportFilter_getSupportedServiceNames();
     405           0 : }
     406             : 
     407             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10