1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: TemplateScanner.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sd.hxx"
34 #include "TemplateScanner.hxx"
36 #ifndef _COMPHELPER_SERVICEFACTORY_HXX
37 #include <comphelper/processfactory.hxx>
39 #include <comphelper/documentconstants.hxx>
41 #include <tools/debug.hxx>
42 #include <vos/mutex.hxx>
43 #include <vcl/svapp.hxx>
44 #include <com/sun/star/frame/XDocumentTemplates.hpp>
45 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
46 #include <com/sun/star/ucb/XCommandEnvironment.hpp>
47 #include <com/sun/star/ucb/XContentAccess.hpp>
48 #include <com/sun/star/sdbc/XResultSet.hpp>
49 #include <com/sun/star/sdbc/XRow.hpp>
53 using namespace ::com::sun::star
;
54 using namespace ::com::sun::star::uno
;
58 const ::rtl::OUString TITLE
= ::rtl::OUString::createFromAscii ("Title");
59 const ::rtl::OUString TARGET_DIR_URL
= ::rtl::OUString::createFromAscii ("TargetDirURL");
60 const ::rtl::OUString DESCRIPTION
= ::rtl::OUString::createFromAscii ("TypeDescription");
61 const ::rtl::OUString TARGET_URL
= ::rtl::OUString::createFromAscii ("TargetURL");
63 const ::rtl::OUString DOCTEMPLATES
= ::rtl::OUString::createFromAscii ("com.sun.star.frame.DocumentTemplates");
65 // These strings are used to find impress templates in the tree of
66 // template files. Should probably be determined dynamically.
67 const ::rtl::OUString IMPRESS_BIN_TEMPLATE
= ::rtl::OUString::createFromAscii ("application/vnd.stardivision.impress");
68 const ::rtl::OUString IMPRESS_XML_TEMPLATE
= MIMETYPE_VND_SUN_XML_IMPRESS
;
69 // The following id comes from the bugdoc in #i2764#.
70 const ::rtl::OUString IMPRESS_XML_TEMPLATE_B
= ::rtl::OUString::createFromAscii ("Impress 2.0");
71 const ::rtl::OUString IMPRESS_XML_TEMPLATE_OASIS
= MIMETYPE_OASIS_OPENDOCUMENT_PRESENTATION
;
74 class FolderDescriptor
79 const ::rtl::OUString
& rsTitle
,
80 const ::rtl::OUString
& rsTargetDir
,
81 const ::rtl::OUString
& rsContentIdentifier
,
82 const Reference
<com::sun::star::ucb::XCommandEnvironment
>& rxFolderEnvironment
)
83 : mnPriority(nPriority
),
85 msTargetDir(rsTargetDir
),
86 msContentIdentifier(rsContentIdentifier
),
87 mxFolderEnvironment(rxFolderEnvironment
)
90 ::rtl::OUString msTitle
;
91 ::rtl::OUString msTargetDir
;
92 ::rtl::OUString msContentIdentifier
;
93 // Reference<sdbc::XResultSet> mxFolderResultSet;
94 Reference
<com::sun::star::ucb::XCommandEnvironment
> mxFolderEnvironment
;
96 class Comparator
{ public:
97 bool operator() (const FolderDescriptor
& r1
, const FolderDescriptor
& r2
)
98 { return r1
.mnPriority
< r2
.mnPriority
; }
102 /** Use a heuristic based on the URL of a top-level template folder to
103 assign a priority that is used to sort the folders.
105 int Classify (const ::rtl::OUString
&, const ::rtl::OUString
& rsURL
)
109 if (rsURL
.getLength() == 0)
111 else if (rsURL
.indexOf(::rtl::OUString::createFromAscii("presnt"))>=0)
115 else if (rsURL
.indexOf(::rtl::OUString::createFromAscii("layout"))>=0)
119 else if (rsURL
.indexOf(::rtl::OUString::createFromAscii("educate"))>=0)
123 else if (rsURL
.indexOf(::rtl::OUString::createFromAscii("finance"))>=0)
129 // All other folders are taken for user supplied and have the
137 } // end of anonymous namespace
145 class TemplateScanner::FolderDescriptorList
146 : public ::std::multiset
<FolderDescriptor
,FolderDescriptor::Comparator
>
150 TemplateScanner::TemplateScanner (void)
151 : meState(INITIALIZE_SCANNING
),
153 mpTemplateDirectory(NULL
),
155 mpLastAddedEntry(NULL
),
156 mpFolderDescriptors(new FolderDescriptorList()),
158 mxFolderEnvironment(),
159 mxEntryEnvironment(),
169 TemplateScanner::~TemplateScanner (void)
171 mpFolderDescriptors
.reset();
173 // Delete all entries of the template list that have not been
174 // transferred to another object.
175 std::vector
<TemplateDir
*>::iterator I
;
176 for (I
=maFolderList
.begin(); I
!=maFolderList
.end(); I
++)
184 TemplateScanner::State
TemplateScanner::GetTemplateRoot (void)
186 State
eNextState (INITIALIZE_FOLDER_SCANNING
);
188 Reference
<lang::XMultiServiceFactory
> xFactory
= ::comphelper::getProcessServiceFactory ();
189 DBG_ASSERT (xFactory
.is(), "TemplateScanner::GetTemplateRoot: xFactory is NULL");
193 Reference
<frame::XDocumentTemplates
> xTemplates (
194 xFactory
->createInstance (DOCTEMPLATES
), UNO_QUERY
);
195 DBG_ASSERT (xTemplates
.is(), "TemplateScanner::GetTemplateRoot: xTemplates is NULL");
198 mxTemplateRoot
= xTemplates
->getContent();
211 TemplateScanner::State
TemplateScanner::InitializeEntryScanning (void)
213 State
eNextState (SCAN_ENTRY
);
215 if (maFolderContent
.isFolder())
217 mxEntryEnvironment
= Reference
<com::sun::star::ucb::XCommandEnvironment
>();
219 // We are interested only in three properties: the entry's name,
220 // its URL, and its content type.
221 Sequence
<rtl::OUString
> aProps (3);
223 aProps
[1] = TARGET_URL
;
224 aProps
[2] = DESCRIPTION
;
226 // Create a cursor to iterate over the templates in this folders.
227 ::ucbhelper::ResultSetInclude eInclude
= ::ucbhelper::INCLUDE_DOCUMENTS_ONLY
;
228 mxEntryResultSet
= Reference
<com::sun::star::sdbc::XResultSet
>(
229 maFolderContent
.createCursor(aProps
, eInclude
));
240 TemplateScanner::State
TemplateScanner::ScanEntry (void)
242 State
eNextState (ERROR
);
244 Reference
<com::sun::star::ucb::XContentAccess
> xContentAccess (mxEntryResultSet
, UNO_QUERY
);
245 Reference
<com::sun::star::sdbc::XRow
> xRow (mxEntryResultSet
, UNO_QUERY
);
247 if (xContentAccess
.is() && xRow
.is() && mxEntryResultSet
.is())
249 if (mxEntryResultSet
->next())
251 ::rtl::OUString
sTitle (xRow
->getString (1));
252 ::rtl::OUString
sTargetURL (xRow
->getString (2));
253 ::rtl::OUString
sContentType (xRow
->getString (3));
255 ::rtl::OUString aId
= xContentAccess
->queryContentIdentifierString();
256 ::ucbhelper::Content aContent
= ::ucbhelper::Content (aId
, mxEntryEnvironment
);
257 if (aContent
.isDocument ())
259 // Check wether the entry is an impress template. If so
260 // add a new entry to the resulting list (which is created
261 // first if necessary).
262 if ( (sContentType
== MIMETYPE_OASIS_OPENDOCUMENT_PRESENTATION_TEMPLATE
)
263 || (sContentType
== IMPRESS_XML_TEMPLATE_OASIS
)
264 || (sContentType
== IMPRESS_BIN_TEMPLATE
)
265 || (sContentType
== IMPRESS_XML_TEMPLATE
)
266 || (sContentType
== IMPRESS_XML_TEMPLATE_B
))
268 mpLastAddedEntry
= new TemplateEntry(sTitle
, sTargetURL
);
269 mpTemplateDirectory
->maEntries
.push_back(mpLastAddedEntry
);
273 // Continue scanning entries.
274 eNextState
= SCAN_ENTRY
;
278 if (mpTemplateDirectory
->maEntries
.empty())
280 delete mpTemplateDirectory
;
281 mpTemplateDirectory
= NULL
;
285 ::vos::OGuard
aGuard(Application::GetSolarMutex());
286 maFolderList
.push_back(mpTemplateDirectory
);
289 // Continue with scanning the next folder.
290 eNextState
= SCAN_FOLDER
;
300 TemplateScanner::State
TemplateScanner::InitializeFolderScanning (void)
302 State
eNextState (ERROR
);
304 mxFolderResultSet
= Reference
<sdbc::XResultSet
>();
308 // Create content for template folders.
309 mxFolderEnvironment
= Reference
<com::sun::star::ucb::XCommandEnvironment
>();
310 ::ucbhelper::Content
aTemplateDir (mxTemplateRoot
, mxFolderEnvironment
);
312 // Define the list of properties we are interested in.
313 Sequence
<rtl::OUString
> aProps (2);
315 aProps
[1] = TARGET_DIR_URL
;
317 // Create an cursor to iterate over the template folders.
318 ::ucbhelper::ResultSetInclude eInclude
= ::ucbhelper::INCLUDE_FOLDERS_ONLY
;
319 mxFolderResultSet
= Reference
<sdbc::XResultSet
>(
320 aTemplateDir
.createCursor(aProps
, eInclude
));
321 if (mxFolderResultSet
.is())
322 eNextState
= GATHER_FOLDER_LIST
;
324 catch (::com::sun::star::uno::Exception
&)
335 TemplateScanner::State
TemplateScanner::GatherFolderList (void)
337 State
eNextState (ERROR
);
339 Reference
<com::sun::star::ucb::XContentAccess
> xContentAccess (mxFolderResultSet
, UNO_QUERY
);
340 if (xContentAccess
.is() && mxFolderResultSet
.is())
342 while (mxFolderResultSet
->next())
344 Reference
<sdbc::XRow
> xRow (mxFolderResultSet
, UNO_QUERY
);
347 ::rtl::OUString
sTitle (xRow
->getString (1));
348 ::rtl::OUString
sTargetDir (xRow
->getString (2));
349 ::rtl::OUString aId
= xContentAccess
->queryContentIdentifierString();
351 mpFolderDescriptors
->insert(
353 Classify(sTitle
,sTargetDir
),
357 mxFolderEnvironment
));
361 eNextState
= SCAN_FOLDER
;
370 TemplateScanner::State
TemplateScanner::ScanFolder (void)
372 State
eNextState (ERROR
);
374 if (mpFolderDescriptors
->size() > 0)
376 FolderDescriptor
aDescriptor (*mpFolderDescriptors
->begin());
377 mpFolderDescriptors
->erase(mpFolderDescriptors
->begin());
379 ::rtl::OUString
sTitle (aDescriptor
.msTitle
);
380 ::rtl::OUString
sTargetDir (aDescriptor
.msTargetDir
);
381 ::rtl::OUString
aId (aDescriptor
.msContentIdentifier
);
383 maFolderContent
= ::ucbhelper::Content (aId
, aDescriptor
.mxFolderEnvironment
);
384 if (maFolderContent
.isFolder())
386 // Scan the folder and insert it into the list of template
388 mpTemplateDirectory
= new TemplateDir (sTitle
, sTargetDir
);
389 if (mpTemplateDirectory
!= NULL
)
391 // Continue with scanning all entries in the folder.
392 eNextState
= INITIALIZE_ENTRY_SCAN
;
407 void TemplateScanner::Scan (void)
409 while (HasNextStep())
416 std::vector
<TemplateDir
*>& TemplateScanner::GetFolderList (void)
424 void TemplateScanner::RunNextStep (void)
428 case INITIALIZE_SCANNING
:
429 meState
= GetTemplateRoot();
432 case INITIALIZE_FOLDER_SCANNING
:
433 meState
= InitializeFolderScanning();
437 meState
= ScanFolder();
440 case GATHER_FOLDER_LIST
:
441 meState
= GatherFolderList();
444 case INITIALIZE_ENTRY_SCAN
:
445 meState
= InitializeEntryScanning();
449 meState
= ScanEntry();
459 mxTemplateRoot
.clear();
460 mxTemplateRoot
.clear();
461 mxFolderEnvironment
.clear();
462 mxEntryEnvironment
.clear();
463 mxFolderResultSet
.clear();
464 mxEntryResultSet
.clear();
465 mpLastAddedEntry
= NULL
;
475 bool TemplateScanner::HasNextStep (void)
491 const TemplateEntry
* TemplateScanner::GetLastAddedEntry (void) const
493 return mpLastAddedEntry
;