Change-Id: I0c52536ebeeb8e71d95c6420f6db7055ff082dfa Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>tags/v4.10.0.201712302008-r
public interface LargeFileRepository { | public interface LargeFileRepository { | ||||
/** | /** | ||||
* Get download action | |||||
* | |||||
* @param id | * @param id | ||||
* id of the object to download | * id of the object to download | ||||
* @return Action for downloading the object | * @return Action for downloading the object | ||||
public Response.Action getDownloadAction(AnyLongObjectId id); | public Response.Action getDownloadAction(AnyLongObjectId id); | ||||
/** | /** | ||||
* Get upload action | |||||
* | |||||
* @param id | * @param id | ||||
* id of the object to upload | * id of the object to upload | ||||
* @param size | * @param size | ||||
public Response.Action getUploadAction(AnyLongObjectId id, long size); | public Response.Action getUploadAction(AnyLongObjectId id, long size); | ||||
/** | /** | ||||
* Get verify action | |||||
* | |||||
* @param id | * @param id | ||||
* id of the object to be verified | * id of the object to be verified | ||||
* @return Action for verifying the object, or {@code null} if the server | * @return Action for verifying the object, or {@code null} if the server | ||||
public @Nullable Response.Action getVerifyAction(AnyLongObjectId id); | public @Nullable Response.Action getVerifyAction(AnyLongObjectId id); | ||||
/** | /** | ||||
* Get size of an object | |||||
* | |||||
* @param id | * @param id | ||||
* id of the object | * id of the object | ||||
* @return length of the object content in bytes, -1 if the object doesn't | * @return length of the object content in bytes, -1 if the object doesn't | ||||
* exist | * exist | ||||
* @throws IOException | |||||
* @throws java.io.IOException | |||||
*/ | */ | ||||
public long getSize(AnyLongObjectId id) throws IOException; | public long getSize(AnyLongObjectId id) throws IOException; | ||||
} | } |
long size; | long size; | ||||
/** | /** | ||||
* Get the <code>oid</code> of this object. | |||||
* | |||||
* @return the object ID. | * @return the object ID. | ||||
*/ | */ | ||||
public String getOid() { | public String getOid() { | ||||
} | } | ||||
/** | /** | ||||
* Get the <code>size</code> of this object. | |||||
* | |||||
* @return the object size. | * @return the object size. | ||||
*/ | */ | ||||
public long getSize() { | public long getSize() { |
* the request | * the request | ||||
* @param path | * @param path | ||||
* the path | * the path | ||||
* | |||||
* @return the large file repository storing large files. | * @return the large file repository storing large files. | ||||
* @throws LfsException | |||||
* @throws org.eclipse.jgit.lfs.errors.LfsException | |||||
* implementations should throw more specific exceptions to | * implementations should throw more specific exceptions to | ||||
* signal which type of error occurred: | * signal which type of error occurred: | ||||
* <dl> | * <dl> | ||||
* <dt>{@link LfsValidationError}</dt> | |||||
* <dt>{@link org.eclipse.jgit.lfs.errors.LfsValidationError}</dt> | |||||
* <dd>when there is a validation error with one or more of the | * <dd>when there is a validation error with one or more of the | ||||
* objects in the request</dd> | * objects in the request</dd> | ||||
* <dt>{@link LfsRepositoryNotFound}</dt> | |||||
* <dt>{@link org.eclipse.jgit.lfs.errors.LfsRepositoryNotFound}</dt> | |||||
* <dd>when the repository does not exist for the user</dd> | * <dd>when the repository does not exist for the user</dd> | ||||
* <dt>{@link LfsRepositoryReadOnly}</dt> | |||||
* <dt>{@link org.eclipse.jgit.lfs.errors.LfsRepositoryReadOnly}</dt> | |||||
* <dd>when the user has read, but not write access. Only | * <dd>when the user has read, but not write access. Only | ||||
* applicable when the operation in the request is "upload"</dd> | * applicable when the operation in the request is "upload"</dd> | ||||
* <dt>{@link LfsRateLimitExceeded}</dt> | |||||
* <dt>{@link org.eclipse.jgit.lfs.errors.LfsRateLimitExceeded}</dt> | |||||
* <dd>when the user has hit a rate limit with the server</dd> | * <dd>when the user has hit a rate limit with the server</dd> | ||||
* <dt>{@link LfsBandwidthLimitExceeded}</dt> | |||||
* <dt>{@link org.eclipse.jgit.lfs.errors.LfsBandwidthLimitExceeded}</dt> | |||||
* <dd>when the bandwidth limit for the user or repository has | * <dd>when the bandwidth limit for the user or repository has | ||||
* been exceeded</dd> | * been exceeded</dd> | ||||
* <dt>{@link LfsInsufficientStorage}</dt> | |||||
* <dt>{@link org.eclipse.jgit.lfs.errors.LfsInsufficientStorage}</dt> | |||||
* <dd>when there is insufficient storage on the server</dd> | * <dd>when there is insufficient storage on the server</dd> | ||||
* <dt>{@link LfsUnavailable}</dt> | |||||
* <dt>{@link org.eclipse.jgit.lfs.errors.LfsUnavailable}</dt> | |||||
* <dd>when LFS is not available</dd> | * <dd>when LFS is not available</dd> | ||||
* <dt>{@link LfsException}</dt> | |||||
* <dt>{@link org.eclipse.jgit.lfs.errors.LfsException}</dt> | |||||
* <dd>when an unexpected internal server error occurred</dd> | * <dd>when an unexpected internal server error occurred</dd> | ||||
* </dl> | * </dl> | ||||
* @since 4.5 | * @since 4.5 | ||||
* the path | * the path | ||||
* @param auth | * @param auth | ||||
* the Authorization HTTP header | * the Authorization HTTP header | ||||
* | |||||
* @return the large file repository storing large files. | * @return the large file repository storing large files. | ||||
* @throws LfsException | |||||
* @throws org.eclipse.jgit.lfs.errors.LfsException | |||||
* implementations should throw more specific exceptions to | * implementations should throw more specific exceptions to | ||||
* signal which type of error occurred: | * signal which type of error occurred: | ||||
* <dl> | * <dl> | ||||
* <dt>{@link LfsValidationError}</dt> | |||||
* <dt>{@link org.eclipse.jgit.lfs.errors.LfsValidationError}</dt> | |||||
* <dd>when there is a validation error with one or more of the | * <dd>when there is a validation error with one or more of the | ||||
* objects in the request</dd> | * objects in the request</dd> | ||||
* <dt>{@link LfsRepositoryNotFound}</dt> | |||||
* <dt>{@link org.eclipse.jgit.lfs.errors.LfsRepositoryNotFound}</dt> | |||||
* <dd>when the repository does not exist for the user</dd> | * <dd>when the repository does not exist for the user</dd> | ||||
* <dt>{@link LfsRepositoryReadOnly}</dt> | |||||
* <dt>{@link org.eclipse.jgit.lfs.errors.LfsRepositoryReadOnly}</dt> | |||||
* <dd>when the user has read, but not write access. Only | * <dd>when the user has read, but not write access. Only | ||||
* applicable when the operation in the request is "upload"</dd> | * applicable when the operation in the request is "upload"</dd> | ||||
* <dt>{@link LfsRateLimitExceeded}</dt> | |||||
* <dt>{@link org.eclipse.jgit.lfs.errors.LfsRateLimitExceeded}</dt> | |||||
* <dd>when the user has hit a rate limit with the server</dd> | * <dd>when the user has hit a rate limit with the server</dd> | ||||
* <dt>{@link LfsBandwidthLimitExceeded}</dt> | |||||
* <dt>{@link org.eclipse.jgit.lfs.errors.LfsBandwidthLimitExceeded}</dt> | |||||
* <dd>when the bandwidth limit for the user or repository has | * <dd>when the bandwidth limit for the user or repository has | ||||
* been exceeded</dd> | * been exceeded</dd> | ||||
* <dt>{@link LfsInsufficientStorage}</dt> | |||||
* <dt>{@link org.eclipse.jgit.lfs.errors.LfsInsufficientStorage}</dt> | |||||
* <dd>when there is insufficient storage on the server</dd> | * <dd>when there is insufficient storage on the server</dd> | ||||
* <dt>{@link LfsUnavailable}</dt> | |||||
* <dt>{@link org.eclipse.jgit.lfs.errors.LfsUnavailable}</dt> | |||||
* <dd>when LFS is not available</dd> | * <dd>when LFS is not available</dd> | ||||
* <dt>{@link LfsException}</dt> | |||||
* <dt>{@link org.eclipse.jgit.lfs.errors.LfsException}</dt> | |||||
* <dd>when an unexpected internal server error occurred</dd> | * <dd>when an unexpected internal server error occurred</dd> | ||||
* </dl> | * </dl> | ||||
* @since 4.7 | * @since 4.7 | ||||
} | } | ||||
} | } | ||||
/** {@inheritDoc} */ | |||||
@Override | @Override | ||||
protected void doPost(HttpServletRequest req, HttpServletResponse res) | protected void doPost(HttpServletRequest req, HttpServletResponse res) | ||||
throws ServletException, IOException { | throws ServletException, IOException { |
private final Path dir; | private final Path dir; | ||||
/** | /** | ||||
* <p>Constructor for FileLfsRepository.</p> | |||||
* | |||||
* @param url | * @param url | ||||
* external URL of this repository | * external URL of this repository | ||||
* @param dir | * @param dir | ||||
* storage directory | * storage directory | ||||
* @throws IOException | |||||
* @throws java.io.IOException | |||||
*/ | */ | ||||
public FileLfsRepository(String url, Path dir) throws IOException { | public FileLfsRepository(String url, Path dir) throws IOException { | ||||
this.url = url; | this.url = url; | ||||
Files.createDirectories(dir); | Files.createDirectories(dir); | ||||
} | } | ||||
/** {@inheritDoc} */ | |||||
@Override | @Override | ||||
public Response.Action getDownloadAction(AnyLongObjectId id) { | public Response.Action getDownloadAction(AnyLongObjectId id) { | ||||
return getAction(id); | return getAction(id); | ||||
} | } | ||||
/** {@inheritDoc} */ | |||||
@Override | @Override | ||||
public Action getUploadAction(AnyLongObjectId id, long size) { | public Action getUploadAction(AnyLongObjectId id, long size) { | ||||
return getAction(id); | return getAction(id); | ||||
} | } | ||||
/** {@inheritDoc} */ | |||||
@Override | @Override | ||||
public @Nullable Action getVerifyAction(AnyLongObjectId id) { | public @Nullable Action getVerifyAction(AnyLongObjectId id) { | ||||
return null; | return null; | ||||
} | } | ||||
/** {@inheritDoc} */ | |||||
@Override | @Override | ||||
public long getSize(AnyLongObjectId id) throws IOException { | public long getSize(AnyLongObjectId id) throws IOException { | ||||
Path p = getPath(id); | Path p = getPath(id); |
private final long timeout; | private final long timeout; | ||||
/** | /** | ||||
* <p>Constructor for FileLfsServlet.</p> | |||||
* | |||||
* @param repository | * @param repository | ||||
* the repository storing the large objects | * the repository storing the large objects | ||||
* @param timeout | * @param timeout | ||||
} | } | ||||
/** | /** | ||||
* Handles object downloads | |||||
* {@inheritDoc} | |||||
* | * | ||||
* @param req | |||||
* servlet request | |||||
* @param rsp | |||||
* servlet response | |||||
* @throws ServletException | |||||
* if a servlet-specific error occurs | |||||
* @throws IOException | |||||
* if an I/O error occurs | |||||
* Handle object downloads | |||||
*/ | */ | ||||
@Override | @Override | ||||
protected void doGet(HttpServletRequest req, | protected void doGet(HttpServletRequest req, | ||||
* servlet response | * servlet response | ||||
* @return object id, or <code>null</code> if the object id could not be | * @return object id, or <code>null</code> if the object id could not be | ||||
* retrieved | * retrieved | ||||
* @throws IOException | |||||
* @throws java.io.IOException | |||||
* if an I/O error occurs | * if an I/O error occurs | ||||
* @since 4.6 | |||||
* @since 4.6 | |||||
*/ | */ | ||||
protected AnyLongObjectId getObjectToTransfer(HttpServletRequest req, | protected AnyLongObjectId getObjectToTransfer(HttpServletRequest req, | ||||
HttpServletResponse rsp) throws IOException { | HttpServletResponse rsp) throws IOException { | ||||
} | } | ||||
/** | /** | ||||
* Handle object uploads | |||||
* {@inheritDoc} | |||||
* | * | ||||
* @param req | |||||
* servlet request | |||||
* @param rsp | |||||
* servlet response | |||||
* @throws ServletException | |||||
* if a servlet-specific error occurs | |||||
* @throws IOException | |||||
* if an I/O error occurs | |||||
* Handle object uploads | |||||
*/ | */ | ||||
@Override | @Override | ||||
protected void doPut(HttpServletRequest req, | protected void doPut(HttpServletRequest req, | ||||
* HTTP status code | * HTTP status code | ||||
* @param message | * @param message | ||||
* error message | * error message | ||||
* @throws IOException | |||||
* @throws java.io.IOException | |||||
* on failure to send the response | * on failure to send the response | ||||
* @since 4.6 | * @since 4.6 | ||||
*/ | */ |
private final ByteBuffer buffer = ByteBuffer.allocateDirect(8192); | private final ByteBuffer buffer = ByteBuffer.allocateDirect(8192); | ||||
/** | /** | ||||
* <p>Constructor for ObjectDownloadListener.</p> | |||||
* | |||||
* @param repository | * @param repository | ||||
* the repository storing large objects | * the repository storing large objects | ||||
* @param context | * @param context | ||||
* the servlet response | * the servlet response | ||||
* @param id | * @param id | ||||
* id of the object to be downloaded | * id of the object to be downloaded | ||||
* @throws IOException | |||||
* @throws java.io.IOException | |||||
*/ | */ | ||||
public ObjectDownloadListener(FileLfsRepository repository, | public ObjectDownloadListener(FileLfsRepository repository, | ||||
AsyncContext context, HttpServletResponse response, | AsyncContext context, HttpServletResponse response, | ||||
} | } | ||||
/** | /** | ||||
* Write file content | |||||
* {@inheritDoc} | |||||
* | * | ||||
* @throws IOException | |||||
* Write file content | |||||
*/ | */ | ||||
@Override | @Override | ||||
public void onWritePossible() throws IOException { | public void onWritePossible() throws IOException { | ||||
} | } | ||||
/** | /** | ||||
* Handle errors | |||||
* {@inheritDoc} | |||||
* | * | ||||
* @param e | |||||
* the cause | |||||
* Handle errors | |||||
*/ | */ | ||||
@Override | @Override | ||||
public void onError(Throwable e) { | public void onError(Throwable e) { |
private final ByteBuffer buffer = ByteBuffer.allocateDirect(8192); | private final ByteBuffer buffer = ByteBuffer.allocateDirect(8192); | ||||
/** | /** | ||||
* Constructor for ObjectUploadListener. | |||||
* | |||||
* @param repository | * @param repository | ||||
* the repository storing large objects | * the repository storing large objects | ||||
* @param context | * @param context | ||||
* a {@link javax.servlet.AsyncContext} object. | |||||
* @param request | * @param request | ||||
* a {@link javax.servlet.http.HttpServletRequest} object. | |||||
* @param response | * @param response | ||||
* a {@link javax.servlet.http.HttpServletResponse} object. | |||||
* @param id | * @param id | ||||
* @throws FileNotFoundException | |||||
* @throws IOException | |||||
* a {@link org.eclipse.jgit.lfs.lib.AnyLongObjectId} object. | |||||
* @throws java.io.FileNotFoundException | |||||
* @throws java.io.IOException | |||||
*/ | */ | ||||
public ObjectUploadListener(FileLfsRepository repository, | public ObjectUploadListener(FileLfsRepository repository, | ||||
AsyncContext context, HttpServletRequest request, | AsyncContext context, HttpServletRequest request, | ||||
} | } | ||||
/** | /** | ||||
* Writes all the received data to the output channel | |||||
* {@inheritDoc} | |||||
* | * | ||||
* @throws IOException | |||||
* Writes all the received data to the output channel | |||||
*/ | */ | ||||
@Override | @Override | ||||
public void onDataAvailable() throws IOException { | public void onDataAvailable() throws IOException { | ||||
} | } | ||||
} | } | ||||
/** | |||||
* @throws IOException | |||||
*/ | |||||
/** {@inheritDoc} */ | |||||
@Override | @Override | ||||
public void onAllDataRead() throws IOException { | public void onAllDataRead() throws IOException { | ||||
close(); | close(); | ||||
} | } | ||||
/** | /** | ||||
* @throws IOException | |||||
* Close resources held by this listener | |||||
* | |||||
* @throws java.io.IOException | |||||
*/ | */ | ||||
protected void close() throws IOException { | protected void close() throws IOException { | ||||
try { | try { | ||||
} | } | ||||
} | } | ||||
/** | |||||
* @param e | |||||
* the exception that caused the problem | |||||
*/ | |||||
/** {@inheritDoc} */ | |||||
@Override | @Override | ||||
public void onError(Throwable e) { | public void onError(Throwable e) { | ||||
try { | try { |
import com.google.gson.JsonSyntaxException; | import com.google.gson.JsonSyntaxException; | ||||
/** | /** | ||||
* Wrapper for {@link Gson} used by LFS servlets. | |||||
* Wrapper for {@link com.google.gson.Gson} used by LFS servlets. | |||||
* | * | ||||
* @since 4.10.0 | |||||
*/ | */ | ||||
public class LfsGson { | public class LfsGson { | ||||
private static final Gson gson = new GsonBuilder() | private static final Gson gson = new GsonBuilder() | ||||
* @param src | * @param src | ||||
* the object for which Json representation is to be created. If | * the object for which Json representation is to be created. If | ||||
* this is a String, it is wrapped in an instance of | * this is a String, it is wrapped in an instance of | ||||
* {@link Error}. | |||||
* {@link org.eclipse.jgit.lfs.server.internal.LfsGson.Error}. | |||||
* @param writer | * @param writer | ||||
* Writer to which the Json representation needs to be written | * Writer to which the Json representation needs to be written | ||||
* @throws JsonIOException | |||||
* @throws com.google.gson.JsonIOException | |||||
* if there was a problem writing to the writer | * if there was a problem writing to the writer | ||||
* @see Gson#toJson(Object, Appendable) | * @see Gson#toJson(Object, Appendable) | ||||
*/ | */ | ||||
* @param classOfT | * @param classOfT | ||||
* specified type to deserialize | * specified type to deserialize | ||||
* @return an Object of type T | * @return an Object of type T | ||||
* @throws JsonIOException | |||||
* @throws com.google.gson.JsonIOException | |||||
* if there was a problem reading from the Reader | * if there was a problem reading from the Reader | ||||
* @throws JsonSyntaxException | |||||
* @throws com.google.gson.JsonSyntaxException | |||||
* if json is not a valid representation for an object of type | * if json is not a valid representation for an object of type | ||||
* @see Gson#fromJson(Reader, java.lang.reflect.Type) | * @see Gson#fromJson(Reader, java.lang.reflect.Type) | ||||
* @param <T> | |||||
* a T object. | |||||
*/ | */ | ||||
public static <T> T fromJson(Reader json, Class<T> classOfT) | public static <T> T fromJson(Reader json, Class<T> classOfT) | ||||
throws JsonSyntaxException, JsonIOException { | throws JsonSyntaxException, JsonIOException { |
public class LfsServerText extends TranslationBundle { | public class LfsServerText extends TranslationBundle { | ||||
/** | /** | ||||
* Get an instance of this translation bundle | |||||
* | |||||
* @return an instance of this translation bundle | * @return an instance of this translation bundle | ||||
*/ | */ | ||||
public static LfsServerText get() { | public static LfsServerText get() { |
private final boolean disableSslVerify; | private final boolean disableSslVerify; | ||||
/** | /** | ||||
* <p>Constructor for S3Config.</p> | |||||
* | |||||
* @param region | * @param region | ||||
* AWS region | * AWS region | ||||
* @param bucket | * @param bucket | ||||
} | } | ||||
/** | /** | ||||
* Get the <code>region</code>. | |||||
* | |||||
* @return Get name of AWS region this bucket resides in | * @return Get name of AWS region this bucket resides in | ||||
*/ | */ | ||||
public String getRegion() { | public String getRegion() { | ||||
} | } | ||||
/** | /** | ||||
* Get the <code>bucket</code>. | |||||
* | |||||
* @return Get S3 storage bucket name | * @return Get S3 storage bucket name | ||||
*/ | */ | ||||
public String getBucket() { | public String getBucket() { | ||||
} | } | ||||
/** | /** | ||||
* Get the <code>storageClass</code>. | |||||
* | |||||
* @return S3 storage class to use for objects stored in this bucket | * @return S3 storage class to use for objects stored in this bucket | ||||
*/ | */ | ||||
public String getStorageClass() { | public String getStorageClass() { | ||||
} | } | ||||
/** | /** | ||||
* Get the <code>accessKey</code>. | |||||
* | |||||
* @return access key for authenticating to AWS | * @return access key for authenticating to AWS | ||||
*/ | */ | ||||
public String getAccessKey() { | public String getAccessKey() { | ||||
} | } | ||||
/** | /** | ||||
* Get the <code>secretKey</code>. | |||||
* | |||||
* @return secret key for authenticating to AWS | * @return secret key for authenticating to AWS | ||||
*/ | */ | ||||
public String getSecretKey() { | public String getSecretKey() { | ||||
} | } | ||||
/** | /** | ||||
* Get the <code>expirationSeconds</code>. | |||||
* | |||||
* @return period in seconds after which requests signed for this bucket | * @return period in seconds after which requests signed for this bucket | ||||
* will expire | * will expire | ||||
*/ | */ |
this.s3Config = config; | this.s3Config = config; | ||||
} | } | ||||
/** {@inheritDoc} */ | |||||
@Override | @Override | ||||
public Response.Action getDownloadAction(AnyLongObjectId oid) { | public Response.Action getDownloadAction(AnyLongObjectId oid) { | ||||
URL endpointUrl = getObjectUrl(oid); | URL endpointUrl = getObjectUrl(oid); | ||||
return a; | return a; | ||||
} | } | ||||
/** {@inheritDoc} */ | |||||
@Override | @Override | ||||
public Response.Action getUploadAction(AnyLongObjectId oid, long size) { | public Response.Action getUploadAction(AnyLongObjectId oid, long size) { | ||||
cacheObjectMetaData(oid, size); | cacheObjectMetaData(oid, size); | ||||
return a; | return a; | ||||
} | } | ||||
/** {@inheritDoc} */ | |||||
@Override | @Override | ||||
public Action getVerifyAction(AnyLongObjectId id) { | public Action getVerifyAction(AnyLongObjectId id) { | ||||
return null; // TODO(ms) implement this | return null; // TODO(ms) implement this | ||||
} | } | ||||
/** {@inheritDoc} */ | |||||
@Override | @Override | ||||
public long getSize(AnyLongObjectId oid) throws IOException { | public long getSize(AnyLongObjectId oid) throws IOException { | ||||
URL endpointUrl = getObjectUrl(oid); | URL endpointUrl = getObjectUrl(oid); |