On 5/10/07, Jarosław Wypychowski <[EMAIL PROTECTED]> wrote:

Fixed.

I did found the source of problem - and the solution.

The problem is in fact architectural.

In my scenario there is a chain of events:

ant->ivy:resolve->ant-call-trigger->ant->ivy:resolve->ant-call-trigger->ant->...

The whole process is in a single Thread.
so when we are in first ant-call - we override the parent Project
settings. When we are in second - we override the parent Project. Ant
build call creates a new project internally in execute of <ant/> task.
So in the original scenario it would fail if the task already finished
and GC cleaned the project. So the comment in my proposal was cleanly
accidental in its help.
Unfortunately going from WeakRef to direct save will not help either -
as we will again override parent's project. There needs to be a complete
change in the way the Project is kept within context.



You might not like my solution - so please tell me how it should look
like to fit Your design.

I've added specialized methods into the IvyContext:
        public void setAntProject(Project project){
                List l=(List)_contextMap.get(
IvyTask.ANT_PROJECT_CONTEXT_KEY);
                if(l==null){
                        l=new ArrayList();
                        _contextMap.put(IvyTask.ANT_PROJECT_CONTEXT_KEY,
l);
                }
                l.add(0,project);
        }

        public void unsetAntProject(Project project){
                List l=(List)_contextMap.get(
IvyTask.ANT_PROJECT_CONTEXT_KEY);
                if(l==null){
                        return;
                }
                l.remove(project);
        }

        public void unsetAntProject(){
                List l=(List)_contextMap.get(
IvyTask.ANT_PROJECT_CONTEXT_KEY);
                if(l==null){
                        return;
                }
                l.remove(0);
        }

        public Project getAntProject(){
                List l=(List)_contextMap.get(
IvyTask.ANT_PROJECT_CONTEXT_KEY);
                if(l==null || l.size()==0){
                        return null;
                }
                return (Project)l.get(0);
        }


And modified get(String) into:

        public Object get(String key) {
                if(IvyTask.ANT_PROJECT_CONTEXT_KEY.equals(key)) return
getAntProject();
                if(_contextMap.get(key) instanceof WeakReference){
                        WeakReference ref = (WeakReference)
_contextMap.get(key);
                        return ref == null ? null : ref.get();
                } else {
                        return _contextMap.get(key);
                }
        }

Next I added doExecute as You suggested and made it stack a project on
and off in the IvyTask.execute():
    public void execute() throws BuildException {
        IvyContext.getContext().setAntProject(getProject());
        doExecute();
        IvyContext.getContext().unsetAntProject(getProject());
    }


Now Projects are stacked during the execution of IvyTasks in single
thread and removed when not needed anymore. Now all my tasks are going
without errors.

Personally I don't really like the solution above (it mixes IvyTask with
IvyContext) - so please suggest a better way.


Well, the problem of your solution is that it makes IvyContext depend on an
Ant class, which we have to avoid to keep Ivy core independent of Ant.

So I see two possible solutions:
* keep IvyContext as is, and set ANT_PROJECT_CONTEXT_KEY to a Stack instead
of a Project. In this case all classes dealing with ANT_PROJECT_CONTEXT_KEY
will have to be aware it's a Stack. Maybe adding a static method like
getCurrentProject() in IvyTask could centralize all the management of this
Stack.
* add methods to manage a Stack in IvyContext, because other classes may
have to deal with the same kind of problem. We could add a push, pop and
peek method, and use these methods instead of set and get from IvyTask,
AntCallTrigger and AntBuildTrigger.
Centralizing the management in IvyTask can make sense in either case. I have
a slight preference for the second one for its reusability, but it's only a
slight preference.

And If You would like me to finish the patch - what format of the patch
would you like ? (diff params ?)


using regular svn diff is appropriate. Please create a JIRA issue for
attaching the patch, it's better to track the problem and to clear legal
issues while applying your patch (you have a box to check when attaching the
patch to allow us to apply it).

Thanks for your contribution!

Xavier


Best Regards

--jw

--
Jaroslaw Wypychowski
Interdyscyplinarne Centrum Modelowania Matematycznego i Komputerowego UW
[EMAIL PROTECTED]




--
Xavier Hanin - Independent Java Consultant
Manage your dependencies with Ivy!
http://incubator.apache.org/ivy/

Reply via email to