| Last week we fixed a bug in 3.0.1 where Dali was not closing
InputStreams (bug 244268). 
After fixing this bug I was able to remove our unit test workarounds
for deleting projects (using ProjectUtility and creating new projects
with unique names). We no longer have any difficulty with deleting
projects in our unit tests.  I mention this in case other teams have
the same problem, a review of InputStream usage might be in order. 
 thanks,
 Karen
 
 Jason A Sholl wrote:
 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
 jsholl@xxxxxxxxxx
 919-543-0011 (t/l 441-0011)
 
 
 
 
 
 
 
 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.
 *
 *
  @author
  Kiril
  Mitov
  k.mitov@xxxxxxx
 *
 */
 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:
wtp-dev-bounces@xxxxxxxxxxx
[mailto:wtp-dev-bounces@xxxxxxxxxxx] On Behalf Of David M
Williams
 Sent: Friday, 1. February 2008 10:16
 To: wtp-dev@xxxxxxxxxxx
 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.
 *
  @param project
 *
  @throws CoreException
 *
  @throws 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
 wtp-dev@xxxxxxxxxxx
 https://dev.eclipse.org/mailman/listinfo/wtp-dev
 
 
 
_______________________________________________
wtp-dev mailing list
wtp-dev@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/wtp-dev
 |