Home » Language IDEs » Java Development Tools (JDT) » IClasspathContainer and JavaModel update
IClasspathContainer and JavaModel update [message #242881] |
Fri, 13 April 2007 21:27 |
Eclipse User |
|
|
|
Originally posted by: sg3235.sbc.com
I have a question concerning the expected method of updating the contents of
a container, for example, a container that monitored the WEB-INF/lib
directory and automatically updates the classpath when files are added or
deleted. I have set up a container and regiseterd a resource change
listener to detect the modifications. When the resource change event fires,
I update the classpath entries stored in the container and invoke
JavaCore.setClasspathContainer. The javadocs say "this API must be invoked
whenever changes in container need to be reflected onto the JavaModel."
Much further down in the docs it says "This operation is batched, and
automatically eliminates unnecessary updates (new container is same as old
one)." I didn't really understand this as my change is obviously not
"unnecessary" until I traced through the JavaCore code and saw that it drops
out because I pass "new IClasspathContainer[] { this }" as a parameter.
I've made it work by passing "new IClasspathContainer[] { this.clone(); }"
instead. However, this seems horribly inefficient. Considerning the JDT
Plug-in Developer Guide" offers little help in creating such a container, I
was wondering how this functionality was expected to work.
Stephen Gevers
|
|
|
Re: IClasspathContainer and JavaModel update [message #242941 is a reply to message #242881] |
Tue, 17 April 2007 13:18 |
Aaron Tarter Messages: 6 Registered: July 2009 |
Junior Member |
|
|
Stephen Gevers wrote:
> I have a question concerning the expected method of updating the contents of
> a container, for example, a container that monitored the WEB-INF/lib
> directory and automatically updates the classpath when files are added or
> deleted. I have set up a container and regiseterd a resource change
> listener to detect the modifications. When the resource change event fires,
> I update the classpath entries stored in the container and invoke
> JavaCore.setClasspathContainer. The javadocs say "this API must be invoked
> whenever changes in container need to be reflected onto the JavaModel."
> Much further down in the docs it says "This operation is batched, and
> automatically eliminates unnecessary updates (new container is same as old
> one)." I didn't really understand this as my change is obviously not
> "unnecessary" until I traced through the JavaCore code and saw that it drops
> out because I pass "new IClasspathContainer[] { this }" as a parameter.
> I've made it work by passing "new IClasspathContainer[] { this.clone(); }"
> instead. However, this seems horribly inefficient. Considerning the JDT
> Plug-in Developer Guide" offers little help in creating such a container, I
> was wondering how this functionality was expected to work.
>
> Stephen Gevers
>
>
In Eclipse 3.2 (not sure about earlier versions), the
getClasspathEntries() will be called on your container whenever a file
is added/deleted through eclipse without having to implement a
ResourceChangeListener. I think the Java model calls
getClasspathEntries() in response to any PRE_BUILD resource changes.
So, if you were returning the files in WEB-INF/lib, and a file in
WEB-INF/lib was deleted, your getClasspathEntries() method is called
automatically and the container is effectively updated. You should not
need to call JavaCore.setClasspathContainer() unless you are trying to
change a container's properties. For instance, if the user clicks
'Edit' in the build path properties and changes some property about the
container. Btw, the WTP eclipse project has a container called "Web App
Libraries" for dynamic web projects that adds files from WEB-INF/lib to
the classpath... you might want to look at the source for this one.
|
|
|
Re: IClasspathContainer and JavaModel update [message #243194 is a reply to message #242941] |
Wed, 25 April 2007 18:16 |
Eclipse User |
|
|
|
Originally posted by: sg3235.sbc.com
Actually the resource change listener is going to be more efficient since I
only have to update my set of classpath entries whenver my directory
changes, rather than go through the folder everytime the getClasspathEntries
method is called. I traced through the call to
JavaCore.setClasspathContainer when I passed "this" in the array of
containers and found that it did nothing. That meant that model was not
updated and the container entry in the package explorer did not change.
That was true both from the call to setClasspathContainer and from the file
being dropped into the directory. That is, unless the call to
getClasspathEntries happened before my set of classpath entries was updated
due to the order of resource delta processing. What was even stranger was
that by going into the Java Build Path properties page caused the package
explorer to update the container entry, but the set of .jar files listed
there had no contents. That is, expanding the .jar entry under my container
showed nothing. Further, the build failed to resolve references into those
..jar files. What that tells me is that, although the getClasspathEntries
was being called and showing the list of .jars in the container, the
contents of those .jars was not being added to the Java Model. When I
replaced the "this" with "this.clone()", the model was immediately updated
through JavaCore.setClasspathContainer, the package explorer refreshed and
showed the correct set of .jars without having to visit the Build Path page,
and the compile succeeded.
So now I'm taking your advice and looking at the source code for WTP
container. The WTP Container extends a class called
FlexibleProjectContainer which registers itself as a ResourceChangeListener.
Although there are some tests in there to determine whether or not the
container is out of date due to the resource change event, the
resourceChanged method eventually invokes an abstract refresh method which
causes the WebAppLibrariesContainer class to create a new instance of itself
and invoke JavaCore.setClasspathContainer with the new instance. So my
implementation that works is following the same basic model as the WTP
implementation.
So maybe my question should be: shouldn't there be a method available that
causes the Java Model to be updated when the container changes rather than
having to create a new instance of the container. Or is there a reason that
creating a new container is desired?
Stephen Gevers
"Aaron J Tarter" <ajtarter@gmail.com> wrote in message
news:f02hdv$s63$1@build.eclipse.org...
> Stephen Gevers wrote:
>> I have a question concerning the expected method of updating the contents
>> of a container, for example, a container that monitored the WEB-INF/lib
>> directory and automatically updates the classpath when files are added or
>> deleted. I have set up a container and regiseterd a resource change
>> listener to detect the modifications. When the resource change event
>> fires, I update the classpath entries stored in the container and invoke
>> JavaCore.setClasspathContainer. The javadocs say "this API must be
>> invoked whenever changes in container need to be reflected onto the
>> JavaModel." Much further down in the docs it says "This operation is
>> batched, and automatically eliminates unnecessary updates (new container
>> is same as old one)." I didn't really understand this as my change is
>> obviously not "unnecessary" until I traced through the JavaCore code and
>> saw that it drops out because I pass "new IClasspathContainer[] { this }"
>> as a parameter. I've made it work by passing "new IClasspathContainer[]
>> { this.clone(); }" instead. However, this seems horribly inefficient.
>> Considerning the JDT Plug-in Developer Guide" offers little help in
>> creating such a container, I was wondering how this functionality was
>> expected to work.
>>
>> Stephen Gevers
>
> In Eclipse 3.2 (not sure about earlier versions), the
> getClasspathEntries() will be called on your container whenever a file is
> added/deleted through eclipse without having to implement a
> ResourceChangeListener. I think the Java model calls
> getClasspathEntries() in response to any PRE_BUILD resource changes. So,
> if you were returning the files in WEB-INF/lib, and a file in WEB-INF/lib
> was deleted, your getClasspathEntries() method is called automatically and
> the container is effectively updated. You should not need to call
> JavaCore.setClasspathContainer() unless you are trying to change a
> container's properties. For instance, if the user clicks 'Edit' in the
> build path properties and changes some property about the container. Btw,
> the WTP eclipse project has a container called "Web App Libraries" for
> dynamic web projects that adds files from WEB-INF/lib to the classpath...
> you might want to look at the source for this one.
|
|
|
Re: IClasspathContainer and JavaModel update [message #243532 is a reply to message #243194] |
Wed, 09 May 2007 01:35 |
Aaron Tarter Messages: 6 Registered: July 2009 |
Junior Member |
|
|
Stephen Gevers wrote:
> Actually the resource change listener is going to be more efficient since I
> only have to update my set of classpath entries whenver my directory
> changes, rather than go through the folder everytime the getClasspathEntries
> method is called. I traced through the call to
> JavaCore.setClasspathContainer when I passed "this" in the array of
> containers and found that it did nothing. That meant that model was not
> updated and the container entry in the package explorer did not change.
> That was true both from the call to setClasspathContainer and from the file
> being dropped into the directory. That is, unless the call to
> getClasspathEntries happened before my set of classpath entries was updated
> due to the order of resource delta processing. What was even stranger was
> that by going into the Java Build Path properties page caused the package
> explorer to update the container entry, but the set of .jar files listed
> there had no contents. That is, expanding the .jar entry under my container
> showed nothing. Further, the build failed to resolve references into those
> .jar files. What that tells me is that, although the getClasspathEntries
> was being called and showing the list of .jars in the container, the
> contents of those .jars was not being added to the Java Model. When I
> replaced the "this" with "this.clone()", the model was immediately updated
> through JavaCore.setClasspathContainer, the package explorer refreshed and
> showed the correct set of .jars without having to visit the Build Path page,
> and the compile succeeded.
>
> So now I'm taking your advice and looking at the source code for WTP
> container. The WTP Container extends a class called
> FlexibleProjectContainer which registers itself as a ResourceChangeListener.
> Although there are some tests in there to determine whether or not the
> container is out of date due to the resource change event, the
> resourceChanged method eventually invokes an abstract refresh method which
> causes the WebAppLibrariesContainer class to create a new instance of itself
> and invoke JavaCore.setClasspathContainer with the new instance. So my
> implementation that works is following the same basic model as the WTP
> implementation.
>
> So maybe my question should be: shouldn't there be a method available that
> causes the Java Model to be updated when the container changes rather than
> having to create a new instance of the container. Or is there a reason that
> creating a new container is desired?
>
> Stephen Gevers
>
> "Aaron J Tarter" <ajtarter@gmail.com> wrote in message
> news:f02hdv$s63$1@build.eclipse.org...
>> Stephen Gevers wrote:
>>> I have a question concerning the expected method of updating the contents
>>> of a container, for example, a container that monitored the WEB-INF/lib
>>> directory and automatically updates the classpath when files are added or
>>> deleted. I have set up a container and regiseterd a resource change
>>> listener to detect the modifications. When the resource change event
>>> fires, I update the classpath entries stored in the container and invoke
>>> JavaCore.setClasspathContainer. The javadocs say "this API must be
>>> invoked whenever changes in container need to be reflected onto the
>>> JavaModel." Much further down in the docs it says "This operation is
>>> batched, and automatically eliminates unnecessary updates (new container
>>> is same as old one)." I didn't really understand this as my change is
>>> obviously not "unnecessary" until I traced through the JavaCore code and
>>> saw that it drops out because I pass "new IClasspathContainer[] { this }"
>>> as a parameter. I've made it work by passing "new IClasspathContainer[]
>>> { this.clone(); }" instead. However, this seems horribly inefficient.
>>> Considerning the JDT Plug-in Developer Guide" offers little help in
>>> creating such a container, I was wondering how this functionality was
>>> expected to work.
>>>
>>> Stephen Gevers
>> In Eclipse 3.2 (not sure about earlier versions), the
>> getClasspathEntries() will be called on your container whenever a file is
>> added/deleted through eclipse without having to implement a
>> ResourceChangeListener. I think the Java model calls
>> getClasspathEntries() in response to any PRE_BUILD resource changes. So,
>> if you were returning the files in WEB-INF/lib, and a file in WEB-INF/lib
>> was deleted, your getClasspathEntries() method is called automatically and
>> the container is effectively updated. You should not need to call
>> JavaCore.setClasspathContainer() unless you are trying to change a
>> container's properties. For instance, if the user clicks 'Edit' in the
>> build path properties and changes some property about the container. Btw,
>> the WTP eclipse project has a container called "Web App Libraries" for
>> dynamic web projects that adds files from WEB-INF/lib to the classpath...
>> you might want to look at the source for this one.
>
>
I still don't see why a new instance needs to be created... anytime the
Java Model is actually going to use the container a PRE-BUILD event will
be fired. This will result in your getClasspathEntries() method being
called, which should update the set of classpath entries that are being
defined by the instance. In regards to your previous comment on the JDT
plug-in developer guide not providing much help - I recently wrote a
tutorial on classpath containers, classpath container pages, and
classpath container initializers that is published on developerWorks at
http://www.ibm.com/developerworks/opensource/edu/os-dw-os-ec lipse-classpath.html.
If you work through the example you will see that it is not
necessary to create a new instance unless the container is being added
to the build path for the first time. In the tutorial, the
getClasspathEntries() method simply lists the files in the directory and
adds them to the classpath each time the getClasspathEntries() is
called. While this method is called frequently, there is no noticeable
delay in the Eclipse builder. As you pointed out, if you want to
improve the performance, you could implement a PREBUILD resource change
listener that builds the list, and then when getClasspathEntries() is
called, you can simply return the prebuilt list, but there is still no
need to create a new instance.
I have noticed in previous versions of Eclipse that the Java Package
Explorer did not always update in response to the entries changing. I
used to trigger the update with a call like
project.setRawClasspath(project.getRawClasspath(), null). As you can
see, this is not changing the classpath, but it triggered the Java
Package Explorer to update.
|
|
|
Re: IClasspathContainer and JavaModel update [message #243537 is a reply to message #243532] |
Wed, 09 May 2007 06:20 |
Eclipse User |
|
|
|
Originally posted by: wharley.bea.com
"Aaron J Tarter" <ajtarter@gmail.com> wrote in message
news:f1r8gr$saq$1@build.eclipse.org...
> I have noticed in previous versions of Eclipse that the Java Package
> Explorer did not always update in response to the entries changing. I
> used to trigger the update with a call like
> project.setRawClasspath(project.getRawClasspath(), null). As you can see,
> this is not changing the classpath, but it triggered the Java Package
> Explorer to update.
Not contradicting any of Aaron's points, but: it should perhaps be noted
that the classpath APIs are not threadsafe. For instance, if the above code
is running on one thread while another thread is updating the classpath, a
race condition will exist in which the update may be ignored. (This has
been a substantial problem in practice for some projects.) In general it is
safest to always and only update the classpath on the main thread.
|
|
|
Goto Forum:
Current Time: Thu Nov 14 08:55:47 GMT 2024
Powered by FUDForum. Page generated in 0.05684 seconds
|