|
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