1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
29 // MARKER(update_precomp.py): autogen include statement, do not remove
30 #include "precompiled_sd.hxx"
32 #include "TemplateScanner.hxx"
34 #include <comphelper/processfactory.hxx>
35 #include <comphelper/documentconstants.hxx>
37 #include <tools/debug.hxx>
38 #include <osl/mutex.hxx>
39 #include <vcl/svapp.hxx>
40 #include <com/sun/star/frame/XDocumentTemplates.hpp>
41 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
42 #include <com/sun/star/ucb/XCommandEnvironment.hpp>
43 #include <com/sun/star/ucb/XContentAccess.hpp>
44 #include <com/sun/star/sdbc/XResultSet.hpp>
45 #include <com/sun/star/sdbc/XRow.hpp>
49 using namespace ::com::sun::star
;
50 using namespace ::com::sun::star::uno
;
54 const ::rtl::OUString TITLE
= ::rtl::OUString::createFromAscii ("Title");
55 const ::rtl::OUString TARGET_DIR_URL
= ::rtl::OUString::createFromAscii ("TargetDirURL");
56 const ::rtl::OUString DESCRIPTION
= ::rtl::OUString::createFromAscii ("TypeDescription");
57 const ::rtl::OUString TARGET_URL
= ::rtl::OUString::createFromAscii ("TargetURL");
59 const ::rtl::OUString DOCTEMPLATES
= ::rtl::OUString::createFromAscii ("com.sun.star.frame.DocumentTemplates");
61 // These strings are used to find impress templates in the tree of
62 // template files. Should probably be determined dynamically.
63 const ::rtl::OUString IMPRESS_BIN_TEMPLATE
= ::rtl::OUString::createFromAscii ("application/vnd.stardivision.impress");
64 const ::rtl::OUString IMPRESS_XML_TEMPLATE
= MIMETYPE_VND_SUN_XML_IMPRESS
;
65 // The following id comes from the bugdoc in #i2764#.
66 const ::rtl::OUString IMPRESS_XML_TEMPLATE_B
= ::rtl::OUString::createFromAscii ("Impress 2.0");
67 const ::rtl::OUString IMPRESS_XML_TEMPLATE_OASIS
= MIMETYPE_OASIS_OPENDOCUMENT_PRESENTATION
;
70 class FolderDescriptor
75 const ::rtl::OUString
& rsTitle
,
76 const ::rtl::OUString
& rsTargetDir
,
77 const ::rtl::OUString
& rsContentIdentifier
,
78 const Reference
<com::sun::star::ucb::XCommandEnvironment
>& rxFolderEnvironment
)
79 : mnPriority(nPriority
),
81 msTargetDir(rsTargetDir
),
82 msContentIdentifier(rsContentIdentifier
),
83 mxFolderEnvironment(rxFolderEnvironment
)
86 ::rtl::OUString msTitle
;
87 ::rtl::OUString msTargetDir
;
88 ::rtl::OUString msContentIdentifier
;
89 // Reference<sdbc::XResultSet> mxFolderResultSet;
90 Reference
<com::sun::star::ucb::XCommandEnvironment
> mxFolderEnvironment
;
92 class Comparator
{ public:
93 bool operator() (const FolderDescriptor
& r1
, const FolderDescriptor
& r2
)
94 { return r1
.mnPriority
< r2
.mnPriority
; }
98 /** Use a heuristic based on the URL of a top-level template folder to
99 assign a priority that is used to sort the folders.
101 int Classify (const ::rtl::OUString
&, const ::rtl::OUString
& rsURL
)
105 if (rsURL
.getLength() == 0)
107 else if (rsURL
.indexOf(::rtl::OUString::createFromAscii("presnt"))>=0)
111 else if (rsURL
.indexOf(::rtl::OUString::createFromAscii("layout"))>=0)
115 else if (rsURL
.indexOf(::rtl::OUString::createFromAscii("educate"))>=0)
119 else if (rsURL
.indexOf(::rtl::OUString::createFromAscii("finance"))>=0)
125 // All other folders are taken for user supplied and have the
133 } // end of anonymous namespace
141 class TemplateScanner::FolderDescriptorList
142 : public ::std::multiset
<FolderDescriptor
,FolderDescriptor::Comparator
>
146 TemplateScanner::TemplateScanner (void)
147 : meState(INITIALIZE_SCANNING
),
149 mpTemplateDirectory(NULL
),
151 mpLastAddedEntry(NULL
),
152 mpFolderDescriptors(new FolderDescriptorList()),
154 mxFolderEnvironment(),
155 mxEntryEnvironment(),
165 TemplateScanner::~TemplateScanner (void)
167 mpFolderDescriptors
.reset();
169 // Delete all entries of the template list that have not been
170 // transferred to another object.
171 std::vector
<TemplateDir
*>::iterator I
;
172 for (I
=maFolderList
.begin(); I
!=maFolderList
.end(); I
++)
180 TemplateScanner::State
TemplateScanner::GetTemplateRoot (void)
182 State
eNextState (INITIALIZE_FOLDER_SCANNING
);
184 Reference
<lang::XMultiServiceFactory
> xFactory
= ::comphelper::getProcessServiceFactory ();
185 DBG_ASSERT (xFactory
.is(), "TemplateScanner::GetTemplateRoot: xFactory is NULL");
189 Reference
<frame::XDocumentTemplates
> xTemplates (
190 xFactory
->createInstance (DOCTEMPLATES
), UNO_QUERY
);
191 DBG_ASSERT (xTemplates
.is(), "TemplateScanner::GetTemplateRoot: xTemplates is NULL");
194 mxTemplateRoot
= xTemplates
->getContent();
207 TemplateScanner::State
TemplateScanner::InitializeEntryScanning (void)
209 State
eNextState (SCAN_ENTRY
);
211 if (maFolderContent
.isFolder())
213 mxEntryEnvironment
= Reference
<com::sun::star::ucb::XCommandEnvironment
>();
215 // We are interested only in three properties: the entry's name,
216 // its URL, and its content type.
217 Sequence
<rtl::OUString
> aProps (3);
219 aProps
[1] = TARGET_URL
;
220 aProps
[2] = DESCRIPTION
;
222 // Create a cursor to iterate over the templates in this folders.
223 ::ucbhelper::ResultSetInclude eInclude
= ::ucbhelper::INCLUDE_DOCUMENTS_ONLY
;
224 mxEntryResultSet
= Reference
<com::sun::star::sdbc::XResultSet
>(
225 maFolderContent
.createCursor(aProps
, eInclude
));
236 TemplateScanner::State
TemplateScanner::ScanEntry (void)
238 State
eNextState (ERROR
);
240 Reference
<com::sun::star::ucb::XContentAccess
> xContentAccess (mxEntryResultSet
, UNO_QUERY
);
241 Reference
<com::sun::star::sdbc::XRow
> xRow (mxEntryResultSet
, UNO_QUERY
);
243 if (xContentAccess
.is() && xRow
.is() && mxEntryResultSet
.is())
245 if (mxEntryResultSet
->next())
247 ::rtl::OUString
sTitle (xRow
->getString (1));
248 ::rtl::OUString
sTargetURL (xRow
->getString (2));
249 ::rtl::OUString
sContentType (xRow
->getString (3));
251 ::rtl::OUString aId
= xContentAccess
->queryContentIdentifierString();
252 ::ucbhelper::Content aContent
= ::ucbhelper::Content (aId
, mxEntryEnvironment
);
253 if (aContent
.isDocument ())
255 // Check wether the entry is an impress template. If so
256 // add a new entry to the resulting list (which is created
257 // first if necessary).
258 if ( (sContentType
== MIMETYPE_OASIS_OPENDOCUMENT_PRESENTATION_TEMPLATE
)
259 || (sContentType
== IMPRESS_XML_TEMPLATE_OASIS
)
260 || (sContentType
== IMPRESS_BIN_TEMPLATE
)
261 || (sContentType
== IMPRESS_XML_TEMPLATE
)
262 || (sContentType
== IMPRESS_XML_TEMPLATE_B
))
264 mpLastAddedEntry
= new TemplateEntry(sTitle
, sTargetURL
);
265 mpTemplateDirectory
->maEntries
.push_back(mpLastAddedEntry
);
269 // Continue scanning entries.
270 eNextState
= SCAN_ENTRY
;
274 if (mpTemplateDirectory
->maEntries
.empty())
276 delete mpTemplateDirectory
;
277 mpTemplateDirectory
= NULL
;
281 SolarMutexGuard aGuard
;
282 maFolderList
.push_back(mpTemplateDirectory
);
285 // Continue with scanning the next folder.
286 eNextState
= SCAN_FOLDER
;
296 TemplateScanner::State
TemplateScanner::InitializeFolderScanning (void)
298 State
eNextState (ERROR
);
300 mxFolderResultSet
= Reference
<sdbc::XResultSet
>();
304 // Create content for template folders.
305 mxFolderEnvironment
= Reference
<com::sun::star::ucb::XCommandEnvironment
>();
306 ::ucbhelper::Content
aTemplateDir (mxTemplateRoot
, mxFolderEnvironment
);
308 // Define the list of properties we are interested in.
309 Sequence
<rtl::OUString
> aProps (2);
311 aProps
[1] = TARGET_DIR_URL
;
313 // Create an cursor to iterate over the template folders.
314 ::ucbhelper::ResultSetInclude eInclude
= ::ucbhelper::INCLUDE_FOLDERS_ONLY
;
315 mxFolderResultSet
= Reference
<sdbc::XResultSet
>(
316 aTemplateDir
.createCursor(aProps
, eInclude
));
317 if (mxFolderResultSet
.is())
318 eNextState
= GATHER_FOLDER_LIST
;
320 catch (::com::sun::star::uno::Exception
&)
331 TemplateScanner::State
TemplateScanner::GatherFolderList (void)
333 State
eNextState (ERROR
);
335 Reference
<com::sun::star::ucb::XContentAccess
> xContentAccess (mxFolderResultSet
, UNO_QUERY
);
336 if (xContentAccess
.is() && mxFolderResultSet
.is())
338 while (mxFolderResultSet
->next())
340 Reference
<sdbc::XRow
> xRow (mxFolderResultSet
, UNO_QUERY
);
343 ::rtl::OUString
sTitle (xRow
->getString (1));
344 ::rtl::OUString
sTargetDir (xRow
->getString (2));
345 ::rtl::OUString aId
= xContentAccess
->queryContentIdentifierString();
347 mpFolderDescriptors
->insert(
349 Classify(sTitle
,sTargetDir
),
353 mxFolderEnvironment
));
357 eNextState
= SCAN_FOLDER
;
366 TemplateScanner::State
TemplateScanner::ScanFolder (void)
368 State
eNextState (ERROR
);
370 if (mpFolderDescriptors
->size() > 0)
372 FolderDescriptor
aDescriptor (*mpFolderDescriptors
->begin());
373 mpFolderDescriptors
->erase(mpFolderDescriptors
->begin());
375 ::rtl::OUString
sTitle (aDescriptor
.msTitle
);
376 ::rtl::OUString
sTargetDir (aDescriptor
.msTargetDir
);
377 ::rtl::OUString
aId (aDescriptor
.msContentIdentifier
);
379 maFolderContent
= ::ucbhelper::Content (aId
, aDescriptor
.mxFolderEnvironment
);
380 if (maFolderContent
.isFolder())
382 // Scan the folder and insert it into the list of template
384 mpTemplateDirectory
= new TemplateDir (sTitle
, sTargetDir
);
385 if (mpTemplateDirectory
!= NULL
)
387 // Continue with scanning all entries in the folder.
388 eNextState
= INITIALIZE_ENTRY_SCAN
;
403 void TemplateScanner::Scan (void)
405 while (HasNextStep())
412 std::vector
<TemplateDir
*>& TemplateScanner::GetFolderList (void)
420 void TemplateScanner::RunNextStep (void)
424 case INITIALIZE_SCANNING
:
425 meState
= GetTemplateRoot();
428 case INITIALIZE_FOLDER_SCANNING
:
429 meState
= InitializeFolderScanning();
433 meState
= ScanFolder();
436 case GATHER_FOLDER_LIST
:
437 meState
= GatherFolderList();
440 case INITIALIZE_ENTRY_SCAN
:
441 meState
= InitializeEntryScanning();
445 meState
= ScanEntry();
455 mxTemplateRoot
.clear();
456 mxTemplateRoot
.clear();
457 mxFolderEnvironment
.clear();
458 mxEntryEnvironment
.clear();
459 mxFolderResultSet
.clear();
460 mxEntryResultSet
.clear();
461 mpLastAddedEntry
= NULL
;
471 bool TemplateScanner::HasNextStep (void)
487 const TemplateEntry
* TemplateScanner::GetLastAddedEntry (void) const
489 return mpLastAddedEntry
;
494 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */