xref: /trunk/main/ucb/source/ucp/odma/odma_provider.cxx (revision 2f86921c)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_ucb.hxx"
26 
27 /**************************************************************************
28 								TODO
29  **************************************************************************
30 
31  *************************************************************************/
32 #include <ucbhelper/contentidentifier.hxx>
33 #include "odma_provider.hxx"
34 #include "odma_content.hxx"
35 #include "odma_contentprops.hxx"
36 #include <com/sun/star/util/Date.hpp>
37 #include <com/sun/star/util/Time.hpp>
38 #include <rtl/uri.hxx>
39 #include <algorithm>
40 #include <osl/file.hxx>
41 
42 using namespace com::sun::star;
43 using namespace odma;
44 
45 //=========================================================================
46 //=========================================================================
47 //
48 // ContentProvider Implementation.
49 //
50 //=========================================================================
51 //=========================================================================
52 ODMHANDLE ContentProvider::m_aOdmHandle = NULL;
53 
ContentProvider(const uno::Reference<lang::XMultiServiceFactory> & rSMgr)54 ContentProvider::ContentProvider(
55                 const uno::Reference< lang::XMultiServiceFactory >& rSMgr )
56 : ::ucbhelper::ContentProviderImplHelper( rSMgr )
57 {
58 
59 }
60 
61 //=========================================================================
62 // virtual
~ContentProvider()63 ContentProvider::~ContentProvider()
64 {
65 	ContentsMap::iterator aIter = m_aContents.begin();
66 	for (;aIter != m_aContents.end() ;++aIter )
67 	{
68 		if(aIter->second->m_bIsOpen)
69 			closeDocument(aIter->first);
70 	}
71 	if(m_aOdmHandle)
72 	{
73 		NODMUnRegisterApp(m_aOdmHandle);
74 		m_aOdmHandle = NULL;
75 	}
76 }
77 // -----------------------------------------------------------------------------
getHandle()78 ODMHANDLE ContentProvider::getHandle()
79 {
80 	if(!m_aOdmHandle)
81 	{
82 		ODMSTATUS odm = NODMRegisterApp(&m_aOdmHandle,ODM_API_VERSION,ODMA_ODMA_REGNAME,NULL,NULL);
83 		switch(odm)
84 		{
85 		case ODM_SUCCESS:
86 			break;
87 		case ODM_E_NODMS:
88 			break;
89 		case ODM_E_CANTINIT:
90 			break;
91 		case ODM_E_VERSION:
92 			break;
93 		default:
94 			break;
95 		}
96 	}
97 	return m_aOdmHandle;
98 }
99 // -----------------------------------------------------------------------------
100 
101 //=========================================================================
102 //
103 // XInterface methods.
104 //
105 //=========================================================================
106 
107 // @@@ Add own interfaces.
108 XINTERFACE_IMPL_3( ContentProvider,
109                    lang::XTypeProvider,
110                    lang::XServiceInfo,
111                    ucb::XContentProvider );
112 
113 //=========================================================================
114 //
115 // XTypeProvider methods.
116 //
117 //=========================================================================
118 
119 // @@@ Add own interfaces.
120 XTYPEPROVIDER_IMPL_3( ContentProvider,
121                       lang::XTypeProvider,
122                       lang::XServiceInfo,
123                       ucb::XContentProvider );
124 
125 //=========================================================================
126 //
127 // XServiceInfo methods.
128 //
129 //=========================================================================
130 
131 // @@@ Adjust implementation name. Keep the prefix "com.sun.star.comp."!
132 // @@@ Adjust service name.
133 XSERVICEINFO_IMPL_1( ContentProvider,
134                      rtl::OUString::createFromAscii(
135                             "com.sun.star.comp.odma.ContentProvider" ),
136                      rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(ODMA_CONTENT_PROVIDER_SERVICE_NAME) ) );
137 
138 //=========================================================================
139 //
140 // Service factory implementation.
141 //
142 //=========================================================================
143 
144 ONE_INSTANCE_SERVICE_FACTORY_IMPL( ContentProvider );
145 
146 //=========================================================================
147 //
148 // XContentProvider methods.
149 //
150 //=========================================================================
151 
152 // virtual
queryContent(const uno::Reference<ucb::XContentIdentifier> & Identifier)153 uno::Reference< ucb::XContent > SAL_CALL ContentProvider::queryContent(
154         const uno::Reference< ucb::XContentIdentifier >& Identifier )
155     throw( ucb::IllegalIdentifierException, uno::RuntimeException )
156 {
157 	// Check URL scheme...
158 	if(!getHandle())
159 		throw ucb::IllegalIdentifierException();
160 
161     rtl::OUString aScheme( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(ODMA_URL_SCHEME) ) );
162 	sal_Int32 nIndex = 0;
163 	rtl::OUString sOdma = aScheme.getToken(3,'.',nIndex);
164 	rtl::OUString sCanonicURL = Identifier->getContentIdentifier();
165 	// check if url starts with odma
166     if ( !(Identifier->getContentProviderScheme().equalsIgnoreAsciiCase( aScheme ) ||
167 		   Identifier->getContentProviderScheme().equalsIgnoreAsciiCase( sOdma )) )
168         throw ucb::IllegalIdentifierException();
169 
170 	if(!(	sCanonicURL.matchIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM(ODMA_URL_SCHEME_SHORT ODMA_URL_SHORT)) ||
171 			sCanonicURL.matchIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM(ODMA_URL_SCHEME ODMA_URL_SHORT))))
172 		throw ucb::IllegalIdentifierException();
173 
174 	// @@@ Further id checks may go here...
175 #if 0
176 	if ( id-check-failes )
177         throw ucb::IllegalIdentifierException();
178 #endif
179 
180 	// @@@ Id normalization may go here...
181 #if 0
182 	// Normalize URL and create new Id.
183     rtl::OUString aCanonicURL = ( Identifier->getContentIdentifier() );
184     uno::Reference< ucb::XContentIdentifier > xCanonicId
185         = new ::ucb::ContentIdentifier( m_xSMgr, aCanonicURL );
186 #else
187     uno::Reference< ucb::XContentIdentifier > xCanonicId = Identifier;
188 #endif
189 
190 	osl::MutexGuard aGuard( m_aMutex );
191 
192 	// Check, if a content with given id already exists...
193     uno::Reference< ucb::XContent > xContent
194 		= queryExistingContent( xCanonicId ).get();
195 	if ( xContent.is() )
196 		return xContent;
197 
198 	// @@@ Decision, which content implementation to instanciate may be
199 	//     made here ( in case you have different content classes ).
200 
201 	// Create a new content.
202 
203 	sCanonicURL = convertURL(sCanonicURL);
204 
205 	::rtl::Reference<ContentProperties> aProp;
206 	// first check if we got an ODMA ID from outside
207 	if( sCanonicURL.matchIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM(ODMA_URL_ODMAID)))
208 	{// we get an orignal ODMA id so we have to look for the name
209 		::rtl::OString sDocId = ::rtl::OUStringToOString(sCanonicURL,RTL_TEXTENCODING_MS_1252);
210 		sal_Char* lpszDocName = new sal_Char[ODM_NAME_MAX];
211 
212 		ODMSTATUS odm = NODMGetDocInfo(	getHandle(),
213 										const_cast<sal_Char*>(sDocId.getStr()),
214 										ODM_NAME,
215 										lpszDocName,
216 										ODM_NAME_MAX
217 									);
218 		if(odm == ODM_SUCCESS)
219 		{
220 			aProp = new ContentProperties();
221 			aProp->m_sDocumentName = ::rtl::OStringToOUString(rtl::OString(lpszDocName),RTL_TEXTENCODING_ASCII_US);
222 			aProp->m_sDocumentId   = sDocId;
223 			aProp->m_sContentType  = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(ODMA_CONTENT_TYPE));
224 			append(aProp);
225 		}
226 		delete [] lpszDocName;
227 	}
228 	else // we got an already fetched name here so look for it
229 	{
230 		// we have a valid document name
231 		aProp = getContentPropertyWithTitle(sCanonicURL);
232 		if(!aProp.is())
233 			aProp = getContentPropertyWithSavedAsName(sCanonicURL);
234 		if(!aProp.is())
235 		{
236 			if(sCanonicURL.equalsIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("/")))
237 			{ // found only the scheme
238 				aProp = new ContentProperties();
239 				aProp->m_sDocumentId = "/";
240 				aProp->m_sTitle = sCanonicURL;
241 				aProp->m_bIsFolder = sal_True;
242 				aProp->m_bIsDocument = !aProp->m_bIsFolder;
243 				m_aContents.insert(ContentsMap::value_type(aProp->m_sDocumentId,aProp));
244 			}
245 			else
246 				aProp = queryContentProperty(sCanonicURL);
247 		}
248 	}
249 	if(!aProp.is())
250 		throw ucb::IllegalIdentifierException();
251 
252 	xContent = new Content( m_xSMgr, this, xCanonicId ,aProp);
253     registerNewContent( xContent );
254 
255 	if ( !xContent->getIdentifier().is() )
256         throw ucb::IllegalIdentifierException();
257 
258 	return xContent;
259 }
260 // -----------------------------------------------------------------------------
closeDocument(const::rtl::OString & _sDocumentId)261 void ContentProvider::closeDocument(const ::rtl::OString& _sDocumentId)
262 {
263 	ContentsMap::iterator aIter = m_aContents.find(_sDocumentId);
264 	if(aIter != m_aContents.end())
265 	{
266 		DWORD dwFlags = ODM_SILENT;
267 		ODMSTATUS odm = NODMCloseDocEx(	ContentProvider::getHandle(),
268 										const_cast<sal_Char*>(_sDocumentId.getStr()),
269 										&dwFlags,
270 										0xFFFFFFFF,
271 										0xFFFFFFFF,
272 										NULL,
273 										0);
274 		OSL_ENSURE(odm == ODM_SUCCESS,"Error while closing a document!");
275 		if(odm == ODM_SUCCESS)
276 			aIter->second->m_bIsOpen = sal_False;
277 	}
278 }
279 // -----------------------------------------------------------------------------
saveDocument(const::rtl::OString & _sDocumentId)280 void ContentProvider::saveDocument(const ::rtl::OString& _sDocumentId)
281 {
282 	ContentsMap::iterator aIter = m_aContents.find(_sDocumentId);
283 	if(aIter != m_aContents.end())
284 	{
285 		sal_Char* lpszDocId = new sal_Char[ODM_DOCID_MAX];
286 		DWORD dwFlags = ODM_SILENT;
287 		ODMSTATUS odm = NODMSaveDocEx(getHandle(),
288 									const_cast<sal_Char*>(_sDocumentId.getStr()),
289 									lpszDocId,
290 									&dwFlags);
291 		OSL_ENSURE(odm == ODM_SUCCESS,"Could not save document!");
292 		if(odm != ODM_SUCCESS)
293 		{
294 			delete [] lpszDocId;
295 			throw uno::Exception();
296 		}
297 		aIter->second->m_sDocumentId = rtl::OString(lpszDocId);
298 		delete [] lpszDocId;
299 	}
300 }
301 // -----------------------------------------------------------------------------
toDate(const::rtl::OString & _sSQLString)302 util::Date toDate(const ::rtl::OString& _sSQLString)
303 {
304 	sal_uInt16	nYear	= 0,
305 				nMonth	= 0,
306 				nDay	= 0;
307 	nYear	= (sal_uInt16)_sSQLString.copy(0,4).toInt32();
308 	nMonth	= (sal_uInt16)_sSQLString.copy(4,2).toInt32();
309 	nDay	= (sal_uInt16)_sSQLString.copy(6,2).toInt32();
310 
311 	return util::Date(nDay,nMonth,nYear);
312 }
313 //-----------------------------------------------------------------------------
toTime(const::rtl::OString & _sSQLString)314 util::Time toTime(const ::rtl::OString& _sSQLString)
315 {
316 	sal_uInt16	nHour	= 0,
317 				nMinute	= 0,
318 				nSecond	= 0;
319 	nHour	= (sal_uInt16)_sSQLString.copy(8,2).toInt32();
320 	nMinute = (sal_uInt16)_sSQLString.copy(10,2).toInt32();
321 	nSecond = (sal_uInt16)_sSQLString.copy(12,2).toInt32();
322 
323 	return util::Time(0,nHour,nMinute,nSecond);
324 }
325 //-----------------------------------------------------------------------------
toDateTime(const::rtl::OString & _sSQLString)326 util::DateTime toDateTime(const ::rtl::OString& _sSQLString)
327 {
328 	util::Date aDate = toDate(_sSQLString);
329 	util::Time aTime = toTime(_sSQLString);
330 
331 	return util::DateTime(0,aTime.Seconds,aTime.Minutes,aTime.Hours,aDate.Day,aDate.Month,aDate.Year);
332 }
333 // -----------------------------------------------------------------------------
fillDocumentProperties(const::rtl::Reference<ContentProperties> & _rProp)334 void ContentProvider::fillDocumentProperties(const ::rtl::Reference<ContentProperties>& _rProp)
335 {
336 	// read some properties from the DMS
337 	sal_Char* lpszDocInfo = new sal_Char[ODM_DOCID_MAX];
338 	sal_Char* pDocId = const_cast<sal_Char*>(_rProp->m_sDocumentId.getStr());
339 
340 	// read the create date of the document
341 	ODMSTATUS odm = NODMGetDocInfo(	getHandle(),
342 									pDocId,
343 									ODM_CREATEDDATE,
344 									lpszDocInfo,
345 									ODM_DOCID_MAX);
346 	if(odm == ODM_SUCCESS)
347 		_rProp->m_aDateCreated = toDateTime(::rtl::OString(lpszDocInfo));
348 
349 	// read the modified date of the document
350 	odm = NODMGetDocInfo(	getHandle(),
351 							pDocId,
352 							ODM_MODIFYDATE,
353 							lpszDocInfo,
354 							ODM_DOCID_MAX);
355 	if(odm == ODM_SUCCESS)
356 		_rProp->m_aDateModified = toDateTime(::rtl::OString(lpszDocInfo));
357 
358 	// read the title of the document
359 	odm = NODMGetDocInfo(	getHandle(),
360 							pDocId,
361 							ODM_TITLETEXT,
362 							lpszDocInfo,
363 							ODM_DOCID_MAX);
364 	if(odm == ODM_SUCCESS)
365 		_rProp->m_sTitle = ::rtl::OStringToOUString(rtl::OString(lpszDocInfo),RTL_TEXTENCODING_ASCII_US);
366 
367 	// read the name of the document
368 	odm = NODMGetDocInfo(	getHandle(),
369 							pDocId,
370 							ODM_NAME,
371 							lpszDocInfo,
372 							ODM_DOCID_MAX);
373 	if(odm == ODM_SUCCESS)
374 		_rProp->m_sDocumentName = ::rtl::OStringToOUString(rtl::OString(lpszDocInfo),RTL_TEXTENCODING_ASCII_US);
375 
376 	// read the author of the document
377 	odm = NODMGetDocInfo(	getHandle(),
378 							pDocId,
379 							ODM_AUTHOR,
380 							lpszDocInfo,
381 							ODM_DOCID_MAX);
382 	if(odm == ODM_SUCCESS)
383 		_rProp->m_sAuthor = ::rtl::OStringToOUString(rtl::OString(lpszDocInfo),RTL_TEXTENCODING_ASCII_US);
384 
385 	// read the subject of the document
386 	odm = NODMGetDocInfo(	getHandle(),
387 							pDocId,
388 							ODM_SUBJECT,
389 							lpszDocInfo,
390 							ODM_DOCID_MAX);
391 	if(odm == ODM_SUCCESS)
392 		_rProp->m_sSubject = ::rtl::OStringToOUString(rtl::OString(lpszDocInfo),RTL_TEXTENCODING_ASCII_US);
393 
394 	// read the keywords of the document
395 	odm = NODMGetDocInfo(	getHandle(),
396 							pDocId,
397 							ODM_KEYWORDS,
398 							lpszDocInfo,
399 							ODM_DOCID_MAX);
400 	if(odm == ODM_SUCCESS)
401 		_rProp->m_sKeywords = ::rtl::OStringToOUString(rtl::OString(lpszDocInfo),RTL_TEXTENCODING_ASCII_US);
402 
403 /*
404 	odm = NODMGetDocInfo(	getHandle(),
405 									const_cast<sal_Char*>(_rProp->m_sDocumentId.getStr()),
406 									ODM_URL,
407 									lpszDocInfo,
408 									ODM_DOCID_MAX);
409 */
410 	delete [] lpszDocInfo;
411 }
412 // -----------------------------------------------------------------------------
append(const::rtl::Reference<ContentProperties> & _rProp)413 void ContentProvider::append(const ::rtl::Reference<ContentProperties>& _rProp)
414 {
415 	// now fill some more properties
416 	fillDocumentProperties(_rProp);
417 	// and append them
418 	m_aContents.insert(ContentsMap::value_type(_rProp->m_sDocumentId,_rProp));
419 }
420 // -----------------------------------------------------------------------------
queryContentProperty(const::rtl::OUString & _sDocumentName)421 ::rtl::Reference<ContentProperties> ContentProvider::queryContentProperty(const ::rtl::OUString& _sDocumentName)
422 {
423 	::rtl::Reference<ContentProperties> aReturn;
424 	sal_Char* lpszDMSList	= new sal_Char[ODM_DMSID_MAX];
425 
426 	ODMSTATUS odm = NODMGetDMS(ODMA_ODMA_REGNAME, lpszDMSList);
427 	if(odm == ODM_SUCCESS)
428 	{
429 		sal_Char* pQueryId = new sal_Char[ODM_QUERYID_MAX];
430 		lpszDMSList[strlen(lpszDMSList)+1] = '\0';
431 
432 		::rtl::OString sTitleText(::rtl::OUStringToOString(_sDocumentName,RTL_TEXTENCODING_ASCII_US));
433 		::rtl::OString sQuery("SELECT ODM_DOCID, ODM_NAME WHERE ODM_TITLETEXT = '");
434 		sQuery += sTitleText;
435 		sQuery += "'";
436 
437 		DWORD dwFlags = ODM_SPECIFIC;
438 		odm = NODMQueryExecute(getHandle(), sQuery,dwFlags, lpszDMSList, pQueryId );
439 		if(odm == ODM_SUCCESS)
440 		{
441 			sal_uInt16 nCount		= 10;
442 			sal_uInt16 nMaxCount	= 10;
443 			sal_Char* lpszDocId		= new sal_Char[ODM_DOCID_MAX * nMaxCount];
444 			sal_Char* lpszDocName	= new sal_Char[ODM_NAME_MAX * nMaxCount];
445 			sal_Char* lpszDocInfo	= new sal_Char[ODM_DOCID_MAX];
446 
447 			::rtl::OUString sContentType(RTL_CONSTASCII_USTRINGPARAM(ODMA_CONTENT_TYPE));
448 			do
449 			{
450 				if(nCount >= nMaxCount)
451 				{
452 					// get the result
453 					nCount = nMaxCount;
454 					odm = NODMQueryGetResults(getHandle(), pQueryId,lpszDocId, lpszDocName, ODM_NAME_MAX, (WORD*)&nCount);
455 				}
456 				if(odm == ODM_SUCCESS)
457 					for(sal_uInt16 i = 0; i < nCount; ++i)
458 					{
459 						odm = NODMGetDocInfo(	getHandle(),
460 												&lpszDocId[ODM_DOCID_MAX*i],
461 												ODM_TITLETEXT,
462 												lpszDocInfo,
463 												ODM_DOCID_MAX);
464 						if( odm == ODM_SUCCESS && sTitleText == ::rtl::OString(lpszDocInfo))
465 						{
466 							aReturn = new ContentProperties();
467 							aReturn->m_sDocumentName	= ::rtl::OStringToOUString(rtl::OString(&lpszDocName[ODM_NAME_MAX*i]),RTL_TEXTENCODING_ASCII_US);
468 							aReturn->m_sDocumentId	= ::rtl::OString(&lpszDocId[ODM_DOCID_MAX*i]);
469 							aReturn->m_sContentType	= sContentType;
470 							append(aReturn);
471 							nCount = 0; // break condition from outer loop
472 							break;
473 						}
474 					}
475 			}
476 			while(nCount > nMaxCount);
477 
478 			delete [] lpszDocInfo;
479 			delete [] lpszDocId;
480 			delete [] lpszDocName;
481 		}
482 
483 		// now close the query
484 		odm = NODMQueryClose(ContentProvider::getHandle(), pQueryId);
485 		delete [] pQueryId;
486 	}
487 	delete [] lpszDMSList;
488 
489 
490 	return aReturn;
491 }
492 // -----------------------------------------------------------------------------
getContentProperty(const::rtl::OUString & _sName,const ContentPropertiesMemberFunctor & _aFunctor) const493 ::rtl::Reference<ContentProperties> ContentProvider::getContentProperty(const ::rtl::OUString& _sName,
494 																   const ContentPropertiesMemberFunctor& _aFunctor) const
495 {
496 	::rtl::Reference<ContentProperties> aReturn;
497 	ContentsMap::const_iterator aFind = ::std::find_if(	m_aContents.begin(),
498 														m_aContents.end(),
499 														::std::compose1(
500 															::std::bind2nd(_aFunctor,_sName),
501 															::std::select2nd<ContentsMap::value_type>()
502 														)
503 													);
504 	if(aFind != m_aContents.end())
505 		aReturn = aFind->second;
506 	return aReturn;
507 }
508 // -----------------------------------------------------------------------------
getContentPropertyWithSavedAsName(const::rtl::OUString & _sSaveAsName) const509 ::rtl::Reference<ContentProperties> ContentProvider::getContentPropertyWithSavedAsName(const ::rtl::OUString& _sSaveAsName) const
510 {
511 	ContentPropertiesMemberFunctor aFunc(::std::mem_fun(&ContentProperties::getSavedAsName));
512 	return getContentProperty(_sSaveAsName,aFunc);
513 }
514 // -----------------------------------------------------------------------------
getContentPropertyWithTitle(const::rtl::OUString & _sTitle) const515 ::rtl::Reference<ContentProperties> ContentProvider::getContentPropertyWithTitle(const ::rtl::OUString& _sTitle) const
516 {
517 	ContentPropertiesMemberFunctor aFunc(::std::mem_fun(&ContentProperties::getTitle));
518 	return getContentProperty(_sTitle,aFunc);
519 }
520 // -----------------------------------------------------------------------------
openDoc(const::rtl::Reference<ContentProperties> & _rProp)521 ::rtl::OUString ContentProvider::openDoc(const ::rtl::Reference<ContentProperties>& _rProp)  throw (uno::Exception)
522 {
523 	OSL_ENSURE(_rProp.is(),"No valid content properties!");
524 	if(!_rProp->m_bIsOpen)
525 	{
526 		sal_Char *pFileName = new sal_Char[ODM_FILENAME_MAX];
527 
528 		DWORD dwFlag = ODM_MODIFYMODE | ODM_SILENT;
529 		ODMSTATUS odm = NODMOpenDoc(getHandle(), dwFlag, const_cast<sal_Char*>(_rProp->m_sDocumentId.getStr()), pFileName);
530 		switch(odm)
531 		{
532 			case ODM_E_INUSE:
533 				dwFlag = ODM_VIEWMODE;
534 				if( NODMOpenDoc(getHandle(), dwFlag, const_cast<sal_Char*>(_rProp->m_sDocumentId.getStr()), pFileName) != ODM_SUCCESS)
535 					break;
536 				// else run through
537 			case ODM_SUCCESS:
538 				::osl::FileBase::getFileURLFromSystemPath(::rtl::OStringToOUString(rtl::OString(pFileName),RTL_TEXTENCODING_ASCII_US)
539 															,_rProp->m_sFileURL);
540 				_rProp->m_bIsOpen = sal_True;
541 				break;
542 			default:
543 				delete [] pFileName;
544 				throw uno::Exception();  // TODO give a more precise error message here
545 		}
546 
547 		delete [] pFileName;
548 	}
549 	return _rProp->m_sFileURL;
550 }
551 // -----------------------------------------------------------------------------
convertURL(const::rtl::OUString & _sCanonicURL)552 ::rtl::OUString ContentProvider::convertURL(const ::rtl::OUString& _sCanonicURL)
553 {
554 	sal_Int32 nPos = 0;
555 	// check if url starts with odma
556 	if(_sCanonicURL.matchIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM(ODMA_URL_SCHEME_SHORT ODMA_URL_SHORT)))
557 	{ // URL starts with odma:// so we have to remove this
558 		nPos = ODMA_URL_SHORT_LGTH;
559 	}
560 	else if(_sCanonicURL.matchIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM(ODMA_URL_SCHEME ODMA_URL_SHORT)))
561 	{ // URL starts with vnd.sun.star.odma:/// so we have to remove this
562 		nPos = ODMA_URL_LGTH;
563 	}
564 
565 	::rtl::OUString sCanonicURL = _sCanonicURL;
566 	// now check what formats we allow
567 	if(nPos == _sCanonicURL.getLength()) // only ask for root entry
568 		sCanonicURL = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/"));
569 
570 	if(nPos < sCanonicURL.getLength())
571 	{
572 		sCanonicURL = sCanonicURL.copy(nPos);
573 		sCanonicURL = rtl::Uri::decode(sCanonicURL,rtl_UriDecodeWithCharset,RTL_TEXTENCODING_UTF8);
574 	}
575 	if(sCanonicURL.getLength() > 1 && sCanonicURL.getStr()[0] == sal_Unicode('/'))
576 	{
577 		sCanonicURL = sCanonicURL.copy(1);
578 		if(sCanonicURL.getLength() == 1 && sCanonicURL.getStr()[0] == sal_Unicode('.'))
579 			sCanonicURL = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/"));
580 	}
581 	return sCanonicURL;
582 }
583 // -----------------------------------------------------------------------------
deleteDocument(const::rtl::Reference<ContentProperties> & _rProp)584 sal_Bool ContentProvider::deleteDocument(const ::rtl::Reference<ContentProperties>& _rProp)
585 {
586 	closeDocument(_rProp->m_sDocumentId);
587 	ODMSTATUS odm = NODMActivate(ContentProvider::getHandle(),
588 								 ODM_DELETE,
589 								 const_cast< sal_Char*>(_rProp->m_sDocumentId.getStr()));
590 	if(odm == ODM_SUCCESS)
591 		m_aContents.erase(_rProp->m_sDocumentId);
592 
593 	return odm == ODM_SUCCESS;
594 }
595 // -----------------------------------------------------------------------------
596