You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@ant.apache.org by xa...@apache.org on 2007/12/07 23:25:32 UTC

svn commit: r602246 - in /ant/ivy/core/trunk: ./ src/java/org/apache/ivy/ src/java/org/apache/ivy/core/module/descriptor/ src/java/org/apache/ivy/core/repository/ src/java/org/apache/ivy/core/search/ src/java/org/apache/ivy/core/settings/ src/java/org/...

Author: xavier
Date: Fri Dec  7 14:25:31 2007
New Revision: 602246

URL: http://svn.apache.org/viewvc?rev=602246&view=rev
Log:
NEW: Introduce RepositoryManagementEngine (IVY-665 - not completed yet)

Added:
    ant/ivy/core/trunk/src/java/org/apache/ivy/core/repository/
    ant/ivy/core/trunk/src/java/org/apache/ivy/core/repository/RepositoryManagementEngine.java   (with props)
    ant/ivy/core/trunk/src/java/org/apache/ivy/core/repository/RepositoryManagementEngineSettings.java   (with props)
    ant/ivy/core/trunk/src/java/org/apache/ivy/util/MemoryUtil.java   (with props)
    ant/ivy/core/trunk/test/java/org/apache/ivy/core/repository/
    ant/ivy/core/trunk/test/java/org/apache/ivy/core/repository/RepositoryManagementEngineTest.java   (with props)
Modified:
    ant/ivy/core/trunk/CHANGES.txt
    ant/ivy/core/trunk/src/java/org/apache/ivy/Ivy.java
    ant/ivy/core/trunk/src/java/org/apache/ivy/core/module/descriptor/DefaultModuleDescriptor.java
    ant/ivy/core/trunk/src/java/org/apache/ivy/core/module/descriptor/ModuleDescriptor.java
    ant/ivy/core/trunk/src/java/org/apache/ivy/core/search/SearchEngine.java
    ant/ivy/core/trunk/src/java/org/apache/ivy/core/settings/IvySettings.java
    ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/resolver/FileSystemResolver.java

Modified: ant/ivy/core/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/CHANGES.txt?rev=602246&r1=602245&r2=602246&view=diff
==============================================================================
--- ant/ivy/core/trunk/CHANGES.txt (original)
+++ ant/ivy/core/trunk/CHANGES.txt Fri Dec  7 14:25:31 2007
@@ -57,6 +57,8 @@
 
    version in SVN
 =====================================
+- NEW: Introduce RepositoryManagementEngine (IVY-665 - not completed yet)
+
 - IMPROVEMENT: Decrease memory footprint (IVY-662)
 
 - FIX: latest compatible conflict manager fails with circular dependencies and dynamic revision (IVY-663)

Modified: ant/ivy/core/trunk/src/java/org/apache/ivy/Ivy.java
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/Ivy.java?rev=602246&r1=602245&r2=602246&view=diff
==============================================================================
--- ant/ivy/core/trunk/src/java/org/apache/ivy/Ivy.java (original)
+++ ant/ivy/core/trunk/src/java/org/apache/ivy/Ivy.java Fri Dec  7 14:25:31 2007
@@ -42,6 +42,7 @@
 import org.apache.ivy.core.publish.PublishEngine;
 import org.apache.ivy.core.publish.PublishOptions;
 import org.apache.ivy.core.report.ResolveReport;
+import org.apache.ivy.core.repository.RepositoryManagementEngine;
 import org.apache.ivy.core.resolve.ResolveEngine;
 import org.apache.ivy.core.resolve.ResolveOptions;
 import org.apache.ivy.core.resolve.ResolvedModuleRevision;
@@ -236,6 +237,8 @@
     private PublishEngine publishEngine;
 
     private InstallEngine installEngine;
+
+    private RepositoryManagementEngine repositoryEngine;
     
     /**
      * The logger engine to use to log messages when using this Ivy instance.
@@ -292,6 +295,10 @@
                 installEngine = new InstallEngine(
                     settings, searchEngine, resolveEngine, publishEngine);
             }
+            if (repositoryEngine == null) {
+                repositoryEngine = new RepositoryManagementEngine(
+                    settings, searchEngine, resolveEngine);
+            }
     
             eventManager.addTransferListener(new TransferListener() {
                 public void transferProgress(TransferEvent evt) {
@@ -918,6 +925,14 @@
 
     public void setSortEngine(SortEngine sortEngine) {
         this.sortEngine = sortEngine;
+    }
+    
+    public RepositoryManagementEngine getRepositoryEngine() {
+        return repositoryEngine;
+    }
+    
+    public void setRepositoryEngine(RepositoryManagementEngine repositoryEngine) {
+        this.repositoryEngine = repositoryEngine;
     }
 
     public void setEventManager(EventManager eventManager) {

Modified: ant/ivy/core/trunk/src/java/org/apache/ivy/core/module/descriptor/DefaultModuleDescriptor.java
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/core/module/descriptor/DefaultModuleDescriptor.java?rev=602246&r1=602245&r2=602246&view=diff
==============================================================================
--- ant/ivy/core/trunk/src/java/org/apache/ivy/core/module/descriptor/DefaultModuleDescriptor.java (original)
+++ ant/ivy/core/trunk/src/java/org/apache/ivy/core/module/descriptor/DefaultModuleDescriptor.java Fri Dec  7 14:25:31 2007
@@ -279,6 +279,10 @@
     public Date getResolvedPublicationDate() {
         return resolvedPublicationDate;
     }
+    
+    public String getRevision() {
+        return getResolvedModuleRevisionId().getRevision();
+    }
 
     public void setModuleRevisionId(ModuleRevisionId revId) {
         if (revId == null) {

Modified: ant/ivy/core/trunk/src/java/org/apache/ivy/core/module/descriptor/ModuleDescriptor.java
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/core/module/descriptor/ModuleDescriptor.java?rev=602246&r1=602245&r2=602246&view=diff
==============================================================================
--- ant/ivy/core/trunk/src/java/org/apache/ivy/core/module/descriptor/ModuleDescriptor.java (original)
+++ ant/ivy/core/trunk/src/java/org/apache/ivy/core/module/descriptor/ModuleDescriptor.java Fri Dec  7 14:25:31 2007
@@ -26,6 +26,7 @@
 import org.apache.ivy.core.module.id.ModuleId;
 import org.apache.ivy.core.module.id.ModuleRevisionId;
 import org.apache.ivy.plugins.conflict.ConflictManager;
+import org.apache.ivy.plugins.latest.ArtifactInfo;
 import org.apache.ivy.plugins.parser.ModuleDescriptorParser;
 import org.apache.ivy.plugins.repository.Resource;
 import org.apache.ivy.plugins.version.VersionMatcher;
@@ -34,7 +35,7 @@
 /**
  *
  */
-public interface ModuleDescriptor extends ExtendableItem {
+public interface ModuleDescriptor extends ExtendableItem, ArtifactInfo {
     public static final String DEFAULT_CONFIGURATION = "default";
 
     public static final String CALLER_ALL_CONFIGURATION = "all";

Added: ant/ivy/core/trunk/src/java/org/apache/ivy/core/repository/RepositoryManagementEngine.java
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/core/repository/RepositoryManagementEngine.java?rev=602246&view=auto
==============================================================================
--- ant/ivy/core/trunk/src/java/org/apache/ivy/core/repository/RepositoryManagementEngine.java (added)
+++ ant/ivy/core/trunk/src/java/org/apache/ivy/core/repository/RepositoryManagementEngine.java Fri Dec  7 14:25:31 2007
@@ -0,0 +1,339 @@
+/*
+ *  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.repository;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.TreeSet;
+
+import org.apache.ivy.core.cache.CacheManager;
+import org.apache.ivy.core.module.descriptor.DefaultDependencyDescriptor;
+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.resolve.ResolveData;
+import org.apache.ivy.core.resolve.ResolveEngine;
+import org.apache.ivy.core.resolve.ResolveOptions;
+import org.apache.ivy.core.resolve.ResolvedModuleRevision;
+import org.apache.ivy.core.search.SearchEngine;
+import org.apache.ivy.plugins.latest.ArtifactInfo;
+import org.apache.ivy.plugins.matcher.PatternMatcher;
+import org.apache.ivy.plugins.matcher.RegexpPatternMatcher;
+import org.apache.ivy.plugins.version.VersionMatcher;
+import org.apache.ivy.util.Message;
+import org.apache.ivy.util.MemoryUtil;
+
+/**
+ * The repository management can be used to load all metadata from a repository, analyze them, and
+ * provide a bunch of information about the whole repository state.
+ * <p>
+ * Since loading all metadata from a repository is not a light task, this engine should only be used
+ * on a machine having good access to the repository (on the same filesystem being usually the best
+ * suited).
+ * </p>
+ * <p>
+ * To access information, you usually have before to call a method to init the data: {@link #load()}
+ * is used to load repository metadata, {@link #analyze()} is used to analyze them. These methods
+ * being very time consuming, they must always be called explicitly.
+ * </p>
+ * <p>
+ * On a large repository, this engine can be very memory consuming to use, it is not suited to be
+ * used in a long running process, but rather in short process loading data and taking action about
+ * the current state of the repository.
+ * </p>
+ * <p>
+ * This engine is not intended to be used concurrently with publish, the order of repository loaded
+ * being undeterministic and long, it could end up in having an inconsistent in memory state.
+ * </p>
+ */
+public class RepositoryManagementEngine {
+    private static final double THOUSAND = 1000.0;
+    private static final int KILO = 1024;
+    
+    ///////////////////////////////////////////
+    // state loaded on #load()
+    ///////////////////////////////////////////
+
+    /**
+     * True if the repository has already been loaded, false otherwise.
+     */
+    private boolean loaded;
+    /**
+     * ModuleDescriptors stored by ModuleRevisionId
+     */
+    private Map/*<ModuleRevisionId,ModuleDescriptor>*/ revisions = new HashMap();
+    /**
+     * ModuleRevisionId for which loading was not possible, with corresponding error message.
+     */
+    private Map/*<ModuleRevisionId,String>*/ errors = new HashMap();
+    /**
+     * List of ModuleRevisionId per ModuleId.
+     */
+    private Map/*<ModuleId,Collection<ModuleRevisionId>>*/ modules = new HashMap();
+    
+    ///////////////////////////////////////////
+    // state loaded on #analyze()
+    ///////////////////////////////////////////
+
+    /**
+     * True when the repository has been analyzed, false otherwise
+     */
+    private boolean analyzed;
+    /**
+     * Cache from requested module revision id to actual module revision id.
+     */
+    private Map/*<ModuleRevisionId,ModuleRevisionId>*/ cache = new HashMap();
+    /**
+     * list of dependers per ModuleRevisionId.
+     */
+    private Map/*<ModuleRevisionId,List<ModuleRevisionId>>*/ dependers = new HashMap();
+    
+    ///////////////////////////////////////////
+    // dependencies
+    ///////////////////////////////////////////
+    private SearchEngine searchEngine;
+    private ResolveEngine resolveEngine;
+    private CacheManager cacheManager;
+    private RepositoryManagementEngineSettings settings;
+    
+
+    public RepositoryManagementEngine(RepositoryManagementEngineSettings settings, 
+            SearchEngine searchEngine, ResolveEngine resolveEngine) {
+        this.settings = settings;
+        this.searchEngine = searchEngine;
+        this.resolveEngine = resolveEngine;
+        // TODO: use a cache configured to avoid actual caching, 
+        // when IVY-399 will be better implemented
+        this.cacheManager = CacheManager.getInstance(settings);
+    }
+
+    /**
+     * Loads data from the repository.
+     * <p>
+     * This method usually takes a long time to proceed. It should never be called from event
+     * dispatch thread in a GUI.
+     * </p>
+     */
+    public void load() {
+        long startingMemoryUse = 0;
+        if (settings.dumpMemoryUsage()) {
+            startingMemoryUse = MemoryUtil.getUsedMemory();
+        }
+        long startTime = System.currentTimeMillis();
+        Message.rawinfo("searching modules... ");
+        ModuleRevisionId[] mrids = searchModules();
+        Message.info("loading repository metadata...");
+        for (int i = 0; i < mrids.length; i++) {
+            try {
+                loadModuleRevision(mrids[i]);
+            } catch (Exception e) {
+                errors.put(mrids[i], e.getMessage());
+            }
+        }
+        long endTime = System.currentTimeMillis();
+        Message.info("\nrepository loaded: " + modules.size() + " modules; "
+                + revisions.size() + " revisions; "
+                + (settings.dumpMemoryUsage() 
+                        ? (MemoryUtil.getUsedMemory() - startingMemoryUse) / KILO + "kB; " 
+                        : "")
+                + (endTime - startTime) / THOUSAND + "s");
+        loaded = true;
+    }
+
+    /**
+     * Analyze data in the repository.
+     * <p>
+     * This method may take a long time to proceed. It should never be called from event
+     * dispatch thread in a GUI.
+     * </p>
+     * @throws IllegalStateException
+     *             if the repository has not been loaded yet
+     * @see #load()
+     */
+    public void analyze() {
+        ensureLoaded();
+        Message.info("\nanalyzing dependencies...");
+        for (Iterator iterator = revisions.values().iterator(); iterator.hasNext();) {
+            ModuleDescriptor md = (ModuleDescriptor) iterator.next();
+            DependencyDescriptor[] dds = md.getDependencies();
+            for (int i = 0; i < dds.length; i++) {
+                ModuleRevisionId dep = getDependency(dds[i]);
+                if (dep == null) {
+                    Message.warn(
+                        "inconsistent repository: declared dependency not found: " + dds[i]);
+                } else {
+                    getDependers(dep).add(md.getModuleRevisionId());
+                }
+            }
+            Message.progress();
+        }
+        analyzed = true;
+    }
+
+    /**
+     * Returns the number of Module Revision in the repository.
+     * 
+     * @return the number of module revisions in the repository.
+     * @throws IllegalStateException
+     *             if the repository has not been loaded yet
+     * @see #load()
+     */
+    public int getRevisionsNumber() {
+        ensureLoaded();
+        return revisions.size();
+    }
+
+    /**
+     * Returns the number of ModuleId in the repository.
+     * 
+     * @return the number of ModuleId in the repository.
+     * @throws IllegalStateException
+     *             if the repository has not been loaded yet
+     * @see #load()
+     */
+    public int getModuleIdsNumber() {
+        ensureLoaded();
+        return modules.size();
+    }
+
+    /**
+     * Returns Module Revisions which have no dependers.
+     * 
+     * @return a Collection of the {@link ModuleRevisionId} of module revisions which have no
+     *         dependers in the repository.
+     * @throws IllegalStateException
+     *             if the repository has not been analyzed yet
+     * @see #analyze()
+     */
+    public Collection getOrphans() {
+        ensureAnalyzed();
+        Collection orphans = new HashSet(revisions.keySet());
+        orphans.removeAll(dependers.keySet());
+        return orphans;
+    }
+
+
+    private ModuleRevisionId[] searchModules() {
+        ModuleRevisionId[] mrids = searchEngine.listModules(
+            ModuleRevisionId.newInstance(
+                PatternMatcher.ANY_EXPRESSION, 
+                PatternMatcher.ANY_EXPRESSION, 
+                PatternMatcher.ANY_EXPRESSION, 
+                PatternMatcher.ANY_EXPRESSION), 
+                RegexpPatternMatcher.INSTANCE);
+        return mrids;
+    }
+
+    private ModuleRevisionId getDependency(DependencyDescriptor dd) {
+        ModuleRevisionId askedMrid = dd.getDependencyRevisionId();
+        VersionMatcher vmatcher = settings.getVersionMatcher();
+        if (vmatcher.isDynamic(askedMrid)) {
+            ModuleRevisionId mrid = (ModuleRevisionId) cache.get(askedMrid);
+            if (mrid == null) {
+                Collection revs = getAllRevisions(askedMrid); 
+                for (Iterator iterator = revs.iterator(); iterator.hasNext();) {
+                    ModuleDescriptor md = (ModuleDescriptor) iterator.next();
+                    if (vmatcher.needModuleDescriptor(
+                            askedMrid, md.getResolvedModuleRevisionId())) {
+                        if (vmatcher.accept(askedMrid, md)) {
+                            mrid = md.getResolvedModuleRevisionId();
+                            break;
+                        }
+                    } else {
+                        if (vmatcher.accept(askedMrid, md.getResolvedModuleRevisionId())) {
+                            mrid = md.getResolvedModuleRevisionId();
+                            break;
+                        }
+                    }
+                }
+                if (mrid == null) {
+                    return null;
+                } else {
+                    cache.put(askedMrid, mrid);
+                }
+            }
+            return mrid;
+        } else {
+            return askedMrid;
+        }
+    }
+
+    private Collection getDependers(ModuleRevisionId id) {
+        Collection depders = (Collection) dependers.get(id);
+        if (depders == null) {
+            depders = new ArrayList();
+            dependers.put(id, depders);
+        }
+        return depders;
+    }
+
+    private void loadModuleRevision(ModuleRevisionId mrid) throws Exception {
+        ResolvedModuleRevision module = settings.getResolver(mrid.getModuleId())
+                    .getDependency(new DefaultDependencyDescriptor(mrid, false), 
+                newResolveData());
+        if (module == null) {
+            Message.warn("module not found while listed: " + mrid);
+        } else {
+            revisions.put(module.getId(), module.getDescriptor());
+            getAllRevisions(module.getId()).add(module.getDescriptor());
+        }
+        Message.progress();
+    }
+
+    private Collection getAllRevisions(ModuleRevisionId id) {
+        Collection revisions = (Collection) modules.get(id.getModuleId());
+        if (revisions == null) {
+            revisions = new TreeSet(new Comparator() {
+                public int compare(Object o1, Object o2) {
+                    ModuleDescriptor md1 = (ModuleDescriptor) o1;
+                    ModuleDescriptor md2 = (ModuleDescriptor) o2;
+                    // we use reverse order compared to latest revision, to have latest revision
+                    // first
+                    return settings.getDefaultLatestStrategy()
+                        .sort(new ArtifactInfo[] {md1, md2}).get(0).equals(md1) ? 1 : -1;
+                }
+            });
+            modules.put(id.getModuleId(), revisions);
+        }
+        return revisions;
+    }
+
+    private ResolveData newResolveData() {
+        return new ResolveData(resolveEngine, 
+            new ResolveOptions().setCache(cacheManager).setUseOrigin(true));
+    }
+
+    private void ensureAnalyzed() {
+        if (!analyzed) {
+            throw new IllegalStateException(
+                "repository must have been analyzed to perform this method");
+        }
+    }
+
+    private void ensureLoaded() {
+        if (!loaded) {
+            throw new IllegalStateException(
+                "repository must have be loaded to perform this method");
+        }
+    }
+}

Propchange: ant/ivy/core/trunk/src/java/org/apache/ivy/core/repository/RepositoryManagementEngine.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: ant/ivy/core/trunk/src/java/org/apache/ivy/core/repository/RepositoryManagementEngineSettings.java
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/core/repository/RepositoryManagementEngineSettings.java?rev=602246&view=auto
==============================================================================
--- ant/ivy/core/trunk/src/java/org/apache/ivy/core/repository/RepositoryManagementEngineSettings.java (added)
+++ ant/ivy/core/trunk/src/java/org/apache/ivy/core/repository/RepositoryManagementEngineSettings.java Fri Dec  7 14:25:31 2007
@@ -0,0 +1,24 @@
+/*
+ *  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.repository;
+
+import org.apache.ivy.core.resolve.ResolveEngineSettings;
+
+public interface RepositoryManagementEngineSettings extends ResolveEngineSettings {
+    public boolean dumpMemoryUsage();
+}

Propchange: ant/ivy/core/trunk/src/java/org/apache/ivy/core/repository/RepositoryManagementEngineSettings.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: ant/ivy/core/trunk/src/java/org/apache/ivy/core/search/SearchEngine.java
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/core/search/SearchEngine.java?rev=602246&r1=602245&r2=602246&view=diff
==============================================================================
--- ant/ivy/core/trunk/src/java/org/apache/ivy/core/search/SearchEngine.java (original)
+++ ant/ivy/core/trunk/src/java/org/apache/ivy/core/search/SearchEngine.java Fri Dec  7 14:25:31 2007
@@ -23,6 +23,7 @@
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 
@@ -54,7 +55,7 @@
      * @return
      */
     public String[] listTokenValues(String token, Map otherTokenValues) {
-        List r = new ArrayList();
+        Collection r = new LinkedHashSet();
         for (Iterator iter = settings.getResolvers().iterator(); iter.hasNext();) {
             DependencyResolver resolver = (DependencyResolver) iter.next();
             r.addAll(Arrays.asList(resolver.listTokenValues(token, otherTokenValues)));
@@ -206,10 +207,13 @@
                                             branches[k], revs[l]));
                                     }
                                 }
+                                tokenValues.remove(IvyPatternHelper.REVISION_KEY);
                             }
                         }
+                        tokenValues.remove(IvyPatternHelper.BRANCH_KEY);
                     }
                 }
+                tokenValues.remove(IvyPatternHelper.MODULE_KEY);
             }
         }
         return (ModuleRevisionId[]) ret.toArray(new ModuleRevisionId[ret.size()]);

Modified: ant/ivy/core/trunk/src/java/org/apache/ivy/core/settings/IvySettings.java
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/core/settings/IvySettings.java?rev=602246&r1=602245&r2=602246&view=diff
==============================================================================
--- ant/ivy/core/trunk/src/java/org/apache/ivy/core/settings/IvySettings.java (original)
+++ ant/ivy/core/trunk/src/java/org/apache/ivy/core/settings/IvySettings.java Fri Dec  7 14:25:31 2007
@@ -47,6 +47,7 @@
 import org.apache.ivy.core.module.id.ModuleId;
 import org.apache.ivy.core.module.status.StatusManager;
 import org.apache.ivy.core.publish.PublishEngineSettings;
+import org.apache.ivy.core.repository.RepositoryManagementEngineSettings;
 import org.apache.ivy.core.resolve.ResolveEngineSettings;
 import org.apache.ivy.core.retrieve.RetrieveEngineSettings;
 import org.apache.ivy.core.sort.SortEngineSettings;
@@ -96,7 +97,8 @@
 
 public class IvySettings implements SortEngineSettings, PublishEngineSettings, ParserSettings,
         DeliverEngineSettings, CacheSettings, CheckEngineSettings, InstallEngineSettings, 
-        ResolverSettings, ResolveEngineSettings, RetrieveEngineSettings {
+        ResolverSettings, ResolveEngineSettings, RetrieveEngineSettings, 
+        RepositoryManagementEngineSettings {
     private static final String DEFAULT_CACHE_ARTIFACT_PATTERN =
         "[organisation]/[module]/[type]s/[artifact]-[revision](.[ext])";
 
@@ -205,6 +207,8 @@
 
     private Boolean debugLocking;
 
+    private Boolean dumpMemoryUsage;
+
     public IvySettings() {
         this(new IvyVariableContainerImpl());
     }
@@ -395,6 +399,26 @@
         Message.verbose("settings loaded (" + (System.currentTimeMillis() - start) + "ms)");
         dumpSettings();
     }
+    
+    /**
+     * Default initialization of settings, useful when you don't want to load your settings from a
+     * settings file or URL, but prefer to set them manually. By calling this method you will still
+     * have the basic initialization done when loading settings.
+     * 
+     * @throws IOException
+     */
+    public void defaultInit() throws IOException {
+        if (getVariable("ivy.default.ivy.user.dir") != null) {
+            setDefaultIvyUserDir(new File(getVariable("ivy.default.ivy.user.dir")));
+        } else {
+            getDefaultIvyUserDir();
+        }
+        getDefaultCache();
+
+        loadDefaultProperties();
+        setVariable("ivy.default.ivy.user.dir", getDefaultIvyUserDir().getAbsolutePath(), false);
+        dumpSettings();
+    }
 
     public void loadDefault() throws ParseException, IOException {
         load(getDefaultSettingsURL());
@@ -1162,6 +1186,16 @@
         }
         return debugLocking.booleanValue();
     }
+
+    public boolean dumpMemoryUsage() {
+        if (dumpMemoryUsage == null) {
+            String var = getVariable("ivy.log.memory");
+            dumpMemoryUsage = Boolean.valueOf(var != null
+                    && Boolean.valueOf(var).booleanValue());
+        }
+        return dumpMemoryUsage.booleanValue();
+    }
+
 
     public boolean logNotConvertedExclusionRule() {
         return logNotConvertedExclusionRule;

Modified: ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/resolver/FileSystemResolver.java
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/resolver/FileSystemResolver.java?rev=602246&r1=602245&r2=602246&view=diff
==============================================================================
--- ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/resolver/FileSystemResolver.java (original)
+++ ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/resolver/FileSystemResolver.java Fri Dec  7 14:25:31 2007
@@ -133,9 +133,10 @@
             if (transactionTempDir == null) {
                 throw new IllegalStateException("no current transaction!");
             }
+            getFileRepository().move(transactionTempDir, transactionDestDir);
             Message.info("\tpublish commited: moved " + transactionTempDir 
                 + " \n\t\tto " + transactionDestDir);
-            getFileRepository().move(transactionTempDir, transactionDestDir);
+            closeTransaction();
         }
     }
 

Added: ant/ivy/core/trunk/src/java/org/apache/ivy/util/MemoryUtil.java
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/util/MemoryUtil.java?rev=602246&view=auto
==============================================================================
--- ant/ivy/core/trunk/src/java/org/apache/ivy/util/MemoryUtil.java (added)
+++ ant/ivy/core/trunk/src/java/org/apache/ivy/util/MemoryUtil.java Fri Dec  7 14:25:31 2007
@@ -0,0 +1,90 @@
+/*
+ *  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.util;
+
+/**
+ * Memory related utilities.
+ */
+public final class MemoryUtil {
+    private static final int SAMPLING_SIZE = 100;
+    private static final int SLEEP_TIME = 100;
+    
+    private MemoryUtil() {
+    }
+
+    /**
+     * Returns the approximate size of a default instance of the given class.
+     * 
+     * @param clazz
+     *            the class to evaluate.
+     * @return the estimated size of instance, in bytes.
+     */
+    public static long sizeOf(Class clazz) {
+        long size = 0;
+        Object[] objects = new Object[SAMPLING_SIZE];
+        try {
+            clazz.newInstance();
+            long startingMemoryUse = getUsedMemory();
+            for (int i = 0; i < objects.length; i++) {
+                objects[i] = clazz.newInstance();
+            }
+            long endingMemoryUse = getUsedMemory();
+            float approxSize = (endingMemoryUse - startingMemoryUse) / (float) objects.length;
+            size = Math.round(approxSize);
+        } catch (Exception e) {
+            System.out.println("WARNING:couldn't instantiate" + clazz);
+            e.printStackTrace();
+        }
+        return size;
+    }
+
+    /**
+     * Returns the currently used memory, after calling garbage collector and waiting enough to get
+     * maximal chance it is actually called. But since {@link Runtime#gc()} is only advisory,
+     * results returned by this method should be treated as rough approximation only.
+     * 
+     * @return the currently used memory, in bytes.
+     */
+    public static long getUsedMemory() {
+        gc();
+        long totalMemory = Runtime.getRuntime().totalMemory();
+        gc();
+        long freeMemory = Runtime.getRuntime().freeMemory();
+        long usedMemory = totalMemory - freeMemory;
+        return usedMemory;
+    }
+
+    private static void gc() {
+        try {
+            System.gc();
+            Thread.sleep(SLEEP_TIME);
+            System.runFinalization();
+            Thread.sleep(SLEEP_TIME);
+            System.gc();
+            Thread.sleep(SLEEP_TIME);
+            System.runFinalization();
+            Thread.sleep(SLEEP_TIME);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+    
+    public static void main(String[] args) throws ClassNotFoundException {
+        System.out.println(sizeOf(Class.forName(args[0])));
+    }
+}
\ No newline at end of file

Propchange: ant/ivy/core/trunk/src/java/org/apache/ivy/util/MemoryUtil.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: ant/ivy/core/trunk/test/java/org/apache/ivy/core/repository/RepositoryManagementEngineTest.java
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/test/java/org/apache/ivy/core/repository/RepositoryManagementEngineTest.java?rev=602246&view=auto
==============================================================================
--- ant/ivy/core/trunk/test/java/org/apache/ivy/core/repository/RepositoryManagementEngineTest.java (added)
+++ ant/ivy/core/trunk/test/java/org/apache/ivy/core/repository/RepositoryManagementEngineTest.java Fri Dec  7 14:25:31 2007
@@ -0,0 +1,68 @@
+/*
+ *  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.repository;
+
+import junit.framework.TestCase;
+
+import org.apache.ivy.TestFixture;
+import org.apache.ivy.TestHelper;
+import org.apache.ivy.core.event.EventManager;
+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.core.sort.SortEngine;
+
+public class RepositoryManagementEngineTest extends TestCase {
+    private RepositoryManagementEngine repository;
+    private TestFixture fixture;
+    
+    protected void setUp() throws Exception {
+        fixture = new TestFixture();
+        IvySettings settings = fixture.getSettings();
+        repository = new RepositoryManagementEngine(settings, new SearchEngine(settings),
+                new ResolveEngine(settings, new EventManager(), new SortEngine(settings)));
+    }
+    
+    protected void tearDown() throws Exception {
+        fixture.clean();
+    }
+    
+    public void testLoad() throws Exception {
+        fixture
+            .addMD("o1#A;1").addMD("o1#A;2").addMD("o1#A;3")
+            .addMD("o1#B;1").addMD("o1#B;2->o1#A;2")
+            .addMD("o2#C;1->{o1#B;1 o1#A;1}")
+            .init();
+        
+        repository.load();
+        assertEquals(3, repository.getModuleIdsNumber());
+        assertEquals(6, repository.getRevisionsNumber());
+    }
+    
+    public void testOrphans() throws Exception {
+        fixture
+            .addMD("o1#A;1").addMD("o1#A;2").addMD("o1#A;3")
+            .addMD("o1#B;1").addMD("o1#B;2->o1#A;2")
+            .addMD("o2#C;1->{o1#B;1 o1#A;1}")
+            .init();
+        
+        repository.load();
+        repository.analyze();
+        TestHelper.assertModuleRevisionIds("o1#A;3 o1#B;2 o2#C;1", repository.getOrphans());
+    }
+}

Propchange: ant/ivy/core/trunk/test/java/org/apache/ivy/core/repository/RepositoryManagementEngineTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain