ant-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Derek Baum <derek.b...@paremus.com>
Subject Re: ivy settings classpath always creates new classloader when used with subant
Date Wed, 29 Oct 2008 20:40:16 GMT
Hi Gilles,

I have been unsuccessful in changing my buildscript in order to have the 
ivysettings defined only once.

Am I doing something wrong, or should I raise Jira to change the 
behaviour of ivysetting/classpath?

Thanks,

Derek

Derek Baum wrote:
> Hi,
>
> Thanks for your response.
>
> Are you suggesting:
>
> 1) if I satisfy the prerequisite,  then I won't need my suggested 
> patch, or
> 2) my patch will only work if the prerequisite is satisfied?
>
> Assuming 1), I tried this, but when I didn't explicitly load 
> ivysettings, a default was loaded instead and the build failed.
>
> Here's my subant target for the example multi-project/build.xml:
>>   <target name="publish-all" depends="buildlist"
>>         description="compile, jar and publish all projects in the 
>> right order">
>>     <subant target="publish" buildpathref="build-list">
>>       <propertyset>
>>         <propertyref name="ivy.loaded" />
>>       </propertyset>
>>     </subant>
>>   </target>
>
> Here's the Ivy taskdef:
>
>>     <target name="load-ivy" unless="ivy.loaded">
>>         <property name="ivy.loaded" value="true"/>
>>         <echo message="Loading Ivy ..."/>
>>         <taskdef resource="org/apache/ivy/ant/antlib.xml"
>>                  uri="antlib:org.apache.ivy.ant"
>>                  loaderRef="ivyLoader"
>>                  classpath="${ivy.jar.file}"/>
>>         <ivy:settings file="${common.dir}/ivysettings.xml" />
>>     </target>
>
> and here's the build output, notice the loading of default settings in 
> new-ivy-version:
>
>> [multi-project]$ ant publish-all
>> Buildfile: build.xml
>>
>> load-ivy:
>>      [echo] Loading Ivy ...
>>
>> buildlist:
>> [ivy:buildlist] :: Ivy 2.0.0-rc1 - 20080916082609 :: 
>> http://ant.apache.org/ivy/ ::
>> :: loading settings :: file = 
>> /Volumes/Users/derek/eclipse/Sigil/bld-ivy/test/multi-project/common/ivysettings.xml

>>
>>
>> publish-all:
>>
>> clean-build:
>>    [delete] Deleting directory 
>> /Volumes/Users/derek/eclipse/Sigil/bld-ivy/test/multi-project/projects/version/build

>>
>>
>> load-ivy:
>>
>> ivy-new-version:
>> No ivy:settings found for the default reference 'ivy.instance'.  A 
>> default instance will be used
>> no settings file found, using default...
>> :: loading settings :: url = 
>> jar:file:/opt/apache-ivy-2.0.0-rc1/ivy-2.0.0-rc1.jar!/org/apache/ivy/core/settings/ivysettings.xml

>>
>>
>> version:
>>     [mkdir] Created dir: 
>> /Volumes/Users/derek/eclipse/Sigil/bld-ivy/test/multi-project/projects/version/build/classes

>>
>
> I therefore had to change the load-ivy target to always define 
> ivysettings:
>
>    <target name="load-ivy" depends="ivy-taskdef">
>        <ivy:settings file="${common.dir}/ivysettings.xml" />
>    </target>
>
> which is why I concluded that a change to the ivysettings/classpath 
> command was needed.
>
> Thanks,
>
> Derek
>
>
>
> Gilles Scokart wrote:
>> There will be a prerequisite for that to work : You must be sure that
>> that ivy itself is not loaded in two ClassLoader.  For that, your
>> taskdef for ivy should itself use a loaderRef, and the subant must
>> have the right options that make the id shared accross the projects.
>>
>> And if that prerequisite is valid, in most case you can arrange your
>> buildscript in order to have the ivysettings defined only once.
>>
>>
>>
>> 2008/10/16 Derek Baum <derek.baum@paremus.com>:
>>  
>>> Hi,
>>>
>>> I have a custom Ivy resolver that keeps a static cache because it is
>>> time-consuming to initialise.
>>>
>>> However, this cache doesn't work in a multi-project build, because the
>>> ivysettings/classpath command is creating a new URLClassLoader for each
>>> subant iteration, so all static class fields are reset.
>>>
>>> <ivysettings>
>>>
>>>  <classpath file="${ivy.settings.dir}/sigil-ivy-plugin.jar" />
>>>
>>>  <typedef name="sigil" 
>>> classname="org.cauldron.bld.ivy.SigilResolver" />
>>>
>>>  ...
>>>
>>> </ivysettings>
>>>
>>>
>>> I'm building multiple projects, using ivy:buildlist and subant, as 
>>> in the
>>> Ivy multi-project example.
>>>
>>> Each iteration of subant, causes IvySettings to reload.
>>> IvySettings.classloader is thus null and so a new URLClassLoader is 
>>> created.
>>>
>>> I temporarily worked around this by loading my plugin at the same 
>>> time as
>>> Ivy (i.e. not using settings/classpath), but I'd really like the
>>> setting/classpath method to work too.
>>>
>>> One possible solution would be to add a "loaderRef" attribute to
>>> settings/classpath, similar to the Ant taskdef/typedef tasks, to 
>>> make it use
>>> the same ClassLoader.
>>>
>>> Alternatively, IvySettings could simply be changed to only create a new
>>> URLClassLoader if the list of URLs  has changed. I attach a simple 
>>> patch to
>>> IvySettings.java that does this and seems to work OK.
>>>
>>> If this is valid and useful, let me know and I'll raise it in Jira.
>>>
>>> Thanks,
>>>
>>> Derek
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>> Index: src/java/org/apache/ivy/core/settings/IvySettings.java
>>> ===================================================================
>>> --- src/java/org/apache/ivy/core/settings/IvySettings.java      
>>> (revision
>>> 705243)
>>> +++ src/java/org/apache/ivy/core/settings/IvySettings.java      
>>> (working
>>> copy)
>>> @@ -644,13 +644,19 @@
>>>         }
>>>     }
>>>
>>> +    private static Map loaderCache =  new HashMap();
>>> +
>>>     private ClassLoader getClassLoader() {
>>>         if (classloader == null) {
>>>             if (classpathURLs.isEmpty()) {
>>>                 classloader = Ivy.class.getClassLoader();
>>>             } else {
>>> -                classloader = new URLClassLoader((URL[]) classpathURLs
>>> +                classloader = (ClassLoader) 
>>> loaderCache.get(classpathURLs);
>>> +                if (classloader == null) {
>>> +                    classloader = new URLClassLoader((URL[]) 
>>> classpathURLs
>>>                         .toArray(new URL[classpathURLs.size()]),
>>> Ivy.class.getClassLoader());
>>> +                    loaderCache.put(classpathURLs, classloader);
>>> +                }
>>>             }
>>>         }
>>>         return classloader;
>>>
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: dev-unsubscribe@ant.apache.org
>>> For additional commands, e-mail: dev-help@ant.apache.org
>>>
>>>     
>>
>>
>>
>>   

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@ant.apache.org
For additional commands, e-mail: dev-help@ant.apache.org


Mime
View raw message