diff options
author | Brett Porter <brett@apache.org> | 2006-09-05 05:12:31 +0000 |
---|---|---|
committer | Brett Porter <brett@apache.org> | 2006-09-05 05:12:31 +0000 |
commit | d29cdf4ab1f77b962802f92f9d94c707fbb39037 (patch) | |
tree | ce726f6612ff1a2922a5848dc081592434596b96 /archiva-repository-layer | |
parent | f85defbfa5ee994ff735c3630de091e56e23b1ab (diff) | |
download | archiva-d29cdf4ab1f77b962802f92f9d94c707fbb39037.tar.gz archiva-d29cdf4ab1f77b962802f92f9d94c707fbb39037.zip |
[MRM-161] move the query layer to a separate module
git-svn-id: https://svn.apache.org/repos/asf/maven/archiva/trunk@440260 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'archiva-repository-layer')
9 files changed, 644 insertions, 0 deletions
diff --git a/archiva-repository-layer/pom.xml b/archiva-repository-layer/pom.xml new file mode 100644 index 000000000..3b177c22e --- /dev/null +++ b/archiva-repository-layer/pom.xml @@ -0,0 +1,43 @@ +<?xml version="1.0"?> + +<!-- + ~ Copyright 2005-2006 The Apache Software Foundation. + ~ + ~ Licensed 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. + --> + +<project> + <parent> + <artifactId>archiva</artifactId> + <groupId>org.apache.maven.archiva</groupId> + <version>1.0-SNAPSHOT</version> + </parent> + <modelVersion>4.0.0</modelVersion> + <groupId>org.apache.maven.archiva</groupId> + <artifactId>archiva-repository-layer</artifactId> + <name>Archiva Repository Interface Layer</name> + <dependencies> + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-artifact</artifactId> + </dependency> + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-artifact-manager</artifactId> + </dependency> + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-repository-metadata</artifactId> + </dependency> + </dependencies> +</project> diff --git a/archiva-repository-layer/src/main/java/org/apache/maven/archiva/layer/AbstractRepositoryQueryLayer.java b/archiva-repository-layer/src/main/java/org/apache/maven/archiva/layer/AbstractRepositoryQueryLayer.java new file mode 100644 index 000000000..60b0e5bb0 --- /dev/null +++ b/archiva-repository-layer/src/main/java/org/apache/maven/archiva/layer/AbstractRepositoryQueryLayer.java @@ -0,0 +1,106 @@ +package org.apache.maven.archiva.layer; + +/* + * Copyright 2005-2006 The Apache Software Foundation. + * + * Licensed 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.repository.ArtifactRepository; +import org.apache.maven.artifact.repository.metadata.ArtifactRepositoryMetadata; +import org.apache.maven.artifact.repository.metadata.Metadata; +import org.apache.maven.artifact.repository.metadata.Snapshot; +import org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Reader; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.util.List; + +/** + * + */ +public abstract class AbstractRepositoryQueryLayer + implements RepositoryQueryLayer +{ + protected ArtifactRepository repository; + + public boolean containsArtifact( Artifact artifact ) + { + File f = new File( repository.getBasedir(), repository.pathOf( artifact ) ); + return f.exists(); + } + + public boolean containsArtifact( Artifact artifact, Snapshot snapshot ) + { + String artifactPath = getSnapshotArtifactRepositoryPath( artifact, snapshot ); + File artifactFile = new File( artifactPath ); + return artifactFile.exists(); + } + + public List getVersions( Artifact artifact ) + throws RepositoryQueryLayerException + { + Metadata metadata = getMetadata( artifact ); + + return metadata.getVersioning().getVersions(); + } + + protected String getSnapshotArtifactRepositoryPath( Artifact artifact, Snapshot snapshot ) + { + File f = new File( repository.getBasedir(), repository.pathOf( artifact ) ); + String snapshotInfo = artifact.getVersion().replaceFirst( "SNAPSHOT", snapshot.getTimestamp() + "-" + + snapshot.getBuildNumber() + ".pom" ); + File snapshotFile = new File( f.getParentFile(), artifact.getArtifactId() + "-" + snapshotInfo ); + return snapshotFile.getAbsolutePath(); + } + + protected Metadata getMetadata( Artifact artifact ) + throws RepositoryQueryLayerException + { + Metadata metadata; + + ArtifactRepositoryMetadata repositoryMetadata = new ArtifactRepositoryMetadata( artifact ); + String path = repository.pathOfRemoteRepositoryMetadata( repositoryMetadata ); + File metadataFile = new File( repository.getBasedir(), path ); + if ( metadataFile.exists() ) + { + MetadataXpp3Reader reader = new MetadataXpp3Reader(); + try + { + metadata = reader.read( new FileReader( metadataFile ) ); + } + catch ( FileNotFoundException e ) + { + throw new RepositoryQueryLayerException( "Error occurred while attempting to read metadata file", e ); + } + catch ( IOException e ) + { + throw new RepositoryQueryLayerException( "Error occurred while attempting to read metadata file", e ); + } + catch ( XmlPullParserException e ) + { + throw new RepositoryQueryLayerException( "Error occurred while attempting to read metadata file", e ); + } + } + else + { + throw new RepositoryQueryLayerException( "Metadata not found: " + metadataFile.getAbsolutePath() ); + } + + return metadata; + } +} diff --git a/archiva-repository-layer/src/main/java/org/apache/maven/archiva/layer/Cache.java b/archiva-repository-layer/src/main/java/org/apache/maven/archiva/layer/Cache.java new file mode 100644 index 000000000..fc68f9ca6 --- /dev/null +++ b/archiva-repository-layer/src/main/java/org/apache/maven/archiva/layer/Cache.java @@ -0,0 +1,221 @@ +package org.apache.maven.archiva.layer; + +/* + * Copyright 2005-2006 The Apache Software Foundation. + * + * Licensed 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(); + } + } + } + } + +} diff --git a/archiva-repository-layer/src/main/java/org/apache/maven/archiva/layer/CachedRepositoryQueryLayer.java b/archiva-repository-layer/src/main/java/org/apache/maven/archiva/layer/CachedRepositoryQueryLayer.java new file mode 100644 index 000000000..91f9c5ff9 --- /dev/null +++ b/archiva-repository-layer/src/main/java/org/apache/maven/archiva/layer/CachedRepositoryQueryLayer.java @@ -0,0 +1,99 @@ +package org.apache.maven.archiva.layer; + +/* + * Copyright 2005-2006 The Apache Software Foundation. + * + * Licensed 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.repository.ArtifactRepository; +import org.apache.maven.artifact.repository.metadata.Metadata; +import org.apache.maven.artifact.repository.metadata.Snapshot; + + +/** + * + */ +public class CachedRepositoryQueryLayer + extends AbstractRepositoryQueryLayer +{ + private Cache cache; + + public static final double CACHE_HIT_RATIO = 0.5; + + public CachedRepositoryQueryLayer( ArtifactRepository repository ) + { + this.repository = repository; + + cache = new Cache( CACHE_HIT_RATIO ); + } + + public double getCacheHitRate() + { + return cache.getHitRate(); + } + + public boolean containsArtifact( Artifact artifact ) + { + boolean artifactFound = true; + + String artifactPath = repository.getBasedir() + "/" + repository.pathOf( artifact ); + + if ( cache.get( artifactPath ) == null ) + { + artifactFound = super.containsArtifact( artifact ); + if ( artifactFound ) + { + cache.put( artifactPath, artifactPath ); + } + } + + return artifactFound; + } + + public boolean containsArtifact( Artifact artifact, Snapshot snapshot ) + { + boolean artifactFound = true; + + String path = getSnapshotArtifactRepositoryPath( artifact, snapshot ); + + if ( cache.get( path ) == null ) + { + artifactFound = super.containsArtifact( artifact, snapshot ); + if ( artifactFound ) + { + cache.put( path, path ); + } + } + + return artifactFound; + } + + /** + * Override method to utilize the cache + */ + protected Metadata getMetadata( Artifact artifact ) + throws RepositoryQueryLayerException + { + Metadata metadata = (Metadata) cache.get( artifact.getId() ); + + if ( metadata == null ) + { + metadata = super.getMetadata( artifact ); + cache.put( artifact.getId(), metadata ); + } + + return metadata; + } +} diff --git a/archiva-repository-layer/src/main/java/org/apache/maven/archiva/layer/DefaultRepositoryQueryLayer.java b/archiva-repository-layer/src/main/java/org/apache/maven/archiva/layer/DefaultRepositoryQueryLayer.java new file mode 100644 index 000000000..582d5f377 --- /dev/null +++ b/archiva-repository-layer/src/main/java/org/apache/maven/archiva/layer/DefaultRepositoryQueryLayer.java @@ -0,0 +1,31 @@ +package org.apache.maven.archiva.layer; + +/* + * Copyright 2005-2006 The Apache Software Foundation. + * + * Licensed 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.repository.ArtifactRepository; + +/** + * + */ +public class DefaultRepositoryQueryLayer + extends AbstractRepositoryQueryLayer +{ + public DefaultRepositoryQueryLayer( ArtifactRepository repository ) + { + this.repository = repository; + } +} diff --git a/archiva-repository-layer/src/main/java/org/apache/maven/archiva/layer/DefaultRepositoryQueryLayerFactory.java b/archiva-repository-layer/src/main/java/org/apache/maven/archiva/layer/DefaultRepositoryQueryLayerFactory.java new file mode 100644 index 000000000..ebfcd18cf --- /dev/null +++ b/archiva-repository-layer/src/main/java/org/apache/maven/archiva/layer/DefaultRepositoryQueryLayerFactory.java @@ -0,0 +1,35 @@ +package org.apache.maven.archiva.layer; + +/* + * Copyright 2005-2006 The Apache Software Foundation. + * + * Licensed 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.repository.ArtifactRepository; + +/** + * Gets the default implementation of a repository query layer for the given repository. + * + * @author <a href="mailto:brett@apache.org">Brett Porter</a> + * @version $Id:DefaultRepositoryQueryLayerFactory.java 437105 2006-08-26 17:22:22 +1000 (Sat, 26 Aug 2006) brett $ + * @plexus.component role="org.apache.maven.archiva.layer.RepositoryQueryLayerFactory" + */ +public class DefaultRepositoryQueryLayerFactory + implements RepositoryQueryLayerFactory +{ + public RepositoryQueryLayer createRepositoryQueryLayer( ArtifactRepository repository ) + { + return new DefaultRepositoryQueryLayer( repository ); + } +} diff --git a/archiva-repository-layer/src/main/java/org/apache/maven/archiva/layer/RepositoryQueryLayer.java b/archiva-repository-layer/src/main/java/org/apache/maven/archiva/layer/RepositoryQueryLayer.java new file mode 100644 index 000000000..93c57ef1f --- /dev/null +++ b/archiva-repository-layer/src/main/java/org/apache/maven/archiva/layer/RepositoryQueryLayer.java @@ -0,0 +1,37 @@ +package org.apache.maven.archiva.layer; + +/* + * Copyright 2005-2006 The Apache Software Foundation. + * + * Licensed 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.repository.metadata.Snapshot; + +import java.util.List; + +/** + * The transitive and metadata validation reports will need to query the repository for artifacts. + */ +public interface RepositoryQueryLayer +{ + String ROLE = RepositoryQueryLayer.class.getName(); + + boolean containsArtifact( Artifact artifact ); + + boolean containsArtifact( Artifact artifact, Snapshot snapshot ); + + List getVersions( Artifact artifact ) + throws RepositoryQueryLayerException; +} diff --git a/archiva-repository-layer/src/main/java/org/apache/maven/archiva/layer/RepositoryQueryLayerException.java b/archiva-repository-layer/src/main/java/org/apache/maven/archiva/layer/RepositoryQueryLayerException.java new file mode 100644 index 000000000..772bf4666 --- /dev/null +++ b/archiva-repository-layer/src/main/java/org/apache/maven/archiva/layer/RepositoryQueryLayerException.java @@ -0,0 +1,34 @@ +package org.apache.maven.archiva.layer; + +/* + * Copyright 2005-2006 The Apache Software Foundation. + * + * Licensed 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. + */ + +/** + * + */ +public class RepositoryQueryLayerException + extends Exception +{ + public RepositoryQueryLayerException( String message, Throwable cause ) + { + super( message, cause ); + } + + public RepositoryQueryLayerException( String message ) + { + super( message ); + } +} diff --git a/archiva-repository-layer/src/main/java/org/apache/maven/archiva/layer/RepositoryQueryLayerFactory.java b/archiva-repository-layer/src/main/java/org/apache/maven/archiva/layer/RepositoryQueryLayerFactory.java new file mode 100644 index 000000000..61142e937 --- /dev/null +++ b/archiva-repository-layer/src/main/java/org/apache/maven/archiva/layer/RepositoryQueryLayerFactory.java @@ -0,0 +1,38 @@ +package org.apache.maven.archiva.layer; + +/* + * Copyright 2005-2006 The Apache Software Foundation. + * + * Licensed 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.repository.ArtifactRepository; + +/** + * Gets the preferred implementation of a repository query layer for the given repository. + * + * @author <a href="mailto:brett@apache.org">Brett Porter</a> + * @version $Id:RepositoryQueryLayerFactory.java 437105 2006-08-26 17:22:22 +1000 (Sat, 26 Aug 2006) brett $ + */ +public interface RepositoryQueryLayerFactory +{ + String ROLE = RepositoryQueryLayerFactory.class.getName(); + + /** + * Create or obtain a query interface. + * + * @param repository the repository to query + * @return the obtained query layer + */ + RepositoryQueryLayer createRepositoryQueryLayer( ArtifactRepository repository ); +} |