1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_dbaccess.hxx"
30 #ifndef DBA_CONTENTHELPER_HXX
31 #include "ContentHelper.hxx"
32 #endif
33 #ifndef _UCBHELPER_CANCELCOMMANDEXECUTION_HXX_
34 #include <ucbhelper/cancelcommandexecution.hxx>
35 #endif
36 #ifndef _COMPHELPER_PROPERTY_HXX_
37 #include <comphelper/property.hxx>
38 #endif
39 #ifndef _COM_SUN_STAR_UCB_UNSUPPORTEDCOMMANDEXCEPTION_HPP_
40 #include <com/sun/star/ucb/UnsupportedCommandException.hpp>
41 #endif
42 #ifndef _COM_SUN_STAR_LANG_ILLEGALARGUMENTEXCEPTION_HPP_
43 #include <com/sun/star/lang/IllegalArgumentException.hpp>
44 #endif
45 #ifndef _COM_SUN_STAR_LANG_ILLEGALACCESSEXCEPTION_HPP_
46 #include <com/sun/star/lang/IllegalAccessException.hpp>
47 #endif
48 #ifndef _COM_SUN_STAR_IO_XOUTPUTSTREAM_HPP_
49 #include <com/sun/star/io/XOutputStream.hpp>
50 #endif
51 #ifndef _COM_SUN_STAR_IO_XACTIVEDATASINK_HPP_
52 #include <com/sun/star/io/XActiveDataSink.hpp>
53 #endif
54 #ifndef _COM_SUN_STAR_BEANS_PROPERTYATTRIBUTE_HPP_
55 #include <com/sun/star/beans/PropertyAttribute.hpp>
56 #endif
57 #ifndef _UCBHELPER_PROPERTYVALUESET_HXX
58 #include <ucbhelper/propertyvalueset.hxx>
59 #endif
60 #ifndef _UCBHELPER_CONTENTIDENTIFIER_HXX
61 #include <ucbhelper/contentidentifier.hxx>
62 #endif
63 #ifndef DBA_UCPRESULTSET_HXX
64 #include "myucp_resultset.hxx"
65 #endif
66 #ifndef _COM_SUN_STAR_CONTAINER_XNAMECONTAINER_HPP_
67 #include <com/sun/star/container/XNameContainer.hpp>
68 #endif
69 #ifndef DBACORE_SDBCORETOOLS_HXX
70 #include "sdbcoretools.hxx"
71 #endif
72 #ifndef DBACCESS_SHARED_DBASTRINGS_HRC
73 #include "dbastrings.hrc"
74 #endif
75 #ifndef _TOOLS_DEBUG_HXX
76 #include <tools/debug.hxx>
77 #endif
78 
79 
80 namespace dbaccess
81 {
82 using namespace ::com::sun::star::uno;
83 using namespace ::com::sun::star::ucb;
84 using namespace ::com::sun::star::beans;
85 using namespace ::com::sun::star::lang;
86 using namespace ::com::sun::star::sdbc;
87 using namespace ::com::sun::star::io;
88 using namespace ::com::sun::star::util;
89 using namespace ::com::sun::star::embed;
90 using namespace ::com::sun::star::container;
91 using namespace ::comphelper;
92 using namespace ::cppu;
93 
94 // -----------------------------------------------------------------------------
95 DBG_NAME(OContentHelper_Impl)
96 OContentHelper_Impl::OContentHelper_Impl()
97 {
98 	DBG_CTOR(OContentHelper_Impl,NULL);
99 }
100 // -----------------------------------------------------------------------------
101 OContentHelper_Impl::~OContentHelper_Impl()
102 {
103 	DBG_DTOR(OContentHelper_Impl,NULL);
104 }
105 // -----------------------------------------------------------------------------
106 
107 OContentHelper::OContentHelper(const Reference< XMultiServiceFactory >& _xORB
108 							   ,const Reference< XInterface >&	_xParentContainer
109 							   ,const TContentPtr& _pImpl)
110 	: OContentHelper_COMPBASE(m_aMutex)
111 	,m_aContentListeners(m_aMutex)
112 	,m_aPropertyChangeListeners(m_aMutex)
113 	,m_xParentContainer(_xParentContainer)
114 	,m_aContext( _xORB )
115     ,m_aErrorHelper( m_aContext )
116 	,m_pImpl(_pImpl)
117 	,m_nCommandId(0)
118 {
119 }
120 //--------------------------------------------------------------------------
121 void SAL_CALL OContentHelper::disposing()
122 {
123 	::osl::MutexGuard aGuard(m_aMutex);
124 
125 	// say our listeners goobye
126 	EventObject aEvt(*this);
127 	m_aContentListeners.disposeAndClear(aEvt);
128 
129 	m_xParentContainer = NULL;
130 }
131 // -----------------------------------------------------------------------------
132 IMPLEMENT_SERVICE_INFO1(OContentHelper,"com.sun.star.comp.sdb.Content","com.sun.star.ucb.Content");
133 IMPLEMENT_IMPLEMENTATION_ID(OContentHelper)
134 // -----------------------------------------------------------------------------
135 // XContent
136 Reference< XContentIdentifier > SAL_CALL OContentHelper::getIdentifier(  ) throw (RuntimeException)
137 {
138 	::osl::MutexGuard aGuard(m_aMutex);
139     ::rtl::OUStringBuffer aIdentifier;
140     aIdentifier.appendAscii( "private:" );
141     aIdentifier.append( impl_getHierarchicalName( true ) );
142     return new ::ucbhelper::ContentIdentifier( m_aContext.getLegacyServiceFactory(), aIdentifier.makeStringAndClear() );
143 }
144 // -----------------------------------------------------------------------------
145 ::rtl::OUString OContentHelper::impl_getHierarchicalName( bool _includingRootContainer ) const
146 {
147     ::rtl::OUStringBuffer aHierarchicalName( m_pImpl->m_aProps.aTitle );
148 	Reference< XInterface > xParent = m_xParentContainer;
149 	while( xParent.is() )
150 	{
151 		Reference<XPropertySet> xProp( xParent, UNO_QUERY );
152 		Reference< XChild > xChild( xParent, UNO_QUERY );
153 		xParent.set( xChild.is() ? xChild->getParent() : Reference< XInterface >(), UNO_QUERY );
154 		if ( xProp.is() && xParent.is() )
155 		{
156 			::rtl::OUString sName;
157 			xProp->getPropertyValue( PROPERTY_NAME ) >>= sName;
158 
159             ::rtl::OUString sPrevious = aHierarchicalName.makeStringAndClear();
160             aHierarchicalName.append( sName );
161             aHierarchicalName.append( sal_Unicode( '/' ) );
162             aHierarchicalName.append( sPrevious );
163 		}
164 	}
165     ::rtl::OUString sHierarchicalName( aHierarchicalName.makeStringAndClear() );
166     if ( !_includingRootContainer )
167         sHierarchicalName = sHierarchicalName.copy( sHierarchicalName.indexOf( '/' ) + 1 );
168     return sHierarchicalName;
169 }
170 
171 // -----------------------------------------------------------------------------
172 ::rtl::OUString SAL_CALL OContentHelper::getContentType() throw (RuntimeException)
173 {
174 	::osl::MutexGuard aGuard(m_aMutex);
175 
176     if ( !m_pImpl->m_aProps.aContentType )
177     {   // content type not yet retrieved
178         m_pImpl->m_aProps.aContentType.reset( determineContentType() );
179     }
180 
181 	return *m_pImpl->m_aProps.aContentType;
182 }
183 // -----------------------------------------------------------------------------
184 void SAL_CALL OContentHelper::addContentEventListener( const Reference< XContentEventListener >& _rxListener ) throw (RuntimeException)
185 {
186 	::osl::MutexGuard aGuard(m_aMutex);
187 	if ( _rxListener.is() )
188 		m_aContentListeners.addInterface(_rxListener);
189 }
190 // -----------------------------------------------------------------------------
191 void SAL_CALL OContentHelper::removeContentEventListener( const Reference< XContentEventListener >& _rxListener ) throw (RuntimeException)
192 {
193 	::osl::MutexGuard aGuard(m_aMutex);
194 	if (_rxListener.is())
195 		m_aContentListeners.removeInterface(_rxListener);
196 }
197 // -----------------------------------------------------------------------------
198 
199 // XCommandProcessor
200 sal_Int32 SAL_CALL OContentHelper::createCommandIdentifier(  ) throw (RuntimeException)
201 {
202 	::osl::MutexGuard aGuard(m_aMutex);
203 	// Just increase counter on every call to generate an identifier.
204 	return ++m_nCommandId;
205 }
206 // -----------------------------------------------------------------------------
207 Any SAL_CALL OContentHelper::execute( const Command& aCommand, sal_Int32 /*CommandId*/, const Reference< XCommandEnvironment >& Environment ) throw (Exception, CommandAbortedException, RuntimeException)
208 {
209 	Any aRet;
210 	if ( aCommand.Name.compareToAscii( "getPropertyValues" ) == 0 )
211 	{
212 		//////////////////////////////////////////////////////////////////
213 		// getPropertyValues
214 		//////////////////////////////////////////////////////////////////
215 
216 		Sequence< Property > Properties;
217 		if ( !( aCommand.Argument >>= Properties ) )
218 		{
219 			OSL_ENSURE( sal_False, "Wrong argument type!" );
220             ucbhelper::cancelCommandExecution(
221                 makeAny( IllegalArgumentException(
222                                     rtl::OUString(),
223                                     static_cast< cppu::OWeakObject * >( this ),
224                                     -1 ) ),
225                 Environment );
226             // Unreachable
227 		}
228 		aRet <<= getPropertyValues( Properties);
229 	}
230 	else if ( aCommand.Name.compareToAscii( "setPropertyValues" ) == 0 )
231 	{
232 		//////////////////////////////////////////////////////////////////
233 		// setPropertyValues
234 		//////////////////////////////////////////////////////////////////
235 
236 		Sequence< PropertyValue > aProperties;
237 		if ( !( aCommand.Argument >>= aProperties ) )
238 		{
239             OSL_ENSURE( sal_False, "Wrong argument type!" );
240             ucbhelper::cancelCommandExecution(
241                 makeAny( IllegalArgumentException(
242                                     rtl::OUString(),
243                                     static_cast< cppu::OWeakObject * >( this ),
244                                     -1 ) ),
245                 Environment );
246             // Unreachable
247         }
248 
249 		if ( !aProperties.getLength() )
250 		{
251             OSL_ENSURE( sal_False, "No properties!" );
252             ucbhelper::cancelCommandExecution(
253                 makeAny( IllegalArgumentException(
254                                     rtl::OUString(),
255                                     static_cast< cppu::OWeakObject * >( this ),
256                                     -1 ) ),
257                 Environment );
258             // Unreachable
259         }
260 
261         aRet <<= setPropertyValues( aProperties, Environment );
262 	}
263 	else if ( aCommand.Name.compareToAscii( "getPropertySetInfo" ) == 0 )
264 	{
265 		//////////////////////////////////////////////////////////////////
266 		// getPropertySetInfo
267 		//////////////////////////////////////////////////////////////////
268 
269 		Reference<XPropertySet> xProp(*this,UNO_QUERY);
270 		if ( xProp.is() )
271 			aRet <<= xProp->getPropertySetInfo();
272 		//	aRet <<= getPropertySetInfo(); // TODO
273 	}
274 	else
275 	{
276 		//////////////////////////////////////////////////////////////////
277 		// Unsupported command
278 		//////////////////////////////////////////////////////////////////
279 
280         OSL_ENSURE( sal_False, "Content::execute - unsupported command!" );
281 
282         ucbhelper::cancelCommandExecution(
283             makeAny( UnsupportedCommandException(
284                             rtl::OUString(),
285                             static_cast< cppu::OWeakObject * >( this ) ) ),
286             Environment );
287         // Unreachable
288     }
289 
290 	return aRet;
291 }
292 // -----------------------------------------------------------------------------
293 void SAL_CALL OContentHelper::abort( sal_Int32 /*CommandId*/ ) throw (RuntimeException)
294 {
295 }
296 // -----------------------------------------------------------------------------
297 
298 // XPropertiesChangeNotifier
299 void SAL_CALL OContentHelper::addPropertiesChangeListener( const Sequence< ::rtl::OUString >& PropertyNames, const Reference< XPropertiesChangeListener >& Listener ) throw (RuntimeException)
300 {
301 	::osl::MutexGuard aGuard(m_aMutex);
302 	sal_Int32 nCount = PropertyNames.getLength();
303 	if ( !nCount )
304 	{
305 		// Note: An empty sequence means a listener for "all" properties.
306 		m_aPropertyChangeListeners.addInterface(::rtl::OUString(), Listener );
307 	}
308 	else
309 	{
310 		const ::rtl::OUString* pSeq = PropertyNames.getConstArray();
311 
312 		for ( sal_Int32 n = 0; n < nCount; ++n )
313 		{
314 			const ::rtl::OUString& rName = pSeq[ n ];
315 			if ( rName.getLength() )
316 				m_aPropertyChangeListeners.addInterface(rName, Listener );
317 		}
318 	}
319 }
320 // -----------------------------------------------------------------------------
321 void SAL_CALL OContentHelper::removePropertiesChangeListener( const Sequence< ::rtl::OUString >& PropertyNames, const Reference< XPropertiesChangeListener >& Listener ) throw (RuntimeException)
322 {
323 	::osl::MutexGuard aGuard(m_aMutex);
324 	sal_Int32 nCount = PropertyNames.getLength();
325 	if ( !nCount )
326 	{
327 		// Note: An empty sequence means a listener for "all" properties.
328 		m_aPropertyChangeListeners.removeInterface( ::rtl::OUString(), Listener );
329 	}
330 	else
331 	{
332 		const ::rtl::OUString* pSeq = PropertyNames.getConstArray();
333 
334 		for ( sal_Int32 n = 0; n < nCount; ++n )
335 		{
336 			const ::rtl::OUString& rName = pSeq[ n ];
337 			if ( rName.getLength() )
338 				m_aPropertyChangeListeners.removeInterface( rName, Listener );
339 		}
340 	}
341 }
342 // -----------------------------------------------------------------------------
343 
344 // XPropertyContainer
345 void SAL_CALL OContentHelper::addProperty( const ::rtl::OUString& /*Name*/, sal_Int16 /*Attributes*/, const Any& /*DefaultValue*/ ) throw (PropertyExistException, IllegalTypeException, IllegalArgumentException, RuntimeException)
346 {
347     DBG_ERROR( "OContentHelper::addProperty: not implemented!" );
348 }
349 // -----------------------------------------------------------------------------
350 void SAL_CALL OContentHelper::removeProperty( const ::rtl::OUString& /*Name*/ ) throw (UnknownPropertyException, NotRemoveableException, RuntimeException)
351 {
352     DBG_ERROR( "OContentHelper::removeProperty: not implemented!" );
353 }
354 // -----------------------------------------------------------------------------
355 // XInitialization
356 void SAL_CALL OContentHelper::initialize( const Sequence< Any >& _aArguments ) throw(Exception, RuntimeException)
357 {
358 	const Any* pBegin = _aArguments.getConstArray();
359 	const Any* pEnd = pBegin + _aArguments.getLength();
360 	PropertyValue aValue;;
361 	for(;pBegin != pEnd;++pBegin)
362 	{
363 		*pBegin >>= aValue;
364 		if ( aValue.Name.equalsAscii("Parent") )
365 		{
366 			m_xParentContainer.set(aValue.Value,UNO_QUERY);
367 		}
368 		else if ( aValue.Name.equalsAscii(PROPERTY_NAME) )
369 		{
370 			aValue.Value >>= m_pImpl->m_aProps.aTitle;
371 		}
372 		else if ( aValue.Name.equalsAscii(PROPERTY_PERSISTENT_NAME) )
373 		{
374 			aValue.Value >>= m_pImpl->m_aProps.sPersistentName;
375 		}
376 	}
377 }
378 // -----------------------------------------------------------------------------
379 Sequence< Any > OContentHelper::setPropertyValues(const Sequence< PropertyValue >& rValues,const Reference< XCommandEnvironment >& /*xEnv*/ )
380 {
381 	osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
382 
383     Sequence< Any > aRet( rValues.getLength() );
384     Sequence< PropertyChangeEvent > aChanges( rValues.getLength() );
385 	sal_Int32 nChanged = 0;
386 
387     PropertyChangeEvent aEvent;
388     aEvent.Source         = static_cast< cppu::OWeakObject * >( this );
389 	aEvent.Further 		  = sal_False;
390 	aEvent.PropertyHandle = -1;
391 
392     const PropertyValue* pValues = rValues.getConstArray();
393 	sal_Int32 nCount = rValues.getLength();
394 
395 	for ( sal_Int32 n = 0; n < nCount; ++n )
396 	{
397         const PropertyValue& rValue = pValues[ n ];
398 
399         if ( rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) )
400         {
401 			// Read-only property!
402             aRet[ n ] <<= IllegalAccessException(
403                             rtl::OUString::createFromAscii(
404                                 "Property is read-only!" ),
405                             static_cast< cppu::OWeakObject * >( this ) );
406 		}
407         else if ( rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) )
408 		{
409 			// Read-only property!
410             aRet[ n ] <<= IllegalAccessException(
411                             rtl::OUString::createFromAscii(
412                                 "Property is read-only!" ),
413                             static_cast< cppu::OWeakObject * >( this ) );
414 		}
415         else if ( rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) )
416 		{
417 			// Read-only property!
418             aRet[ n ] <<= IllegalAccessException(
419                             rtl::OUString::createFromAscii(
420                                 "Property is read-only!" ),
421                             static_cast< cppu::OWeakObject * >( this ) );
422 		}
423         else if ( rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Title" ) ) )
424 		{
425             rtl::OUString aNewValue;
426 			if ( rValue.Value >>= aNewValue )
427 			{
428 				if ( aNewValue != m_pImpl->m_aProps.aTitle )
429 				{
430 					aEvent.PropertyName = rValue.Name;
431                     aEvent.OldValue     = makeAny( m_pImpl->m_aProps.aTitle );
432 
433                     try
434                     {
435                         impl_rename_throw( aNewValue ,false);
436                         OSL_ENSURE( m_pImpl->m_aProps.aTitle == aNewValue, "OContentHelper::setPropertyValues('Title'): rename did not work!" );
437 
438                         aEvent.NewValue     = makeAny( aNewValue );
439 					    aChanges.getArray()[ nChanged ] = aEvent;
440 					    nChanged++;
441                     }
442                     catch( const Exception& )
443                     {
444                     	OSL_ENSURE( sal_False, "OContentHelper::setPropertyValues('Title'): caught an exception while renaming!" );
445                     }
446 				}
447                 else
448                 {
449                     // Old value equals new value. No error!
450                 }
451 			}
452             else
453             {
454                 aRet[ n ] <<= IllegalTypeException(
455                                 rtl::OUString::createFromAscii(
456                                     "Property value has wrong type!" ),
457                                 static_cast< cppu::OWeakObject * >( this ) );
458             }
459 		}
460 
461 		// @@@ Process other properties supported directly.
462 #if 0
463         else if ( rValue.Name.equalsAsciiL(
464                         RTL_CONSTASCII_STRINGPARAM( "xxxxxx" ) ) )
465 		{
466 		}
467 #endif
468 		else
469 		{
470             aRet[ n ] <<= Exception(
471                             rtl::OUString::createFromAscii(
472                                 "No property set for storing the value!" ),
473                             static_cast< cppu::OWeakObject * >( this ) );
474 		}
475 	}
476 
477 	if ( nChanged > 0 )
478 	{
479 		// @@@ Save changes.
480 //		storeData();
481 
482 		notifyDataSourceModified();
483 		aGuard.clear();
484 		aChanges.realloc( nChanged );
485 		notifyPropertiesChange( aChanges );
486 	}
487 
488     return aRet;
489 }
490 // -----------------------------------------------------------------------------
491 //=========================================================================
492 // static
493 Reference< XRow > OContentHelper::getPropertyValues( const Sequence< Property >& rProperties)
494 {
495 	// Note: Empty sequence means "get values of all supported properties".
496 
497     rtl::Reference< ::ucbhelper::PropertyValueSet > xRow = new ::ucbhelper::PropertyValueSet( m_aContext.getLegacyServiceFactory() );
498 
499 	sal_Int32 nCount = rProperties.getLength();
500 	if ( nCount )
501 	{
502         const Property* pProps = rProperties.getConstArray();
503 		for ( sal_Int32 n = 0; n < nCount; ++n )
504 		{
505             const Property& rProp = pProps[ n ];
506 
507 			// Process Core properties.
508 
509             if ( rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) )
510             {
511 				xRow->appendString ( rProp, getContentType() );
512 			}
513             else if ( rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Title" ) ) )
514 			{
515 				xRow->appendString ( rProp, m_pImpl->m_aProps.aTitle );
516 			}
517             else if ( rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) )
518 			{
519 				xRow->appendBoolean( rProp, m_pImpl->m_aProps.bIsDocument );
520 			}
521             else if ( rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) )
522 			{
523 				xRow->appendBoolean( rProp, m_pImpl->m_aProps.bIsFolder );
524 			}
525 			else
526 				xRow->appendVoid(rProp);
527 
528 			// @@@ Process other properties supported directly.
529 #if 0
530             else if ( rProp.Name.equalsAsciiL(
531                     RTL_CONSTASCII_STRINGPARAM( "xxxxxx" ) ) )
532 			{
533 			}
534 #endif
535 		}
536 	}
537 	else
538 	{
539 		// Append all Core Properties.
540 		xRow->appendString (
541             Property( rtl::OUString::createFromAscii( "ContentType" ),
542 					  -1,
543                       getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
544                       PropertyAttribute::BOUND
545                         | PropertyAttribute::READONLY ),
546 			getContentType() );
547 		xRow->appendString (
548             Property( rtl::OUString::createFromAscii( "Title" ),
549 					  -1,
550                       getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
551                       PropertyAttribute::BOUND ),
552 			m_pImpl->m_aProps.aTitle );
553 		xRow->appendBoolean(
554             Property( rtl::OUString::createFromAscii( "IsDocument" ),
555 					  -1,
556 					  getCppuBooleanType(),
557                       PropertyAttribute::BOUND
558                         | PropertyAttribute::READONLY ),
559 			m_pImpl->m_aProps.bIsDocument );
560 		xRow->appendBoolean(
561             Property( rtl::OUString::createFromAscii( "IsFolder" ),
562 					  -1,
563 					  getCppuBooleanType(),
564                       PropertyAttribute::BOUND
565                         | PropertyAttribute::READONLY ),
566 			m_pImpl->m_aProps.bIsFolder );
567 
568 		// @@@ Append other properties supported directly.
569 	}
570 
571     return Reference< XRow >( xRow.get() );
572 }
573 // -----------------------------------------------------------------------------
574 // -----------------------------------------------------------------------------
575 void OContentHelper::notifyPropertiesChange( const Sequence< PropertyChangeEvent >& evt ) const
576 {
577 
578 	sal_Int32 nCount = evt.getLength();
579 	if ( nCount )
580 	{
581 		// First, notify listeners interested in changes of every property.
582 		OInterfaceContainerHelper* pAllPropsContainer = m_aPropertyChangeListeners.getContainer( ::rtl::OUString() );
583 		if ( pAllPropsContainer )
584 		{
585 			OInterfaceIteratorHelper aIter( *pAllPropsContainer );
586 			while ( aIter.hasMoreElements() )
587 			{
588 				// Propagate event.
589 				Reference< XPropertiesChangeListener > xListener( aIter.next(), UNO_QUERY );
590 				if ( xListener.is() )
591 					xListener->propertiesChange( evt );
592 			}
593 		}
594 
595 		typedef Sequence< PropertyChangeEvent > PropertyEventSequence;
596 		typedef ::std::map< XPropertiesChangeListener*, PropertyEventSequence* > PropertiesEventListenerMap;
597 		PropertiesEventListenerMap aListeners;
598 
599 
600 		const PropertyChangeEvent* propertyChangeEvent = evt.getConstArray();
601 
602 		for ( sal_Int32 n = 0; n < nCount; ++n, ++propertyChangeEvent )
603 		{
604 			const PropertyChangeEvent& rEvent = *propertyChangeEvent;
605 			const ::rtl::OUString& rName = rEvent.PropertyName;
606 
607 			OInterfaceContainerHelper* pPropsContainer = m_aPropertyChangeListeners.getContainer( rName );
608 			if ( pPropsContainer )
609 			{
610 				OInterfaceIteratorHelper aIter( *pPropsContainer );
611 				while ( aIter.hasMoreElements() )
612 				{
613 					PropertyEventSequence* propertyEvents = NULL;
614 
615 					XPropertiesChangeListener* pListener = static_cast< XPropertiesChangeListener * >( aIter.next() );
616 					PropertiesEventListenerMap::iterator it = aListeners.find( pListener );
617 					if ( it == aListeners.end() )
618 					{
619 						// Not in map - create and insert new entry.
620 						propertyEvents = new PropertyEventSequence( nCount );
621 						aListeners[ pListener ] = propertyEvents;
622 					}
623 					else
624 						propertyEvents = (*it).second;
625 
626 					if ( propertyEvents )
627 						(*propertyEvents)[n] = rEvent;
628 				}
629 			}
630 		}
631 
632 		// Notify listeners.
633 		PropertiesEventListenerMap::iterator it = aListeners.begin();
634 		while ( !aListeners.empty() )
635 		{
636 			XPropertiesChangeListener* pListener =
637 					static_cast< XPropertiesChangeListener * >( (*it).first );
638 			PropertyEventSequence* pSeq = (*it).second;
639 
640 			// Remove current element.
641 			aListeners.erase( it );
642 
643 			// Propagate event.
644 			pListener->propertiesChange( *pSeq );
645 
646 			delete pSeq;
647 
648 			it = aListeners.begin();
649 		}
650 	}
651 }
652 // -----------------------------------------------------------------------------
653 // com::sun::star::lang::XUnoTunnel
654 //------------------------------------------------------------------
655 sal_Int64 OContentHelper::getSomething( const Sequence< sal_Int8 > & rId ) throw (RuntimeException)
656 {
657 	if (rId.getLength() == 16 && 0 == rtl_compareMemory(getUnoTunnelImplementationId().getConstArray(),  rId.getConstArray(), 16 ) )
658 		return reinterpret_cast<sal_Int64>(this);
659 
660 	return 0;
661 }
662 
663 // -----------------------------------------------------------------------------
664 OContentHelper* OContentHelper::getImplementation( const Reference< XInterface >& _rxComponent )
665 {
666 	OContentHelper* pContent( NULL );
667 
668     Reference< XUnoTunnel > xUnoTunnel( _rxComponent, UNO_QUERY );
669 	if ( xUnoTunnel.is() )
670 		pContent = reinterpret_cast< OContentHelper* >( xUnoTunnel->getSomething( getUnoTunnelImplementationId() ) );
671 
672     return pContent;
673 }
674 
675 // -----------------------------------------------------------------------------
676 Reference< XInterface > SAL_CALL OContentHelper::getParent(  ) throw (RuntimeException)
677 {
678 	::osl::MutexGuard aGuard(m_aMutex);
679 	return m_xParentContainer;
680 }
681 // -----------------------------------------------------------------------------
682 void SAL_CALL OContentHelper::setParent( const Reference< XInterface >& _xParent ) throw (NoSupportException, RuntimeException)
683 {
684 	::osl::MutexGuard aGuard(m_aMutex);
685 	m_xParentContainer = _xParent;
686 }
687 
688 // -----------------------------------------------------------------------------
689 void OContentHelper::impl_rename_throw(const ::rtl::OUString& _sNewName,bool _bNotify )
690 {
691 	osl::ClearableGuard< osl::Mutex > aGuard(m_aMutex);
692     if ( _sNewName.equals( m_pImpl->m_aProps.aTitle ) )
693         return;
694     try
695 	{
696         Sequence< PropertyChangeEvent > aChanges( 1 );
697 
698         aChanges[0].Source          = static_cast< cppu::OWeakObject * >( this );
699 	    aChanges[0].Further 	    = sal_False;
700         aChanges[0].PropertyName    = PROPERTY_NAME;
701 	    aChanges[0].PropertyHandle  = PROPERTY_ID_NAME;
702         aChanges[0].OldValue        <<= m_pImpl->m_aProps.aTitle;
703         aChanges[0].NewValue        <<= _sNewName;
704 
705 		aGuard.clear();
706 
707 		m_pImpl->m_aProps.aTitle = _sNewName;
708         if ( _bNotify )
709             notifyPropertiesChange( aChanges );
710         notifyDataSourceModified();
711 	}
712 	catch(const PropertyVetoException&)
713 	{
714 		throw ElementExistException(_sNewName,*this);
715 	}
716 }
717 // -----------------------------------------------------------------------------
718 void SAL_CALL OContentHelper::rename( const ::rtl::OUString& newName ) throw (SQLException, ElementExistException, RuntimeException)
719 {
720 
721     impl_rename_throw(newName);
722 	//Reference<XNameContainer> xNameCont(m_xParentContainer,UNO_QUERY);
723 	//if ( xNameCont.is() )
724 	//{
725 	//	if ( xNameCont->hasByName(newName) )
726 	//		throw ElementExistException(newName,*this);
727 
728 	//	try
729 	//	{
730 	//		if ( xNameCont->hasByName(m_pImpl->m_aProps.aTitle) )
731 	//			xNameCont->removeByName(m_pImpl->m_aProps.aTitle);
732 
733 	//		m_pImpl->m_aProps.aTitle = newName;
734 	//		xNameCont->insertByName(m_pImpl->m_aProps.aTitle,makeAny(Reference<XContent>(*this,UNO_QUERY)));
735 	//		notifyDataSourceModified();
736 	//	}
737 	//	catch(IllegalArgumentException)
738 	//	{
739 	//		throw SQLException();
740 	//	}
741 	//	catch(NoSuchElementException)
742 	//	{
743 	//		throw SQLException();
744 	//	}
745 	//	catch(WrappedTargetException)
746 	//	{
747 	//		throw SQLException();
748 	//	}
749 	//}
750 	//else
751 	//	m_pImpl->m_aProps.aTitle = newName;
752 
753 }
754 // -----------------------------------------------------------------------------
755 void OContentHelper::notifyDataSourceModified()
756 {
757 	::dbaccess::notifyDataSourceModified(m_xParentContainer,sal_True);
758 }
759 //........................................................................
760 }	// namespace dbaccess
761 //........................................................................
762 
763