diff options
author | Martin Stockhammer <martin_s@apache.org> | 2019-07-28 15:24:13 +0200 |
---|---|---|
committer | Martin Stockhammer <martin_s@apache.org> | 2019-07-28 15:24:13 +0200 |
commit | bb3b074aaf5a2be0d81c950ecf1588fe8efa3316 (patch) | |
tree | 8f165780e4d81cfdb6ed4a73c40fbed3a6f39a69 /archiva-modules/archiva-base/archiva-storage-api | |
parent | 8e4acdc82a875ca32e39eb216b879c002d228de3 (diff) | |
download | archiva-bb3b074aaf5a2be0d81c950ecf1588fe8efa3316.tar.gz archiva-bb3b074aaf5a2be0d81c950ecf1588fe8efa3316.zip |
Refactoring to StorageAsset access
Diffstat (limited to 'archiva-modules/archiva-base/archiva-storage-api')
3 files changed, 380 insertions, 0 deletions
diff --git a/archiva-modules/archiva-base/archiva-storage-api/pom.xml b/archiva-modules/archiva-base/archiva-storage-api/pom.xml new file mode 100644 index 000000000..06c853dda --- /dev/null +++ b/archiva-modules/archiva-base/archiva-storage-api/pom.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <parent> + <artifactId>archiva-base</artifactId> + <groupId>org.apache.archiva</groupId> + <version>3.0.0-SNAPSHOT</version> + </parent> + <modelVersion>4.0.0</modelVersion> + + <artifactId>archiva-storage-api</artifactId> + + <name>Archiva Base :: Repository API</name> + + <properties> + <site.staging.base>${project.parent.parent.basedir}</site.staging.base> + </properties> + + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <configuration> + <systemPropertyVariables> + <basedir>${basedir}</basedir> + </systemPropertyVariables> + </configuration> + </plugin> + </plugins> + </build> + +</project>
\ No newline at end of file diff --git a/archiva-modules/archiva-base/archiva-storage-api/src/main/java/org/apache/archiva/repository/storage/RepositoryStorage.java b/archiva-modules/archiva-base/archiva-storage-api/src/main/java/org/apache/archiva/repository/storage/RepositoryStorage.java new file mode 100644 index 000000000..68ad39b81 --- /dev/null +++ b/archiva-modules/archiva-base/archiva-storage-api/src/main/java/org/apache/archiva/repository/storage/RepositoryStorage.java @@ -0,0 +1,159 @@ +package org.apache.archiva.repository.storage; + +/* + * 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.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.channels.ReadableByteChannel; +import java.nio.channels.WritableByteChannel; +import java.nio.file.CopyOption; +import java.util.function.Consumer; + +/** + * + * This is the low level API to access artifacts in a repository. Each artifact is represented + * by one storage asset. Each asset can be accessed by a path that is independent on the underlying storage + * implementation. Paths always use '/' as path separator. The path is local to the repository and + * is unique for each asset. + * The storage API knows nothing about the repository layout or repository specific metadata. + * If you use this API you must either have knowledge about the specific repository layout or use the structure + * as it is, e.g. for browsing. + * + * The base implementation for the storage uses a directory structure on the local filesystem. + * + * + * It is the decision of the repository type specific implementation, if this API provides access to all elements, that + * is really stored or just a selected view. + * + * Checking access is not part of this API. + */ +public interface RepositoryStorage { + /** + * Returns information about a specific storage asset. + * @param path + * @return + */ + StorageAsset getAsset(String path); + + /** + * Consumes the data and sets a lock for the file during the operation. + * + * @param asset The asset from which the data is consumed. + * @param consumerFunction The consumer that reads the data + * @param readLock If true, a read lock is acquired on the asset. + * @throws IOException + */ + void consumeData(StorageAsset asset, Consumer<InputStream> consumerFunction, boolean readLock) throws IOException; + + /** + * Consumes the data and sets a lock for the file during the operation. + * + * @param asset The asset from which the data is consumed. + * @param consumerFunction The consumer that reads the data + * @param readLock If true, a read lock is acquired on the asset. + * @throws IOException + */ + void consumeDataFromChannel( StorageAsset asset, Consumer<ReadableByteChannel> consumerFunction, boolean readLock) throws IOException; + + /** + * Writes data to the asset using a write lock. + * + * @param asset The asset to which the data is written. + * @param consumerFunction The function that provides the data. + * @param writeLock If true, a write lock is acquired on the destination. + */ + void writeData( StorageAsset asset, Consumer<OutputStream> consumerFunction, boolean writeLock) throws IOException;; + + /** + * Writes data and sets a lock during the operation. + * + * @param asset The asset to which the data is written. + * @param consumerFunction The function that provides the data. + * @param writeLock If true, a write lock is acquired on the destination. + * @throws IOException + */ + void writeDataToChannel( StorageAsset asset, Consumer<WritableByteChannel> consumerFunction, boolean writeLock) throws IOException; + + /** + * Adds a new asset to the underlying storage. + * @param path The path to the asset. + * @param container True, if the asset should be a container, false, if it is a file. + * @return + */ + StorageAsset addAsset(String path, boolean container); + + /** + * Removes the given asset from the storage. + * + * @param asset + * @throws IOException + */ + void removeAsset(StorageAsset asset) throws IOException; + + /** + * Moves the asset to the given location and returns the asset object for the destination. Moves only assets that + * belong to the same storage instance. It will throw a IOException if the assets are from differents storage + * instances. + * + * @param origin The original asset + * @param destination The destination path pointing to the new asset. + * @param copyOptions The copy options. + * @return The asset representation of the moved object. + */ + StorageAsset moveAsset(StorageAsset origin, String destination, CopyOption... copyOptions) throws IOException; + + /** + * Moves the asset to the given location and returns the asset object for the destination. Moves only assets that + * belong to the same storage instance. It will throw a IOException if the assets are from differents storage + * instances. + * * + * @param origin The original asset + * @param destination The destination path. + * @param copyOptions The copy options (e.g. {@link java.nio.file.StandardCopyOption#REPLACE_EXISTING} + * @throws IOException If it was not possible to copy the asset. + */ + void moveAsset(StorageAsset origin, StorageAsset destination, CopyOption... copyOptions) throws IOException; + + /** + * Copies the given asset to the new destination. Copies only assets that belong to the same storage instance. + * It will throw a IOException if the assets are from differents storage instances. + * + * @param origin The original asset + * @param destination The path to the new asset + * @param copyOptions The copy options, e.g. (e.g. {@link java.nio.file.StandardCopyOption#REPLACE_EXISTING} + * @return The asset representation of the copied object + * @throws IOException If it was not possible to copy the asset + */ + StorageAsset copyAsset(StorageAsset origin, String destination, CopyOption... copyOptions) throws IOException; + + /** + * Copies the given asset to the new destination. Copies only assets that belong to the same storage instance. + * It will throw a IOException if the assets are from differents storage instances. + * + * @param origin The original asset + * @param destination The path to the new asset + * @param copyOptions The copy options, e.g. (e.g. {@link java.nio.file.StandardCopyOption#REPLACE_EXISTING} + * @throws IOException If it was not possible to copy the asset + */ + void copyAsset( StorageAsset origin, StorageAsset destination, CopyOption... copyOptions) throws IOException; + + +} diff --git a/archiva-modules/archiva-base/archiva-storage-api/src/main/java/org/apache/archiva/repository/storage/StorageAsset.java b/archiva-modules/archiva-base/archiva-storage-api/src/main/java/org/apache/archiva/repository/storage/StorageAsset.java new file mode 100644 index 000000000..5e6b52987 --- /dev/null +++ b/archiva-modules/archiva-base/archiva-storage-api/src/main/java/org/apache/archiva/repository/storage/StorageAsset.java @@ -0,0 +1,186 @@ +package org.apache.archiva.repository.storage; + +/* + * 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.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.channels.ReadableByteChannel; +import java.nio.channels.WritableByteChannel; +import java.nio.file.Path; +import java.time.Instant; +import java.util.List; + +/** + * A instance of this interface represents information about a specific asset in a repository. + * The asset may be an real artifact, a directory, or a virtual asset. + * + * Each asset has a unique path relative to the repository. + * + * The implementation may read the data directly from the filesystem or underlying storage implementation. + * + * @author Martin Stockhammer <martin_s@apache.org> + */ +public interface StorageAsset +{ + + /** + * Returns the storage this asset belongs to. + * @return + */ + RepositoryStorage getStorage(); + + /** + * Returns the complete path relative to the repository to the given asset. + * + * @return A path starting with '/' that uniquely identifies the asset in the repository. + */ + String getPath(); + + /** + * Returns the name of the asset. It may be just the filename. + * @return + */ + String getName(); + + /** + * Returns the time of the last modification. + * + * @return + */ + Instant getModificationTime(); + + /** + * Returns true, if this asset is a container type and contains further child assets. + * @return + */ + boolean isContainer(); + + /** + * List the child assets. + * + * @return The list of children. If there are no children and if the asset is not a container, a empty list will be returned. + */ + List<StorageAsset> list(); + + /** + * The size in bytes of the asset. If the asset does not have a size, -1 should be returned. + * + * @return The size if the asset has a size, otherwise -1 + */ + long getSize(); + + /** + * Returns the input stream of the artifact content. + * It will throw a IOException, if the stream could not be created. + * Implementations should create a new stream instance for each invocation and make sure that the + * stream is proper closed after usage. + * + * @return The InputStream representing the content of the artifact. + * @throws IOException + */ + InputStream getReadStream() throws IOException; + + /** + * Returns a NIO representation of the data. + * + * @return A channel to the asset data. + * @throws IOException + */ + ReadableByteChannel getReadChannel() throws IOException; + + /** + * + * Returns an output stream where you can write data to the asset. The operation is not locked or synchronized. + * User of this method have to make sure, that the stream is proper closed after usage. + * + * @param replace If true, the original data will be replaced, otherwise the data will be appended. + * @return The OutputStream where the data can be written. + * @throws IOException + */ + OutputStream getWriteStream( boolean replace) throws IOException; + + /** + * Returns a NIO representation of the asset where you can write the data. + * + * @param replace True, if the content should be replaced by the data written to the stream. + * @return The Channel for writing the data. + * @throws IOException + */ + WritableByteChannel getWriteChannel( boolean replace) throws IOException; + + /** + * Replaces the content. The implementation may do an atomic move operation, or keep a backup. If + * the operation fails, the implementation should try to restore the old data, if possible. + * + * The original file may be deleted, if the storage was successful. + * + * @param newData Replaces the data by the content of the given file. + */ + boolean replaceDataFromFile( Path newData) throws IOException; + + /** + * Returns true, if the asset exists. + * + * @return True, if the asset exists, otherwise false. + */ + boolean exists(); + + /** + * Creates the asset in the underlying storage, if it does not exist. + */ + void create() throws IOException; + + /** + * Returns the real path to the asset, if it exist. Not all implementations may implement this method. + * The method throws {@link UnsupportedOperationException}, if and only if {@link #isFileBased()} returns false. + * + * @return The filesystem path to the asset. + * @throws UnsupportedOperationException If the underlying storage is not file based. + */ + Path getFilePath() throws UnsupportedOperationException; + + /** + * Returns true, if the asset can return a file path for the given asset. If this is true, the {@link #getFilePath()} + * will not throw a {@link UnsupportedOperationException} + * + * @return + */ + boolean isFileBased(); + + /** + * Returns true, if there is a parent to this asset. + * @return + */ + boolean hasParent(); + + /** + * Returns the parent of this asset. + * @return The asset, or <code>null</code>, if it does not exist. + */ + StorageAsset getParent(); + + /** + * Returns the asset relative to the given path + * @param toPath + * @return + */ + StorageAsset resolve(String toPath); +} |