|
42 | 42 | import io.minio.messages.CompleteMultipartUpload; |
43 | 43 | import io.minio.messages.CopyObjectResult; |
44 | 44 | import io.minio.messages.CreateBucketConfiguration; |
| 45 | +import io.minio.messages.DeleteError; |
| 46 | +import io.minio.messages.DeleteObject; |
| 47 | +import io.minio.messages.DeleteRequest; |
| 48 | +import io.minio.messages.DeleteResult; |
45 | 49 | import io.minio.messages.ErrorResponse; |
46 | 50 | import io.minio.messages.InitiateMultipartUploadResult; |
47 | 51 | import io.minio.messages.Item; |
@@ -1884,6 +1888,160 @@ public void removeObject(String bucketName, String objectName) |
1884 | 1888 | } |
1885 | 1889 |
|
1886 | 1890 |
|
| 1891 | + private List<DeleteError> removeObject(String bucketName, List<DeleteObject> objectList) |
| 1892 | + throws InvalidBucketNameException, NoSuchAlgorithmException, InsufficientDataException, IOException, |
| 1893 | + InvalidKeyException, NoResponseException, XmlPullParserException, ErrorResponseException, |
| 1894 | + InternalException { |
| 1895 | + Map<String,String> queryParamMap = new HashMap<>(); |
| 1896 | + queryParamMap.put("delete", ""); |
| 1897 | + |
| 1898 | + DeleteRequest request = new DeleteRequest(objectList); |
| 1899 | + HttpResponse response = executePost(bucketName, null, null, queryParamMap, request); |
| 1900 | + |
| 1901 | + String bodyContent = ""; |
| 1902 | + // Use scanner to read entire body stream to string. |
| 1903 | + Scanner scanner = new Scanner(response.body().charStream()); |
| 1904 | + try { |
| 1905 | + scanner.useDelimiter("\\A"); |
| 1906 | + if (scanner.hasNext()) { |
| 1907 | + bodyContent = scanner.next(); |
| 1908 | + } |
| 1909 | + } finally { |
| 1910 | + response.body().close(); |
| 1911 | + scanner.close(); |
| 1912 | + } |
| 1913 | + |
| 1914 | + List<DeleteError> errorList = null; |
| 1915 | + |
| 1916 | + bodyContent = bodyContent.trim(); |
| 1917 | + // Check if body content is <Error> message. |
| 1918 | + DeleteError error = new DeleteError(new StringReader(bodyContent)); |
| 1919 | + if (error.code() != null) { |
| 1920 | + // As it is <Error> message, add to error list. |
| 1921 | + errorList = new LinkedList<DeleteError>(); |
| 1922 | + errorList.add(error); |
| 1923 | + } else { |
| 1924 | + // As it is not <Error> message, parse it as <DeleteResult> message. |
| 1925 | + DeleteResult result = new DeleteResult(new StringReader(bodyContent)); |
| 1926 | + errorList = result.errorList(); |
| 1927 | + } |
| 1928 | + |
| 1929 | + return errorList; |
| 1930 | + } |
| 1931 | + |
| 1932 | + |
| 1933 | + /** |
| 1934 | + * Removes multiple objects from a bucket. |
| 1935 | + * |
| 1936 | + * </p><b>Example:</b><br> |
| 1937 | + * <pre>{@code // Create object list for removal. |
| 1938 | + * List<String> objectNames = new LinkedList<String>(); |
| 1939 | + * objectNames.add("my-objectname1"); |
| 1940 | + * objectNames.add("my-objectname2"); |
| 1941 | + * objectNames.add("my-objectname3"); |
| 1942 | + * for (Result<DeleteError> errorResult: minioClient.removeObject("my-bucketname", objectNames)) { |
| 1943 | + * DeleteError error = errorResult.get(); |
| 1944 | + * System.out.println("Failed to remove '" + error.objectName() + "'. Error:" + error.message()); |
| 1945 | + * } }</pre> |
| 1946 | + * |
| 1947 | + * @param bucketName Bucket name. |
| 1948 | + * @param objectNames List of Object names in the bucket. |
| 1949 | + */ |
| 1950 | + public Iterable<Result<DeleteError>> removeObject(final String bucketName, final Iterable<String> objectNames) { |
| 1951 | + return new Iterable<Result<DeleteError>>() { |
| 1952 | + @Override |
| 1953 | + public Iterator<Result<DeleteError>> iterator() { |
| 1954 | + return new Iterator<Result<DeleteError>>() { |
| 1955 | + private Result<DeleteError> error; |
| 1956 | + private Iterator<DeleteError> errorIterator; |
| 1957 | + private boolean completed = false; |
| 1958 | + |
| 1959 | + private synchronized void populate() { |
| 1960 | + List<DeleteError> errorList = null; |
| 1961 | + try { |
| 1962 | + List<DeleteObject> objectList = new LinkedList<DeleteObject>(); |
| 1963 | + int i = 0; |
| 1964 | + for (String objectName: objectNames) { |
| 1965 | + objectList.add(new DeleteObject(objectName)); |
| 1966 | + i++; |
| 1967 | + // Maximum 1000 objects are allowed in a request |
| 1968 | + if (i == 1000) { |
| 1969 | + break; |
| 1970 | + } |
| 1971 | + } |
| 1972 | + |
| 1973 | + if (i == 0) { |
| 1974 | + return; |
| 1975 | + } |
| 1976 | + |
| 1977 | + errorList = removeObject(bucketName, objectList); |
| 1978 | + } catch (InvalidBucketNameException | NoSuchAlgorithmException | InsufficientDataException | IOException |
| 1979 | + | InvalidKeyException | NoResponseException | XmlPullParserException | ErrorResponseException |
| 1980 | + | InternalException e) { |
| 1981 | + this.error = new Result<>(null, e); |
| 1982 | + } finally { |
| 1983 | + if (errorList != null) { |
| 1984 | + this.errorIterator = errorList.iterator(); |
| 1985 | + } else { |
| 1986 | + this.errorIterator = new LinkedList<DeleteError>().iterator(); |
| 1987 | + } |
| 1988 | + } |
| 1989 | + } |
| 1990 | + |
| 1991 | + @Override |
| 1992 | + public boolean hasNext() { |
| 1993 | + if (this.completed) { |
| 1994 | + return false; |
| 1995 | + } |
| 1996 | + |
| 1997 | + if (this.error == null && this.errorIterator == null) { |
| 1998 | + populate(); |
| 1999 | + } |
| 2000 | + |
| 2001 | + if (this.error != null) { |
| 2002 | + return true; |
| 2003 | + } |
| 2004 | + |
| 2005 | + if (this.errorIterator.hasNext()) { |
| 2006 | + return true; |
| 2007 | + } |
| 2008 | + |
| 2009 | + this.completed = true; |
| 2010 | + return false; |
| 2011 | + } |
| 2012 | + |
| 2013 | + @Override |
| 2014 | + public Result<DeleteError> next() { |
| 2015 | + if (this.completed) { |
| 2016 | + throw new NoSuchElementException(); |
| 2017 | + } |
| 2018 | + |
| 2019 | + if (this.error == null && this.errorIterator == null) { |
| 2020 | + populate(); |
| 2021 | + } |
| 2022 | + |
| 2023 | + if (this.error != null) { |
| 2024 | + this.completed = true; |
| 2025 | + return this.error; |
| 2026 | + } |
| 2027 | + |
| 2028 | + if (this.errorIterator.hasNext()) { |
| 2029 | + return new Result<>(this.errorIterator.next(), null); |
| 2030 | + } |
| 2031 | + |
| 2032 | + this.completed = true; |
| 2033 | + throw new NoSuchElementException(); |
| 2034 | + } |
| 2035 | + |
| 2036 | + @Override |
| 2037 | + public void remove() { |
| 2038 | + throw new UnsupportedOperationException(); |
| 2039 | + } |
| 2040 | + }; |
| 2041 | + } |
| 2042 | + }; |
| 2043 | + } |
| 2044 | + |
1887 | 2045 | /** |
1888 | 2046 | * Lists object information in given bucket. |
1889 | 2047 | * |
|
0 commit comments