appfw/apparchitecture/apserv/APSSCAN.CPP
changeset 0 2e3d3ce01487
equal deleted inserted replaced
-1:000000000000 0:2e3d3ce01487
       
     1 // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // AppArc recognizer and application scanning
       
    15 // 
       
    16 // apsscan.cpp
       
    17 //
       
    18 
       
    19 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
       
    20 #if !defined(__APA_INTERNAL_H__)
       
    21 #include "apainternal.h"
       
    22 #endif
       
    23 #endif //SYMBIAN_ENABLE_SPLIT_HEADERS
       
    24 #include "APSSCAN.H"
       
    25 #include <ecom/ecom.h>
       
    26 
       
    27 class CApaFsMonitor::CApaFsNotifier : public CActive
       
    28 	{
       
    29 public:
       
    30 	~CApaFsNotifier();
       
    31 	static CApaFsNotifier* NewLC(RFs& aFs, const TDesC& aLocation, MApaFsChangeObserver& aObserver);
       
    32 	void Start(TNotifyType aNotifyType);
       
    33 private:
       
    34 	CApaFsNotifier(RFs& aFs, MApaFsChangeObserver& aObserver);
       
    35 	void DoCancel();
       
    36 	void RunL();
       
    37 private:
       
    38 	RFs& iFs;
       
    39 	MApaFsChangeObserver& iObserver;
       
    40 	HBufC* iLocation;
       
    41 	};
       
    42 
       
    43 CApaFsMonitor::CApaFsNotifier::~CApaFsNotifier()
       
    44 	{
       
    45 	Cancel();
       
    46 	delete iLocation;
       
    47 	}
       
    48 
       
    49 CApaFsMonitor::CApaFsNotifier* CApaFsMonitor::CApaFsNotifier::NewLC(RFs& aFs, const TDesC& aLocation, MApaFsChangeObserver& aObserver)
       
    50 	{ // static
       
    51 	CApaFsNotifier* self=new(ELeave) CApaFsNotifier(aFs, aObserver);
       
    52 	CleanupStack::PushL(self);
       
    53 	self->iLocation = aLocation.AllocL();
       
    54 	return self;
       
    55 	}
       
    56 
       
    57 CApaFsMonitor::CApaFsNotifier::CApaFsNotifier(RFs& aFs, MApaFsChangeObserver& aObserver)
       
    58 	: CActive(EPriorityLow), // priority must be higher than that of CApaFsMonitor::iFsTimer, to ensure the RunL of each completed CApaFsNotifier object is executed before the RunL of a completed CApaFsMonitor::iFsTimer
       
    59 	iFs(aFs),
       
    60 	iObserver(aObserver)
       
    61 	{
       
    62 	CActiveScheduler::Add(this);
       
    63 	}
       
    64 
       
    65 
       
    66 void CApaFsMonitor::CApaFsNotifier::Start(TNotifyType aNotifyType)
       
    67 	{
       
    68 	if (iLocation->Length())
       
    69 		{
       
    70 		iFs.NotifyChange(aNotifyType, iStatus, *iLocation);
       
    71 		}
       
    72 	else
       
    73 		{
       
    74 		iFs.NotifyChange(aNotifyType, iStatus);
       
    75 		}
       
    76 	SetActive();
       
    77 	}
       
    78 
       
    79 void CApaFsMonitor::CApaFsNotifier::DoCancel()
       
    80 	{
       
    81 	iFs.NotifyChangeCancel(iStatus);
       
    82 	}
       
    83 
       
    84 void CApaFsMonitor::CApaFsNotifier::RunL()
       
    85 	{
       
    86 	if (iStatus == KErrNone)
       
    87 		{
       
    88 		iObserver.FsChanged();
       
    89 		}
       
    90 	}
       
    91 
       
    92 
       
    93 
       
    94 // An FsMonitor checks for any changes to the file system
       
    95 // If a change is detected, a CallBack function is called after a short pause.
       
    96 // If there are further changes, the CallBack is not called again until after 3 secs have elapsed.
       
    97 
       
    98 const TInt KApaFsMonitorPause=250000;			// Wait 0.25s before calling CallBack
       
    99 const TInt KApaFsMonitorPeriod=3000000;			// Don't call CallBack again before 3s have elapsed
       
   100 
       
   101 //
       
   102 // Class CApaFsMonitor
       
   103 //
       
   104 
       
   105 EXPORT_C CApaFsMonitor::~CApaFsMonitor()
       
   106 /** Deletes the timer object, file system change notification
       
   107 active objects and location descriptors. */
       
   108 	{
       
   109 	if (iFsTimer)
       
   110 		{
       
   111 		iFsTimer->Cancel();
       
   112 		delete iFsTimer;
       
   113 		}
       
   114 	iNotifiers.ResetAndDestroy();
       
   115 	iNotifiers.Close();
       
   116 	}
       
   117 
       
   118 CApaFsMonitor::CApaFsMonitor(RFs& aFs, TCallBack aCallBack)
       
   119  	:iFs(aFs),
       
   120  	iCallBack(aCallBack)
       
   121 	{
       
   122 	}
       
   123 
       
   124 
       
   125 EXPORT_C CApaFsMonitor* CApaFsMonitor::NewL(RFs& aFs,const TDesC& aLocation, TCallBack aCallBack)
       
   126 /** Allocates and constructs a file system monitor.
       
   127 
       
   128 @param aFs A session with the file server.
       
   129 @param aLocation Optional name of the file or directory to be 
       
   130 monitored. If the length of the descriptor is zero, the object 
       
   131 monitors changes to all files and directories in the file system.
       
   132 Additional locations to monitor may be specified by calling
       
   133 AddLocationL.
       
   134 @param aCallBack The callback function.
       
   135 @return The file system monitor.
       
   136 @see CApaFsMonitor::AddLocationL() */
       
   137 	{
       
   138 	CApaFsMonitor* self=new(ELeave) CApaFsMonitor(aFs, aCallBack);
       
   139 	CleanupStack::PushL(self);
       
   140 	self->iFsTimer=CPeriodic::NewL(CActive::EPriorityIdle);
       
   141 	self->AddLocationL(aLocation);
       
   142 	CleanupStack::Pop(self);
       
   143 	return self;
       
   144 	}
       
   145 
       
   146 /** Adds an additional file system location to monitor.
       
   147 
       
   148 @param aLocation Name of the file or directory to be monitored. */
       
   149 EXPORT_C void CApaFsMonitor::AddLocationL(const TDesC& aLocation)
       
   150 	{
       
   151 	CApaFsNotifier* const notifier = CApaFsNotifier::NewLC(iFs, aLocation, *this);
       
   152 	User::LeaveIfError(iNotifiers.Append(notifier));
       
   153 	CleanupStack::Pop(notifier);
       
   154 	}
       
   155 
       
   156 /** Cancels all file system notification active objects owned by
       
   157 this monitor.
       
   158 
       
   159 A call to this function may be followed immediately by a call
       
   160 to Start() to change the notification type.
       
   161 
       
   162 @see CApaFsMonitor::Start() */
       
   163 EXPORT_C void CApaFsMonitor::Cancel()
       
   164 	{
       
   165 	const TInt notifierCount = iNotifiers.Count();
       
   166 	for (TInt ii=0; ii < notifierCount; ii++)
       
   167 		{
       
   168 		iNotifiers[ii]->Cancel();
       
   169 		}
       
   170 	}
       
   171 
       
   172 TBool CApaFsMonitor::AnyNotificationImpending() const
       
   173 	{
       
   174 	for (TInt i=iNotifiers.Count()-1; i>=0; --i)
       
   175 		{
       
   176 		if (iNotifiers[i]->iStatus!=KRequestPending)
       
   177 			{
       
   178 			return ETrue;
       
   179 			}
       
   180 		}
       
   181 	return EFalse;
       
   182 	}
       
   183 
       
   184 void CApaFsMonitor::FsChanged()
       
   185 	{
       
   186 	iFsHasChanged=ETrue;
       
   187 	if (!iIsBlocked && !iFsTimer->IsActive())
       
   188 		iFsTimer->Start(KApaFsMonitorPause,KApaFsMonitorPeriod,TCallBack(TimerCallBack,this));
       
   189 	}
       
   190 
       
   191 EXPORT_C void CApaFsMonitor::Start(TNotifyType aNotifyType)
       
   192 /** Sets the type of notification required and starts a file system notification
       
   193 active object for each location being monitored.
       
   194 
       
   195 You can either request notification of changes to all files in the file system, 
       
   196 or to specific files, depending on the aLocation parameter specified in the NewL() 
       
   197 function.
       
   198 
       
   199 @param aNotifyType A set of flags that indicate what kinds of change should cause 
       
   200 notifications. */
       
   201 	{
       
   202 	iNotifyType=aNotifyType;
       
   203 
       
   204 	DoStart();
       
   205 	}
       
   206 
       
   207 void CApaFsMonitor::DoStart()
       
   208 	{
       
   209 	const TInt notifierCount = iNotifiers.Count();
       
   210 	for (TInt ii=0; ii < notifierCount; ii++)
       
   211 		{
       
   212 		CApaFsNotifier* const notifier = iNotifiers[ii];
       
   213 		if (!notifier->IsActive())
       
   214 			{
       
   215 			notifier->Start(iNotifyType);
       
   216 			}
       
   217 		}
       
   218 	}
       
   219 
       
   220 EXPORT_C TNotifyType CApaFsMonitor::NotifyType() const
       
   221 /** Gets the type of notification as passed to Start(). 
       
   222 
       
   223 If Start() has not yet been called, the type of notification is undefined.
       
   224 
       
   225 @return Flags that indicate what kinds of change should cause notifications. */
       
   226 	{
       
   227 	return iNotifyType;
       
   228 	}
       
   229 
       
   230 EXPORT_C void CApaFsMonitor::SetBlocked(TBool aIsBlocked)
       
   231 /** Blocks or unblocks file system monitoring. 
       
   232 
       
   233 While in a blocked state, the callback never gets called. If monitoring is 
       
   234 unblocked using this function, and a change has occurred when in the blocked 
       
   235 state then the timer is started, causing the callback to be called initially 
       
   236 after 0.25 seconds, followed by subsequent delays of 3 seconds.
       
   237 
       
   238 @param aIsBlocked True to block callbacks, false to unblock them. */
       
   239 	{
       
   240 	iIsBlocked=aIsBlocked;
       
   241 	if (iIsBlocked==EFalse)		// If end of a blocked period, notify if a change was detected
       
   242 		{
       
   243 		if (iFsHasChanged && !iFsTimer->IsActive())
       
   244 			{
       
   245 			iFsTimer->Start(KApaFsMonitorPause,KApaFsMonitorPeriod,TCallBack(TimerCallBack,this));
       
   246 			}
       
   247 		}
       
   248 	}
       
   249 
       
   250 TInt CApaFsMonitor::TimerCallBack(TAny* aObject)
       
   251 	{
       
   252 	CApaFsMonitor* self=(CApaFsMonitor*)aObject;
       
   253 	if (self->iFsHasChanged && !self->iIsBlocked)
       
   254 		{
       
   255 		self->iFsHasChanged=EFalse;
       
   256 		self->DoStart();
       
   257 		self->iCallBack.CallBack();		// Should not leave, but if it does, it's OK
       
   258 		}
       
   259 	else
       
   260 		self->iFsTimer->Cancel();
       
   261 	return KErrNone;
       
   262 	}
       
   263 
       
   264 //
       
   265 // CApaEComMonitor class
       
   266 //
       
   267 CApaEComMonitor::CApaEComMonitor(TCallBack aCallBack)
       
   268 	: CActive(EPriorityIdle), iCallBack (aCallBack)
       
   269 	{
       
   270 	CActiveScheduler::Add(this);
       
   271 	}
       
   272 
       
   273 CApaEComMonitor::~CApaEComMonitor()
       
   274 	{
       
   275 	Cancel();
       
   276 	delete iEComTimer;
       
   277 	if (iEComSession)
       
   278 		{
       
   279 		iEComSession->Close();
       
   280 		}
       
   281 	}
       
   282 
       
   283 CApaEComMonitor* CApaEComMonitor::NewL(TCallBack aCallBack)
       
   284 	{
       
   285 	CApaEComMonitor* self=new(ELeave) CApaEComMonitor(aCallBack);
       
   286 	CleanupStack::PushL(self);
       
   287 	self->ConstructL();
       
   288 	CleanupStack::Pop(self);
       
   289 	return self;
       
   290 	}
       
   291 
       
   292 void CApaEComMonitor::ConstructL()
       
   293 	{
       
   294 	iEComSession = &(REComSession::OpenL());
       
   295 	iEComTimer = CPeriodic::NewL(CActive::EPriorityIdle);
       
   296 	}
       
   297 
       
   298 void CApaEComMonitor::DoCancel()
       
   299 	{
       
   300 	iEComTimer->Cancel();
       
   301 	iEComSession->CancelNotifyOnChange(iStatus);
       
   302 	}
       
   303 
       
   304 void CApaEComMonitor::Start ()
       
   305 	{
       
   306 	DoStart();
       
   307 	}
       
   308 
       
   309 void CApaEComMonitor::DoStart()
       
   310 	{
       
   311 	iEComSession->NotifyOnChange (iStatus);
       
   312 	SetActive();
       
   313 	}
       
   314 
       
   315 //callback to to call the ecomrecognizer scanning routine upon notification from ECom
       
   316 TInt CApaEComMonitor::TimerCallBack(TAny* aObject)
       
   317 	{
       
   318 	CApaEComMonitor* self=(CApaEComMonitor*)aObject;
       
   319 	if (self->iEComHasChanged)
       
   320 		{
       
   321 		self->iEComHasChanged=EFalse;
       
   322 		self->DoStart();
       
   323 		self->iCallBack.CallBack();		// Should not leave, but if it does, it's OK
       
   324 		}
       
   325 	else
       
   326 		self->iEComTimer->Cancel();
       
   327 	return KErrNone;
       
   328 	}
       
   329 
       
   330 const TInt KApaEComMonitorPause=250000;			// Wait 0.25s before calling CallBack
       
   331 const TInt KApaEComMonitorPeriod=3000000;			// Don't call CallBack again before 3s have elapsed
       
   332 
       
   333 void CApaEComMonitor::RunL()
       
   334 	{
       
   335 	if (iStatus == KErrNone)
       
   336 		{
       
   337 		iEComHasChanged = ETrue;
       
   338 		if  (!iEComTimer->IsActive())
       
   339 			{
       
   340 			iEComTimer->Start(KApaEComMonitorPause,KApaEComMonitorPeriod,TCallBack(TimerCallBack,this));
       
   341 			}
       
   342 		}
       
   343 	}
       
   344 
       
   345