diff --git a/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/JackrabbitValueFactory.java b/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/JackrabbitValueFactory.java new file mode 100644 index 000000000..712db46d9 --- /dev/null +++ b/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/JackrabbitValueFactory.java @@ -0,0 +1,121 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.jackrabbit.api; + +import javax.jcr.AccessDeniedException; +import javax.jcr.Binary; +import javax.jcr.RepositoryException; +import javax.jcr.ValueFactory; + +import org.apache.jackrabbit.api.binary.BinaryUpload; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.osgi.annotation.versioning.ProviderType; + +/** + * Defines optional functionality that a {@link ValueFactory} may choose to + * provide. A {@link ValueFactory} may also implement this interface without + * supporting all of the capabilities in this interface. Each method of the + * interface describes the behavior of that method if the underlying capability + * is not available. + */ +@ProviderType +public interface JackrabbitValueFactory extends ValueFactory { + /** + * Initiate a transaction to upload binary data directly to a storage + * location. {@link IllegalArgumentException} will be thrown if an upload + * cannot be supported for the required parameters, or if the parameters are + * otherwise invalid. For example, if the value of {@code maxSize} exceeds + * the size limits for a single binary upload for the implementation or the + * service provider, or if the value of {@code maxSize} divided by {@code + * maxParts} exceeds the size limit for an upload or upload part of the + * implementation or the service provider, {@link IllegalArgumentException} + * may be thrown. + *

+ * Each service provider has specific limitations on upload sizes, + * multi-part upload support, part sizes, etc. which can result in {@link + * IllegalArgumentException} being thrown. You should consult the + * documentation for your underlying implementation and your service + * provider for details. + *

+ * If this call is successful, a {@link BinaryUpload} is returned + * which contains the information a client needs to successfully complete + * a direct upload. + * + * @param maxSize The expected maximum size of the binary to be uploaded by + * the client. If the actual size of the binary is known, this + * size should be used; otherwise, the client should make a best + * guess. If a client calls this method with one size and then + * later determines that the guess was too small, the transaction + * should be restarted by calling this method again with the correct + * size. + * @param maxURIs The maximum number of upload URIs that the client can + * accept. The implementation will ensure that an upload of size + * {@code maxSize} can be completed by splitting the value of {@code + * maxSize} into parts, such that the size of the largest part does + * not exceed any known implementation or service provider + * limitations on upload part size and such that the number of parts + * does not exceed the value of {@code maxURIs}. If this is not + * possible, {@link IllegalArgumentException} will be thrown. A + * client may specify -1 for this value, indicating that any number + * of URIs may be returned. + * @return A {@link BinaryUpload} that can be used by the client to complete + * the upload via a call to {@link #completeBinaryUpload(String)}, + * or {@code null} if the implementation does not support the direct + * upload feature. + * @throws IllegalArgumentException if the provided arguments are + * invalid or if a valid upload cannot be completed given the + * provided arguments. + * @throws AccessDeniedException if it is determined that insufficient + * permission exists to perform the upload. + */ + @Nullable + BinaryUpload initiateBinaryUpload(long maxSize, int maxURIs) + throws IllegalArgumentException, AccessDeniedException; + + /** + * Complete a transaction to upload binary data directly to a storage + * location. The client must provide a valid {@code uploadToken} that can + * only be obtained via a previous call to {@link + * #initiateBinaryUpload(long, int)}. If the {@code uploadToken} is + * unreadable or invalid, {@link IllegalArgumentException} will be thrown. + *

+ * Calling this method does not associate the returned {@link Binary} with + * any location in the repository. It is the responsibility of the client + * to do this if desired. + *

+ * The {@code uploadToken} can be obtained from the {@link + * BinaryUpload} returned from a prior call to {@link + * #initiateBinaryUpload(long, int)}. Clients should treat the {@code + * uploadToken} as an immutable string, and should expect that + * implementations will sign the string and verify the signature when this + * method is called. + * + * @param uploadToken A String that is used to identify the direct upload + * transaction. + * @return The uploaded {@link Binary}, or {@code null} if the + * implementation does not support the direct upload feature. + * @throws IllegalArgumentException if the {@code uploadToken} is + * unreadable or invalid. + * @throws RepositoryException if a repository access error occurs. + */ + @Nullable + Binary completeBinaryUpload(@NotNull String uploadToken) + throws IllegalArgumentException, RepositoryException; +} diff --git a/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/binary/BinaryDownload.java b/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/binary/BinaryDownload.java new file mode 100644 index 000000000..04d311bd5 --- /dev/null +++ b/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/binary/BinaryDownload.java @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.jackrabbit.api.binary; + +import java.net.URI; + +import javax.jcr.Binary; +import javax.jcr.RepositoryException; + +import org.jetbrains.annotations.Nullable; +import org.osgi.annotation.versioning.ProviderType; + +/** + * This extension interface provides a mechanism whereby a client can download + * a {@link Binary} directly from a storage location. + */ +@ProviderType +public interface BinaryDownload extends Binary { + /** + * Get a URI for downloading a binary directly from a storage location with + * the provided {@link BinaryDownloadOptions}. This is probably a + * signed URI with a short TTL, although the API does not require it to be + * so. + *

+ * The implementation will attempt to apply the specified {@code + * downloadOptions} to the subsequent download. For example, if the caller + * knows that the URL refers to a specific type of content, the caller can + * specify that content type by setting the MIME type and encoding in the + * {@code downloadOptions}. The caller may also use a default instance + * obtained via {@link BinaryDownloadOptions#DEFAULT} in which case the + * caller is indicating that the default behavior of the service provider is + * acceptable. + * + * @param downloadOptions A {@link BinaryDownloadOptions} instance + * which is used to request specific options on the binary to be + * downloaded. {@link BinaryDownloadOptions#DEFAULT} should be used + * if the caller wishes to accept the service provider's default + * behavior. + * @return A URI for downloading the binary directly, or {@code null} if the + * binary cannot be downloaded directly or if the underlying + * implementation does not support this capability. + * @throws {@link RepositoryException} if an error occurs trying to locate + * the binary. + */ + @Nullable + URI getURI(BinaryDownloadOptions downloadOptions) + throws RepositoryException; +} diff --git a/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/binary/BinaryDownloadOptions.java b/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/binary/BinaryDownloadOptions.java new file mode 100644 index 000000000..66f25f0d0 --- /dev/null +++ b/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/binary/BinaryDownloadOptions.java @@ -0,0 +1,317 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.jackrabbit.api.binary; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.osgi.annotation.versioning.ProviderType; + +/** + * Specifies the options to be used when obtaining a direct download URI via + * {@link BinaryDownload#getURI(BinaryDownloadOptions)}. Setting these options + * allows the caller to instruct the service provider that these options should + * be applied to the response to a request made with the URI returned. + *

+ * To specify download options, obtain a {@link BinaryDownloadOptionsBuilder} + * via the {@link #builder()} method, then specify the options desired and + * get the object via {@link BinaryDownloadOptionsBuilder#build()}. + *

+ * If no options are needed, use {@link BinaryDownloadOptions#DEFAULT} which + * instructs the implementation to use the service provider default behavior. + */ +@ProviderType +public final class BinaryDownloadOptions { + private final String mimeType; + private final String encoding; + private final String fileName; + private final String dispositionType; + + private BinaryDownloadOptions(final String mimeType, + final String encoding, + final String fileName, + final String dispositionType) { + this.mimeType = mimeType; + this.encoding = encoding; + this.fileName = fileName; + this.dispositionType = dispositionType; + } + + /** + * Provides a default instance of this class. Using the default instance + * indicates that the caller is willing to accept the service provider + * default behavior. + */ + public static final BinaryDownloadOptions DEFAULT = + BinaryDownloadOptions.builder().build(); + + /** + * Returns the MIME type that should be assumed for the binary that is to be + * downloaded. This value should be a valid {@code jcr:mimeType}. This + * value can be set by calling {@link + * BinaryDownloadOptionsBuilder#withMimeType(String)} when building an + * instance of this class. + * + * @return A String representation of the MIME type, or {@code null} if no + * MIME type has been specified. + * @see + * JCR 2.0 Repository Model - jcr:mimeType + */ + @Nullable + public final String getMimeType() { return mimeType; } + + /** + * Returns the encoding that should be assumed for the binary that is to be + * downloaded. This value should be a valid {@code jcr:encoding}. This + * value can be set by calling {@link + * BinaryDownloadOptionsBuilder#withEncoding(String)} when building an + * instance of this class. + * + * @return A String representation of the encoding, or {@code null} if no + * encoding has been specified. + * @see + * JCR 2.0 Repository Model - jcr:encoding + */ + @Nullable + public final String getEncoding() { return encoding; } + + /** + * Returns the filename that should be assumed for the binary that is to be + * downloaded. This value can be set by calling {@link + * BinaryDownloadOptionsBuilder#withFileName(String)} when building an + * instance of this class. + * + * @return A String representation of the file name, or {@code null} if no + * file name has been specified. + */ + @Nullable + public final String getFileName() { return fileName; } + + /** + * Returns the disposition type that should be assumed for the binary that + * is to be downloaded. This value can be set by calling {@link + * BinaryDownloadOptionsBuilder#withDispositionTypeInline()} or {@link + * BinaryDownloadOptionsBuilder#withDispositionTypeAttachment()} when + * building an instance of this class. The default value of this setting is + * "attachment". + * + * @return A String representation of the disposition type, or {@code null} + * if no disposition type has been specified. + */ + @Nullable + public final String getDispositionType() { return dispositionType; } + + /** + * Returns a {@link BinaryDownloadOptionsBuilder} instance to be used for + * creating an instance of this class. + * + * @return A builder instance. + */ + @NotNull + public static BinaryDownloadOptionsBuilder builder() { + return new BinaryDownloadOptionsBuilder(); + } + + /** + * Used to build an instance of {@link BinaryDownloadOptions} with the + * options set as desired by the caller. + */ + public static final class BinaryDownloadOptionsBuilder { + private String mimeType = null; + private String encoding = null; + private String fileName = null; + private DispositionType dispositionType = null; + + private BinaryDownloadOptionsBuilder() { } + + /** + * Sets the MIME type of the {@link BinaryDownloadOptions} object to be + * built. This value should be a valid {@code jcr:mimeType}. + *

+ * Calling this method has the effect of instructing the service + * provider to set {@code mimeType} as the MIME type of the content type + * in the {@code Content-Type} header of the response to a request + * issued with a URI obtained by calling {@link + * BinaryDownload#getURI(BinaryDownloadOptions)}. This value can be + * later retrieved by calling {@link + * BinaryDownloadOptions#getMimeType()} on the instance returned from a + * call to {@link #build()}. + *

+ * Note that if the MIME type is text-based, the caller may also wish to + * set the encoding which is done separately. See {@link + * #withEncoding(String)}. + *

+ * The caller should ensure that the MIME type set is valid; the + * implementation does not perform any validation of this setting. + *

+ * If no MIME type is provided, no {@code Content-Type} header will be + * specified to the service provider. + * + * @param mimeType A String representation of the jcr:mimeType. + * @return The calling instance. + * @see + * JCR 2.0 Repository Model - jcr:mimeType + */ + @NotNull + public BinaryDownloadOptionsBuilder withMimeType(@NotNull String mimeType) { + this.mimeType = mimeType; + return this; + } + + /** + * Sets the encoding of the {@link BinaryDownloadOptions} object to be + * built. This value should be a valid {@code jcr:encoding}. + *

+ * Calling this method has the effect of instructing the service + * provider to set {@code encoding} as the encoding of the content type + * in the {@code Content-Type} header of the response to a request + * issued with a URI obtained by calling {@link + * BinaryDownload#getURI(BinaryDownloadOptions)}. This value can be + * later retrieved by calling {@link + * BinaryDownloadOptions#getEncoding()} on the instance returned by a + * call to {@link #build()}. + *

+ * Note that setting the encoding only makes sense if the MIME type has + * also been set to a text-based MIME type. See {@link + * #withMimeType(String)}. + *

+ * The caller should ensure that the proper encoding has been set for + * the MIME type; the implementation does not perform any validation of + * these settings. + * + * @param encoding A String representation of the jcr:encoding. + * @return The calling instance. + * @see + * JCR 2.0 Repository Model - jcr:encoding + */ + @NotNull + public BinaryDownloadOptionsBuilder withEncoding(@NotNull String encoding) { + this.encoding = encoding; + return this; + } + + /** + * Sets the filename of the {@link BinaryDownloadOptions} object to be + * built. + *

+ * Calling this method has the effect of instructing the service + * provider to set {@code fileName} as the filename in the {@code + * Content-Disposition} header of the response to a request issued with + * a URI obtained by calling {@link + * BinaryDownload#getURI(BinaryDownloadOptions)}. This value can be + * later retrieved by calling {@link + * BinaryDownloadOptions#getFileName()} on the instance returned by a + * call to {@link #build()}. + *

+ * If no filename is provided, no {@code Content-Disposition} header + * will be specified to the service provider. + * + * @param fileName A String representation of the filename. + * @return The calling instance. + */ + @NotNull + public BinaryDownloadOptionsBuilder withFileName(@NotNull String fileName) { + this.fileName = fileName; + return this; + } + + /** + * Sets the disposition type of the {@link BinaryDownloadOptions} object + * to be built to {@code inline}. + *

+ * Calling this method has the effect of instructing the service + * provider to set the disposition type in the {@code + * Content-Disposition} header of the response to {@code inline}. This + * value can be later retrieved by calling {@link + * BinaryDownloadOptions#getDispositionType()} on the instance built by + * calling {@link #build()}. + *

+ * If this value is not set, the default value of {@code attachment} + * will be used. + *

+ * Note that a fileName must also be set for the {@code + * Content-Disposition} header to be specified to the service provider. + * See {@link #withFileName(String)}. + * + * @return The calling instance. + */ + @NotNull + public BinaryDownloadOptionsBuilder withDispositionTypeInline() { + dispositionType = DispositionType.INLINE; + return this; + } + + /** + * Sets the disposition type of the {@link BinaryDownloadOptions} object + * to be built to {@code attachment}. + *

+ * Calling this method has the effect of instructing the service + * provider to set the disposition type in the {@code + * Content-Disposition} header of the response to {@code attachment}. + * This value can later be retrieved by calling {@link + * BinaryDownloadOptions#getDispositionType()} on the instance built by + * calling {@link #build()}. + *

+ * If this value is not set, the default value of {@code attachment} + * will be used. + *

+ * Note that a fileName must also be set for the {@code + * Content-Disposition} header to be specified to the service provider. + * See {@link #withFileName(String)}. + * + * @return The calling instance. + */ + @NotNull + public BinaryDownloadOptionsBuilder withDispositionTypeAttachment() { + dispositionType = DispositionType.ATTACHMENT; + return this; + } + + /** + * Construct a {@link BinaryDownloadOptions} instance with the + * properties specified to the builder. + * + * @return A new {@link BinaryDownloadOptions} instance built with the + * properties specified to the builder. + */ + @NotNull + public BinaryDownloadOptions build() { + return new BinaryDownloadOptions(mimeType, + encoding, + fileName, + null != dispositionType ? dispositionType.toString() : null + ); + } + + private enum DispositionType { + INLINE("inline"), + ATTACHMENT("attachment"); + + private final String value; + + DispositionType(final String value) { + this.value = value; + } + + @Override + public String toString() { + return value; + } + } + } +} diff --git a/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/binary/BinaryUpload.java b/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/binary/BinaryUpload.java new file mode 100644 index 000000000..e8414a349 --- /dev/null +++ b/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/binary/BinaryUpload.java @@ -0,0 +1,146 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.jackrabbit.api.binary; + +import java.net.URI; + +import org.apache.jackrabbit.api.JackrabbitValueFactory; +import org.jetbrains.annotations.NotNull; +import org.osgi.annotation.versioning.ProviderType; + +/** + * This extension interface provides a mechanism whereby a client can upload a + * binary directly to a storage location. An object of this type can be + * created by a call to {@link + * JackrabbitValueFactory#initiateBinaryUpload(long, int)} which will return an + * object of this type if the underlying implementation supports direct upload + * functionality. When calling this method, the client indicates the expected + * size of the binary and the number of URIs that it is willing to accept. The + * implementation will attempt to create an instance of this class that is + * suited to enabling the client to complete the upload successfully. + *

+ * Using an instance of this class, a client can then use one or more of the + * included URIs for uploading the binary directly by calling {@link + * #getUploadURIs()} and iterating through the URIs returned. Multi-part + * uploads are supported by the interface, although they may not be supported + * by the underlying implementation. + *

+ * Once a client finishes uploading the binary data, the client must then call + * {@link JackrabbitValueFactory#completeBinaryUpload(String)} to complete the + * upload. This call requires an upload token which can be obtained from an + * instance of this class by calling {@link #getUploadToken()}. + */ +@ProviderType +public interface BinaryUpload { + /** + * Returns an Iterable of URIs that can be used for uploading binary data + * directly to a storage location. The first URI can be used for uploading + * binary data as a single entity, or multiple URIs can be used if the + * client wishes to do multi-part uploads. + *

+ * Clients are not necessarily required to use all of the URIs provided. A + * client may choose to use fewer, or even only one of the URIs. However, + * regardless of the number of URIs used, they must be consumed in sequence. + * For example, if a client wishes to upload a binary in three parts and + * there are five URIs returned, the client must use the first URI to + * upload the first part, the second URI to upload the second part, and + * the third URI to upload the third part. The client is not required to + * use the fourth and fifth URIs. However, using the second URI to upload + * the third part may result in either an upload failure or a corrupted + * upload; likewise, skipping the second URI to use subsequent URIs may + * result in either an upload failure or a corrupted upload. + *

+ * Clients should be aware that some storage providers have limitations on + * the minimum and maximum size of a binary payload for a single upload, so + * clients should take these limitations into account when deciding how many + * of the URIs to use. Underlying implementations may also choose to + * enforce their own limitations. + *

+ * While the API supports multi-part uploading via multiple upload URIs, + * implementations are not required to support multi-part uploading. If the + * underlying implementation does not support multi-part uploading, a single + * URI will be returned regardless of the size of the data being uploaded. + *

+ * Some storage providers also support multi-part uploads by reusing a + * single URI multiple times, in which case the implementation may also + * return a single URI regardless of the size of the data being uploaded. + *

+ * You should consult both the DataStore implementation documentation and + * the storage service provider documentation for details on such matters as + * multi-part upload support, upload minimum and maximum sizes, etc. + * + * @return Iterable of URIs that can be used for uploading directly to a + * storage location. + */ + @NotNull + Iterable getUploadURIs(); + + /** + * The smallest part size a client may upload for a multi-part upload, not + * counting the final part. This is usually either a service provider or + * implementation limitation. + *

+ * Note that the API offers no guarantees that uploading parts of this size + * can successfully complete the requested upload using the URIs provided + * via {@link #getUploadURIs()}. In other words, clients wishing to perform + * a multi-part upload must split the upload into parts of at least this + * size, but the sizes may need to be larger in order to successfully + * complete the upload. + * + * @return The smallest size acceptable for multi-part uploads. + */ + long getMinPartSize(); + + /** + * The largest part size a client may upload for a multi-part upload. This + * is usually either a service provider or implementation limitation. + *

+ * The API guarantees that a client can successfully complete a direct + * upload of the binary data of the requested size using the provided URIs + * by splitting the binary data into parts of the size returned by this + * method. + *

+ * The client is not required to use part sizes of this size; smaller sizes + * may be used so long as they are at least as large as the size returned by + * {@link #getMinPartSize()}. + *

+ * If the binary size specified by a client when calling {@link + * JackrabbitValueFactory#initiateBinaryUpload(long, int)} ends up being + * smaller than the actual size of the binary being uploaded, these API + * guarantees no longer apply, and it may not be possible to complete the + * upload using the URIs provided. In such cases, the client should restart + * the transaction using the correct size. + * + * @return The maximum size of an upload part for multi-part uploads. + */ + long getMaxPartSize(); + + /** + * Returns the upload token to be used in a subsequent call to {@link + * JackrabbitValueFactory#completeBinaryUpload(String)}. This upload token + * is used by the implementation to identify this upload. Clients should + * treat the upload token as an immutable string, as the underlying + * implementation may choose to implement techniques to detect tampering and + * reject the upload if the token is modified. + * + * @return This upload's unique upload token. + */ + @NotNull + String getUploadToken(); +} diff --git a/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/binary/package-info.java b/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/binary/package-info.java new file mode 100644 index 000000000..6e58e945f --- /dev/null +++ b/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/binary/package-info.java @@ -0,0 +1,22 @@ +/* + * 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. + */ +@Version("1.0.0") +package org.apache.jackrabbit.api.binary; + +import org.osgi.annotation.versioning.Version; \ No newline at end of file diff --git a/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/package-info.java b/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/package-info.java index 4ae9eed6d..0c62b5830 100644 --- a/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/package-info.java +++ b/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/package-info.java @@ -18,5 +18,5 @@ /** * Jackrabbit extensions for JCR core interfaces */ -@org.osgi.annotation.versioning.Version("2.4.1") +@org.osgi.annotation.versioning.Version("2.5.0") package org.apache.jackrabbit.api;