You are viewing a plain text version of this content. The canonical link for it is here.
Posted to ivy-commits@incubator.apache.org by xa...@apache.org on 2007/01/31 15:54:45 UTC

svn commit: r501865 [2/2] - in /incubator/ivy/core/trunk/src/java/org/apache/ivy: ./ core/ core/cache/ core/check/ core/deliver/ core/event/ core/install/ core/publish/ core/resolve/ core/retrieve/ core/search/ core/sort/

Added: incubator/ivy/core/trunk/src/java/org/apache/ivy/core/deliver/DeliverEngine.java
URL: http://svn.apache.org/viewvc/incubator/ivy/core/trunk/src/java/org/apache/ivy/core/deliver/DeliverEngine.java?view=auto&rev=501865
==============================================================================
--- incubator/ivy/core/trunk/src/java/org/apache/ivy/core/deliver/DeliverEngine.java (added)
+++ incubator/ivy/core/trunk/src/java/org/apache/ivy/core/deliver/DeliverEngine.java Wed Jan 31 07:54:39 2007
@@ -0,0 +1,167 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+package org.apache.ivy.core.deliver;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.text.ParseException;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Properties;
+
+import org.apache.ivy.core.IvyPatternHelper;
+import org.apache.ivy.core.cache.CacheManager;
+import org.apache.ivy.core.module.descriptor.DependencyDescriptor;
+import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
+import org.apache.ivy.core.module.id.ModuleRevisionId;
+import org.apache.ivy.core.settings.IvySettings;
+import org.apache.ivy.plugins.parser.xml.XmlModuleDescriptorParser;
+import org.apache.ivy.plugins.parser.xml.XmlModuleDescriptorUpdater;
+import org.apache.ivy.util.Message;
+import org.xml.sax.SAXException;
+
+public class DeliverEngine {
+	private IvySettings _settings;
+	
+    public DeliverEngine(IvySettings settings) {
+		_settings = settings;
+	}
+
+	public void deliver(ModuleRevisionId mrid,
+            String revision,
+            File cache, 
+            String destIvyPattern, 
+            String status,
+            Date pubdate,
+            PublishingDependencyRevisionResolver pdrResolver, 
+            boolean validate
+            ) throws IOException, ParseException {
+        deliver(mrid, revision, cache, destIvyPattern, status, pubdate, pdrResolver, validate, true);
+    }
+    
+    /**
+     * delivers a resolved ivy file based upon last resolve call status and
+     * the given PublishingDependencyRevisionResolver.
+     * If resolve report file cannot be found in cache, then it throws 
+     * an IllegalStateException (maybe resolve has not been called before ?)
+     * Moreover, the given PublishingDependencyRevisionResolver is used for each 
+     * dependency to get its published information. This can particularly useful
+     * when the publish is made for a delivery, and when we wish to deliver each
+     * dependency which is still in integration. The PublishingDependencyRevisionResolver
+     * can then do the delivering work for the dependency and return the new (delivered)
+     * dependency info (with the delivered revision). Note that 
+     * PublishingDependencyRevisionResolver is only called for each <b>direct</b> dependency.
+     * 
+     * @param status the new status, null to keep the old one
+     * @throws ParseException
+     */
+    public void deliver(ModuleRevisionId mrid,
+            String revision,
+            File cache, 
+            String destIvyPattern, 
+            String status,
+            Date pubdate,
+            PublishingDependencyRevisionResolver pdrResolver, 
+            boolean validate,
+            boolean resolveDynamicRevisions) throws IOException, ParseException {
+        Message.info(":: delivering :: "+mrid+" :: "+revision+" :: "+status+" :: "+pubdate);
+        Message.verbose("\tvalidate = "+validate);
+        long start = System.currentTimeMillis();
+        destIvyPattern = _settings.substitute(destIvyPattern);
+        CacheManager cacheManager = getCacheManager(cache);
+        
+        // 1) find the resolved module descriptor in cache
+        File ivyFile = cacheManager.getResolvedIvyFileInCache(mrid);
+        if (!ivyFile.exists()) {
+            throw new IllegalStateException("ivy file not found in cache for "+mrid+": please resolve dependencies before publishing ("+ivyFile+")");
+        }
+        ModuleDescriptor md = null;
+        URL ivyFileURL = null;
+        try {
+            ivyFileURL = ivyFile.toURL();
+            md = XmlModuleDescriptorParser.getInstance().parseDescriptor(_settings, ivyFileURL, validate);
+            md.setResolvedModuleRevisionId(ModuleRevisionId.newInstance(mrid, revision));
+            md.setResolvedPublicationDate(pubdate);
+        } catch (MalformedURLException e) {
+            throw new RuntimeException("malformed url obtained for file "+ivyFile , e);
+        } catch (ParseException e) {
+            throw new RuntimeException("bad ivy file in cache for "+mrid+": please clean and resolve again" , e);
+        }
+        
+        // 2) parse resolvedRevisions From properties file
+        Map resolvedRevisions = new HashMap(); // Map (ModuleId -> String revision)
+        Map dependenciesStatus = new HashMap(); // Map (ModuleId -> String status)
+        File ivyProperties = cacheManager.getResolvedIvyPropertiesInCache(mrid);
+        if (!ivyProperties.exists()) {
+            throw new IllegalStateException("ivy properties not found in cache for "+mrid+": please resolve dependencies before publishing ("+ivyFile+")");
+        }
+        Properties props = new Properties();
+        props.load(new FileInputStream(ivyProperties));
+        
+        for (Iterator iter = props.keySet().iterator(); iter.hasNext();) {
+            String depMridStr = (String)iter.next();
+            String[] parts = props.getProperty(depMridStr).split(" ");
+            ModuleRevisionId decodedMrid = ModuleRevisionId.decode(depMridStr);
+            if (resolveDynamicRevisions) {
+                resolvedRevisions.put(decodedMrid, parts[0]);
+            }
+            dependenciesStatus.put(decodedMrid, parts[1]);
+        }
+        
+        // 3) use pdrResolver to resolve dependencies info
+        Map resolvedDependencies = new HashMap(); // Map (ModuleRevisionId -> String revision)
+        DependencyDescriptor[] dependencies = md.getDependencies();
+        for (int i = 0; i < dependencies.length; i++) {
+            String rev = (String)resolvedRevisions.get(dependencies[i].getDependencyRevisionId());
+            if (rev == null) {
+                rev = dependencies[i].getDependencyRevisionId().getRevision();
+            }
+            String depStatus = (String)dependenciesStatus.get(dependencies[i].getDependencyRevisionId());
+            resolvedDependencies.put(dependencies[i].getDependencyRevisionId(), 
+                    pdrResolver.resolve(md, status, 
+                            ModuleRevisionId.newInstance(dependencies[i].getDependencyRevisionId(), rev), 
+                            depStatus));
+        }
+        
+        // 4) copy the source resolved ivy to the destination specified, 
+        //    updating status, revision and dependency revisions obtained by
+        //    PublishingDependencyRevisionResolver
+        String publishedIvy = IvyPatternHelper.substitute(destIvyPattern, md.getResolvedModuleRevisionId());
+        Message.info("\tdelivering ivy file to "+publishedIvy);
+        try {
+            XmlModuleDescriptorUpdater.update(_settings, ivyFileURL, 
+                    new File(publishedIvy),
+                    resolvedDependencies, status, revision, pubdate, null, true);
+        } catch (SAXException ex) {
+            throw new RuntimeException("bad ivy file in cache for "+mrid+": please clean and resolve again" , ex);
+        }
+        
+        Message.verbose("\tdeliver done ("+(System.currentTimeMillis()-start)+"ms)");
+    }
+
+	private CacheManager getCacheManager(File cache) {
+		//TODO : reuse instance
+		CacheManager cacheManager = new CacheManager(_settings, cache);
+		return cacheManager;
+	}
+}

Modified: incubator/ivy/core/trunk/src/java/org/apache/ivy/core/event/EventManager.java
URL: http://svn.apache.org/viewvc/incubator/ivy/core/trunk/src/java/org/apache/ivy/core/event/EventManager.java?view=diff&rev=501865&r1=501864&r2=501865
==============================================================================
--- incubator/ivy/core/trunk/src/java/org/apache/ivy/core/event/EventManager.java (original)
+++ incubator/ivy/core/trunk/src/java/org/apache/ivy/core/event/EventManager.java Wed Jan 31 07:54:39 2007
@@ -1,3 +1,20 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
 package org.apache.ivy.core.event;
 
 import java.util.Arrays;

Added: incubator/ivy/core/trunk/src/java/org/apache/ivy/core/install/InstallEngine.java
URL: http://svn.apache.org/viewvc/incubator/ivy/core/trunk/src/java/org/apache/ivy/core/install/InstallEngine.java?view=auto&rev=501865
==============================================================================
--- incubator/ivy/core/trunk/src/java/org/apache/ivy/core/install/InstallEngine.java (added)
+++ incubator/ivy/core/trunk/src/java/org/apache/ivy/core/install/InstallEngine.java Wed Jan 31 07:54:39 2007
@@ -0,0 +1,156 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+package org.apache.ivy.core.install;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.Iterator;
+
+import org.apache.ivy.core.cache.CacheManager;
+import org.apache.ivy.core.module.descriptor.Configuration;
+import org.apache.ivy.core.module.descriptor.DefaultDependencyDescriptor;
+import org.apache.ivy.core.module.descriptor.DefaultModuleDescriptor;
+import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
+import org.apache.ivy.core.module.id.ModuleId;
+import org.apache.ivy.core.module.id.ModuleRevisionId;
+import org.apache.ivy.core.publish.PublishEngine;
+import org.apache.ivy.core.report.ResolveReport;
+import org.apache.ivy.core.resolve.IvyNode;
+import org.apache.ivy.core.resolve.ResolveEngine;
+import org.apache.ivy.core.search.SearchEngine;
+import org.apache.ivy.core.settings.IvySettings;
+import org.apache.ivy.plugins.conflict.NoConflictManager;
+import org.apache.ivy.plugins.matcher.ExactPatternMatcher;
+import org.apache.ivy.plugins.matcher.MatcherHelper;
+import org.apache.ivy.plugins.matcher.PatternMatcher;
+import org.apache.ivy.plugins.resolver.DependencyResolver;
+import org.apache.ivy.util.Message;
+import org.apache.ivy.util.filter.Filter;
+import org.apache.ivy.util.filter.FilterHelper;
+
+public class InstallEngine {
+	private IvySettings _settings;
+	private ResolveEngine _resolveEngine;
+	private PublishEngine _publishEngine;
+	private SearchEngine _searchEngine;
+	
+	public InstallEngine(IvySettings settings, SearchEngine searchEngine, ResolveEngine resolveEngine, PublishEngine publishEngine) {
+		_settings = settings;
+		_searchEngine = searchEngine;
+		_resolveEngine = resolveEngine;
+		_publishEngine = publishEngine;
+	}
+
+	public ResolveReport install(ModuleRevisionId mrid, String from, String to, boolean transitive, boolean validate, boolean overwrite, Filter artifactFilter, File cache, String matcherName) throws IOException {
+        if (cache == null) {
+            cache = _settings.getDefaultCache();
+        }
+        if (artifactFilter == null) {
+            artifactFilter = FilterHelper.NO_FILTER;
+        }
+        DependencyResolver fromResolver = _settings.getResolver(from);
+        DependencyResolver toResolver = _settings.getResolver(to);
+        if (fromResolver == null) {
+            throw new IllegalArgumentException("unknown resolver "+from+". Available resolvers are: "+_settings.getResolverNames());
+        }
+        if (toResolver == null) {
+            throw new IllegalArgumentException("unknown resolver "+to+". Available resolvers are: "+_settings.getResolverNames());
+        }
+        PatternMatcher matcher = _settings.getMatcher(matcherName);
+        if (matcher == null) {
+            throw new IllegalArgumentException("unknown matcher "+matcherName+". Available matchers are: "+_settings.getMatcherNames());
+        }
+        
+        // build module file declaring the dependency
+        Message.info(":: installing "+mrid+" ::");
+        DependencyResolver oldDicator = _resolveEngine.getDictatorResolver();
+        boolean log = _settings.logNotConvertedExclusionRule();
+        try {
+        	_settings.setLogNotConvertedExclusionRule(true);
+        	_resolveEngine.setDictatorResolver(fromResolver);
+            
+            DefaultModuleDescriptor md = new DefaultModuleDescriptor(ModuleRevisionId.newInstance("apache", "ivy-install", "1.0"), _settings.getStatusManager().getDefaultStatus(), new Date());
+            md.addConfiguration(new Configuration("default"));
+            md.addConflictManager(new ModuleId(ExactPatternMatcher.ANY_EXPRESSION, ExactPatternMatcher.ANY_EXPRESSION), ExactPatternMatcher.INSTANCE, new NoConflictManager());
+            
+            if (MatcherHelper.isExact(matcher, mrid)) {
+                DefaultDependencyDescriptor dd = new DefaultDependencyDescriptor(md, mrid, false, false, transitive);
+                dd.addDependencyConfiguration("default", "*");
+                md.addDependency(dd);
+            } else {
+                Collection mrids = _searchEngine.findModuleRevisionIds(fromResolver, mrid, matcher); 
+                                
+                for (Iterator iter = mrids.iterator(); iter.hasNext();) {
+                    ModuleRevisionId foundMrid = (ModuleRevisionId)iter.next();
+                    Message.info("\tfound "+foundMrid+" to install: adding to the list");
+                    DefaultDependencyDescriptor dd = new DefaultDependencyDescriptor(md, foundMrid, false, false, transitive);
+                    dd.addDependencyConfiguration("default", "*");
+                    md.addDependency(dd);
+                }
+            }                       
+            
+            // resolve using appropriate resolver
+            ResolveReport report = new ResolveReport(md);
+            
+            Message.info(":: resolving dependencies ::");
+            IvyNode[] dependencies = _resolveEngine.getDependencies(md, new String[] {"default"}, cache, null, report, validate);
+            report.setDependencies(Arrays.asList(dependencies), artifactFilter);
+            
+            Message.info(":: downloading artifacts to cache ::");
+            _resolveEngine.downloadArtifacts(report, getCacheManager(cache), false, artifactFilter);
+
+            // now that everything is in cache, we can publish all these modules
+            Message.info(":: installing in "+to+" ::");
+            for (int i = 0; i < dependencies.length; i++) {
+                ModuleDescriptor depmd = dependencies[i].getDescriptor();
+                if (depmd != null) {
+                    Message.verbose("installing "+depmd.getModuleRevisionId());
+                    _publishEngine.publish(depmd, 
+                            toResolver, 
+                            Collections.singleton(cache.getAbsolutePath()+"/"+_settings.getCacheArtifactPattern()), 
+                            cache.getAbsolutePath()+"/"+_settings.getCacheIvyPattern(), 
+                            null,
+                            overwrite,
+                            null);
+                }
+            }
+
+            Message.info(":: install resolution report ::");
+            
+            // output report
+            report.output(_settings.getReportOutputters(), cache);
+
+            return report;
+        } finally {
+        	_resolveEngine.setDictatorResolver(oldDicator);
+            _settings.setLogNotConvertedExclusionRule(log);
+        }
+    }
+	
+	private CacheManager getCacheManager(File cache) {
+		//TODO : reuse instance
+		CacheManager cacheManager = new CacheManager(_settings, cache);
+		return cacheManager;
+	}
+
+
+}

Added: incubator/ivy/core/trunk/src/java/org/apache/ivy/core/publish/PublishEngine.java
URL: http://svn.apache.org/viewvc/incubator/ivy/core/trunk/src/java/org/apache/ivy/core/publish/PublishEngine.java?view=auto&rev=501865
==============================================================================
--- incubator/ivy/core/trunk/src/java/org/apache/ivy/core/publish/PublishEngine.java (added)
+++ incubator/ivy/core/trunk/src/java/org/apache/ivy/core/publish/PublishEngine.java Wed Jan 31 07:54:39 2007
@@ -0,0 +1,248 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+package org.apache.ivy.core.publish;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.StringTokenizer;
+
+import org.apache.ivy.core.IvyContext;
+import org.apache.ivy.core.IvyPatternHelper;
+import org.apache.ivy.core.cache.CacheManager;
+import org.apache.ivy.core.module.descriptor.Artifact;
+import org.apache.ivy.core.module.descriptor.DefaultArtifact;
+import org.apache.ivy.core.module.descriptor.MDArtifact;
+import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
+import org.apache.ivy.core.module.id.ModuleRevisionId;
+import org.apache.ivy.core.settings.IvySettings;
+import org.apache.ivy.plugins.parser.xml.XmlModuleDescriptorParser;
+import org.apache.ivy.plugins.parser.xml.XmlModuleDescriptorUpdater;
+import org.apache.ivy.plugins.resolver.DependencyResolver;
+import org.apache.ivy.util.Message;
+import org.xml.sax.SAXException;
+
+public class PublishEngine {
+	private IvySettings _settings;
+	
+    public PublishEngine(IvySettings settings) {
+		_settings = settings;
+	}
+	/**
+     * 
+     * @param pubrevision 
+     * @param resolverName the name of a resolver to use for publication
+     * @param srcArtifactPattern a pattern to find artifacts to publish with the given resolver
+     * @param srcIvyPattern a pattern to find ivy file to publish, null if ivy file should not be published
+     * @return a collection of missing artifacts (those that are not published)
+     * @throws ParseException
+     */
+    public Collection publish(ModuleRevisionId mrid, String pubrevision, File cache, String srcArtifactPattern, String resolverName, String srcIvyPattern, boolean validate) throws IOException {
+        return publish(mrid, pubrevision, cache, srcArtifactPattern, resolverName, srcIvyPattern, validate, false);
+    }
+    /**
+     * 
+     * @param pubrevision 
+     * @param resolverName the name of a resolver to use for publication
+     * @param srcArtifactPattern a pattern to find artifacts to publish with the given resolver
+     * @param srcIvyPattern a pattern to find ivy file to publish, null if ivy file should not be published
+     * @return a collection of missing artifacts (those that are not published)
+     * @throws ParseException
+     */
+    public Collection publish(ModuleRevisionId mrid, String pubrevision, File cache, String srcArtifactPattern, String resolverName, String srcIvyPattern, boolean validate, boolean overwrite) throws IOException {
+    	return publish(mrid, pubrevision, cache, srcArtifactPattern, resolverName, srcIvyPattern, null, null, null, validate, overwrite, false, null);
+    }
+    public Collection publish(ModuleRevisionId mrid, String pubrevision, File cache, String srcArtifactPattern, String resolverName, String srcIvyPattern, String status, Date pubdate, Artifact[] extraArtifacts, boolean validate, boolean overwrite, boolean update, String conf) throws IOException {
+    	return publish(mrid, pubrevision, cache, Collections.singleton(srcArtifactPattern), resolverName, srcIvyPattern, status, pubdate, extraArtifacts, validate, overwrite, update, conf);
+    }
+    /**
+     * Publishes a module to the repository.
+     * 
+     * The publish can update the ivy file to publish if update is set to true. In this case it will use
+     * the given pubrevision, pubdate and status. If pudate is null it will default to the current date.
+     * If status is null it will default to the current ivy file status (which itself defaults to integration if none is found).
+     * If update is false, then if the revision is not the same in the ivy file than the one expected (given as parameter),
+     * this method will fail with an  IllegalArgumentException.
+     * pubdate and status are not used if update is false.
+     * extra artifacts can be used to publish more artifacts than actually declared in the ivy file.
+     * This can be useful to publish additional metadata or reports.
+     * The extra artifacts array can be null (= no extra artifacts), and if non null only the name, type, ext url 
+     * and extra attributes of the artifacts are really used. Other methods can return null safely. 
+     * 
+     * @param mrid
+     * @param pubrevision
+     * @param cache
+     * @param srcArtifactPattern
+     * @param resolverName
+     * @param srcIvyPattern
+     * @param status
+     * @param pubdate
+     * @param validate
+     * @param overwrite
+     * @param update
+     * @return
+     * @throws IOException
+     */
+    public Collection publish(ModuleRevisionId mrid, String pubrevision, File cache, Collection srcArtifactPattern, String resolverName, String srcIvyPattern, String status, Date pubdate, Artifact[] extraArtifacts, boolean validate, boolean overwrite, boolean update, String conf) throws IOException {
+        Message.info(":: publishing :: "+mrid.getModuleId());
+        Message.verbose("\tvalidate = "+validate);
+        long start = System.currentTimeMillis();
+        srcIvyPattern = _settings.substitute(srcIvyPattern);
+        CacheManager cacheManager = getCacheManager(cache);
+        // 1) find the resolved module descriptor
+        ModuleRevisionId pubmrid = ModuleRevisionId.newInstance(mrid, pubrevision);
+        File ivyFile;
+        if (srcIvyPattern != null) {
+        	ivyFile = new File(IvyPatternHelper.substitute(srcIvyPattern, DefaultArtifact.newIvyArtifact(pubmrid, new Date())));
+        	if (!ivyFile.exists()) {
+        		throw new IllegalArgumentException("ivy file to publish not found for "+mrid+": call deliver before ("+ivyFile+")");
+        	}
+        } else {
+        	ivyFile = cacheManager.getResolvedIvyFileInCache(mrid);
+        	if (!ivyFile.exists()) {
+        		throw new IllegalStateException("ivy file not found in cache for "+mrid+": please resolve dependencies before publishing ("+ivyFile+")");
+        	}
+        }
+        
+        ModuleDescriptor md = null;
+        URL ivyFileURL = null;
+        try {
+        	ivyFileURL = ivyFile.toURL();
+        	md = XmlModuleDescriptorParser.getInstance().parseDescriptor(_settings, ivyFileURL, false);
+        	if (srcIvyPattern != null) {
+            	if (!pubrevision.equals(md.getModuleRevisionId().getRevision())) {
+            		if (update) {
+            			File tmp = File.createTempFile("ivy", ".xml");
+            			tmp.deleteOnExit();
+            			try {
+							XmlModuleDescriptorUpdater.update(_settings, ivyFileURL, tmp, new HashMap(), status==null?md.getStatus():status, pubrevision, pubdate==null?new Date():pubdate, null, true);
+							ivyFile = tmp;
+							// we parse the new file to get updated module descriptor
+							md = XmlModuleDescriptorParser.getInstance().parseDescriptor(_settings, ivyFile.toURL(), false);
+							srcIvyPattern = ivyFile.getAbsolutePath();
+						} catch (SAXException e) {
+				        	throw new IllegalStateException("bad ivy file for "+mrid+": "+ivyFile+": "+e);
+						}
+            		} else {
+            			throw new IllegalArgumentException("cannot publish "+ivyFile+" as "+pubrevision+": bad revision found in ivy file. Use deliver before.");
+            		}
+            	}
+        	} else {
+				md.setResolvedModuleRevisionId(pubmrid);
+        	}
+        } catch (MalformedURLException e) {
+        	throw new RuntimeException("malformed url obtained for file "+ivyFile);
+        } catch (ParseException e) {
+        	throw new IllegalStateException("bad ivy file for "+mrid+": "+ivyFile+": "+e);
+        }
+        
+        DependencyResolver resolver = _settings.getResolver(resolverName);
+        if (resolver == null) {
+            throw new IllegalArgumentException("unknown resolver "+resolverName);
+        }
+        
+        // collect all declared artifacts of this module
+        Collection missing = publish(md, resolver, srcArtifactPattern, srcIvyPattern, extraArtifacts, overwrite, conf);
+        Message.verbose("\tpublish done ("+(System.currentTimeMillis()-start)+"ms)");
+        return missing;
+    }
+
+    public Collection publish(ModuleDescriptor md, DependencyResolver resolver, Collection srcArtifactPattern, String srcIvyPattern, Artifact[] extraArtifacts, boolean overwrite, String conf) throws IOException {
+        Collection missing = new ArrayList();
+        Set artifactsSet = new HashSet();
+		String[] confs;
+		if (null == conf || "".equals(conf)) {
+			confs = md.getConfigurationsNames();
+		} else {
+			StringTokenizer st = new StringTokenizer(conf, ",");
+			confs = new String[st.countTokens()];
+			int counter = 0;
+			while (st.hasMoreTokens()) {
+				confs[counter] = st.nextToken().trim();
+				counter++;
+			}
+		}
+
+		for (int i = 0; i < confs.length; i++) {
+            Artifact[] artifacts = md.getArtifacts(confs[i]);
+            for (int j = 0; j < artifacts.length; j++) {
+                artifactsSet.add(artifacts[j]);
+            }
+        }
+        if (extraArtifacts != null) {
+        	for (int i = 0; i < extraArtifacts.length; i++) {
+				artifactsSet.add(new MDArtifact(md, extraArtifacts[i].getName(), extraArtifacts[i].getType(), extraArtifacts[i].getExt(), extraArtifacts[i].getUrl(), extraArtifacts[i].getExtraAttributes()));
+			}
+        }
+        // for each declared published artifact in this descriptor, do:
+        for (Iterator iter = artifactsSet.iterator(); iter.hasNext();) {
+            Artifact artifact = (Artifact) iter.next();
+            //   1) copy the artifact using src patterns and resolver
+            boolean published = false;
+            for (Iterator iterator = srcArtifactPattern.iterator(); iterator.hasNext() && !published;) {
+				String pattern = (String) iterator.next();
+				published = publish(artifact, _settings.substitute(pattern), resolver, overwrite);
+			}
+            if (!published) {
+            	Message.info("missing artifact "+artifact+":");
+                for (Iterator iterator = srcArtifactPattern.iterator(); iterator.hasNext();) {
+    				String pattern = (String) iterator.next();
+                	Message.info("\t"+new File(IvyPatternHelper.substitute(pattern, artifact))+" file does not exist");
+                }
+                missing.add(artifact);
+            }
+        }
+        if (srcIvyPattern != null) {
+            Artifact artifact = MDArtifact.newIvyArtifact(md);
+            if (!publish(artifact, srcIvyPattern, resolver, overwrite)) {
+                Message.info("missing ivy file for "+md.getModuleRevisionId()+": "+new File(IvyPatternHelper.substitute(srcIvyPattern, artifact))+" file does not exist");
+                missing.add(artifact);
+            }
+        }
+        return missing;
+    }
+
+    private boolean publish(Artifact artifact, String srcArtifactPattern, DependencyResolver resolver, boolean overwrite) throws IOException {
+    	IvyContext.getContext().checkInterrupted();
+        File src = new File(IvyPatternHelper.substitute(srcArtifactPattern, artifact));
+        if (src.exists()) {
+            resolver.publish(artifact, src, overwrite);
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+	private CacheManager getCacheManager(File cache) {
+		//TODO : reuse instance
+		CacheManager cacheManager = new CacheManager(_settings, cache);
+		return cacheManager;
+	}
+
+
+}

Modified: incubator/ivy/core/trunk/src/java/org/apache/ivy/core/resolve/DownloadOptions.java
URL: http://svn.apache.org/viewvc/incubator/ivy/core/trunk/src/java/org/apache/ivy/core/resolve/DownloadOptions.java?view=diff&rev=501865&r1=501864&r2=501865
==============================================================================
--- incubator/ivy/core/trunk/src/java/org/apache/ivy/core/resolve/DownloadOptions.java (original)
+++ incubator/ivy/core/trunk/src/java/org/apache/ivy/core/resolve/DownloadOptions.java Wed Jan 31 07:54:39 2007
@@ -1,3 +1,20 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
 package org.apache.ivy.core.resolve;
 
 import java.io.File;

Modified: incubator/ivy/core/trunk/src/java/org/apache/ivy/core/resolve/ResolveEngine.java
URL: http://svn.apache.org/viewvc/incubator/ivy/core/trunk/src/java/org/apache/ivy/core/resolve/ResolveEngine.java?view=diff&rev=501865&r1=501864&r2=501865
==============================================================================
--- incubator/ivy/core/trunk/src/java/org/apache/ivy/core/resolve/ResolveEngine.java (original)
+++ incubator/ivy/core/trunk/src/java/org/apache/ivy/core/resolve/ResolveEngine.java Wed Jan 31 07:54:39 2007
@@ -1,3 +1,20 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
 package org.apache.ivy.core.resolve;
 
 import java.io.File;
@@ -258,6 +275,7 @@
 	}
 
 	private CacheManager getCacheManager(File cache) {
+		//TODO : reuse instance
 		CacheManager cacheManager = new CacheManager(_settings, cache);
 		return cacheManager;
 	}

Added: incubator/ivy/core/trunk/src/java/org/apache/ivy/core/retrieve/RetrieveEngine.java
URL: http://svn.apache.org/viewvc/incubator/ivy/core/trunk/src/java/org/apache/ivy/core/retrieve/RetrieveEngine.java?view=auto&rev=501865
==============================================================================
--- incubator/ivy/core/trunk/src/java/org/apache/ivy/core/retrieve/RetrieveEngine.java (added)
+++ incubator/ivy/core/trunk/src/java/org/apache/ivy/core/retrieve/RetrieveEngine.java Wed Jan 31 07:54:39 2007
@@ -0,0 +1,312 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+package org.apache.ivy.core.retrieve;
+
+import java.io.File;
+import java.io.IOException;
+import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.ivy.core.IvyContext;
+import org.apache.ivy.core.IvyPatternHelper;
+import org.apache.ivy.core.cache.CacheManager;
+import org.apache.ivy.core.module.descriptor.Artifact;
+import org.apache.ivy.core.module.descriptor.DefaultArtifact;
+import org.apache.ivy.core.module.id.ModuleId;
+import org.apache.ivy.core.module.id.ModuleRevisionId;
+import org.apache.ivy.core.settings.IvySettings;
+import org.apache.ivy.plugins.report.XmlReportParser;
+import org.apache.ivy.util.FileUtil;
+import org.apache.ivy.util.Message;
+import org.apache.ivy.util.filter.Filter;
+import org.apache.ivy.util.filter.FilterHelper;
+
+public class RetrieveEngine {
+	private IvySettings _settings;
+	
+	public RetrieveEngine(IvySettings settings) {
+		_settings = settings;
+	}
+	
+	/**
+     * example of destFilePattern :
+     * - lib/[organisation]/[module]/[artifact]-[revision].[type]
+     * - lib/[artifact].[type] : flatten with no revision
+     * moduleId is used with confs and localCacheDirectory to determine
+     * an ivy report file, used as input for the copy
+     * If such a file does not exist for any conf (resolve has not been called before ?)
+     * then an IllegalStateException is thrown and nothing is copied.
+     */
+    public int retrieve(ModuleId moduleId, String[] confs, final File cache, String destFilePattern) {
+        return retrieve(moduleId, confs, cache, destFilePattern, null);
+    }
+    /**
+     * If destIvyPattern is null no ivy files will be copied.
+     */
+    public int retrieve(ModuleId moduleId, String[] confs, final File cache, String destFilePattern, String destIvyPattern) {
+    	return retrieve(moduleId, confs, cache, destFilePattern, destIvyPattern, FilterHelper.NO_FILTER);
+    }
+    
+    public int retrieve(ModuleId moduleId, String[] confs, final File cache, String destFilePattern, String destIvyPattern, Filter artifactFilter) {
+    	return retrieve(moduleId, confs, cache, destFilePattern, destIvyPattern, artifactFilter, false, false);
+    }
+    public int retrieve(ModuleId moduleId, String[] confs, final File cache, String destFilePattern, String destIvyPattern, Filter artifactFilter, boolean sync, boolean useOrigin) {
+    	return retrieve(moduleId, confs, cache, destFilePattern, destIvyPattern, artifactFilter, sync, useOrigin, false);
+    }
+    public int retrieve(ModuleId moduleId, String[] confs, final File cache, String destFilePattern, String destIvyPattern, Filter artifactFilter, boolean sync, boolean useOrigin, boolean makeSymlinks) {
+    	if (artifactFilter == null) {
+    		artifactFilter = FilterHelper.NO_FILTER;
+    	}
+    	
+        Message.info(":: retrieving :: "+moduleId+(sync?" [sync]":""));
+        Message.info("\tconfs: "+Arrays.asList(confs));
+        long start = System.currentTimeMillis();
+        
+        destFilePattern = IvyPatternHelper.substituteVariables(destFilePattern, _settings.getVariables());
+        destIvyPattern = IvyPatternHelper.substituteVariables(destIvyPattern, _settings.getVariables());
+        CacheManager cacheManager = getCacheManager(cache);
+        try {
+            Map artifactsToCopy = determineArtifactsToCopy(moduleId, confs, cache, destFilePattern, destIvyPattern, artifactFilter);
+            File fileRetrieveRoot = new File(IvyPatternHelper.getTokenRoot(destFilePattern));
+            File ivyRetrieveRoot = destIvyPattern == null ? null : new File(IvyPatternHelper.getTokenRoot(destIvyPattern));
+            Collection targetArtifactsStructure = new HashSet(); // Set(File) set of all paths which should be present at then end of retrieve (useful for sync) 
+            Collection targetIvysStructure = new HashSet(); // same for ivy files
+            
+            // do retrieve
+            int targetsCopied = 0;
+            int targetsUpToDate = 0;
+            for (Iterator iter = artifactsToCopy.keySet().iterator(); iter.hasNext();) {
+                Artifact artifact = (Artifact)iter.next();
+                File archive;
+				if ("ivy".equals(artifact.getType())) {
+					archive = cacheManager.getIvyFileInCache(artifact.getModuleRevisionId());
+				} else {
+					archive = cacheManager.getArchiveFileInCache(artifact, cacheManager.getSavedArtifactOrigin(artifact), useOrigin);
+					if (!useOrigin && !archive.exists()) {
+						// file is not available in cache, maybe the last resolve was performed with useOrigin=true.
+						// we try to use the best we can
+						archive = cacheManager.getArchiveFileInCache(artifact, cacheManager.getSavedArtifactOrigin(artifact));
+					}
+				}
+                Set dest = (Set)artifactsToCopy.get(artifact);
+                Message.verbose("\tretrieving "+archive);
+                for (Iterator it2 = dest.iterator(); it2.hasNext();) {
+                	IvyContext.getContext().checkInterrupted();
+                    File destFile = new File((String)it2.next());
+                    if (!_settings.isCheckUpToDate() || !upToDate(archive, destFile)) {
+                        Message.verbose("\t\tto "+destFile);
+                        if (makeSymlinks) {
+                            FileUtil.symlink(archive, destFile, null, false);
+                        } else {
+                            FileUtil.copy(archive, destFile, null);
+                        }
+                        targetsCopied++;
+                    } else {
+                        Message.verbose("\t\tto "+destFile+" [NOT REQUIRED]");
+                        targetsUpToDate++;
+                    }
+                    if ("ivy".equals(artifact.getType())) {
+                    	targetIvysStructure.addAll(FileUtil.getPathFiles(ivyRetrieveRoot, destFile));
+                    } else {
+                    	targetArtifactsStructure.addAll(FileUtil.getPathFiles(fileRetrieveRoot, destFile));
+                    }
+                }
+            }
+            
+            if (sync) {
+				Message.verbose("\tsyncing...");
+                Collection existingArtifacts = FileUtil.listAll(fileRetrieveRoot);
+                Collection existingIvys = ivyRetrieveRoot == null ? null : FileUtil.listAll(ivyRetrieveRoot);
+
+                if (fileRetrieveRoot.equals(ivyRetrieveRoot)) {
+                	Collection target = targetArtifactsStructure;
+                	target.addAll(targetIvysStructure);
+                	Collection existing = existingArtifacts;
+                	existing.addAll(existingIvys);
+                	sync(target, existing);
+                } else {
+                	sync(targetArtifactsStructure, existingArtifacts);
+                	if (existingIvys != null) {
+                		sync(targetIvysStructure, existingIvys);
+                	}
+                }
+            }
+            Message.info("\t"+targetsCopied+" artifacts copied, "+targetsUpToDate+" already retrieved");
+            Message.verbose("\tretrieve done ("+(System.currentTimeMillis()-start)+"ms)");
+            
+            return targetsCopied;
+        } catch (Exception ex) {
+            throw new RuntimeException("problem during retrieve of "+moduleId+": "+ex, ex);
+        }
+    }
+
+    public CacheManager getCacheManager(File cache) {
+    	// TODO reuse instance
+		return new CacheManager(_settings, cache);
+	}
+
+	private void sync(Collection target, Collection existing) {
+		Collection toRemove = new HashSet();
+		for (Iterator iter = existing.iterator(); iter.hasNext();) {
+			File file = (File) iter.next();
+			toRemove.add(file.getAbsoluteFile());
+		}
+		for (Iterator iter = target.iterator(); iter.hasNext();) {
+			File file = (File) iter.next();
+			toRemove.remove(file.getAbsoluteFile());
+		}
+		for (Iterator iter = toRemove.iterator(); iter.hasNext();) {
+			File file = (File) iter.next();
+			if (file.exists()) {
+				Message.verbose("\t\tdeleting "+file);
+				FileUtil.forceDelete(file);
+			}
+		}
+	}
+
+	public Map determineArtifactsToCopy(ModuleId moduleId, String[] confs, final File cache, String destFilePattern, String destIvyPattern) throws ParseException, IOException {
+    	return determineArtifactsToCopy(moduleId, confs, cache, destFilePattern, destIvyPattern, FilterHelper.NO_FILTER);
+    }
+    
+    public Map determineArtifactsToCopy(ModuleId moduleId, String[] confs, final File cache, String destFilePattern, String destIvyPattern, Filter artifactFilter) throws ParseException, IOException {
+        if (artifactFilter == null) {
+        	artifactFilter = FilterHelper.NO_FILTER;
+        }
+        
+        // find what we must retrieve where
+        final Map artifactsToCopy = new HashMap(); // Artifact source -> Set (String copyDestAbsolutePath)
+        final Map conflictsMap = new HashMap(); // String copyDestAbsolutePath -> Set (Artifact source)
+        final Map conflictsConfMap = new HashMap(); // String copyDestAbsolutePath -> Set (String conf)
+        XmlReportParser parser = new XmlReportParser();
+        for (int i = 0; i < confs.length; i++) {
+            final String conf = confs[i];
+            Collection artifacts = new ArrayList(Arrays.asList(parser.getArtifacts(moduleId, conf, cache)));
+            if (destIvyPattern != null) {
+                ModuleRevisionId[] mrids = parser.getRealDependencyRevisionIds(moduleId, conf, cache);
+                for (int j = 0; j < mrids.length; j++) {
+                    artifacts.add(DefaultArtifact.newIvyArtifact(mrids[j], null));
+                }
+            }
+            for (Iterator iter = artifacts.iterator(); iter.hasNext();) {
+                Artifact artifact = (Artifact)iter.next();
+                String destPattern = "ivy".equals(artifact.getType()) ? destIvyPattern: destFilePattern;
+                
+                if (!"ivy".equals(artifact.getType()) && !artifactFilter.accept(artifact)) {
+                	continue;	// skip this artifact, the filter didn't accept it!
+                }
+                
+                String destFileName = IvyPatternHelper.substitute(destPattern, artifact, conf);
+                
+                Set dest = (Set)artifactsToCopy.get(artifact);
+                if (dest == null) {
+                    dest = new HashSet();
+                    artifactsToCopy.put(artifact, dest);
+                }
+                String copyDest = new File(destFileName).getAbsolutePath();
+                dest.add(copyDest);
+                
+                Set conflicts = (Set)conflictsMap.get(copyDest);
+                Set conflictsConf = (Set)conflictsConfMap.get(copyDest);
+                if (conflicts == null) {
+                    conflicts = new HashSet();
+                    conflictsMap.put(copyDest, conflicts);
+                }
+                if (conflictsConf == null) {
+                    conflictsConf = new HashSet();
+                    conflictsConfMap.put(copyDest, conflictsConf);
+                }
+                conflicts.add(artifact);
+                conflictsConf.add(conf);
+            }
+        }
+        
+        // resolve conflicts if any
+        for (Iterator iter = conflictsMap.keySet().iterator(); iter.hasNext();) {
+            String copyDest = (String)iter.next();
+            Set artifacts = (Set)conflictsMap.get(copyDest);
+            Set conflictsConfs = (Set)conflictsConfMap.get(copyDest);
+            if (artifacts.size() > 1) {
+                List artifactsList = new ArrayList(artifacts);
+                // conflicts battle is resolved by a sort using a conflict resolving policy comparator
+                // which consider as greater a winning artifact
+                Collections.sort(artifactsList, getConflictResolvingPolicy());
+                // after the sort, the winning artifact is the greatest one, i.e. the last one
+                Message.info("\tconflict on "+copyDest+" in "+conflictsConfs+": "+((Artifact)artifactsList.get(artifactsList.size() -1)).getModuleRevisionId().getRevision()+" won");
+                
+                // we now iterate over the list beginning with the artifact preceding the winner,
+                // and going backward to the least artifact
+                for (int i=artifactsList.size() - 2; i >=0; i--) {
+                    Artifact looser = (Artifact)artifactsList.get(i);
+                    Message.verbose("\t\tremoving conflict looser artifact: "+looser);
+                    // for each loser, we remove the pair (loser - copyDest) in the artifactsToCopy map
+                    Set dest = (Set)artifactsToCopy.get(looser);
+                    dest.remove(copyDest);
+                    if (dest.isEmpty()) {
+                        artifactsToCopy.remove(looser);
+                    }
+                }
+            }
+        }
+        return artifactsToCopy;
+    }
+    
+    private boolean upToDate(File source, File target) {
+        if (!target.exists()) {
+            return false;
+        }
+        return source.lastModified() <= target.lastModified();
+    }
+
+    /**
+     * The returned comparator should consider greater the artifact which
+     * gains the conflict battle.
+     * This is used only during retrieve... prefer resolve conflict manager
+     * to resolve conflicts.
+     * @return
+     */
+    private Comparator getConflictResolvingPolicy() {
+        return new Comparator() {
+            // younger conflict resolving policy
+            public int compare(Object o1, Object o2) {
+                Artifact a1 = (Artifact)o1;
+                Artifact a2 = (Artifact)o2;
+                if (a1.getPublicationDate().after(a2.getPublicationDate())) {
+                    // a1 is after a2 <=> a1 is younger than a2 <=> a1 wins the conflict battle
+                    return +1;
+                } else if (a1.getPublicationDate().before(a2.getPublicationDate())) {
+                    // a1 is before a2 <=> a2 is younger than a1 <=> a2 wins the conflict battle
+                    return -1;
+                } else {
+                    return 0;
+                }
+            }
+        };
+    }
+
+
+}

Added: incubator/ivy/core/trunk/src/java/org/apache/ivy/core/search/SearchEngine.java
URL: http://svn.apache.org/viewvc/incubator/ivy/core/trunk/src/java/org/apache/ivy/core/search/SearchEngine.java?view=auto&rev=501865
==============================================================================
--- incubator/ivy/core/trunk/src/java/org/apache/ivy/core/search/SearchEngine.java (added)
+++ incubator/ivy/core/trunk/src/java/org/apache/ivy/core/search/SearchEngine.java Wed Jan 31 07:54:39 2007
@@ -0,0 +1,287 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+package org.apache.ivy.core.search;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.ivy.core.IvyPatternHelper;
+import org.apache.ivy.core.module.id.ModuleId;
+import org.apache.ivy.core.module.id.ModuleRevisionId;
+import org.apache.ivy.core.settings.IvySettings;
+import org.apache.ivy.plugins.matcher.Matcher;
+import org.apache.ivy.plugins.matcher.MatcherHelper;
+import org.apache.ivy.plugins.matcher.PatternMatcher;
+import org.apache.ivy.plugins.namespace.NameSpaceHelper;
+import org.apache.ivy.plugins.namespace.Namespace;
+import org.apache.ivy.plugins.resolver.AbstractResolver;
+import org.apache.ivy.plugins.resolver.DependencyResolver;
+import org.apache.ivy.util.Message;
+
+public class SearchEngine {
+	private IvySettings _settings;
+	
+    public SearchEngine(IvySettings settings) {
+		_settings = settings;
+	}
+
+	/**
+     * Returns an empty array when no token values are found.
+     *  
+     * @param token
+     * @param otherTokenValues
+     * @return
+     */
+	public String[] listTokenValues(String token, Map otherTokenValues) {
+        List r = new ArrayList();
+        for (Iterator iter = _settings.getResolvers().iterator(); iter.hasNext();) {
+            DependencyResolver resolver = (DependencyResolver)iter.next();
+            r.addAll(Arrays.asList(resolver.listTokenValues(token, otherTokenValues)));
+        }
+        return (String[])r.toArray(new String[r.size()]);
+	}
+    
+    public OrganisationEntry[] listOrganisationEntries() {
+        List entries = new ArrayList();
+        for (Iterator iter = _settings.getResolvers().iterator(); iter.hasNext();) {
+            DependencyResolver resolver = (DependencyResolver)iter.next();
+            entries.addAll(Arrays.asList(resolver.listOrganisations()));
+        }
+        return (OrganisationEntry[])entries.toArray(new OrganisationEntry[entries.size()]);
+    }
+    public String[] listOrganisations() {
+        Collection orgs = new HashSet();
+        for (Iterator iter = _settings.getResolvers().iterator(); iter.hasNext();) {
+            DependencyResolver resolver = (DependencyResolver)iter.next();
+            OrganisationEntry[] entries = resolver.listOrganisations();
+            if (entries != null) {
+                for (int i = 0; i < entries.length; i++) {
+                    if (entries[i] != null) {
+                        orgs.add(entries[i].getOrganisation());
+                    }
+                }
+            }
+        }
+        return (String[])orgs.toArray(new String[orgs.size()]);
+    }
+    public ModuleEntry[] listModuleEntries(OrganisationEntry org) {
+        List entries = new ArrayList();
+        for (Iterator iter = _settings.getResolvers().iterator(); iter.hasNext();) {
+            DependencyResolver resolver = (DependencyResolver)iter.next();
+            entries.addAll(Arrays.asList(resolver.listModules(org)));
+        }
+        return (ModuleEntry[])entries.toArray(new ModuleEntry[entries.size()]);
+    }
+    public String[] listModules(String org) {
+        List mods = new ArrayList();
+        for (Iterator iter = _settings.getResolvers().iterator(); iter.hasNext();) {
+            DependencyResolver resolver = (DependencyResolver)iter.next();
+            ModuleEntry[] entries = resolver.listModules(new OrganisationEntry(resolver, org));
+            if (entries != null) {
+                for (int i = 0; i < entries.length; i++) {
+                    if (entries[i] != null) {
+                        mods.add(entries[i].getModule());
+                    }
+                }
+            }
+        }
+        return (String[])mods.toArray(new String[mods.size()]);
+    }
+    public RevisionEntry[] listRevisionEntries(ModuleEntry module) {
+        List entries = new ArrayList();
+        for (Iterator iter = _settings.getResolvers().iterator(); iter.hasNext();) {
+            DependencyResolver resolver = (DependencyResolver)iter.next();
+            entries.addAll(Arrays.asList(resolver.listRevisions(module)));
+        }
+        return (RevisionEntry[])entries.toArray(new RevisionEntry[entries.size()]);
+    }
+    public String[] listRevisions(String org, String module) {
+        List revs = new ArrayList();
+        for (Iterator iter = _settings.getResolvers().iterator(); iter.hasNext();) {
+            DependencyResolver resolver = (DependencyResolver)iter.next();
+            RevisionEntry[] entries = resolver.listRevisions(new ModuleEntry(new OrganisationEntry(resolver, org), module));
+            if (entries != null) {
+                for (int i = 0; i < entries.length; i++) {
+                    if (entries[i] != null) {
+                        revs.add(entries[i].getRevision());
+                    }
+                }
+            }
+        }
+        return (String[])revs.toArray(new String[revs.size()]);
+    }
+    
+
+
+
+
+	/**
+	 * List module ids of the module accessible through the current resolvers
+	 * matching the given mid criteria according to the given matcher.
+	 * 
+	 * @param criteria
+	 * @param matcher
+	 * @return
+	 */
+	public ModuleId[] listModules(ModuleId criteria, PatternMatcher matcher) {
+		List ret = new ArrayList();
+		Matcher orgMatcher = matcher.getMatcher(criteria.getOrganisation());
+		Matcher modMatcher = matcher.getMatcher(criteria.getName());
+		Map tokenValues = new HashMap();
+		String[] orgs = listTokenValues(IvyPatternHelper.ORGANISATION_KEY, tokenValues);
+		for (int i = 0; i < orgs.length; i++) {
+			if (orgMatcher.matches(orgs[i])) {
+				tokenValues.put(IvyPatternHelper.ORGANISATION_KEY, orgs[i]);
+				String[] mods = listTokenValues(IvyPatternHelper.MODULE_KEY, tokenValues);
+				for (int j = 0; j < mods.length; j++) {
+					if (modMatcher.matches(mods[j])) {
+						ret.add(new ModuleId(orgs[i], mods[j]));
+					}
+				}
+			}
+		}
+		return (ModuleId[]) ret.toArray(new ModuleId[ret.size()]);
+	}
+	
+	
+	/**
+	 * List module revision ids of the module accessible through the current resolvers
+	 * matching the given mrid criteria according to the given matcher.
+	 * 
+	 * @param criteria
+	 * @param matcher
+	 * @return
+	 */
+	public ModuleRevisionId[] listModules(ModuleRevisionId criteria, PatternMatcher matcher) {
+		List ret = new ArrayList();
+		Matcher orgMatcher = matcher.getMatcher(criteria.getOrganisation());
+		Matcher modMatcher = matcher.getMatcher(criteria.getName());
+		Matcher branchMatcher = matcher.getMatcher(criteria.getBranch());
+		Matcher revMatcher = matcher.getMatcher(criteria.getRevision());
+		Map tokenValues = new HashMap();
+		String[] orgs = listTokenValues(IvyPatternHelper.ORGANISATION_KEY, tokenValues);
+		for (int i = 0; i < orgs.length; i++) {
+			if (orgMatcher.matches(orgs[i])) {
+				tokenValues.put(IvyPatternHelper.ORGANISATION_KEY, orgs[i]);
+				String[] mods = listTokenValues(IvyPatternHelper.MODULE_KEY, tokenValues);
+				for (int j = 0; j < mods.length; j++) {
+					if (modMatcher.matches(mods[j])) {
+						tokenValues.put(IvyPatternHelper.MODULE_KEY, mods[j]);
+						String[] branches = listTokenValues(IvyPatternHelper.BRANCH_KEY, tokenValues);
+						if (branches == null || branches.length == 0) {
+							branches = new String[]  {_settings.getDefaultBranch(new ModuleId(orgs[i], mods[j]))};
+						}
+						for (int k = 0; k < branches.length; k++) {
+							if (branches[k] == null || branchMatcher.matches(branches[k])) {
+								tokenValues.put(IvyPatternHelper.BRANCH_KEY, tokenValues);
+								String[] revs = listTokenValues(IvyPatternHelper.REVISION_KEY, tokenValues);
+								for (int l = 0; l < revs.length; l++) {
+									if (revMatcher.matches(revs[l])) {
+										ret.add(ModuleRevisionId.newInstance(orgs[i], mods[j], branches[k], revs[l]));
+									}
+								}
+							}
+						}
+					}
+				}
+			}
+		}
+		return (ModuleRevisionId[]) ret.toArray(new ModuleRevisionId[ret.size()]);
+	}
+
+    public Collection findModuleRevisionIds(DependencyResolver resolver, ModuleRevisionId pattern, PatternMatcher matcher) {
+        Collection mrids = new ArrayList();
+        String resolverName = resolver.getName();
+        
+        Message.verbose("looking for modules matching "+pattern+" using "+matcher.getName());
+        Namespace fromNamespace = resolver instanceof AbstractResolver ? ((AbstractResolver)resolver).getNamespace() : null;
+        
+        Collection modules = new ArrayList();
+        
+        OrganisationEntry[] orgs = resolver.listOrganisations();
+        if (orgs == null || orgs.length == 0) {
+            // hack for resolvers which are not able to list organisation, we try to see if the asked organisation is not an exact one:
+            String org = pattern.getOrganisation();
+            if (fromNamespace != null) {
+                org = NameSpaceHelper.transform(pattern.getModuleId(), fromNamespace.getFromSystemTransformer()).getOrganisation();
+            }
+            modules.addAll(Arrays.asList(resolver.listModules(new OrganisationEntry(resolver, org))));                    
+        } else {
+            Matcher orgMatcher = matcher.getMatcher(pattern.getOrganisation());
+            for (int i = 0; i < orgs.length; i++) {
+                String org = orgs[i].getOrganisation();
+                String systemOrg = org;
+                if (fromNamespace != null) {
+                    systemOrg = NameSpaceHelper.transformOrganisation(org, fromNamespace.getToSystemTransformer());
+                }
+                if (orgMatcher.matches(systemOrg)) {
+                    modules.addAll(Arrays.asList(resolver.listModules(new OrganisationEntry(resolver, org))));                    
+                }
+            }
+        }                
+        Message.debug("found " + modules.size() + " modules for "+pattern.getOrganisation()+" on " + resolverName);
+        boolean foundModule = false;
+        for (Iterator iter = modules.iterator(); iter.hasNext();) {
+            ModuleEntry mEntry = (ModuleEntry)iter.next();
+            
+            ModuleId foundMid = new ModuleId(mEntry.getOrganisation(), mEntry.getModule());
+            ModuleId systemMid = foundMid;
+            if (fromNamespace != null) {
+                systemMid = NameSpaceHelper.transform(foundMid, fromNamespace.getToSystemTransformer());
+            }
+            
+            if (MatcherHelper.matches(matcher, pattern.getModuleId(), systemMid)) {
+                // The module corresponds to the searched module pattern
+                foundModule = true;
+                RevisionEntry[] rEntries = resolver.listRevisions(mEntry);
+                Message.debug("found " + rEntries.length + " revisions for [" + mEntry.getOrganisation() + ", "+ mEntry.getModule() + "] on " + resolverName);
+
+                boolean foundRevision = false;
+                for (int j = 0; j < rEntries.length; j++) {
+                    RevisionEntry rEntry = rEntries[j];
+                    
+                    ModuleRevisionId foundMrid = ModuleRevisionId.newInstance(mEntry.getOrganisation(), mEntry.getModule(), rEntry.getRevision());
+                    ModuleRevisionId systemMrid = foundMrid;
+                    if (fromNamespace != null) {
+                        systemMrid = fromNamespace.getToSystemTransformer().transform(foundMrid);
+                    }
+                    
+                    if (MatcherHelper.matches(matcher, pattern, systemMrid)) {
+                        // We have a matching module revision
+                        foundRevision = true;
+                        mrids.add(systemMrid);
+                    }
+                }
+                if (!foundRevision) {
+                    Message.debug("no revision found matching "+pattern+" in [" + mEntry.getOrganisation() + "," + mEntry.getModule()+ "] using " + resolverName);                            
+                }
+            }
+        }
+        if (!foundModule) {
+            Message.debug("no module found matching "+pattern+" using " + resolverName);                            
+        }
+        return mrids;
+    }
+
+}

Modified: incubator/ivy/core/trunk/src/java/org/apache/ivy/core/sort/SortEngine.java
URL: http://svn.apache.org/viewvc/incubator/ivy/core/trunk/src/java/org/apache/ivy/core/sort/SortEngine.java?view=diff&rev=501865&r1=501864&r2=501865
==============================================================================
--- incubator/ivy/core/trunk/src/java/org/apache/ivy/core/sort/SortEngine.java (original)
+++ incubator/ivy/core/trunk/src/java/org/apache/ivy/core/sort/SortEngine.java Wed Jan 31 07:54:39 2007
@@ -1,3 +1,20 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
 package org.apache.ivy.core.sort;
 
 import java.util.ArrayList;