Re: having datatypes load classes
On Thu, 10 Apr 2003, Marc Portier [EMAIL PROTECTED] wrote: seems to me however the current LoaderUtil more has somewhat of a jdk-version match-up function? It used to be used for that, yes. But this part of its functionality is no longer needed in Ant 1.6 as we've dropped JDK 1.1 compatibility. CVS HEAD is going to drop Java 1.1 compatibility, so some changes in the whole classloader area are to be expected. could you elaborate, and maybe be explicit on how this can affect my doing ATM? If only I knew 8-) One thing that looks as if it was changing is that Ant's classes themselves will be loaded by a classloader that is not the system classloader. I don't think it is going to affect your doing, but I'm not 100% sure. The other thing is that you may be able to simplify things when you know you don't have to care about 1.1 compatibilty. Stefan
Re: having datatypes load classes
Dominique, I really appreciate this effort towards extra explanation, I had read the pointers from your first post by now and this surely completed my undderstanding. However, in the mean time I have been investigating some along the way Stefan has shown... I am facing the 1.6 required along that path now, but that's not a real showstopper for me (just a bit of a nuance in upgrading what I have been using up to know) I don't want to question the elegance, or correctness of your solution, it's just that the other way comes a bit more natural to me. I'm sure your approach will help many others. regards, -marc= Dominique Devienne wrote: Two comments: 1) DynamicTag is fully Ant 1.5.x compatible. No need for 1.6. Just use it along side your own classes, and you're good to go. 2) DynamicTag *relies* on taskdef or typedef (you can declare your custom extension either way), which takes care of all the classloading, already has all the special stuff like loaderref. Any enhancement to these tasks automatically benefit DynamicTag. With your use case, imagine you have a JAR of all your filters, with a properties file within it called filters.properties like so: xincludefilter = org.outerj.xml.XIncludeFilter filter1 = org.outerj.xml.SomeFilter You could do: typedef resource=org/outerj/xml/filters.properties classpath=org_outerj_xml.jar / target name=test depends=-init xmlchain toDir=./build/chain extension=.xxx fileset refid=workOnStuf / customfilters filter1 attr1=v1 attr2=v2 mysubelement .../ /filter1 xincludefilter .../ customfilters xmlfilter refid=other-filter/ /xmlchain /target And in your code, all you have to do is: public Object createCustomFilters() { // dynatag must contain at least 1 element, no upper limit DynamicTag dynatag = new DynamicTag(org.outerj.xml.XmlFilter.class, 1, Integet.MAX_INT); _filterVector.addElement(dynatag); return dynatag; } Then at execute time, convert the DynamicTags added to the vector to real filters (pseudo-code): Vector filters = new Vector(); foreach o in _filterVector { if (o instanceof DynamicTag) { filters.addAll(((DynamicTag)o).getTags()); } } DynamicTag guarantees you all elements within it are of the required type, the fictitious XmlFilter interface here. The really nice part is that you code XIncludeFilter and SomeFilter like a regular bean, and Ant automatically configures it using its normal rules (calls setters methods, or add/create methods, with all the magic type conversion it does to go from String to int, File (resolved to basedir), etc...). Your current filters might not have much in term of configuration now, but DynamicTag allows a very rich configuration of any extension point. I personally think it's pretty elegant, and doesn't require mucking at all with class loading issues. But again, my perspective is biased, since I authored DynamicTag. --DD -Original Message- From: Marc Portier [mailto:[EMAIL PROTECTED] Sent: Wednesday, April 09, 2003 1:32 AM To: Ant Developers List Subject: Re: having datatypes load classes Stefan Bodewig wrote: On Tue, 08 Apr 2003, Marc Portier [EMAIL PROTECTED] wrote: but since that pattern is to be seen more around ant iteself, I was hoping for some reuse here One would think so, but the truth is that you'll find copy-paste reuse in this area instead of delegation or something. Patches for a nice little utility class are welcome 8-) Stefan, thx for the invitation, if others want to be on the party: please join. Have to think about this some more, and have to read the replies from Dominique first (which at first sight seem to go somewhat over the 'nice little' attributes that I was seeking as well) woke up with something along the lines of a ClassLoaderFactory (name should be tuned down a bit, too much expectations here, inspiration welcome, PathUtil?) - public ClassLoader getClassLoaderForPath(Path); having the responsibility to check off against the project map of references (as does the Definer) possibly having a variant - public ClassLoader getUniqueClassLoaderForPath(Path) while the first would follow the documented rules of the ant.reuse.loader property, the latter would always make a new one, and never store that in the references map. in fact if ant.reuse.loader == false the behaviour of both methods would be equal. combination of both offers the flexibility to cover all the use cases I see I'm guessing this approach would offer the least pressure on having to rethink more interfaces/existing stuff. (compared to e.g. introduction of the ClassLoader datatype that was suggested in the thread I mentioned) Another advantage I see is that it's orthogonal to existing stuff, so people could just use it without neading to switch to cvs head or something (me included :-)) The real effort would be in refactoring and testing the existing implementations
Re: having datatypes load classes
We already have LoaderUtil in the util subpackage. Might fit there. I started on PathUtil for the moment, all is static so could be injected easily, seems to me however the current LoaderUtil more has somewhat of a jdk-version match-up function? - public ClassLoader getClassLoaderForPath(Path); - public ClassLoader getUniqueClassLoaderForPath(Path) getting into it (taking the reverseLoader inspiration from Definer) the signatures are becoming: - public static ClassLoader //letting myself go wild in overloading: getClassLoaderForPath(Project p, Reference ref); getClassLoaderForPath(Project p, Reference ref, boolean reverseLoader); getClassLoaderForPath(Path path, String pathId); getUniqueClassLoaderForPath(Path path); //the useful ones being: getClassLoaderForPath(Path path, String pathId, boolean reverseLoader); getUniqueClassLoaderForPath(Path path, boolean reverseLoader); We'll probably need both to address all needs, yes. Please note that CVS HEAD is going to drop Java 1.1 compatibility, so some changes in the whole classloader area are to be expected. could you elaborate, and maybe be explicit on how this can affect my doing ATM? I just encountered enough reason to ditch my 1.5.x and go for CVS HEAD to add this to, so I am interested... Farming out the common actions to instantiate a user defined class loaded from a user defined path will also provide additional benefits here, a single entry point that could ensure we check the context classloader first and that avoids Class.forName completely. Something like public Object newInstance(String classname, ClassLoader userDefinedLoader) makes sense, and just wrapping the classic instantiation/loading extensions into the BuildException then only bad thing is it breaks my PathUtil naming somewhat :-) with the semantics hinted at above. Stefan - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] regards, -marc= -- Marc Portierhttp://outerthought.org/ Outerthought - Open Source, Java XML Competence Support Center Read my weblog at http://radio.weblogs.com/0116284/ [EMAIL PROTECTED] [EMAIL PROTECTED]
Re: having datatypes load classes
Provided patch under bugzilla 18906 - ended up being ClasspathUtil.java - added the newInstance idea as well I need to get on with the show first now, but like to refactor other parts of ant where similar cut/paste code might be lingering (for sure o.a.t.a.taskdefs.Definer is candidate) Hope to be adding that patch early next week, although answers on this part of the thread might make me see how pointless that is: We'll probably need both to address all needs, yes. Please note that CVS HEAD is going to drop Java 1.1 compatibility, so some changes in the whole classloader area are to be expected. could you elaborate, and maybe be explicit on how this can affect my doing ATM? I just encountered enough reason to ditch my 1.5.x and go for CVS HEAD to add this to, so I am interested... regards, -marc= -- Marc Portierhttp://outerthought.org/ Outerthought - Open Source, Java XML Competence Support Center Read my weblog at http://radio.weblogs.com/0116284/ [EMAIL PROTECTED] [EMAIL PROTECTED]
Re: having datatypes load classes
On Tue, 08 Apr 2003, Marc Portier [EMAIL PROTECTED] wrote: but since that pattern is to be seen more around ant iteself, I was hoping for some reuse here One would think so, but the truth is that you'll find copy-paste reuse in this area instead of delegation or something. Patches for a nice little utility class are welcome 8-) Stefan
Re: having datatypes load classes
Stefan Bodewig wrote: On Tue, 08 Apr 2003, Marc Portier [EMAIL PROTECTED] wrote: but since that pattern is to be seen more around ant iteself, I was hoping for some reuse here One would think so, but the truth is that you'll find copy-paste reuse in this area instead of delegation or something. Patches for a nice little utility class are welcome 8-) Stefan, thx for the invitation, if others want to be on the party: please join. Have to think about this some more, and have to read the replies from Dominique first (which at first sight seem to go somewhat over the 'nice little' attributes that I was seeking as well) woke up with something along the lines of a ClassLoaderFactory (name should be tuned down a bit, too much expectations here, inspiration welcome, PathUtil?) - public ClassLoader getClassLoaderForPath(Path); having the responsibility to check off against the project map of references (as does the Definer) possibly having a variant - public ClassLoader getUniqueClassLoaderForPath(Path) while the first would follow the documented rules of the ant.reuse.loader property, the latter would always make a new one, and never store that in the references map. in fact if ant.reuse.loader == false the behaviour of both methods would be equal. combination of both offers the flexibility to cover all the use cases I see I'm guessing this approach would offer the least pressure on having to rethink more interfaces/existing stuff. (compared to e.g. introduction of the ClassLoader datatype that was suggested in the thread I mentioned) Another advantage I see is that it's orthogonal to existing stuff, so people could just use it without neading to switch to cvs head or something (me included :-)) The real effort would be in refactoring and testing the existing implementations to use this utility then (but that's somewhat future music) (also thinking about singleton vs statics for the beast) not overseeing _all_ use cases, and some general greenhorn feeling around the complete internals of ant makes me hesitate and think some more first though. but again, all of this might be in the answers from Dominique already. regards, -marc= Stefan - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] -- Marc Portierhttp://outerthought.org/ Outerthought - Open Source, Java XML Competence Support Center Read my weblog at http://radio.weblogs.com/0116284/ [EMAIL PROTECTED] [EMAIL PROTECTED]
RE: having datatypes load classes
Two comments: 1) DynamicTag is fully Ant 1.5.x compatible. No need for 1.6. Just use it along side your own classes, and you're good to go. 2) DynamicTag *relies* on taskdef or typedef (you can declare your custom extension either way), which takes care of all the classloading, already has all the special stuff like loaderref. Any enhancement to these tasks automatically benefit DynamicTag. With your use case, imagine you have a JAR of all your filters, with a properties file within it called filters.properties like so: xincludefilter = org.outerj.xml.XIncludeFilter filter1 = org.outerj.xml.SomeFilter You could do: typedef resource=org/outerj/xml/filters.properties classpath=org_outerj_xml.jar / target name=test depends=-init xmlchain toDir=./build/chain extension=.xxx fileset refid=workOnStuf / customfilters filter1 attr1=v1 attr2=v2 mysubelement .../ /filter1 xincludefilter .../ customfilters xmlfilter refid=other-filter/ /xmlchain /target And in your code, all you have to do is: public Object createCustomFilters() { // dynatag must contain at least 1 element, no upper limit DynamicTag dynatag = new DynamicTag(org.outerj.xml.XmlFilter.class, 1, Integet.MAX_INT); _filterVector.addElement(dynatag); return dynatag; } Then at execute time, convert the DynamicTags added to the vector to real filters (pseudo-code): Vector filters = new Vector(); foreach o in _filterVector { if (o instanceof DynamicTag) { filters.addAll(((DynamicTag)o).getTags()); } } DynamicTag guarantees you all elements within it are of the required type, the fictitious XmlFilter interface here. The really nice part is that you code XIncludeFilter and SomeFilter like a regular bean, and Ant automatically configures it using its normal rules (calls setters methods, or add/create methods, with all the magic type conversion it does to go from String to int, File (resolved to basedir), etc...). Your current filters might not have much in term of configuration now, but DynamicTag allows a very rich configuration of any extension point. I personally think it's pretty elegant, and doesn't require mucking at all with class loading issues. But again, my perspective is biased, since I authored DynamicTag. --DD -Original Message- From: Marc Portier [mailto:[EMAIL PROTECTED] Sent: Wednesday, April 09, 2003 1:32 AM To: Ant Developers List Subject: Re: having datatypes load classes Stefan Bodewig wrote: On Tue, 08 Apr 2003, Marc Portier [EMAIL PROTECTED] wrote: but since that pattern is to be seen more around ant iteself, I was hoping for some reuse here One would think so, but the truth is that you'll find copy-paste reuse in this area instead of delegation or something. Patches for a nice little utility class are welcome 8-) Stefan, thx for the invitation, if others want to be on the party: please join. Have to think about this some more, and have to read the replies from Dominique first (which at first sight seem to go somewhat over the 'nice little' attributes that I was seeking as well) woke up with something along the lines of a ClassLoaderFactory (name should be tuned down a bit, too much expectations here, inspiration welcome, PathUtil?) - public ClassLoader getClassLoaderForPath(Path); having the responsibility to check off against the project map of references (as does the Definer) possibly having a variant - public ClassLoader getUniqueClassLoaderForPath(Path) while the first would follow the documented rules of the ant.reuse.loader property, the latter would always make a new one, and never store that in the references map. in fact if ant.reuse.loader == false the behaviour of both methods would be equal. combination of both offers the flexibility to cover all the use cases I see I'm guessing this approach would offer the least pressure on having to rethink more interfaces/existing stuff. (compared to e.g. introduction of the ClassLoader datatype that was suggested in the thread I mentioned) Another advantage I see is that it's orthogonal to existing stuff, so people could just use it without neading to switch to cvs head or something (me included :-)) The real effort would be in refactoring and testing the existing implementations to use this utility then (but that's somewhat future music) (also thinking about singleton vs statics for the beast) not overseeing _all_ use cases, and some general greenhorn feeling around the complete internals of ant makes me hesitate and think some more first though. but again, all of this might be in the answers from Dominique already. regards, -marc=
RE: having datatypes load classes
See http://marc.theaimsgroup.com/?l=ant-devm=104870800508326w=2 And http://nagoya.apache.org/bugzilla/show_bug.cgi?id=17199 I prefer the first link, since I'm the author of it, but the second link addresses the same issue. If your xmlfilter elements do not need any configurations though, it may be overkill. That's for you to decide. --DD -Original Message- From: Marc Portier [mailto:[EMAIL PROTECTED] Sent: Tuesday, April 08, 2003 4:35 PM To: [EMAIL PROTECTED] Subject: having datatypes load classes Hi all, I'm writing some Ant task that requires the flexibility of having nested data-types that can load their own classes. target name=test depends=-init xmlchain toDir=./build/chain extension=.xxx fileset refid=workOnStuf / xmlfilter classname=org.outerj.xml.XIncludeFilter / xmlfilter refid=other-filter/ /xmlchain /target For sure I will need to have the @classpathref and nested classpath to actually get doing it, but since that pattern is to be seen more around ant iteself, I was hoping for some reuse here What I have found is the o.a.t.a.taskdefs.Definer which functions as a basis for the Taskdef and Typedef tasks But has a somewhat awkward execute() in there to be properly used inside this new xmlfilter datatype I foresee. I would hate duplicating/porting the Definer code into my own class here, so maybe there could be some ClassPathHelper object that can come to aid both? (But then that is probably just saying that the existing Path could have a method getClassLoader() ?) Looking out for some similar questions I have come across this elder thread: http://marc.theaimsgroup.com/?l=ant-devm=104024233924058w=2 which definitely touches the issue somewhat any advice is welcome, I have a real issue I want to tackle asap, but I like to consider returning the effort of your good thoughts into some actual contribution if such would be appreciated. regards, -marc= -- Marc Portierhttp://outerthought.org/ Outerthought - Open Source, Java XML Competence Support Center Read my weblog at http://radio.weblogs.com/0116284/ [EMAIL PROTECTED] [EMAIL PROTECTED] - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]