blob: ef8b774ffeedec86b7eb5ea602bdcaa3d1a65908 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
#include "filterdetect.hxx"
#include <osl/diagnose.h>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/io/XActiveDataSource.hpp>
#include <com/sun/star/io/XOutputStream.hpp>
#include <com/sun/star/io/XInputStream.hpp>
#include <com/sun/star/io/XSeekable.hpp>
#include <com/sun/star/xml/sax/XDocumentHandler.hpp>
#include <com/sun/star/xml/sax/InputSource.hpp>
#include <com/sun/star/xml/sax/XParser.hpp>
#include <com/sun/star/xml/XImportFilter.hpp>
#include <com/sun/star/xml/XExportFilter.hpp>
#include <com/sun/star/frame/XModel.hpp>
#include <com/sun/star/frame/XController.hpp>
#include <com/sun/star/task/XStatusIndicator.hpp>
#include <com/sun/star/task/XStatusIndicatorFactory.hpp>
#include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
#include <com/sun/star/style/XStyleLoader.hpp>
#include <com/sun/star/io/XInputStream.hpp>
#include <com/sun/star/document/XExtendedFilterDetection.hpp>
#include <com/sun/star/beans/PropertyState.hpp>
#include <com/sun/star/ucb/XSimpleFileAccess.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
using namespace rtl;
using namespace com::sun::star::uno;
using namespace com::sun::star::document;
using namespace com::sun::star::lang;
using namespace com::sun::star::io;
using namespace com::sun::star::beans;
using namespace com::sun::star::xml::sax;
using namespace com::sun::star::xml;
using namespace com::sun::star::task;
using namespace com::sun::star::frame;
using namespace com::sun::star::container;
using namespace com::sun::star::ucb;
OUString SAL_CALL FilterDetect::detect(Sequence< PropertyValue >& aArguments )
throw( RuntimeException )
{
// type name to return
OUString sOriginalTypeName;
OUString sTypeName;
OUString sURL;
// stream of the document to be detected
Reference< XInputStream > xInStream;
for ( sal_Int32 i = 0 ; i < aArguments.getLength(); i++)
{
OUString aName = aArguments[i].Name;
if (aName.equalsAscii("TypeName" ) )
aArguments[i].Value >>= sOriginalTypeName;
if (aName.equalsAscii("URL" ) )
aArguments[i].Value >>= sURL;
if (aName.equalsAscii("InputStream" ) )
aArguments[i].Value >>= xInStream;
}
if (!xInStream.is())
{
// open the stream if it was not suplied by the framework
Reference< XSimpleFileAccess > xSFI(mxMSF->createInstance(
OUString::createFromAscii("com.sun.star.ucb.SimpleFileAccess" )), UNO_QUERY);
if (sURL.getLength() > 0 && xSFI.is())
{
try
{
xInStream = xSFI->openFileRead( sURL);
}
catch( Exception& )
{
return sTypeName;
}
} else {
// failed to access UCB
return sTypeName;
}
}
// flatxml starts with an office:document element. this element
// conatains a clas="..." attribut by which we can deduct the
// type of document that is to be loaded
//
// WARNING:
// parsing the plain text of the document is an easy way to do this
// but not the purest solution, since namespaces and other xml details
// may lead to another syntactic expression of the same document.
// this example works for the way the office serializes it's XML stream
// but might need extension for other data sources...
static OString aDocToken("office:document");
// static OString aClassToken("office:class=\"");
static OString aMimeTypeToken("office:mimetype=\"");
sal_Int32 nHeadSize = 4096;
Sequence< sal_Int8 > aHeadData(nHeadSize);
// rewind seekable stream
Reference< XSeekable > xSeek(xInStream, UNO_QUERY);
if (xSeek.is())
xSeek->seek(0);
long bytestRead = xInStream->readBytes(aHeadData, nHeadSize);
OString aHead = OString((const sal_Char *)aHeadData.getConstArray(), bytestRead).toAsciiLowerCase();
// check for document element of flatxml format
if (aHead.indexOf(aDocToken) >= 0)
{
// read document class
sal_Int32 n = aHead.indexOf(aMimeTypeToken);
if (n >= 0)
{
n += aMimeTypeToken.getLength();
OString aMimeType = aHead.copy(n, aHead.indexOf('\"', n) - n);
// return type for class found
if (aMimeType.equals("application/x-vnd.oasis.opendocument.text") ||
aMimeType.equals("application/vnd.oasis.opendocument.text"))
sTypeName = OUString::createFromAscii("devguide_FlatXMLType_Cpp_writer");
else if (aMimeType.equals("application/x-vnd.oasis.opendocument.text-master") ||
aMimeType.equals("application/vnd.oasis.opendocument.text-master"))
sTypeName = OUString::createFromAscii("devguide_FlatXMLType_Cpp_master");
else if (aMimeType.equals("application/x-vnd.oasis.openoffice.text-global") ||
aMimeType.equals("application/vnd.oasis.openoffice.text-global"))
sTypeName = OUString::createFromAscii("devguide_FlatXMLType_Cpp_master");
else if (aMimeType.equals("application/x-vnd.oasis.opendocument.spreadsheet") ||
aMimeType.equals("application/vnd.oasis.opendocument.spreadsheet"))
sTypeName = OUString::createFromAscii("devguide_FlatXMLType_Cpp_calc");
else if (aMimeType.equals("application/x-vnd.oasis.opendocument.drawing") ||
aMimeType.equals("application/vnd.oasis.opendocument.drawing"))
sTypeName = OUString::createFromAscii("devguide_FlatXMLType_Cpp_draw");
else if (aMimeType.equals("application/x-vnd.oasis.opendocument.presentation") ||
aMimeType.equals("application/vnd.oasis.opendocument.presentation"))
sTypeName = OUString::createFromAscii("devguide_FlatXMLType_Cpp_impress");
else if (aMimeType.equals("application/x-vnd.oasis.opendocument.presentation") ||
aMimeType.equals("application/vnd.oasis.opendocument.presentation"))
sTypeName = OUString::createFromAscii("devguide_FlatXMLType_Cpp_impress");
}
}
return sTypeName;
}
// XInitialization
void SAL_CALL FilterDetect::initialize( const Sequence< Any >& aArguments )
throw (Exception, RuntimeException)
{
Sequence < PropertyValue > aAnySeq;
sal_Int32 nLength = aArguments.getLength();
if ( nLength && ( aArguments[0] >>= aAnySeq ) )
{
const PropertyValue * pValue = aAnySeq.getConstArray();
nLength = aAnySeq.getLength();
for ( sal_Int32 i = 0 ; i < nLength; i++)
{
if ( pValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "Type" ) ) )
{
pValue[i].Value >>= msFilterName;
}
else if ( pValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "UserData" ) ) )
{
pValue[i].Value >>= msUserData;
}
else if ( pValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "TemplateName" ) ) )
{
pValue[i].Value>>=msTemplateName;
}
}
}
}
OUString FilterDetect_getImplementationName ()
throw (RuntimeException)
{
return OUString ( RTL_CONSTASCII_USTRINGPARAM ( "devguide.officedev.samples.filter.FlatXmlDetect" ) );
}
#define SERVICE_NAME1 "com.sun.star.document.ExtendedTypeDetection"
sal_Bool SAL_CALL FilterDetect_supportsService( const OUString& ServiceName )
throw (RuntimeException)
{
return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME1 ) );
}
Sequence< OUString > SAL_CALL FilterDetect_getSupportedServiceNames( )
throw (RuntimeException)
{
Sequence < OUString > aRet(2);
OUString* pArray = aRet.getArray();
pArray[0] = OUString ( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME1 ) );
return aRet;
}
#undef SERVICE_NAME1
#undef SERVICE_NAME2
Reference< XInterface > SAL_CALL FilterDetect_createInstance( const Reference< XMultiServiceFactory > & rSMgr)
throw( Exception )
{
return (cppu::OWeakObject*) new FilterDetect( rSMgr );
}
// XServiceInfo
OUString SAL_CALL FilterDetect::getImplementationName( )
throw (RuntimeException)
{
return FilterDetect_getImplementationName();
}
sal_Bool SAL_CALL FilterDetect::supportsService( const OUString& rServiceName )
throw (RuntimeException)
{
return FilterDetect_supportsService( rServiceName );
}
Sequence< OUString > SAL_CALL FilterDetect::getSupportedServiceNames( )
throw (RuntimeException)
{
return FilterDetect_getSupportedServiceNames();
}