git-svn-id: https://svn.apache.org/repos/asf/maven/archiva/trunk@511901 13f79535-47bb-0310-9956-ffa450edef68tags/archiva-0.9-alpha-1
@@ -30,6 +30,15 @@ | |||
<artifactId>archiva-repository-layer</artifactId> | |||
<name>Archiva Repository Interface Layer</name> | |||
<dependencies> | |||
<dependency> | |||
<groupId>org.apache.maven.archiva</groupId> | |||
<artifactId>archiva-common</artifactId> | |||
</dependency> | |||
<dependency> | |||
<groupId>org.codehaus.plexus.cache</groupId> | |||
<artifactId>plexus-cache-ehcache</artifactId> | |||
<version>1.0-alpha-1</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>org.apache.maven</groupId> | |||
<artifactId>maven-artifact</artifactId> |
@@ -1,224 +0,0 @@ | |||
package org.apache.maven.archiva.layer; | |||
/* | |||
* 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. | |||
*/ | |||
import java.util.Iterator; | |||
import java.util.LinkedHashMap; | |||
import java.util.Map; | |||
/** | |||
* Class to implement caching. | |||
*/ | |||
public class Cache | |||
{ | |||
private final Map cache; | |||
private final double cacheHitRatio; | |||
private final int cacheMaxSize; | |||
private long cacheHits; | |||
private long cacheMiss; | |||
/** | |||
* Caches all data and expires only the oldest data when the specified cache hit rate is reached. | |||
*/ | |||
public Cache( double cacheHitRatio ) | |||
{ | |||
this( cacheHitRatio, 0 ); | |||
} | |||
/** | |||
* Caches all data and expires only the oldest data when the maximum cache size is reached | |||
*/ | |||
public Cache( int cacheMaxSize ) | |||
{ | |||
this( (double) 1, cacheMaxSize ); | |||
} | |||
/** | |||
* Caches all data and expires only the oldest data when either the specified cache hit rate is reached | |||
* or the maximum cache size is reached. | |||
*/ | |||
public Cache( double cacheHitRatio, int cacheMaxSize ) | |||
{ | |||
this.cacheHitRatio = cacheHitRatio; | |||
this.cacheMaxSize = cacheMaxSize; | |||
if ( cacheMaxSize > 0 ) | |||
{ | |||
cache = new LinkedHashMap( cacheMaxSize ); | |||
} | |||
else | |||
{ | |||
cache = new LinkedHashMap(); | |||
} | |||
} | |||
/** | |||
* Check if the specified key is already mapped to an object. | |||
* | |||
* @param key the key used to map the cached object | |||
* @return true if the cache contains an object associated with the given key | |||
*/ | |||
public boolean containsKey( Object key ) | |||
{ | |||
boolean contains; | |||
synchronized ( cache ) | |||
{ | |||
contains = cache.containsKey( key ); | |||
if ( contains ) | |||
{ | |||
cacheHits++; | |||
} | |||
else | |||
{ | |||
cacheMiss++; | |||
} | |||
} | |||
return contains; | |||
} | |||
/** | |||
* Check for a cached object and return it if it exists. Returns null when the keyed object is not found | |||
* | |||
* @param key the key used to map the cached object | |||
* @return the object mapped to the given key, or null if no cache object is mapped to the given key | |||
*/ | |||
public Object get( Object key ) | |||
{ | |||
Object retValue = null; | |||
synchronized ( cache ) | |||
{ | |||
if ( cache.containsKey( key ) ) | |||
{ | |||
// remove and put: this promotes it to the top since we use a linked hash map | |||
retValue = cache.remove( key ); | |||
cache.put( key, retValue ); | |||
cacheHits++; | |||
} | |||
else | |||
{ | |||
cacheMiss++; | |||
} | |||
} | |||
return retValue; | |||
} | |||
/** | |||
* Cache the given value and map it using the given key | |||
* | |||
* @param key the object to map the valued object | |||
* @param value the object to cache | |||
*/ | |||
public void put( Object key, Object value ) | |||
{ | |||
// remove and put: this promotes it to the top since we use a linked hash map | |||
synchronized ( cache ) | |||
{ | |||
if ( cache.containsKey( key ) ) | |||
{ | |||
cache.remove( key ); | |||
} | |||
cache.put( key, value ); | |||
} | |||
manageCache(); | |||
} | |||
/** | |||
* Compute for the efficiency of this cache. | |||
* | |||
* @return the ratio of cache hits to the cache misses to queries for cache objects | |||
*/ | |||
public double getHitRate() | |||
{ | |||
synchronized ( cache ) | |||
{ | |||
return cacheHits == 0 && cacheMiss == 0 ? 0 : (double) cacheHits / (double) ( cacheHits + cacheMiss ); | |||
} | |||
} | |||
/** | |||
* Get the total number of cache objects currently cached. | |||
*/ | |||
public int size() | |||
{ | |||
return cache.size(); | |||
} | |||
/** | |||
* Empty the cache and reset the cache hit rate | |||
*/ | |||
public void clear() | |||
{ | |||
synchronized ( cache ) | |||
{ | |||
cacheHits = 0; | |||
cacheMiss = 0; | |||
cache.clear(); | |||
} | |||
} | |||
private void manageCache() | |||
{ | |||
synchronized ( cache ) | |||
{ | |||
Iterator iterator = cache.entrySet().iterator(); | |||
if ( cacheMaxSize == 0 ) | |||
{ | |||
//desired HitRatio is reached, we can trim the cache to conserve memory | |||
if ( cacheHitRatio <= getHitRate() ) | |||
{ | |||
iterator.next(); | |||
iterator.remove(); | |||
} | |||
} | |||
else if ( cache.size() > cacheMaxSize ) | |||
{ | |||
// maximum cache size is reached | |||
while ( cache.size() > cacheMaxSize ) | |||
{ | |||
iterator.next(); | |||
iterator.remove(); | |||
} | |||
} | |||
else | |||
{ | |||
//even though the max has not been reached, the desired HitRatio is already reached, | |||
// so we can trim the cache to conserve memory | |||
if ( cacheHitRatio <= getHitRate() ) | |||
{ | |||
iterator.next(); | |||
iterator.remove(); | |||
} | |||
} | |||
} | |||
} | |||
} |
@@ -21,29 +21,32 @@ package org.apache.maven.archiva.layer; | |||
import org.apache.maven.artifact.Artifact; | |||
import org.apache.maven.artifact.repository.ArtifactRepository; | |||
import org.codehaus.plexus.cache.Cache; | |||
import java.util.List; | |||
/** | |||
* CachedRepositoryQueryLayer | |||
* CachedRepositoryQueryLayer - simple wrapper around another non-cached Repository Query Layer. | |||
* | |||
* @version $Id$ | |||
* @plexus.component role="org.apache.maven.archiva.layer.RepositoryQueryLayer" role-hint="cached" | |||
*/ | |||
public class CachedRepositoryQueryLayer | |||
implements RepositoryQueryLayer | |||
{ | |||
/** | |||
* @plexus.requirement | |||
*/ | |||
private Cache cache; | |||
public static final double CACHE_HIT_RATIO = 0.5; | |||
/** | |||
* @plexus.requirement | |||
*/ | |||
private RepositoryQueryLayer layer; | |||
public CachedRepositoryQueryLayer( RepositoryQueryLayer layer ) | |||
{ | |||
this.layer = layer; | |||
cache = new Cache( CACHE_HIT_RATIO ); | |||
} | |||
public CachedRepositoryQueryLayer( RepositoryQueryLayer layer, Cache cache ) | |||
@@ -52,11 +55,6 @@ public class CachedRepositoryQueryLayer | |||
this.layer = layer; | |||
} | |||
public double getCacheHitRate() | |||
{ | |||
return cache.getHitRate(); | |||
} | |||
public boolean containsArtifact( Artifact artifact ) | |||
{ | |||
boolean artifactFound = true; |
@@ -0,0 +1,74 @@ | |||
package org.apache.maven.archiva.repository; | |||
/* | |||
* 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. | |||
*/ | |||
import java.util.List; | |||
/** | |||
* DefinedRepositories - maintains the list of defined repositories. | |||
* | |||
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a> | |||
* @version $Id$ | |||
*/ | |||
public interface DefinedRepositories | |||
{ | |||
/** | |||
* Get the entire list of repositories. | |||
* | |||
* @return the list of repositories. | |||
*/ | |||
public List getAllRepositories(); | |||
/** | |||
* Get the list of managed (local) repositories. | |||
* | |||
* @return the list of managed (local) repositories. | |||
*/ | |||
public List getManagedRepositories(); | |||
/** | |||
* Get the list of remote repositories. | |||
* | |||
* @return the list of remote repositories. | |||
*/ | |||
public List getRemoteRepositories(); | |||
/** | |||
* Add a repository. | |||
* | |||
* @param repository the repository to add. | |||
*/ | |||
public void addRepository(Repository repository); | |||
/** | |||
* Remove a repository. | |||
* | |||
* @param repository the repository to add. | |||
*/ | |||
public void removeRepository(Repository repository); | |||
/** | |||
* Get a repository using the provided repository key. | |||
* | |||
* @param repositoryKey the repository key to find the repository via. | |||
* @return the repository associated with the provided Repository Key, or null if not found. | |||
*/ | |||
public Repository getRepository( String repositoryKey ); | |||
} |
@@ -0,0 +1,211 @@ | |||
package org.apache.maven.archiva.repository; | |||
/* | |||
* 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. | |||
*/ | |||
import org.apache.maven.artifact.Artifact; | |||
import org.apache.maven.artifact.metadata.ArtifactMetadata; | |||
import org.apache.maven.artifact.repository.ArtifactRepository; | |||
import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy; | |||
import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout; | |||
/** | |||
* Repository | |||
* | |||
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a> | |||
* @version $Id$ | |||
*/ | |||
public class Repository | |||
implements ArtifactRepository | |||
{ | |||
protected String id; | |||
protected String name; | |||
protected String source; | |||
protected RepositoryURL url; | |||
protected ArtifactRepositoryLayout layout; | |||
protected ArtifactRepositoryPolicy releases; | |||
protected ArtifactRepositoryPolicy snapshots; | |||
protected boolean blacklisted; | |||
/* .\ Constructor \.__________________________________________________ */ | |||
/** | |||
* Construct a Repository. | |||
* | |||
* @param id the unique identifier for this repository. | |||
* @param name the name for this repository. | |||
* @param url the base URL for this repository (this should point to the top level URL for the entire repository) | |||
* @param layout the layout technique for this repository. | |||
*/ | |||
public Repository( String id, String name, String url, ArtifactRepositoryLayout layout ) | |||
{ | |||
this.id = id; | |||
this.name = name; | |||
this.url = new RepositoryURL( url ); | |||
this.layout = layout; | |||
} | |||
/* .\ Information \.__________________________________________________ */ | |||
/** | |||
* Get the unique ID for this repository. | |||
* | |||
* @return the unique ID for this repository. | |||
*/ | |||
public String getId() | |||
{ | |||
return id; | |||
} | |||
/** | |||
* Get the Name of this repository. | |||
* This is usually the human readable name for the repository. | |||
* | |||
* @return the name of this repository. | |||
*/ | |||
public String getName() | |||
{ | |||
return name; | |||
} | |||
public String getUrl() | |||
{ | |||
return url.toString(); | |||
} | |||
public void setLayout( ArtifactRepositoryLayout layout ) | |||
{ | |||
this.layout = layout; | |||
} | |||
public ArtifactRepositoryLayout getLayout() | |||
{ | |||
return layout; | |||
} | |||
public void setSource( String source ) | |||
{ | |||
this.source = source; | |||
} | |||
public String getSource() | |||
{ | |||
return source; | |||
} | |||
/* .\ Tasks \.________________________________________________________ */ | |||
public String pathOf( Artifact artifact ) | |||
{ | |||
return getLayout().pathOf( artifact ); | |||
} | |||
/* .\ State \.________________________________________________________ */ | |||
public void setBlacklisted( boolean blacklisted ) | |||
{ | |||
this.blacklisted = blacklisted; | |||
} | |||
public boolean isBlacklisted() | |||
{ | |||
return blacklisted; | |||
} | |||
public boolean isManaged() | |||
{ | |||
return this.url.getProtocol().equals( "file" ); | |||
} | |||
public boolean isRemote() | |||
{ | |||
return !this.url.getProtocol().equals( "file" ); | |||
} | |||
public void setSnapshots( ArtifactRepositoryPolicy snapshots ) | |||
{ | |||
this.snapshots = snapshots; | |||
} | |||
public ArtifactRepositoryPolicy getSnapshots() | |||
{ | |||
return snapshots; | |||
} | |||
public void setReleases( ArtifactRepositoryPolicy releases ) | |||
{ | |||
this.releases = releases; | |||
} | |||
public ArtifactRepositoryPolicy getReleases() | |||
{ | |||
return releases; | |||
} | |||
public boolean equals( Object other ) | |||
{ | |||
return ( other == this || ( ( other instanceof Repository ) && ( (Repository) other ).getId().equals( getId() ) ) ); | |||
} | |||
public int hashCode() | |||
{ | |||
return getId().hashCode(); | |||
} | |||
/* .\ ArtifactRepository Requirements \.______________________________ */ | |||
public String getBasedir() | |||
{ | |||
return url.getPath(); | |||
} | |||
public String getKey() | |||
{ | |||
return getId(); | |||
} | |||
public String getProtocol() | |||
{ | |||
return url.getProtocol(); | |||
} | |||
public boolean isUniqueVersion() | |||
{ | |||
// TODO: Determine Importance | |||
return false; | |||
} | |||
public String pathOfRemoteRepositoryMetadata( ArtifactMetadata artifactMetadata ) | |||
{ | |||
return layout.pathOfRemoteRepositoryMetadata( artifactMetadata ); | |||
} | |||
public String pathOfLocalRepositoryMetadata( ArtifactMetadata metadata, ArtifactRepository repository ) | |||
{ | |||
return layout.pathOfLocalRepositoryMetadata( metadata, repository ); | |||
} | |||
} |
@@ -0,0 +1,52 @@ | |||
package org.apache.maven.archiva.repository; | |||
/* | |||
* 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. | |||
*/ | |||
/** | |||
* RepositoryException | |||
* | |||
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a> | |||
* @version $Id$ | |||
*/ | |||
public class RepositoryException | |||
extends Exception | |||
{ | |||
public RepositoryException() | |||
{ | |||
super(); | |||
} | |||
public RepositoryException( String message, Throwable cause ) | |||
{ | |||
super( message, cause ); | |||
} | |||
public RepositoryException( String message ) | |||
{ | |||
super( message ); | |||
} | |||
public RepositoryException( Throwable cause ) | |||
{ | |||
super( cause ); | |||
} | |||
} |
@@ -0,0 +1,156 @@ | |||
package org.apache.maven.archiva.repository; | |||
/* | |||
* 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. | |||
*/ | |||
/** | |||
* RepositoryURL - Mutable (and protocol forgiving) URL object. | |||
* | |||
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a> | |||
* @version $Id$ | |||
*/ | |||
public class RepositoryURL | |||
{ | |||
private String url; | |||
private String protocol; | |||
private String host; | |||
private String port; | |||
private String username; | |||
private String password; | |||
private String path; | |||
public RepositoryURL( String url ) | |||
{ | |||
this.url = url; | |||
// .\ Parse the URL \.____________________________________________ | |||
int pos; | |||
pos = url.indexOf( "://" ); | |||
if ( pos == ( -1 ) ) | |||
{ | |||
throw new IllegalArgumentException( "Invalid URL, unable to parse protocol:// from " + url ); | |||
} | |||
protocol = url.substring( 0, pos ); | |||
// attempt to find the start of the 'path' | |||
pos = url.indexOf( "/", protocol.length() + 3 ); | |||
// no path specified - ex "http://localhost" | |||
if ( pos == ( -1 ) ) | |||
{ | |||
// set pos to end of string. (needed for 'middle section') | |||
pos = url.length(); | |||
// default path | |||
path = "/"; | |||
} | |||
else | |||
{ | |||
// get actual path. | |||
path = url.substring( pos ); | |||
} | |||
// get the middle section ( username : password @ hostname : port ) | |||
String middle = url.substring( protocol.length() + 3, pos ); | |||
pos = middle.indexOf( '@' ); | |||
// we have an authentication section. | |||
if ( pos > 0 ) | |||
{ | |||
String authentication = middle.substring( 0, pos ); | |||
middle = middle.substring( pos + 1 ); // lop off authentication for host:port search | |||
pos = authentication.indexOf( ':' ); | |||
// we have a password. | |||
if ( pos > 0 ) | |||
{ | |||
username = authentication.substring( 0, pos ); | |||
password = authentication.substring( pos + 1 ); | |||
} | |||
else | |||
{ | |||
username = authentication; | |||
} | |||
} | |||
pos = middle.indexOf( ':' ); | |||
// we have a defined port | |||
if ( pos > 0 ) | |||
{ | |||
host = middle.substring( 0, pos ); | |||
port = middle.substring( pos + 1 ); | |||
} | |||
else | |||
{ | |||
host = middle; | |||
} | |||
} | |||
public String toString() | |||
{ | |||
return url; | |||
} | |||
public String getUsername() | |||
{ | |||
return username; | |||
} | |||
public String getPassword() | |||
{ | |||
return password; | |||
} | |||
public String getHost() | |||
{ | |||
return host; | |||
} | |||
public String getPath() | |||
{ | |||
return path; | |||
} | |||
public String getPort() | |||
{ | |||
return port; | |||
} | |||
public String getProtocol() | |||
{ | |||
return protocol; | |||
} | |||
public String getUrl() | |||
{ | |||
return url; | |||
} | |||
} |
@@ -0,0 +1,41 @@ | |||
package org.apache.maven.archiva.repository.connector; | |||
/* | |||
* 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. | |||
*/ | |||
import org.apache.maven.archiva.repository.Repository; | |||
import java.util.List; | |||
/** | |||
* RepositoryConnector | |||
* | |||
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a> | |||
* @version $Id$ | |||
*/ | |||
public interface RepositoryConnector | |||
{ | |||
public Repository getSourceRepository(); | |||
public Repository getTargetRepository(); | |||
public List getBlacklist(); | |||
public List getWhitelist(); | |||
} |
@@ -1,146 +0,0 @@ | |||
package org.apache.maven.archiva.layer; | |||
/* | |||
* 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. | |||
*/ | |||
import junit.framework.TestCase; | |||
/** | |||
* | |||
*/ | |||
public class CacheTest | |||
extends TestCase | |||
{ | |||
private Cache cache; | |||
private static final double CACHE_HIT_RATIO = 0.5; | |||
private static final double CACHE_HIT_RATIO_THRESHOLD = 0.75; | |||
public void testCacheManagementBasedOnHitsRatio() | |||
{ | |||
cache = new Cache( CACHE_HIT_RATIO ); | |||
newCacheObjectTests(); | |||
String key = "key"; | |||
String value = "value"; | |||
for ( int ctr = 1; ctr < 10; ctr++ ) | |||
{ | |||
cache.put( key + ctr, value + ctr ); | |||
} | |||
while ( cache.getHitRate() < CACHE_HIT_RATIO_THRESHOLD ) | |||
{ | |||
cache.get( "key2" ); | |||
} | |||
cache.put( "key10", "value10" ); | |||
assertNull( "first key must be expired", cache.get( "key1" ) ); | |||
} | |||
public void testCacheManagementBasedOnCacheSize() | |||
{ | |||
cache = new Cache( 9 ); | |||
newCacheObjectTests(); | |||
String key = "key"; | |||
String value = "value"; | |||
for ( int ctr = 1; ctr < 10; ctr++ ) | |||
{ | |||
cache.put( key + ctr, value + ctr ); | |||
} | |||
cache.put( "key10", "value10" ); | |||
assertNull( "first key must be expired", cache.get( "key1" ) ); | |||
assertEquals( "check cache size to be max size", 9, cache.size() ); | |||
} | |||
public void testCacheManagementBasedOnCacheSizeAndHitRate() | |||
{ | |||
cache = new Cache( CACHE_HIT_RATIO, 9 ); | |||
newCacheObjectTests(); | |||
String key = "key"; | |||
String value = "value"; | |||
for ( int ctr = 1; ctr < 5; ctr++ ) | |||
{ | |||
cache.put( key + ctr, value + ctr ); | |||
} | |||
while ( cache.getHitRate() < CACHE_HIT_RATIO ) | |||
{ | |||
cache.get( "key3" ); | |||
} | |||
cache.put( "key10", "value10" ); | |||
assertNull( "first key must be expired", cache.get( "key1" ) ); | |||
while ( cache.getHitRate() >= CACHE_HIT_RATIO ) | |||
{ | |||
cache.get( "key11" ); | |||
} | |||
for ( int ctr = 5; ctr < 10; ctr++ ) | |||
{ | |||
cache.put( key + ctr, value + ctr ); | |||
} | |||
cache.put( "key11", "value11" ); | |||
assertNull( "second key must be expired", cache.get( "key2" ) ); | |||
assertEquals( "check cache size to be max size", 9, cache.size() ); | |||
} | |||
public void testCacheOnRedundantData() | |||
{ | |||
cache = new Cache( CACHE_HIT_RATIO, 9 ); | |||
newCacheObjectTests(); | |||
String key = "key"; | |||
String value = "value"; | |||
for ( int ctr = 1; ctr < 10; ctr++ ) | |||
{ | |||
cache.put( key + ctr, value + ctr ); | |||
} | |||
cache.put( "key1", "value1" ); | |||
cache.put( "key10", "value10" ); | |||
assertNull( "second key must be gone", cache.get( "key2" ) ); | |||
assertEquals( "check cache size to be max size", 9, cache.size() ); | |||
} | |||
private void newCacheObjectTests() | |||
{ | |||
assertEquals( (double) 0, cache.getHitRate(), 0 ); | |||
assertEquals( "check cache size", 0, cache.size() ); | |||
String value = "value"; | |||
String key = "key"; | |||
cache.put( key, value ); | |||
assertEquals( "check cache hit", value, cache.get( key ) ); | |||
assertEquals( (double) 1, cache.getHitRate(), 0 ); | |||
assertEquals( "check cache size", 1, cache.size() ); | |||
assertNull( "check cache miss", cache.get( "none" ) ); | |||
assertEquals( CACHE_HIT_RATIO, cache.getHitRate(), 0 ); | |||
cache.clear(); | |||
assertNull( "check flushed object", cache.get( "key" ) ); | |||
assertEquals( (double) 0, cache.getHitRate(), 0 ); | |||
assertEquals( "check flushed cache size", 0, cache.size() ); | |||
cache.clear(); | |||
} | |||
} |
@@ -1,5 +1,7 @@ | |||
package org.apache.maven.archiva.layer; | |||
import org.codehaus.plexus.cache.Cache; | |||
/* | |||
* Licensed to the Apache Software Foundation (ASF) under one | |||
* or more contributor license agreements. See the NOTICE file | |||
@@ -32,7 +34,7 @@ public class CachedRepositoryQueryLayerTest | |||
{ | |||
super.setUp(); | |||
cache = new Cache( CachedRepositoryQueryLayer.CACHE_HIT_RATIO ); | |||
cache = (Cache) lookup( Cache.ROLE, "test" ); | |||
queryLayer = new CachedRepositoryQueryLayer( new DefaultRepositoryQueryLayer( repository ), cache ); | |||
} | |||
@@ -40,25 +42,16 @@ public class CachedRepositoryQueryLayerTest | |||
public void testUseFileCache() | |||
{ | |||
testContainsArtifactTrue(); | |||
assertEquals( 0, cache.getHitRate(), 0 ); | |||
testContainsArtifactTrue(); | |||
assertEquals( CachedRepositoryQueryLayer.CACHE_HIT_RATIO, cache.getHitRate(), 0 ); | |||
} | |||
public void testUseMetadataCache() | |||
throws Exception | |||
{ | |||
testArtifactVersions(); | |||
assertEquals( 0, cache.getHitRate(), 0 ); | |||
testArtifactVersions(); | |||
assertEquals( CachedRepositoryQueryLayer.CACHE_HIT_RATIO, cache.getHitRate(), 0 ); | |||
} | |||
public void testUseFileCacheOnSnapshot() | |||
{ | |||
testContainsSnapshotArtifactTrue(); | |||
assertEquals( 0, cache.getHitRate(), 0 ); | |||
testContainsSnapshotArtifactTrue(); | |||
assertEquals( CachedRepositoryQueryLayer.CACHE_HIT_RATIO, cache.getHitRate(), 0 ); | |||
} | |||
} |
@@ -0,0 +1,89 @@ | |||
package org.apache.maven.archiva.repository; | |||
/* | |||
* 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. | |||
*/ | |||
import java.net.MalformedURLException; | |||
import junit.framework.TestCase; | |||
/** | |||
* RepositoryURLTest | |||
* | |||
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a> | |||
* @version $Id$ | |||
*/ | |||
public class RepositoryURLTest | |||
extends TestCase | |||
{ | |||
private void assertURL( String actualURL, String protocol, String username, String password, String hostname, | |||
String port, String path ) | |||
{ | |||
RepositoryURL url = new RepositoryURL( actualURL ); | |||
assertEquals( protocol, url.getProtocol() ); | |||
assertEquals( username, url.getUsername() ); | |||
assertEquals( password, url.getPassword() ); | |||
assertEquals( hostname, url.getHost() ); | |||
assertEquals( port, url.getPort() ); | |||
assertEquals( path, url.getPath() ); | |||
} | |||
public void testProtocolHttp() | |||
throws MalformedURLException | |||
{ | |||
assertURL( "http://localhost/path/to/resource.txt", "http", null, null, "localhost", null, | |||
"/path/to/resource.txt" ); | |||
} | |||
public void testProtocolWagonWebdav() | |||
throws MalformedURLException | |||
{ | |||
assertURL( "dav:http://localhost/path/to/resource.txt", "dav:http", null, null, "localhost", null, | |||
"/path/to/resource.txt" ); | |||
} | |||
public void testProtocolHttpWithPort() | |||
throws MalformedURLException | |||
{ | |||
assertURL( "http://localhost:9090/path/to/resource.txt", "http", null, null, "localhost", "9090", | |||
"/path/to/resource.txt" ); | |||
} | |||
public void testProtocolHttpWithUsername() | |||
throws MalformedURLException | |||
{ | |||
assertURL( "http://user@localhost/path/to/resource.txt", "http", "user", null, "localhost", null, | |||
"/path/to/resource.txt" ); | |||
} | |||
public void testProtocolHttpWithUsernamePassword() | |||
throws MalformedURLException | |||
{ | |||
assertURL( "http://user:pass@localhost/path/to/resource.txt", "http", "user", "pass", "localhost", null, | |||
"/path/to/resource.txt" ); | |||
} | |||
public void testProtocolHttpWithUsernamePasswordPort() | |||
throws MalformedURLException | |||
{ | |||
assertURL( "http://user:pass@localhost:9090/path/to/resource.txt", "http", "user", "pass", "localhost", "9090", | |||
"/path/to/resource.txt" ); | |||
} | |||
} |