Take a look at org.eclipse.wst.common.tests.ProjectUtility in the
org.eclipse.wst.common.tests plugin. There is a method in there for
deleting projects as well.
Thank you,
Jason A. Sholl
[EMAIL PROTECTED]
919-543-0011 (t/l 441-0011)
*"Mitov, Kiril" <[EMAIL PROTECTED]>*
Sent by: [EMAIL PROTECTED]
02/01/2008 07:47 AM
Please respond to
"General discussion of project-wide or architectural issues."
<[email protected]>
To
"General discussion of project-wide or architectural issues."
<[email protected]>
cc
Subject
RE: [wtp-dev] JUnit tip: How to delete projects
When it comes to deleting files I have once implemented this method
*private* *void* deleteFileAndUpdate(IFile file) *throws* Exception {
ChangeListenerWithSemaphore listener = *new*
ChangeListenerWithSemaphore(1);
ResourcesPlugin./getWorkspace/().addResourceChangeListener(listener,
IResourceChangeEvent./POST_CHANGE/);
*int* retries = 3;
*while* (retries > 0) {
*try* {
/deleteFile/(file);
*if* (listener.waitForEvents()) {
retries = 0;
*break*;
}
} *catch* (CoreException e) {
... more core here... see in the description.
} *finally* {
retries--;
}
}
/assertTrue/(retries == -1);
ResourcesPlugin./getWorkspace/().removeResourceChangeListener(listener);
}
The basic idea here is that you have not deleted a file/folder/project
until you receive a ResourceChangeEvent for the deletion.
Since the event might be in the *same thread *or in *another thread
*it is important to stop the current thread until an event occurs.
This is what I am doing here. This has also worked for folders and
projects. The *listener.waitForEvents() *is blocking the current
thread until a notification for the deletion is received. In general
the thread is blocked until the *specified number of events *(the
number in the constructor of ChangeListenerWithSemaphore) is reached.
But this can easily be changed to an another logic.
Here the "retires" are the number of failiers that I am willing to
accept. In the catch(CoreException e) there is a special logic. If the
message of the exception is "The requested operation cannot be
performed on a file with a user-mapped section open" the code of the
catch block is:
/*
* An exception was occurring - "The requested
operation cannot
* be performed on a file with a user-mapped
section open".
* Running the finalization as suggested at
*
http://webteam.archive.org/jira/browse/HER-661?decorator=printable
*/
System./runFinalization/();
System./gc/();
But I was unable to investigate the error more deeply.
The deleteFile method is:
*protected* *static* *boolean* deleteFile(*final* IFile file) *throws*
Exception {
ResourcesPlugin./getWorkspace/().run(*new*
IWorkspaceRunnable() {
*public* *void* run(IProgressMonitor monitor)
*throws* CoreException {
file.delete(*false*, monitor);
}
}, monitor);
*return* *true*;
}
The code of ChangeListenerWithSemaphore is
/**
* This change listener will release a semaphore after the resource
changed
* method is called. For every resourceChanged call one release will
be called.
*
* [EMAIL PROTECTED] Kiril Mitov [EMAIL PROTECTED]
*
*/
*public* *final* *class* ChangeListenerWithSemaphore *implements*
IResourceChangeListener {
*private* *final* Semaphore s;
*private* *final* List<Object> deltas;
*private* *final* *int* expectedEvents;
*private* *final* List<IResourceChangeEvent> receivedEvents;
*public* ChangeListenerWithSemaphore(*int* expectedEvents)
*throws* InterruptedException {
*this*.expectedEvents = expectedEvents;
*this*.s = *new* Semaphore(1);
*this*.s.acquire();
*this*.deltas = Collections./synchronizedList/(*new*
LinkedList<Object>());
*this*.receivedEvents =
Collections./synchronizedList/(*new* LinkedList<IResourceChangeEvent>());
}
*public* *synchronized* *void*
resourceChanged(IResourceChangeEvent event) {
receivedEvents.add(event);
*if* (receivedEvents.size() > expectedEvents)
*throw* *new* IllegalStateException("The expected
events were already reached");
*try* {
deltas.add(event.getDelta());
} *catch* (Exception e) {
Activator./getDefault/().getLog().log(*new*
Status(IStatus./ERROR/, Activator./PLUGIN_ID/, e.getMessage(), e));
*return*;
} *finally* {
*if* (expectedEvents == receivedEvents.size())
s.release();
}
}
*public* *boolean* waitForEvents() *throws* InterruptedException {
*return* s.tryAcquire(5, TimeUnit./SECONDS/);
}
*public* *synchronized* List<Object> getDeltas() {
*return* deltas;
}
*public* *synchronized* *int* getEvents() {
*return* receivedEvents.size();
}
*public* List<IResourceChangeEvent> getReceivedEvents() {
*return* receivedEvents;
}
}
This is how I am creating, deleting and updating files.
Best Regards,
Kiril
------------------------------------------------------------------------
*From:* [EMAIL PROTECTED]
[mailto:[EMAIL PROTECTED] *On Behalf Of *David M Williams*
Sent:* Friday, 1. February 2008 10:16*
To:* [EMAIL PROTECTED]
Subject:* [wtp-dev] JUnit tip: How to delete projects
Some of our JUnits suites require that projects or other resources be
deleted during the test, for various reasons, and I think some of the
"random errors" we see are because it's hard to delete a project, or
file, in a multi-threaded Eclipse. If there is a file from the project
open in another thread, for example, perhaps in a thread that's
running validation, hence reading files, the delete will fail
("randomly") and then that might cause a JUnit test to fail, directly
or indirectly (by having an unexpected state).
I had to solve this, just this evening, and took me a while, reading
platform test examples, and googling around, to find a solution that I
think is fairly good ... for JUnit tests, at least.
I've pasted the code below ... just in case it helps anyone. Hopefully
the constants are obvious, but if anyone wants to see the whole class,
it is
org.eclipse.jst.jsp.core.tests.taglibindex.TestIndex
And ... as always the case in open development ... if anyone has other
tips/tricks, or better ways, feel free to let us know.
Thanks,
/**
* It's not easy to delete projects. If any of it's files are
open by another thread,
* the operation will fail. So, this method will make several
attempts before giving up.
* [EMAIL PROTECTED] project
* [EMAIL PROTECTED] CoreException
* [EMAIL PROTECTED] InterruptedException
*/
*private* *void* deleteProject(IProject project) *throws*
CoreException, InterruptedException {
*int* nTrys = 0;
*while* (project != *null* && project.exists() && nTrys
< MAX_RETRYS) {
*try* {
nTrys++;
project.delete(*true*, *true*, *null*);
}
*catch* (ResourceException e) {
*if* (DEBUG) {
System./out/.println();
System./out/.println("Could not
delete project on attempt number: "+ nTrys);
IStatus eStatus = e.getStatus();
// should always be
MultiStatus, but we'll check
*if* (eStatus *instanceof*
MultiStatus) {
MultiStatus mStatus =
(MultiStatus) eStatus;
IStatus[] iStatus =
mStatus.getChildren();
*for* (*int* j = 0; j <
iStatus.length; j++) {
System./out/.println("Status: " + j + " " + iStatus[j]);
}
}
*else* {
System./out/.println("Status: " + eStatus);
}
}
/*
* If we could not delete the first
time, wait a bit and
* re-try. If we could not delete, it
is likely because
* another thread has a file open, or
similar (such as the
* validation thread).
*/
Thread./sleep/(PAUSE_TIME);
}
}
*if* (project != *null* && project.exists()) {
/fail/("Error in test infrastructure. Could not
delete project " + project + " after " + MAX_RETRYS + "attempts.");
}
}_______________________________________________
wtp-dev mailing list
[email protected]
https://dev.eclipse.org/mailman/listinfo/wtp-dev
------------------------------------------------------------------------
_______________________________________________
wtp-dev mailing list
[email protected]
https://dev.eclipse.org/mailman/listinfo/wtp-dev