git-svn-id: https://svn.apache.org/repos/asf/maven/archiva/trunk@511901 13f79535-47bb-0310-9956-ffa450edef68tags/archiva-0.9-alpha-1
<artifactId>archiva-repository-layer</artifactId> | <artifactId>archiva-repository-layer</artifactId> | ||||
<name>Archiva Repository Interface Layer</name> | <name>Archiva Repository Interface Layer</name> | ||||
<dependencies> | <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> | <dependency> | ||||
<groupId>org.apache.maven</groupId> | <groupId>org.apache.maven</groupId> | ||||
<artifactId>maven-artifact</artifactId> | <artifactId>maven-artifact</artifactId> |
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(); | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} |
import org.apache.maven.artifact.Artifact; | import org.apache.maven.artifact.Artifact; | ||||
import org.apache.maven.artifact.repository.ArtifactRepository; | import org.apache.maven.artifact.repository.ArtifactRepository; | ||||
import org.codehaus.plexus.cache.Cache; | |||||
import java.util.List; | import java.util.List; | ||||
/** | /** | ||||
* CachedRepositoryQueryLayer | |||||
* CachedRepositoryQueryLayer - simple wrapper around another non-cached Repository Query Layer. | |||||
* | * | ||||
* @version $Id$ | * @version $Id$ | ||||
* @plexus.component role="org.apache.maven.archiva.layer.RepositoryQueryLayer" role-hint="cached" | |||||
*/ | */ | ||||
public class CachedRepositoryQueryLayer | public class CachedRepositoryQueryLayer | ||||
implements RepositoryQueryLayer | implements RepositoryQueryLayer | ||||
{ | { | ||||
/** | |||||
* @plexus.requirement | |||||
*/ | |||||
private Cache cache; | private Cache cache; | ||||
public static final double CACHE_HIT_RATIO = 0.5; | |||||
/** | |||||
* @plexus.requirement | |||||
*/ | |||||
private RepositoryQueryLayer layer; | private RepositoryQueryLayer layer; | ||||
public CachedRepositoryQueryLayer( RepositoryQueryLayer layer ) | public CachedRepositoryQueryLayer( RepositoryQueryLayer layer ) | ||||
{ | { | ||||
this.layer = layer; | this.layer = layer; | ||||
cache = new Cache( CACHE_HIT_RATIO ); | |||||
} | } | ||||
public CachedRepositoryQueryLayer( RepositoryQueryLayer layer, Cache cache ) | public CachedRepositoryQueryLayer( RepositoryQueryLayer layer, Cache cache ) | ||||
this.layer = layer; | this.layer = layer; | ||||
} | } | ||||
public double getCacheHitRate() | |||||
{ | |||||
return cache.getHitRate(); | |||||
} | |||||
public boolean containsArtifact( Artifact artifact ) | public boolean containsArtifact( Artifact artifact ) | ||||
{ | { | ||||
boolean artifactFound = true; | boolean artifactFound = true; |
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 ); | |||||
} |
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 ); | |||||
} | |||||
} |
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 ); | |||||
} | |||||
} |
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; | |||||
} | |||||
} |
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(); | |||||
} |
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(); | |||||
} | |||||
} |
package org.apache.maven.archiva.layer; | package org.apache.maven.archiva.layer; | ||||
import org.codehaus.plexus.cache.Cache; | |||||
/* | /* | ||||
* Licensed to the Apache Software Foundation (ASF) under one | * Licensed to the Apache Software Foundation (ASF) under one | ||||
* or more contributor license agreements. See the NOTICE file | * or more contributor license agreements. See the NOTICE file | ||||
{ | { | ||||
super.setUp(); | super.setUp(); | ||||
cache = new Cache( CachedRepositoryQueryLayer.CACHE_HIT_RATIO ); | |||||
cache = (Cache) lookup( Cache.ROLE, "test" ); | |||||
queryLayer = new CachedRepositoryQueryLayer( new DefaultRepositoryQueryLayer( repository ), cache ); | queryLayer = new CachedRepositoryQueryLayer( new DefaultRepositoryQueryLayer( repository ), cache ); | ||||
} | } | ||||
public void testUseFileCache() | public void testUseFileCache() | ||||
{ | { | ||||
testContainsArtifactTrue(); | testContainsArtifactTrue(); | ||||
assertEquals( 0, cache.getHitRate(), 0 ); | |||||
testContainsArtifactTrue(); | |||||
assertEquals( CachedRepositoryQueryLayer.CACHE_HIT_RATIO, cache.getHitRate(), 0 ); | |||||
} | } | ||||
public void testUseMetadataCache() | public void testUseMetadataCache() | ||||
throws Exception | throws Exception | ||||
{ | { | ||||
testArtifactVersions(); | testArtifactVersions(); | ||||
assertEquals( 0, cache.getHitRate(), 0 ); | |||||
testArtifactVersions(); | |||||
assertEquals( CachedRepositoryQueryLayer.CACHE_HIT_RATIO, cache.getHitRate(), 0 ); | |||||
} | } | ||||
public void testUseFileCacheOnSnapshot() | public void testUseFileCacheOnSnapshot() | ||||
{ | { | ||||
testContainsSnapshotArtifactTrue(); | testContainsSnapshotArtifactTrue(); | ||||
assertEquals( 0, cache.getHitRate(), 0 ); | |||||
testContainsSnapshotArtifactTrue(); | |||||
assertEquals( CachedRepositoryQueryLayer.CACHE_HIT_RATIO, cache.getHitRate(), 0 ); | |||||
} | } | ||||
} | } |
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" ); | |||||
} | |||||
} |