Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Language IDEs » Java Development Tools (JDT) » Resource Change Listener
Resource Change Listener [message #1092374] Thu, 22 August 2013 14:01 Go to next message
Kevin Regan is currently offline Kevin Regan
Messages: 33
Registered: May 2013
Member
It seems that for a resource change event to fire, a change must happen to a resource that is currently open in an editor in the workspace. In other words, I have added a file to my project and was hoping to listen for changes to this file from an external entity - however, the only time I get notified about changes to it is if I have it open in a text editor. Is there a way to make the resource change listener functionality notify me if the resource changes in the file system, regardless of whether it is open in the workspace? Or am I forced to implement my own listener outside of the eclipse workspace domain?

/************* RESOURCE CHNAGE LISTENER TEST *********************/
				
		IResourceChangeListener listener = new IResourceChangeListener() {
			public void printDelta(IResourceDelta d, String indent) { 
				
				IResource resource = d.getResource();
				IJavaElement javaElement = JavaCore.create(resource);
				String resourceName = null;
				if (javaElement instanceof IJavaProject) { 
					resourceName = "Java project " + resource.getName();
				} else if (javaElement instanceof IPackageFragmentRoot) { 
					resourceName = "PFR " + resource.getName();
				} else if (javaElement instanceof IPackageFragment) { 
					resourceName = "PF " + resource.getName();
					
				} else if (javaElement instanceof ICompilationUnit) { 
					resourceName = "CU " + resource.getName();
				} else {
					resourceName = resource.getName();
				}
				
				System.out.println(indent.concat("Delta " + d.getKind() + " for resource " + resourceName));
								
				for (IResourceDelta childDelta : d.getAffectedChildren()) {
					printDelta(childDelta, indent.concat("\t"));
				}
			}
			public void resourceChanged(IResourceChangeEvent e) { 
			
				
				if (e.getType() == IResourceChangeEvent.POST_CHANGE) {
					System.out.println("Post change event");
					
					
					IResourceDelta delta = e.getDelta();
					printDelta(delta, "");
					
				} else {
					System.out.println("Event type was " + e.getType());
				}
			}
		};
		
		ResourcesPlugin.getWorkspace().addResourceChangeListener(listener);
		
		/************* ***************************************************/





Thank you.
Re: Resource Change Listener [message #1092412 is a reply to message #1092374] Thu, 22 August 2013 15:19 Go to previous messageGo to next message
Ed Merks is currently offline Ed Merks
Messages: 25999
Registered: July 2009
Senior Member
Kevin,


On 22/08/2013 8:01 PM, Kevin Regan wrote:
> It seems that for a resource change event to fire, a change must
> happen to a resource that is currently open in an editor in the
> workspace.
No.
> In other words, I have added a file to my project and was hoping to
> listen for changes to this file from an external entity - however, the
> only time I get notified about changes to it is if I have it open in a
> text editor. Is there a way to make the resource change listener
> functionality notify me if the resource changes in the file system,
> regardless of whether it is open in the workspace?
That's normally how it works.
> Or am I forced to implement my own listener outside of the eclipse
> workspace domain?
No.
>
>
> /************* RESOURCE CHNAGE LISTENER TEST *********************/
>
> IResourceChangeListener listener = new
> IResourceChangeListener() {
> public void printDelta(IResourceDelta d, String indent) {
> IResource resource = d.getResource();
> IJavaElement javaElement = JavaCore.create(resource);
> String resourceName = null;
> if (javaElement instanceof IJavaProject) {
> resourceName = "Java project " + resource.getName();
> } else if (javaElement instanceof
> IPackageFragmentRoot) { resourceName = "PFR " +
> resource.getName();
> } else if (javaElement instanceof IPackageFragment) {
> resourceName = "PF " + resource.getName();
>
> } else if (javaElement instanceof ICompilationUnit) {
> resourceName = "CU " + resource.getName();
> } else {
> resourceName = resource.getName();
> }
>
> System.out.println(indent.concat("Delta " +
> d.getKind() + " for resource " + resourceName));
>
> for (IResourceDelta childDelta :
> d.getAffectedChildren()) {
> printDelta(childDelta, indent.concat("\t"));
> }
> }
> public void resourceChanged(IResourceChangeEvent e) {
>
> if (e.getType() == IResourceChangeEvent.POST_CHANGE) {
Keep in mind that these are bit flags, so generally you should test by
using a bitwise or.

Try removing the guard so that you visit all changes for every delta...
> System.out.println("Post change event");
>
>
> IResourceDelta delta = e.getDelta();
> printDelta(delta, "");
>
> } else {
> System.out.println("Event type was " + e.getType());
> }
> }
> };
>
> ResourcesPlugin.getWorkspace().addResourceChangeListener(listener);
>
> /*************
> ***************************************************/
>
>
>
>
>
> Thank you.
Re: Resource Change Listener [message #1092493 is a reply to message #1092412] Thu, 22 August 2013 17:55 Go to previous messageGo to next message
Kevin Regan is currently offline Kevin Regan
Messages: 33
Registered: May 2013
Member
Thanks a lot for your reply Ed. I implemented your suggestion to remove the guard (the examples I saw on line were doing equality checks but I should have looked at the javadoc and realized it was a bitmask):

/************* RESOURCE CHNAGE LISTENER TEST *********************/
				
		IResourceChangeListener listener = new IResourceChangeListener() {
			public void printDelta(IResourceDelta d, String indent) { 
				
				IResource resource = d.getResource();
				IJavaElement javaElement = JavaCore.create(resource);
				String resourceName = null;
				if (javaElement instanceof IJavaProject) { 
					resourceName = "Java project " + resource.getName();
				} else if (javaElement instanceof IPackageFragmentRoot) { 
					resourceName = "PFR " + resource.getName();
				} else if (javaElement instanceof IPackageFragment) { 
					resourceName = "PF " + resource.getName();
					
				} else if (javaElement instanceof ICompilationUnit) { 
					resourceName = "CU " + resource.getName();
				} else {
					resourceName = resource.getName();
				}
				
				System.out.println(indent.concat("Delta " + d.getKind() + " for resource " + resourceName));
								
				for (IResourceDelta childDelta : d.getAffectedChildren()) {
					printDelta(childDelta, indent.concat("\t"));
				}
			}
			public void resourceChanged(IResourceChangeEvent e) { 
			
				System.out.println("Resource change event type = " + e.getType());
				//if (e.getType() | IResourceChangeEvent.POST_CHANGE) {
					//System.out.println("Post change event");
					
					
					IResourceDelta delta = e.getDelta();
					printDelta(delta, "");
					
				/*} else {
					System.out.println("Event type was " + e.getType());
				}*/
			}
		};



Basically, I have a startup plugin that programmatically creates an Eclipse project using information passed in on the command line to eclipse. For testing purposes, I created a file in the project:

			IFile myPropertyFile = project.getFile("mysettings");
			
			if (!myPropertyFile.exists()) {				
				myPropertyFile.create(new ByteArrayInputStream("handle=1abcff23aa".getBytes()), true, getProgressMonitor());
			}


In windows explorer I go to the file and edit it using a basic editor. I do not get any notification in the resource change listener when I do this. Am I doing something wrong here?

Note that I just did the same test by editing one of the Java source files that also reside in the project and did not get a notification about that either (just to make sure it didn't have to do with the type of element).

In both cases, if I subsequently go into eclipse and open the file that I previously modified outside of eclipse I get the notification at that time:


Resource change event type = 1
Delta 4 for resource
Delta 4 for resource Java project Test
Delta 4 for resource mysettings


[Updated on: Thu, 22 August 2013 17:57]

Report message to a moderator

Re: Resource Change Listener [message #1092712 is a reply to message #1092493] Fri, 23 August 2013 01:46 Go to previous messageGo to next message
Ed Merks is currently offline Ed Merks
Messages: 25999
Registered: July 2009
Senior Member
Kevin,

If changes are made directly to the underlying file system (rather than
through Eclipse's IResource APIs) such changes are noticed only when the
workspace resources are refreshed. There are preferences that affect
how/when such refreshes occur (other than manual File->Referesh). I.e.,
Window->Preferences->Workspace->* I.e., "Refresh using native hooks or
polling" and "Refresh on access". If you often will make changes
outside of the IDE's APIs, you'd probably want to enable both these
options...

On 22/08/2013 11:55 PM, Kevin Regan wrote:
> Thanks a lot for your reply Ed. I implemented your suggestion to
> remove the guard (the examples I saw on line were doing equality
> checks but I should have looked at the javadoc and realized it was a
> bitmask):
>
> /************* RESOURCE CHNAGE LISTENER TEST *********************/
>
> IResourceChangeListener listener = new
> IResourceChangeListener() {
> public void printDelta(IResourceDelta d, String indent) {
> IResource resource = d.getResource();
> IJavaElement javaElement = JavaCore.create(resource);
> String resourceName = null;
> if (javaElement instanceof IJavaProject) {
> resourceName = "Java project " + resource.getName();
> } else if (javaElement instanceof
> IPackageFragmentRoot) { resourceName = "PFR " +
> resource.getName();
> } else if (javaElement instanceof IPackageFragment) {
> resourceName = "PF " + resource.getName();
>
> } else if (javaElement instanceof ICompilationUnit) {
> resourceName = "CU " + resource.getName();
> } else {
> resourceName = resource.getName();
> }
>
> System.out.println(indent.concat("Delta " +
> d.getKind() + " for resource " + resourceName));
>
> for (IResourceDelta childDelta :
> d.getAffectedChildren()) {
> printDelta(childDelta, indent.concat("\t"));
> }
> }
> public void resourceChanged(IResourceChangeEvent e) {
> System.out.println("Resource change event type = " +
> e.getType());
> //if (e.getType() | IResourceChangeEvent.POST_CHANGE) {
> //System.out.println("Post change event");
>
>
> IResourceDelta delta = e.getDelta();
> printDelta(delta, "");
>
> /*} else {
> System.out.println("Event type was " + e.getType());
> }*/
> }
> };
>
>
>
> Basically, I have a startup plugin that programmatically creates an
> Eclipse project using information passed in on the command line to
> eclipse. For testing purposes, I created a file in the project:
>
>
> IFile myPropertyFile = project.getFile("mysettings");
>
> if (!myPropertyFile.exists()) {
> myPropertyFile.create(new
> ByteArrayInputStream("handle=1abcff23aa".getBytes()), true,
> getProgressMonitor());
> }
>
>
> Using windows explorer and VIM I go to the file created in the windows
> file system and edit the file. I do not get any notification in the
> resource change listener when I do this. Am I doing something wrong
> here?
> Note that I just did the same test by editing one of the Java source
> files that also reside in the project and did not get a notification
> about that either (just to make sure it didn't have to do with the
> type of element).
> In both cases, if I subsequently go into eclipse and open the file
> that I previously modified outside of eclipse I get the notification
> at that time:
>
>
> Resource change event type = 1
> Delta 4 for resource Delta 4 for resource Java project Test
> Delta 4 for resource mysettings
>
>
>
Re: Resource Change Listener [message #1093088 is a reply to message #1092712] Fri, 23 August 2013 10:47 Go to previous messageGo to next message
Kevin Regan is currently offline Kevin Regan
Messages: 33
Registered: May 2013
Member
Hi Ed, thanks again for your response. That would explain why I'm not getting pinged about the updates. Do you know if there is any way to set that option on a per project basis as opposed to a workspace-wide preference? The reason being, I only need this as a means to make the functionality of my plugin work - I am relying on detecting changes to this file so that I can trigger functionality in my plugin and I do not want to have to have the users of this plugin make workspace wide changes just for this one reason. Appreciate your help!
Re: Resource Change Listener [message #1095034 is a reply to message #1093088] Mon, 26 August 2013 10:29 Go to previous message
Kevin Regan is currently offline Kevin Regan
Messages: 33
Registered: May 2013
Member
Just answering my own question on the off chance that someone comes across this thread looking for the information. I was able to force the setting Ed mentioned during startup of my plugin via:

IEclipsePreferences prefs = InstanceScope.INSTANCE.getNode(PLUGIN_ID);
		prefs.putBoolean(ResourcesPlugin.PREF_AUTO_REFRESH, true);
		
		try {
			prefs.flush();
		} catch (BackingStoreException e2) {
			// TODO Auto-generated catch block
			e2.printStackTrace();
		}


The polling is on a slow interval it seems and I have yet to find a preference or any way to change that interval.

[Updated on: Mon, 26 August 2013 10:29]

Report message to a moderator

Previous Topic:Memory consumption
Next Topic:Can't remove project from workspace...
Goto Forum:
  


Current Time: Wed Aug 20 08:46:12 EDT 2014

Powered by FUDForum. Page generated in 0.02528 seconds