Author: gscokart
Date: Thu Aug 14 07:11:20 2008
New Revision: 685906
URL: http://svn.apache.org/viewvc?rev=685906&view=rev
Log:
IMPROVEMENT: Add a memory cache for the module descriptor that are parsed from
the cache (IVY-883)
Added:
ant/ivy/core/trunk/src/java/org/apache/ivy/core/cache/ModuleDescriptorMemoryCache.java
(with props)
ant/ivy/core/trunk/src/java/org/apache/ivy/core/cache/ModuleDescriptorProvider.java
(with props)
ant/ivy/core/trunk/src/java/org/apache/ivy/core/cache/ParserSettingsMonitor.java
(with props)
ant/ivy/core/trunk/test/java/org/apache/ivy/core/cache/ModuleDescriptorMemoryCacheTest.java
(with props)
Modified:
ant/ivy/core/trunk/CHANGES.txt
ant/ivy/core/trunk/doc/settings/caches/cache.html
ant/ivy/core/trunk/src/java/org/apache/ivy/core/IvyPatternHelper.java
ant/ivy/core/trunk/src/java/org/apache/ivy/core/cache/DefaultRepositoryCacheManager.java
ant/ivy/core/trunk/src/java/org/apache/ivy/core/settings/IvySettings.java
Modified: ant/ivy/core/trunk/CHANGES.txt
URL:
http://svn.apache.org/viewvc/ant/ivy/core/trunk/CHANGES.txt?rev=685906&r1=685905&r2=685906&view=diff
==============================================================================
--- ant/ivy/core/trunk/CHANGES.txt (original)
+++ ant/ivy/core/trunk/CHANGES.txt Thu Aug 14 07:11:20 2008
@@ -105,6 +105,7 @@
- IMPROVEMENT: Smarter determination if an expression is exact or not for
RegexpPatternMatcher and GlobPatternMatcher
- IMPROVEMENT: Check branch consistency during resolve (IVY-858)
- IMPROVEMENT: Give the possibility to not compute ivy.deps.changed (IVY-876)
+- IMPROVEMENT: Add a memory cache for the module descriptor that are parsed
from the cache (IVY-883)
- IMPROVEMENT: Improve performance (IVY-872)
- FIX: Incorrect parsing artifactPattern attribute in a sftp resolver
(IVY-661) (thanks to Alexey Kiselev)
Modified: ant/ivy/core/trunk/doc/settings/caches/cache.html
URL:
http://svn.apache.org/viewvc/ant/ivy/core/trunk/doc/settings/caches/cache.html?rev=685906&r1=685905&r2=685906&view=diff
==============================================================================
--- ant/ivy/core/trunk/doc/settings/caches/cache.html (original)
+++ ant/ivy/core/trunk/doc/settings/caches/cache.html Thu Aug 14 07:11:20 2008
@@ -26,10 +26,14 @@
<textarea id="xooki-source">
<b>Tag:</b> cache
+<span class="since">Since 2.0</span>.
+
<span class="tagdoc" id="ivysettings.caches.cache">Defines a repository cache
instance based on the default repository cache implementation.</span>
The default repository cache implementation caches files on the local
filesystem in subdirectories of a configured base directory.
+By default also, the parsed module descriptor read from the cache are kept in
a memory cache in case they are reused. This may enhance the performance of
multi-module build, provided that all modules are build using the same ivy
instance. The size of this memory cache is configurable in term of number of
module descriptors. A size of 0 means no memory caching.
+
<h1>Attributes</h1>
<table class="ivy-attributes">
<thead>
@@ -51,6 +55,7 @@
<td>No, defaults to default lock strategy as configured in
[[settings/caches]]</td></tr>
<tr><td>defaultTTL</td><td>the default [[settings/caches/ttl TTL]] to use
when no specific one is defined</td>
<td>No, defaults to ${ivy.cache.ttl.default}</td></tr>
+ <tr><td>memorySize</td><td>the number of parsed module descriptors to keep
in a memory cache.</td><td>No, default to 150</td></tr>
</tbody>
</table>
Modified: ant/ivy/core/trunk/src/java/org/apache/ivy/core/IvyPatternHelper.java
URL:
http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/core/IvyPatternHelper.java?rev=685906&r1=685905&r2=685906&view=diff
==============================================================================
--- ant/ivy/core/trunk/src/java/org/apache/ivy/core/IvyPatternHelper.java
(original)
+++ ant/ivy/core/trunk/src/java/org/apache/ivy/core/IvyPatternHelper.java Thu
Aug 14 07:11:20 2008
@@ -171,8 +171,13 @@
Matcher m = VAR_PATTERN.matcher(pattern);
- StringBuffer sb = new StringBuffer();
+ boolean useVariables = false;
+ StringBuffer sb = null;
while (m.find()) {
+ if (!useVariables) {
+ useVariables = true;
+ sb = new StringBuffer();
+ }
String var = m.group(1);
String val = (String) variables.getVariable(var);
if (val != null) {
@@ -189,13 +194,15 @@
} else {
val = m.group();
}
- m
- .appendReplacement(sb, val.replaceAll("\\\\",
"\\\\\\\\").replaceAll("\\$",
- "\\\\\\$"));
+ m.appendReplacement(sb, val.replaceAll("\\\\", "\\\\\\\\")
+ .replaceAll("\\$","\\\\\\$"));
+ }
+ if (useVariables) {
+ m.appendTail(sb);
+ return sb.toString();
+ } else {
+ return pattern;
}
- m.appendTail(sb);
-
- return sb.toString();
}
public static String substituteTokens(String pattern, Map tokens) {
Modified:
ant/ivy/core/trunk/src/java/org/apache/ivy/core/cache/DefaultRepositoryCacheManager.java
URL:
http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/core/cache/DefaultRepositoryCacheManager.java?rev=685906&r1=685905&r2=685906&view=diff
==============================================================================
---
ant/ivy/core/trunk/src/java/org/apache/ivy/core/cache/DefaultRepositoryCacheManager.java
(original)
+++
ant/ivy/core/trunk/src/java/org/apache/ivy/core/cache/DefaultRepositoryCacheManager.java
Thu Aug 14 07:11:20 2008
@@ -20,7 +20,6 @@
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
-import java.net.URL;
import java.text.ParseException;
import java.util.Date;
import java.util.Map;
@@ -48,6 +47,7 @@
import org.apache.ivy.plugins.namespace.NameSpaceHelper;
import org.apache.ivy.plugins.parser.ModuleDescriptorParser;
import org.apache.ivy.plugins.parser.ModuleDescriptorParserRegistry;
+import org.apache.ivy.plugins.parser.ParserSettings;
import org.apache.ivy.plugins.parser.xml.XmlModuleDescriptorParser;
import org.apache.ivy.plugins.repository.ArtifactResourceResolver;
import org.apache.ivy.plugins.repository.ResourceDownloader;
@@ -68,6 +68,8 @@
private static final String DEFAULT_IVY_PATTERN =
"[organisation]/[module](/[branch])/ivy-[revision].xml";
+ private static final int DEFAULT_MEMORY_CACHE_SIZE = 150;
+
private IvySettings settings;
private File basedir;
@@ -96,6 +98,8 @@
private Long defaultTTL = null;
+ private ModuleDescriptorMemoryCache memoryModuleDescrCache;
+
public DefaultRepositoryCacheManager() {
}
@@ -228,7 +232,18 @@
parseDuration(duration));
}
-
+ public void setMemorySize(int size) {
+ memoryModuleDescrCache = new ModuleDescriptorMemoryCache(size);
+ }
+
+ public ModuleDescriptorMemoryCache getMemoryCache() {
+ if (memoryModuleDescrCache==null) {
+ memoryModuleDescrCache = new
ModuleDescriptorMemoryCache(DEFAULT_MEMORY_CACHE_SIZE);
+ }
+ return memoryModuleDescrCache;
+ }
+
+
private static final Pattern DURATION_PATTERN
= Pattern.compile("(?:(\\d+)d)? ?(?:(\\d+)h)? ?(?:(\\d+)m)?
?(?:(\\d+)s)? ?(?:(\\d+)ms)?");
@@ -542,8 +557,8 @@
if (ivyFile.exists()) {
// found in cache !
try {
- ModuleDescriptor depMD =
XmlModuleDescriptorParser.getInstance()
- .parseDescriptor(settings, ivyFile.toURI().toURL(),
options.isValidate());
+ XmlModuleDescriptorParser parser =
XmlModuleDescriptorParser.getInstance();
+ ModuleDescriptor depMD = getMdFromCache(parser, options,
ivyFile);
String resolverName = getSavedResolverName(depMD);
String artResolverName = getSavedArtResolverName(depMD);
DependencyResolver resolver =
settings.getResolver(resolverName);
@@ -603,6 +618,38 @@
return null;
}
+
+ private class MyModuleDescriptorProvider implements
ModuleDescriptorProvider {
+
+ private final ModuleDescriptorParser mdParser;
+
+ public MyModuleDescriptorProvider(ModuleDescriptorParser mdParser) {
+ this.mdParser = mdParser;
+ }
+
+ public ModuleDescriptor provideModule(ParserSettings ivySettings,
+ File descriptorURL, boolean validate) throws ParseException,
IOException {
+ return mdParser.parseDescriptor(ivySettings,
descriptorURL.toURI().toURL(), validate);
+ }
+ }
+
+ private ModuleDescriptor getMdFromCache(XmlModuleDescriptorParser
mdParser,
+ CacheMetadataOptions options, File ivyFile)
+ throws ParseException, IOException, MalformedURLException {
+ ModuleDescriptorMemoryCache cache = getMemoryCache();
+ ModuleDescriptorProvider mdProvider = new
MyModuleDescriptorProvider(mdParser);
+ return cache.get(ivyFile, settings, options.isValidate(), mdProvider);
+ }
+
+ private ModuleDescriptor getStaledMd(ModuleDescriptorParser mdParser,
+ CacheMetadataOptions options, File ivyFile)
+ throws ParseException, IOException, MalformedURLException {
+ ModuleDescriptorMemoryCache cache = getMemoryCache();
+ ModuleDescriptorProvider mdProvider = new
MyModuleDescriptorProvider(mdParser);
+ return cache.getStale(ivyFile, settings, options.isValidate(),
mdProvider);
+ }
+
+
private String getResolvedRevision(ModuleRevisionId mrid,
CacheMetadataOptions options) {
if (!lockMetadataArtifact(mrid)) {
Message.error("impossible to acquire lock for " + mrid);
@@ -887,17 +934,8 @@
return null;
}
- URL cachedMDURL = null;
- try {
- cachedMDURL = report.getLocalFile().toURI().toURL();
- } catch (MalformedURLException ex) {
- Message.warn("malformed url exception for original in cache
file: "
- + report.getLocalFile() + ": " + ex.getMessage());
- return null;
- }
try {
- ModuleDescriptor md = parser.parseDescriptor(
- settings, cachedMDURL, mdRef.getResource(),
options.isValidate());
+ ModuleDescriptor md = getStaledMd(parser, options,
report.getLocalFile());
if (md == null) {
throw new IllegalStateException(
"module descriptor parser returned a null module
descriptor, "
Added:
ant/ivy/core/trunk/src/java/org/apache/ivy/core/cache/ModuleDescriptorMemoryCache.java
URL:
http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/core/cache/ModuleDescriptorMemoryCache.java?rev=685906&view=auto
==============================================================================
---
ant/ivy/core/trunk/src/java/org/apache/ivy/core/cache/ModuleDescriptorMemoryCache.java
(added)
+++
ant/ivy/core/trunk/src/java/org/apache/ivy/core/cache/ModuleDescriptorMemoryCache.java
Thu Aug 14 07:11:20 2008
@@ -0,0 +1,134 @@
+/*
+ * 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.cache;
+
+import java.io.File;
+import java.io.IOException;
+import java.text.ParseException;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+
+import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
+import org.apache.ivy.plugins.parser.ParserSettings;
+import org.apache.ivy.util.Message;
+
+/**
+ * Cache ModuleDescriptors so that when the same module is used twice (in
multi-module build for
+ * instance), it is parsed only once.
+ * This cache is has a limited size, and keep the most recently used entries.
+ * The entry in the cache are invalidated if there is a change to one variable
+ * used in the module descriptor.
+ */
+class ModuleDescriptorMemoryCache {
+
+ private final int maxSize;
+ private final LinkedHashMap/*<File,CacheEntry>*/ valueMap;
+
+
+ /**
+ * Create a cache of the given size
+ * @param size
+ */
+ public ModuleDescriptorMemoryCache(int size) {
+ this.maxSize = size;
+ this.valueMap = new LinkedHashMap(size);
+ }
+
+ public ModuleDescriptor get(File ivyFile, ParserSettings ivySettings,
boolean validated,
+ ModuleDescriptorProvider mdProvider) throws ParseException,
IOException {
+
+ ModuleDescriptor descriptor = getFromCache(ivyFile, ivySettings,
validated);
+ if (descriptor==null) {
+ descriptor = getStale(ivyFile, ivySettings, validated, mdProvider);
+ }
+ return descriptor;
+ }
+
+ /**
+ * Get the module descriptor from the mdProvider and store it into the
cache.
+ */
+ public ModuleDescriptor getStale(File ivyFile, ParserSettings ivySettings,
boolean validated,
+ ModuleDescriptorProvider mdProvider) throws ParseException,
IOException {
+ ParserSettingsMonitor settingsMonitor = new
ParserSettingsMonitor(ivySettings);
+ ModuleDescriptor descriptor = mdProvider.provideModule(
+ settingsMonitor.getMonitoredSettings() , ivyFile, validated);
+ putInCache(ivyFile, settingsMonitor, validated, descriptor);
+ return descriptor;
+ }
+
+ ModuleDescriptor getFromCache(File ivyFile, ParserSettings ivySettings,
boolean validated) {
+ if (maxSize<=0) {
+ //cache is disbaled
+ return null;
+ }
+ CacheEntry entry = (CacheEntry) valueMap.get(ivyFile);
+ if (entry!=null) {
+ if (entry.isStale(validated, ivySettings)) {
+ Message.debug("Entry is found in the ModuleDescriptorCache but
entry should be " +
+ "reevaluated : " + ivyFile);
+ valueMap.remove(ivyFile);
+ return null;
+ } else {
+ //Move the entry at the end of the list
+ valueMap.remove(ivyFile);
+ valueMap.put(ivyFile, entry);
+ Message.debug("Entry is found in the ModuleDescriptorCache : "
+ ivyFile);
+ return entry.md;
+ }
+ }
+ else {
+ Message.debug("No entry is found in the ModuleDescriptorCache : "
+ ivyFile);
+ return null;
+ }
+ }
+
+
+
+ void putInCache(File url, ParserSettingsMonitor ivySettingsMonitor,
boolean validated,
+ ModuleDescriptor descriptor) {
+ if (maxSize<=0) {
+ //cache is disabled
+ return;
+ }
+ if (valueMap.size()>=maxSize) {
+ Message.debug("ModuleDescriptorCache is full, remove one entry");
+ Iterator it = valueMap.values().iterator();
+ it.next();
+ it.remove();
+ }
+ valueMap.put(url, new CacheEntry(descriptor , validated,
ivySettingsMonitor));
+ }
+
+
+ private static class CacheEntry {
+ final ModuleDescriptor md;
+ final boolean validated;
+ final ParserSettingsMonitor parserSettingsMonitor;
+
+ CacheEntry(ModuleDescriptor md ,boolean validated,
ParserSettingsMonitor parserSettingsMonitor ) {
+ this.md = md;
+ this.validated = validated;
+ this.parserSettingsMonitor = parserSettingsMonitor;
+ }
+
+ boolean isStale(boolean validated, ParserSettings newParserSettings) {
+ return (validated && !this.validated) ||
parserSettingsMonitor.hasChanged(newParserSettings);
+ }
+ }
+
+}
Propchange:
ant/ivy/core/trunk/src/java/org/apache/ivy/core/cache/ModuleDescriptorMemoryCache.java
------------------------------------------------------------------------------
svn:eol-style = native
Added:
ant/ivy/core/trunk/src/java/org/apache/ivy/core/cache/ModuleDescriptorProvider.java
URL:
http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/core/cache/ModuleDescriptorProvider.java?rev=685906&view=auto
==============================================================================
---
ant/ivy/core/trunk/src/java/org/apache/ivy/core/cache/ModuleDescriptorProvider.java
(added)
+++
ant/ivy/core/trunk/src/java/org/apache/ivy/core/cache/ModuleDescriptorProvider.java
Thu Aug 14 07:11:20 2008
@@ -0,0 +1,31 @@
+/*
+ * 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.cache;
+
+import java.io.File;
+import java.io.IOException;
+import java.text.ParseException;
+
+import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
+import org.apache.ivy.plugins.parser.ParserSettings;
+
+interface ModuleDescriptorProvider {
+
+ public ModuleDescriptor provideModule(ParserSettings ivySettings, File
descriptorFile,
+ boolean validate) throws ParseException, IOException;
+}
Propchange:
ant/ivy/core/trunk/src/java/org/apache/ivy/core/cache/ModuleDescriptorProvider.java
------------------------------------------------------------------------------
svn:eol-style = native
Added:
ant/ivy/core/trunk/src/java/org/apache/ivy/core/cache/ParserSettingsMonitor.java
URL:
http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/core/cache/ParserSettingsMonitor.java?rev=685906&view=auto
==============================================================================
---
ant/ivy/core/trunk/src/java/org/apache/ivy/core/cache/ParserSettingsMonitor.java
(added)
+++
ant/ivy/core/trunk/src/java/org/apache/ivy/core/cache/ParserSettingsMonitor.java
Thu Aug 14 07:11:20 2008
@@ -0,0 +1,138 @@
+/*
+ * 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.cache;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.apache.ivy.core.RelativeUrlResolver;
+import org.apache.ivy.core.module.id.ModuleRevisionId;
+import org.apache.ivy.core.module.status.StatusManager;
+import org.apache.ivy.plugins.conflict.ConflictManager;
+import org.apache.ivy.plugins.matcher.PatternMatcher;
+import org.apache.ivy.plugins.namespace.Namespace;
+import org.apache.ivy.plugins.parser.ParserSettings;
+import org.apache.ivy.plugins.resolver.DependencyResolver;
+import org.apache.ivy.util.Message;
+
+
+/**
+ * Keep traces of the usage of a ParserSettings in order to check afterwards
that
+ * the relevant settings didn't changed.
+ * A ParserSettingsMonitor provide a ParserSettings that must be used in place
of the
+ * orignal one.
+ * The current implementation consider that a settings changed iff one of the
used variable has changed.
+ */
+class ParserSettingsMonitor {
+
+ private ParserSettings delegatedSettings;
+ private final Map/*<String,String>*/ substitutes;
+
+
+ public ParserSettingsMonitor(ParserSettings settings) {
+ this.delegatedSettings = settings;
+ this.substitutes = new HashMap();
+ }
+
+ /**
+ * @return The parser settings that must be used in place of the orignal
settings
+ * The returned object delegates all the call to the original settings.
+ */
+ public ParserSettings getMonitoredSettings() {
+ return monitoredSettings;
+ }
+
+ /**
+ * Free the ressource used during the monitoring, keeping only the info
+ * required to evaluate hasChanged.
+ */
+ public void endMonitoring() {
+ monitoredSettings = null;
+ delegatedSettings = null;
+ }
+
+ /**
+ * Check if the newSettings is compatible with the original settings that
+ * has been monitored. Only the info that was actually used is compared.
+ */
+ public boolean hasChanged(ParserSettings newSettings) {
+ for(Iterator it = substitutes.entrySet().iterator() ; it.hasNext() ;) {
+ Map.Entry entry = (Entry) it.next();
+ String key = (String) entry.getKey();
+ Object oldValue = entry.getValue();
+ String newValue = newSettings.substitute(key);
+ if (! oldValue.equals(newValue)) {
+ Message.debug("settings variable has changed for : " +
entry.getKey());
+ return true;
+ }
+ }
+ return false;
+ }
+
+
+ private ParserSettings monitoredSettings = new ParserSettings() {
+
+ public ConflictManager getConflictManager(String name) {
+ return delegatedSettings.getConflictManager(name);
+ }
+
+ public PatternMatcher getMatcher(String matcherName) {
+ return delegatedSettings.getMatcher(matcherName);
+ }
+
+ public Namespace getNamespace(String namespace) {
+ return delegatedSettings.getNamespace(namespace);
+ }
+
+ public RelativeUrlResolver getRelativeUrlResolver() {
+ return delegatedSettings.getRelativeUrlResolver();
+ }
+
+ public ResolutionCacheManager getResolutionCacheManager() {
+ return delegatedSettings.getResolutionCacheManager();
+ }
+
+ public DependencyResolver getResolver(ModuleRevisionId mRevId) {
+ return delegatedSettings.getResolver(mRevId);
+ }
+
+ public StatusManager getStatusManager() {
+ return delegatedSettings.getStatusManager();
+ }
+
+ public Map substitute(Map strings) {
+ Map substituted = new LinkedHashMap();
+ for (Iterator it = strings.entrySet().iterator(); it.hasNext();) {
+ Map.Entry entry = (Map.Entry) it.next();
+ substituted.put(entry.getKey(), substitute((String)
entry.getValue()));
+ }
+ return substituted;
+ }
+
+ public String substitute(String value) {
+ String r = delegatedSettings.substitute(value);
+ if (value!=null && value!=r) {
+ substitutes.put(value, r);
+ }
+ return r;
+ }
+ };
+}
Propchange:
ant/ivy/core/trunk/src/java/org/apache/ivy/core/cache/ParserSettingsMonitor.java
------------------------------------------------------------------------------
svn:eol-style = native
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=685906&r1=685905&r2=685906&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
Thu Aug 14 07:11:20 2008
@@ -576,6 +576,7 @@
* @param str
* the string in which substitution should be made
* @return the string where all current ivy variables have been
substituted by their value
+ * If the input str doesn't use any variable, the same object is
returned
*/
public String substitute(String str) {
return IvyPatternHelper.substituteVariables(str, variableContainer);
Added:
ant/ivy/core/trunk/test/java/org/apache/ivy/core/cache/ModuleDescriptorMemoryCacheTest.java
URL:
http://svn.apache.org/viewvc/ant/ivy/core/trunk/test/java/org/apache/ivy/core/cache/ModuleDescriptorMemoryCacheTest.java?rev=685906&view=auto
==============================================================================
---
ant/ivy/core/trunk/test/java/org/apache/ivy/core/cache/ModuleDescriptorMemoryCacheTest.java
(added)
+++
ant/ivy/core/trunk/test/java/org/apache/ivy/core/cache/ModuleDescriptorMemoryCacheTest.java
Thu Aug 14 07:11:20 2008
@@ -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.cache;
+
+import java.io.File;
+import java.io.IOException;
+import java.text.ParseException;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+import org.apache.ivy.core.module.descriptor.DefaultModuleDescriptor;
+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.ParserSettings;
+
+public class ModuleDescriptorMemoryCacheTest extends TestCase {
+
+ ModuleDescriptorMemoryCache cache = new ModuleDescriptorMemoryCache(2);
+ ParserSettings ivySettings = new IvySettings();
+ IvySettings ivySettings2 = new IvySettings();
+
+ File url1 = new File("file://cached/file.txt");;
+ File url2 = new File("file://cached/file2.txt");;
+ File url3 = new File("file://cached/file3.txt");;
+
+ ModuleRevisionId mrid1 = ModuleRevisionId.newInstance("org", "name",
"rev");
+ ModuleDescriptor md1 = DefaultModuleDescriptor.newDefaultInstance(mrid1);
+
+ ModuleRevisionId mrid2 = ModuleRevisionId.newInstance("org", "name",
"rev2");
+ ModuleDescriptor md2 = DefaultModuleDescriptor.newDefaultInstance(mrid2);
+
+ ModuleRevisionId mrid3 = ModuleRevisionId.newInstance("org", "name",
"rev3");
+ ModuleDescriptor md3 = DefaultModuleDescriptor.newDefaultInstance(mrid3);
+
+
+ public void testUseModuleDescriptorProviderWhenModuleNotCached() throws
ParseException, IOException {
+ ModuleDescriptorProviderMock providerMock = new
ModuleDescriptorProviderMock(md1);
+ assertEquals(md1 , cache.get(url1,ivySettings , false, providerMock));
+ providerMock.assertCalled();
+ }
+
+
+ public void testCacheResultOfModuleDescriptorProvider() throws
ParseException, IOException {
+ ModuleDescriptorProviderMock providerMock = new
ModuleDescriptorProviderMock(md1);
+ ModuleDescriptorProviderMock providerMock2 = null;
+ assertEquals(md1 , cache.get(url1,ivySettings , false, providerMock));
+ assertEquals(md1 , cache.get(url1,ivySettings , false,
providerMock2));
+ }
+
+
+ public void testValidationClearInvalidatedCache() throws ParseException,
IOException {
+ ModuleDescriptorProviderMock providerMock = new
ModuleDescriptorProviderMock(md1);
+ ModuleDescriptorProviderMock providerMock2 = new
ModuleDescriptorProviderMock(md1);;
+ assertEquals(md1 , cache.get(url1,ivySettings , false, providerMock));
+ assertEquals(md1 , cache.get(url1,ivySettings , true, providerMock2));
+ providerMock2.assertCalled();
+ }
+
+
+ public void testValidationDontClearvalidatedCache() throws ParseException,
IOException {
+ ModuleDescriptorProviderMock providerMock = new
ModuleDescriptorProviderMock(md1);
+ ModuleDescriptorProviderMock providerMock2 = null;
+ assertEquals(md1 , cache.get(url1,ivySettings , true, providerMock));
+ assertEquals(md1 , cache.get(url1,ivySettings , false,
providerMock2));
+ }
+
+
+ public void testSizeIsLimitied() throws ParseException, IOException {
+ ModuleDescriptorProviderMock providerMock = new
ModuleDescriptorProviderMock(md1);
+ ModuleDescriptorProviderMock providerMock1b = new
ModuleDescriptorProviderMock(md1);
+ ModuleDescriptorProviderMock providerMock2 = new
ModuleDescriptorProviderMock(md2);
+ ModuleDescriptorProviderMock providerMock3 = new
ModuleDescriptorProviderMock(md3);
+ cache.get(url1,ivySettings , false, providerMock);
+ cache.get(url2,ivySettings , false, providerMock2);
+ cache.get(url3,ivySettings , false, providerMock3);//adding 1
+ cache.get(url1,ivySettings , false, providerMock1b);//and one has been
removed
+ providerMock1b.assertCalled();
+ }
+
+ public void testLastRecentlyUsedIsFlushedWhenSizeExceed() throws
ParseException, IOException {
+ ModuleDescriptorProviderMock providerMock = new
ModuleDescriptorProviderMock(md1);
+ ModuleDescriptorProviderMock providerMock2 = new
ModuleDescriptorProviderMock(md2);
+ ModuleDescriptorProviderMock providerMock2b = new
ModuleDescriptorProviderMock(md1);
+ ModuleDescriptorProviderMock providerMock3 = new
ModuleDescriptorProviderMock(md3);
+ cache.get(url1,ivySettings , false, providerMock);
+ cache.get(url2,ivySettings , false, providerMock2);
+ cache.get(url1,ivySettings , false, null);
+ cache.get(url3,ivySettings , false, providerMock3);
+ cache.get(url1,ivySettings , false, null);//and one has been removed
+ cache.get(url2,ivySettings , false, providerMock2b);
+ providerMock2b.assertCalled();
+ }
+
+
+ public void testVariableChangeInvalidateEntry() throws ParseException,
IOException {
+ ModuleDescriptorProviderMock providerMock = new
ModuleDescriptorProviderMock(md1);
+ ModuleDescriptorProviderMock providerMock2 = new
ModuleDescriptorProviderMock(md1);
+ assertEquals(md1 , cache.get(url1,ivySettings2 , false, providerMock));
+ ivySettings2.getVariables().setVariable("val", "changedVal", true);
+ assertEquals(md1 , cache.get(url1,ivySettings2 , false,
providerMock2));
+ providerMock2.assertCalled();
+ }
+
+
+ public void testGetStaleDontReadFromCache() throws ParseException,
IOException {
+ ModuleDescriptorProviderMock providerMock = new
ModuleDescriptorProviderMock(md1);
+ ModuleDescriptorProviderMock providerMock2 = new
ModuleDescriptorProviderMock(md2);
+ assertEquals(md1 , cache.get(url1,ivySettings , false, providerMock));
+ assertEquals(md2 , cache.getStale(url1,ivySettings , false,
providerMock2));
+ providerMock2.assertCalled();
+ }
+
+ public void testGetStaleStoreResultInCache() throws ParseException,
IOException {
+ ModuleDescriptorProviderMock providerMock = new
ModuleDescriptorProviderMock(md1);
+ ModuleDescriptorProviderMock providerMock2 = null;
+ assertEquals(md1 , cache.getStale(url1,ivySettings , false,
providerMock));
+ assertEquals(md1 , cache.get(url1,ivySettings , false,
providerMock2));
+ }
+
+ public void testASizeOf0MeansNoCache() throws ParseException, IOException {
+ cache = new ModuleDescriptorMemoryCache(0);
+ ModuleDescriptorProviderMock providerMock = new
ModuleDescriptorProviderMock(md1);
+ ModuleDescriptorProviderMock providerMock2 = new
ModuleDescriptorProviderMock(md1);
+ assertEquals(md1 , cache.get(url1,ivySettings , false, providerMock));
+ assertEquals(md1 , cache.get(url1,ivySettings , false, providerMock2));
+ providerMock2.assertCalled();
+ }
+
+ private static class ModuleDescriptorProviderMock implements
ModuleDescriptorProvider {
+
+ private boolean called = false;
+ private final ModuleDescriptor result;
+
+ public ModuleDescriptorProviderMock(ModuleDescriptor result) {
+ this.result = result;
+ }
+
+ public ModuleDescriptor provideModule(ParserSettings ivySettings, File
descriptorFile,
+ boolean validate) {
+ if (ivySettings!=null) ivySettings.substitute("${val}");
+ called = true;
+ return result;
+ }
+
+ public void assertCalled() {
+ Assert.assertTrue(called);
+ }
+ }
+
+}
Propchange:
ant/ivy/core/trunk/test/java/org/apache/ivy/core/cache/ModuleDescriptorMemoryCacheTest.java
------------------------------------------------------------------------------
svn:eol-style = native