|
18 | 18 |
|
19 | 19 | import static java.util.Objects.requireNonNull; |
20 | 20 |
|
| 21 | +import static com.google.common.base.Throwables.propagate; |
| 22 | + |
| 23 | +import java.io.BufferedReader; |
| 24 | +import java.io.IOException; |
| 25 | +import java.io.InputStreamReader; |
21 | 26 | import java.util.ArrayList; |
22 | 27 | import java.util.List; |
23 | 28 | import java.util.Objects; |
|
37 | 42 | import javax.ws.rs.Produces; |
38 | 43 | import javax.ws.rs.QueryParam; |
39 | 44 | import javax.ws.rs.WebApplicationException; |
| 45 | +import javax.ws.rs.core.Context; |
40 | 46 | import javax.ws.rs.core.MediaType; |
41 | 47 | import javax.ws.rs.core.Response; |
42 | 48 | import javax.xml.bind.annotation.XmlAttribute; |
|
50 | 56 | import com.fasterxml.jackson.annotation.JsonProperty; |
51 | 57 | import com.fasterxml.jackson.core.JsonProcessingException; |
52 | 58 | import com.fasterxml.jackson.databind.ObjectMapper; |
| 59 | +import com.google.common.collect.Lists; |
53 | 60 |
|
| 61 | +import org.glassfish.grizzly.http.server.Request; |
54 | 62 | import org.jclouds.blobstore.BlobStore; |
55 | 63 | import org.jclouds.blobstore.ContainerNotFoundException; |
56 | | - |
57 | 64 | import org.jclouds.blobstore.domain.StorageMetadata; |
| 65 | +import org.jclouds.util.Strings2; |
58 | 66 |
|
59 | 67 | @Singleton |
60 | 68 | @Path("/v1/{account}") |
61 | 69 | public final class AccountResource extends BlobStoreResource { |
| 70 | + private static final Iterable<Character> skipPathEncoding = Lists.charactersOf("/:;="); |
62 | 71 |
|
63 | 72 | @GET |
64 | 73 | public Response getAccount(@NotNull @PathParam("account") String account, |
@@ -111,42 +120,61 @@ public Response headAccount(@NotNull @PathParam("account") String account, |
111 | 120 | @Consumes(MediaType.TEXT_PLAIN) |
112 | 121 | @Produces(MediaType.APPLICATION_JSON) |
113 | 122 | public BulkDeleteResult bulkDelete(@NotNull @PathParam("account") String account, |
114 | | - @QueryParam("bulk-delete") boolean bulkDelete, |
| 123 | + @QueryParam("bulk-delete") String bulkDelete, |
115 | 124 | @HeaderParam("X-Auth-Token") String authToken, |
116 | | - String objectsList) throws JsonProcessingException { |
117 | | - if (!bulkDelete) { |
| 125 | + @Context Request request) throws JsonProcessingException { |
| 126 | + if (bulkDelete == null) { |
118 | 127 | // TODO: Currently this will match the account delete request as well, which we do not implement |
119 | 128 | throw new WebApplicationException(Response.Status.NOT_IMPLEMENTED); |
120 | 129 | } |
121 | 130 |
|
122 | | - if (objectsList == null) { |
123 | | - return new BulkDeleteResult(); |
124 | | - } |
125 | | - String[] objects = objectsList.split("\n"); |
126 | 131 | BlobStore blobStore = getBlobStore(authToken).get(); |
127 | 132 | if (blobStore == null) { |
128 | 133 | throw new WebApplicationException(Response.Status.BAD_REQUEST); |
129 | 134 | } |
| 135 | + |
| 136 | + BufferedReader in = new BufferedReader(new InputStreamReader(request.getInputStream())); |
| 137 | + String line; |
| 138 | + ArrayList<String> objects = new ArrayList<>(); |
| 139 | + |
| 140 | + boolean isTransient = blobStore.getContext().unwrap().getId().equals("transient"); |
| 141 | + try { |
| 142 | + while ((line = in.readLine()) != null) { |
| 143 | + if (isTransient) { |
| 144 | + // jclouds does not escape things correctly |
| 145 | + line = Strings2.urlEncode(line, skipPathEncoding); |
| 146 | + } |
| 147 | + objects.add(line); |
| 148 | + } |
| 149 | + } catch (IOException e) { |
| 150 | + throw propagate(e); |
| 151 | + } |
| 152 | + |
130 | 153 | BulkDeleteResult result = new BulkDeleteResult(); |
131 | 154 | for (String objectContainer : objects) { |
132 | 155 | try { |
133 | | - if (!objectContainer.startsWith("/")) { |
134 | | - result.errors.add(objectContainer); |
135 | | - continue; |
| 156 | + if (objectContainer.startsWith("/")) { |
| 157 | + objectContainer = objectContainer.substring(1); |
136 | 158 | } |
137 | | - int separatorIndex = objectContainer.indexOf("/", 1); |
| 159 | + int separatorIndex = objectContainer.indexOf('/'); |
138 | 160 | if (separatorIndex < 0) { |
139 | 161 | blobStore.deleteContainer(objectContainer.substring(1)); |
140 | 162 | result.numberDeleted += 1; |
141 | 163 | continue; |
142 | 164 | } |
143 | | - String container = objectContainer.substring(1, separatorIndex); |
| 165 | + String container = objectContainer.substring(0, separatorIndex); |
144 | 166 | String object = objectContainer.substring(separatorIndex + 1); |
145 | | - blobStore.removeBlob(container, object); |
146 | | - result.numberDeleted += 1; |
| 167 | + |
| 168 | + if (!blobStore.blobExists(container, object)) { |
| 169 | + result.numberNotFound += 1; |
| 170 | + } else { |
| 171 | + blobStore.removeBlob(container, object); |
| 172 | + result.numberDeleted += 1; |
| 173 | + } |
147 | 174 | } catch (ContainerNotFoundException e) { |
148 | 175 | result.numberNotFound += 1; |
149 | 176 | } catch (Exception e) { |
| 177 | + e.printStackTrace(); |
150 | 178 | result.errors.add(objectContainer); |
151 | 179 | } |
152 | 180 | } |
|
0 commit comments