http://git-wip-us.apache.org/repos/asf/jclouds/blob/8505539a/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/domain/Account.java ---------------------------------------------------------------------- diff --git a/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/domain/Account.java b/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/domain/Account.java new file mode 100644 index 0000000..b52907c --- /dev/null +++ b/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/domain/Account.java @@ -0,0 +1,219 @@ +/* + * 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.jclouds.openstack.swift.v1.domain; + +import static com.google.common.base.MoreObjects.toStringHelper; +import static com.google.common.base.Objects.equal; +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Map; +import java.util.Map.Entry; + +import com.google.common.base.MoreObjects.ToStringHelper; +import com.google.common.base.Objects; +import com.google.common.base.Optional; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.Multimap; + +/** + * Represents an Account in OpenStack Object Storage. + * + * @see org.jclouds.openstack.swift.v1.features.AccountApi + */ +public class Account { + + private final long containerCount; + private final long objectCount; + private final long bytesUsed; + private final Map<String, String> metadata; + private final Multimap<String, String> headers; + + // parsed from headers, so ConstructorProperties here would be misleading + protected Account(long containerCount, long objectCount, long bytesUsed, Map<String, String> metadata, + Multimap<String, String> headers) { + this.containerCount = containerCount; + this.objectCount = objectCount; + this.bytesUsed = bytesUsed; + this.metadata = metadata == null ? ImmutableMap.<String, String> of() : metadata; + this.headers = headers == null ? ImmutableMultimap.<String, String> of() : headers; + } + + /** + * @return The count of containers for this account. + */ + public long getContainerCount() { + return containerCount; + } + + /** + * @return The count of objects for this account. + */ + public long getObjectCount() { + return objectCount; + } + + /** + * @return The number of bytes used by this account. + */ + public long getBytesUsed() { + return bytesUsed; + } + + /** + * @return The {@link Optional<String>} temporary URL key for this account. + */ + public Optional<String> getTemporaryUrlKey() { + return Optional.fromNullable(metadata.get("temp-url-key")); + } + + /** + * <h3>NOTE</h3> + * In current swift implementations, headers keys are lower-cased. This means + * characters such as turkish will probably not work out well. + * + * @return a {@code Map<String, String>} containing the account metadata. + */ + public Map<String, String> getMetadata() { + return metadata; + } + + /** + * @return The HTTP headers for this account. + */ + public Multimap<String, String> getHeaders() { + return headers; + } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object instanceof Account) { + Account that = Account.class.cast(object); + return equal(getContainerCount(), that.getContainerCount()) + && equal(getObjectCount(), that.getObjectCount()) + && equal(getBytesUsed(), that.getBytesUsed()) + && equal(getMetadata(), that.getMetadata()); + } else { + return false; + } + } + + @Override + public int hashCode() { + return Objects.hashCode(getContainerCount(), getObjectCount(), getBytesUsed(), getMetadata()); + } + + @Override + public String toString() { + return string().toString(); + } + + protected ToStringHelper string() { + return toStringHelper(this) + .add("containerCount", getContainerCount()) + .add("objectCount", getObjectCount()) + .add("bytesUsed", getBytesUsed()) + .add("metadata", getMetadata()); + } + + public static Builder builder() { + return new Builder(); + } + + public Builder toBuilder() { + return builder().fromAccount(this); + } + + public static class Builder { + protected long containerCount; + protected long objectCount; + protected long bytesUsed; + protected Multimap<String, String> headers = ImmutableMultimap.of(); + protected Map<String, String> metadata = ImmutableMap.of(); + + /** + * @param containerCount the count of containers for this account. + * + * @see Account#getContainerCount() + */ + public Builder containerCount(long containerCount) { + this.containerCount = containerCount; + return this; + } + + /** + * @param objectCount the count of objects for this account. + * + * @see Account#getObjectCount() + */ + public Builder objectCount(long objectCount) { + this.objectCount = objectCount; + return this; + } + + /** + * @param bytesUsed the number of bytes used by this account. + * + * @see Account#getBytesUsed() + */ + public Builder bytesUsed(long bytesUsed) { + this.bytesUsed = bytesUsed; + return this; + } + + /** + * <h3>NOTE</h3> + * This method will lower-case all metadata keys due to a Swift implementation + * decision. + * + * @param metadata the metadata for this account. + * + * @see Account#getMetadata() + */ + public Builder metadata(Map<String, String> metadata) { + ImmutableMap.Builder<String, String> builder = ImmutableMap.<String, String> builder(); + for (Entry<String, String> entry : checkNotNull(metadata, "metadata").entrySet()) { + builder.put(entry.getKey().toLowerCase(), entry.getValue()); + } + this.metadata = builder.build(); + return this; + } + + /** + * @see Account#getHeaders() + */ + public Builder headers(Multimap<String, String> headers) { + this.headers = headers; + return this; + } + + public Account build() { + return new Account(containerCount, objectCount, bytesUsed, metadata, headers); + } + + public Builder fromAccount(Account from) { + return containerCount(from.getContainerCount()) + .objectCount(from.getObjectCount()) + .bytesUsed(from.getBytesUsed()) + .metadata(from.getMetadata()) + .headers(from.getHeaders()); + } + } +}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/8505539a/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/domain/BulkDeleteResponse.java ---------------------------------------------------------------------- diff --git a/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/domain/BulkDeleteResponse.java b/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/domain/BulkDeleteResponse.java new file mode 100644 index 0000000..4f79044 --- /dev/null +++ b/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/domain/BulkDeleteResponse.java @@ -0,0 +1,101 @@ +/* + * 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.jclouds.openstack.swift.v1.domain; + +import static com.google.common.base.MoreObjects.toStringHelper; +import static com.google.common.base.Objects.equal; +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Map; + +import com.google.common.base.MoreObjects.ToStringHelper; +import com.google.common.base.Objects; + +/** + * Represents a response from a Bulk Delete request. + * + * @see org.jclouds.openstack.swift.v1.features.BulkApi + */ +public class BulkDeleteResponse { + public static BulkDeleteResponse create(int deleted, int notFound, Map<String, String> errors) { + return new BulkDeleteResponse(deleted, notFound, errors); + } + + private final int deleted; + private final int notFound; + private final Map<String, String> errors; + + private BulkDeleteResponse(int deleted, int notFound, Map<String, String> errors) { + this.deleted = deleted; + this.notFound = notFound; + this.errors = checkNotNull(errors, "errors"); + } + + /** + * @return The number of files deleted. + * */ + public int getDeleted() { + return deleted; + } + + /** + * @return The number of files not found. + */ + public int getNotFound() { + return notFound; + } + + /** + * @return a {@code Map<String, String>} containing each path that failed + * to be deleted and its corresponding error response. + */ + public Map<String, String> getErrors() { + return errors; + } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object instanceof BulkDeleteResponse) { + BulkDeleteResponse that = BulkDeleteResponse.class.cast(object); + return equal(getDeleted(), that.getDeleted()) + && equal(getNotFound(), that.getNotFound()) + && equal(getErrors(), that.getErrors()); + } else { + return false; + } + } + + @Override + public int hashCode() { + return Objects.hashCode(getDeleted(), getNotFound(), getErrors()); + } + + protected ToStringHelper string() { + return toStringHelper(this) + .add("deleted", getDeleted()) + .add("notFound", getNotFound()) + .add("errors", getErrors()); + } + + @Override + public String toString() { + return string().toString(); + } +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/8505539a/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/domain/Container.java ---------------------------------------------------------------------- diff --git a/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/domain/Container.java b/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/domain/Container.java new file mode 100644 index 0000000..4a31ab7 --- /dev/null +++ b/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/domain/Container.java @@ -0,0 +1,237 @@ +/* + * 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.jclouds.openstack.swift.v1.domain; + +import static com.google.common.base.MoreObjects.toStringHelper; +import static com.google.common.base.Objects.equal; +import static com.google.common.base.Preconditions.checkNotNull; + +import java.beans.ConstructorProperties; +import java.util.Map; +import java.util.Map.Entry; + +import com.google.common.base.MoreObjects.ToStringHelper; +import com.google.common.base.Objects; +import com.google.common.base.Optional; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.Multimap; + +/** + * Represents a Container in OpenStack Object Storage. + * + * @see org.jclouds.openstack.swift.v1.features.ContainerApi + */ +public class Container implements Comparable<Container> { + + private final String name; + private final long objectCount; + private final long bytesUsed; + private final Optional<Boolean> anybodyRead; + private final Map<String, String> metadata; + private final Multimap<String, String> headers; + + @ConstructorProperties({ "name", "count", "bytes", "anybodyRead", "metadata", "headers"}) + protected Container(String name, long objectCount, long bytesUsed, Optional<Boolean> anybodyRead, + Map<String, String> metadata, Multimap<String, String> headers) { + this.name = checkNotNull(name, "name"); + this.objectCount = objectCount; + this.bytesUsed = bytesUsed; + this.anybodyRead = anybodyRead == null ? Optional.<Boolean> absent() : anybodyRead; + this.metadata = metadata == null ? ImmutableMap.<String, String> of() : metadata; + this.headers = headers == null ? ImmutableMultimap.<String, String> of() : headers; + } + + /** + * @return The name of this container. + */ + public String getName() { + return name; + } + + /** + * @return The count of objects for this container. + */ + public long getObjectCount() { + return objectCount; + } + + /** + * @return The number of bytes used by this container. + */ + public long getBytesUsed() { + return bytesUsed; + } + + /** + * Absent except in {@link ContainerApi#get(String) Get Container} commands. + * + * @return true if this container is publicly readable, false otherwise. + * + * @see org.jclouds.openstack.swift.v1.options.CreateContainerOptions#anybodyRead() + */ + public Optional<Boolean> getAnybodyRead() { + return anybodyRead; + } + + /** + * <h3>NOTE</h3> + * In current swift implementations, headers keys are lower-cased. This means + * characters such as turkish will probably not work out well. + * + * @return a {@code Map<String, String>} containing this container's metadata. + */ + public Map<String, String> getMetadata() { + return metadata; + } + + /** + * @return The HTTP headers for this account. + */ + public Multimap<String, String> getHeaders() { + return headers; + } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object instanceof Container) { + final Container that = Container.class.cast(object); + return equal(getName(), that.getName()) + && equal(getObjectCount(), that.getObjectCount()) + && equal(getBytesUsed(), that.getBytesUsed()) + && equal(getMetadata(), that.getMetadata()); + } else { + return false; + } + } + + @Override + public int hashCode() { + return Objects.hashCode(getName(), getObjectCount(), getBytesUsed(), getAnybodyRead(), getMetadata()); + } + + @Override + public String toString() { + return string().toString(); + } + + protected ToStringHelper string() { + return toStringHelper(this).omitNullValues() + .add("name", getName()) + .add("objectCount", getObjectCount()) + .add("bytesUsed", getBytesUsed()) + .add("anybodyRead", getAnybodyRead().orNull()) + .add("metadata", getMetadata()); + } + + @Override + public int compareTo(Container that) { + if (that == null) + return 1; + if (this == that) + return 0; + return this.getName().compareTo(that.getName()); + } + + public static Builder builder() { + return new Builder(); + } + + public Builder toBuilder() { + return builder().fromContainer(this); + } + + public static class Builder { + protected String name; + protected long objectCount; + protected long bytesUsed; + protected Optional<Boolean> anybodyRead = Optional.absent(); + protected Map<String, String> metadata = ImmutableMap.of(); + protected Multimap<String, String> headers = ImmutableMultimap.of(); + + /** + * @see Container#getName() + */ + public Builder name(String name) { + this.name = checkNotNull(name, "name"); + return this; + } + + /** + * @see Container#getObjectCount() + */ + public Builder objectCount(long objectCount) { + this.objectCount = objectCount; + return this; + } + + /** + * @see Container#getBytesUsed() + */ + public Builder bytesUsed(long bytesUsed) { + this.bytesUsed = bytesUsed; + return this; + } + + /** + * @see Container#getAnybodyRead() + */ + public Builder anybodyRead(Boolean anybodyRead) { + this.anybodyRead = Optional.fromNullable(anybodyRead); + return this; + } + + /** + * <h3>NOTE</h3> + * This method will lower-case all metadata keys. + * + * @see Container#getMetadata() + */ + public Builder metadata(Map<String, String> metadata) { + ImmutableMap.Builder<String, String> builder = ImmutableMap.<String, String> builder(); + for (Entry<String, String> entry : checkNotNull(metadata, "metadata").entrySet()) { + builder.put(entry.getKey().toLowerCase(), entry.getValue()); + } + this.metadata = builder.build(); + return this; + } + + /** + * @see Container#getHeaders() + */ + public Builder headers(Multimap<String, String> headers) { + this.headers = headers; + return this; + } + + public Container build() { + return new Container(name, objectCount, bytesUsed, anybodyRead, metadata, headers); + } + + public Builder fromContainer(Container from) { + return name(from.getName()) + .objectCount(from.getObjectCount()) + .bytesUsed(from.getBytesUsed()) + .anybodyRead(from.getAnybodyRead().orNull()) + .metadata(from.getMetadata()) + .headers(from.getHeaders()); + } + } +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/8505539a/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/domain/ExtractArchiveResponse.java ---------------------------------------------------------------------- diff --git a/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/domain/ExtractArchiveResponse.java b/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/domain/ExtractArchiveResponse.java new file mode 100644 index 0000000..7e06e0e --- /dev/null +++ b/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/domain/ExtractArchiveResponse.java @@ -0,0 +1,90 @@ +/* + * 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.jclouds.openstack.swift.v1.domain; + +import static com.google.common.base.MoreObjects.toStringHelper; +import static com.google.common.base.Objects.equal; +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Map; + +import com.google.common.base.MoreObjects.ToStringHelper; +import com.google.common.base.Objects; + +/** + * Represents a response from an Extract Archive request. + * + * @see org.jclouds.openstack.swift.v1.features.BulkApi + */ +public class ExtractArchiveResponse { + public static ExtractArchiveResponse create(int created, Map<String, String> errors) { + return new ExtractArchiveResponse(created, errors); + } + + private final int created; + private final Map<String, String> errors; + + private ExtractArchiveResponse(int created, Map<String, String> errors) { + this.created = created; + this.errors = checkNotNull(errors, "errors"); + } + + /** + * @return The number of files created. + */ + public int getCreated() { + return created; + } + + /** + * @return a {@code Map<String, String>} containing each path that failed + * to be created and its corresponding error response. + */ + public Map<String, String> getErrors() { + return errors; + } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object instanceof ExtractArchiveResponse) { + ExtractArchiveResponse that = ExtractArchiveResponse.class.cast(object); + return equal(getCreated(), that.getCreated()) + && equal(getErrors(), that.getErrors()); + } else { + return false; + } + } + + @Override + public int hashCode() { + return Objects.hashCode(getCreated(), getErrors()); + } + + protected ToStringHelper string() { + return toStringHelper(this) + .add("created", getCreated()) + .add("errors", getErrors()); + } + + @Override + public String toString() { + return string().toString(); + } +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/8505539a/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/domain/ObjectList.java ---------------------------------------------------------------------- diff --git a/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/domain/ObjectList.java b/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/domain/ObjectList.java new file mode 100644 index 0000000..5bc3136 --- /dev/null +++ b/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/domain/ObjectList.java @@ -0,0 +1,57 @@ +/* + * 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.jclouds.openstack.swift.v1.domain; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.List; + +import com.google.common.collect.ForwardingList; + +/** + * Represents a list of objects in a container. + * + * @see Container + * @see SwiftObject + * @see org.jclouds.openstack.swift.v1.features.ObjectApi#list() + */ +public class ObjectList extends ForwardingList<SwiftObject> { + + public static ObjectList create(List<SwiftObject> objects, Container container) { + return new ObjectList(objects, container); + } + + private final List<SwiftObject> objects; + private final Container container; + + protected ObjectList(List<SwiftObject> objects, Container container) { + this.objects = checkNotNull(objects, "objects"); + this.container = checkNotNull(container, "container"); + } + + /** + * @return the parent {@link Container} the objects reside in. + */ + public Container getContainer() { + return container; + } + + @Override + protected List<SwiftObject> delegate() { + return objects; + } +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/8505539a/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/domain/Segment.java ---------------------------------------------------------------------- diff --git a/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/domain/Segment.java b/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/domain/Segment.java new file mode 100644 index 0000000..a5f064f --- /dev/null +++ b/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/domain/Segment.java @@ -0,0 +1,136 @@ +/* + * 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.jclouds.openstack.swift.v1.domain; + +import static com.google.common.base.MoreObjects.toStringHelper; +import static com.google.common.base.Objects.equal; +import static com.google.common.base.Preconditions.checkNotNull; + +import javax.inject.Named; + +import com.google.common.base.MoreObjects.ToStringHelper; +import com.google.common.base.Objects; + +/** + * Represents a single segment of a multi-part upload. + * + * @see org.jclouds.openstack.swift.v1.features.StaticLargeObjectApi + */ +public class Segment { + + private final String path; + private final String etag; + @Named("size_bytes") + private final long sizeBytes; + + private Segment(String path, String etag, long sizeBytes) { + this.path = checkNotNull(path, "path"); + this.etag = checkNotNull(etag, "etag of %s", path); + this.sizeBytes = checkNotNull(sizeBytes, "sizeBytes of %s", path); + } + + /** + * @return The container and object name in the format: {@code <container-name>/<object-name>} + */ + public String getPath() { + return path; + } + + /** + * @return The ETag of the content of the segment object. + */ + public String getETag() { + return etag; + } + + /** + * @return The size of the segment object. + */ + public long getSizeBytes() { + return sizeBytes; + } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object instanceof Segment) { + Segment that = Segment.class.cast(object); + return equal(getPath(), that.getPath()) + && equal(getETag(), that.getETag()) + && equal(getSizeBytes(), that.getSizeBytes()); + } else { + return false; + } + } + + @Override + public int hashCode() { + return Objects.hashCode(getPath(), getETag(), getSizeBytes()); + } + + @Override + public String toString() { + return string().toString(); + } + + protected ToStringHelper string() { + return toStringHelper(this) + .add("path", getPath()) + .add("etag", getETag()) + .add("sizeBytes", getSizeBytes()); + } + + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + protected String path; + protected String etag; + protected long sizeBytes; + + /** + * @see Segment#getPath() + */ + public Builder path(String path) { + this.path = path; + return this; + } + + /** + * @see Segment#getEtag() + */ + public Builder etag(String etag) { + this.etag = etag; + return this; + } + + /** + * @see Segment#getSizeBytes() + */ + public Builder sizeBytes(long sizeBytes) { + this.sizeBytes = sizeBytes; + return this; + } + + public Segment build() { + return new Segment(path, etag, sizeBytes); + } + } +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/8505539a/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/domain/SwiftObject.java ---------------------------------------------------------------------- diff --git a/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/domain/SwiftObject.java b/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/domain/SwiftObject.java new file mode 100644 index 0000000..2184ff2 --- /dev/null +++ b/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/domain/SwiftObject.java @@ -0,0 +1,267 @@ +/* + * 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.jclouds.openstack.swift.v1.domain; + +import static com.google.common.base.MoreObjects.toStringHelper; +import static com.google.common.base.Objects.equal; +import static com.google.common.base.Preconditions.checkNotNull; + +import java.net.URI; +import java.util.Date; +import java.util.Map; +import java.util.Map.Entry; + +import org.jclouds.io.Payload; + +import com.google.common.base.MoreObjects.ToStringHelper; +import com.google.common.base.Objects; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.Multimap; + +/** + * Represents an object in OpenStack Object Storage. + * + * + * @see ObjectApi + */ +public class SwiftObject implements Comparable<SwiftObject> { + + private final String name; + private final URI uri; + private final String etag; + private final Date lastModified; + private final Multimap<String, String> headers; + private final Map<String, String> metadata; + private final Payload payload; + + protected SwiftObject(String name, URI uri, String etag, Date lastModified, + Multimap<String, String> headers, Map<String, String> metadata, Payload payload) { + this.name = checkNotNull(name, "name"); + this.uri = checkNotNull(uri, "uri of %s", uri); + this.etag = checkNotNull(etag, "etag of %s", name).replace("\"", ""); + this.lastModified = checkNotNull(lastModified, "lastModified of %s", name); + this.headers = headers == null ? ImmutableMultimap.<String, String> of() : checkNotNull(headers, "headers of %s", name); + this.metadata = metadata == null ? ImmutableMap.<String, String> of() : metadata; + this.payload = checkNotNull(payload, "payload of %s", name); + } + + /** + * @return The name of this object. + */ + public String getName() { + return name; + } + + /** + * @return The {@link URI} for this object. + */ + public URI getUri() { + return uri; + } + + /** + * @return The ETag of the content of this object. + * @deprecated Please use {@link #getETag()} as this method will be removed in jclouds 1.8. + */ + public String getEtag() { + return etag; + } + + /** + * @return The ETag of the content of this object. + */ + public String getETag() { + return etag; + } + + /** + * @return The {@link Date} that this object was last modified. + */ + public Date getLastModified() { + return lastModified; + } + + /** + * @return The HTTP headers for this object. + */ + public Multimap<String, String> getHeaders() { + return headers; + } + + /** + * <h3>NOTE</h3> + * In current swift implementations, headers keys are lower-cased. This means + * characters such as turkish will probably not work out well. + * + * @return a {@code Map<String, String>} containing this object's metadata. The map is empty + * except in {@link ObjectApi#head(String) GetObjectMetadata} or + * {@link ObjectApi#get(String) GetObject} commands. + */ + public Map<String, String> getMetadata() { + return metadata; + } + + /** + * <h3>NOTE</h3> + * The object will only have a {@link Payload#getInput()} when retrieved via the + * {@link ObjectApi#get(String) GetObject} command. + * + * @return The {@link Payload} for this object. + */ + public Payload getPayload() { + return payload; + } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object instanceof SwiftObject) { + final SwiftObject that = SwiftObject.class.cast(object); + return equal(getName(), that.getName()) + && equal(getUri(), that.getUri()) + && equal(getETag(), that.getETag()); + } else { + return false; + } + } + + @Override + public int hashCode() { + return Objects.hashCode(getName(), getUri(), getETag()); + } + + @Override + public String toString() { + return string().toString(); + } + + protected ToStringHelper string() { + return toStringHelper(this) + .add("name", getName()) + .add("uri", getUri()) + .add("etag", getETag()) + .add("lastModified", getLastModified()) + .add("metadata", getMetadata()); + } + + @Override + public int compareTo(SwiftObject that) { + if (that == null) + return 1; + if (this == that) + return 0; + return this.getName().compareTo(that.getName()); + } + + public static Builder builder() { + return new Builder(); + } + + public Builder toBuilder() { + return builder().fromObject(this); + } + + public static class Builder { + protected String name; + protected URI uri; + protected String etag; + protected Date lastModified; + protected Payload payload; + protected Multimap<String, String> headers = ImmutableMultimap.of(); + protected Map<String, String> metadata = ImmutableMap.of(); + + /** + * @see SwiftObject#getName() + */ + public Builder name(String name) { + this.name = checkNotNull(name, "name"); + return this; + } + + /** + * @see SwiftObject#getUri() + */ + public Builder uri(URI uri) { + this.uri = checkNotNull(uri, "uri"); + return this; + } + + /** + * @see SwiftObject#getETag() + */ + public Builder etag(String etag) { + this.etag = etag; + return this; + } + + /** + * @see SwiftObject#getLastModified() + */ + public Builder lastModified(Date lastModified) { + this.lastModified = lastModified; + return this; + } + + /** + * @see SwiftObject#getPayload() + */ + public Builder payload(Payload payload) { + this.payload = payload; + return this; + } + + /** + * @see SwiftObject#getHeaders() + */ + public Builder headers(Multimap<String, String> headers) { + this.headers = headers; + return this; + } + + /** + * Will lower-case all metadata keys due to a swift implementation + * decision. + * + * @see SwiftObject#getMetadata() + */ + public Builder metadata(Map<String, String> metadata) { + ImmutableMap.Builder<String, String> builder = ImmutableMap.<String, String> builder(); + for (Entry<String, String> entry : checkNotNull(metadata, "metadata").entrySet()) { + builder.put(entry.getKey().toLowerCase(), entry.getValue()); + } + this.metadata = builder.build(); + return this; + } + + public SwiftObject build() { + return new SwiftObject(name, uri, etag, lastModified, headers, metadata, payload); + } + + public Builder fromObject(SwiftObject from) { + return name(from.getName()) + .uri(from.getUri()) + .etag(from.getETag()) + .lastModified(from.getLastModified()) + .headers(from.getHeaders()) + .metadata(from.getMetadata()) + .payload(from.getPayload()); + } + } +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/8505539a/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/features/AccountApi.java ---------------------------------------------------------------------- diff --git a/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/features/AccountApi.java b/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/features/AccountApi.java new file mode 100644 index 0000000..c9d5b9d --- /dev/null +++ b/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/features/AccountApi.java @@ -0,0 +1,111 @@ +/* + * 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.jclouds.openstack.swift.v1.features; + +import static javax.ws.rs.core.MediaType.APPLICATION_JSON; +import static org.jclouds.openstack.swift.v1.reference.SwiftHeaders.ACCOUNT_TEMPORARY_URL_KEY; + +import java.util.Map; + +import javax.inject.Named; +import javax.ws.rs.Consumes; +import javax.ws.rs.HEAD; +import javax.ws.rs.HeaderParam; +import javax.ws.rs.POST; + +import org.jclouds.Fallbacks.FalseOnNotFoundOr404; +import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest; +import org.jclouds.openstack.swift.v1.binders.BindMetadataToHeaders.BindAccountMetadataToHeaders; +import org.jclouds.openstack.swift.v1.binders.BindMetadataToHeaders.BindRemoveAccountMetadataToHeaders; +import org.jclouds.openstack.swift.v1.domain.Account; +import org.jclouds.openstack.swift.v1.functions.ParseAccountFromHeaders; +import org.jclouds.rest.annotations.BinderParam; +import org.jclouds.rest.annotations.Fallback; +import org.jclouds.rest.annotations.RequestFilters; +import org.jclouds.rest.annotations.ResponseParser; + +import com.google.common.annotations.Beta; + +/** + * Provides access to the OpenStack Object Storage (Swift) Account API features. + * + * <p/> + * Account metadata prefixed with {@code X-Account-Meta-} will be converted + * appropriately using a binder/parser. + * <p/> + * This API is new to jclouds and hence is in Beta. That means we need people to use it and give us feedback. Based + * on that feedback, minor changes to the interfaces may happen. This code will replace + * org.jclouds.openstack.swift.SwiftClient in jclouds 2.0 and it is recommended you adopt it sooner than later. + * + * + * @see {@link Account} + */ +@Beta +@RequestFilters(AuthenticateRequest.class) +@Consumes(APPLICATION_JSON) +public interface AccountApi { + + /** + * Gets the {@link Account}. + * + * @return The {@link Account} object. + */ + @Named("account:get") + @HEAD + @ResponseParser(ParseAccountFromHeaders.class) + Account get(); + + /** + * Creates or updates the {@link Account} metadata. + * + * @param metadata the metadata to create or update. + * + * @return {@code true} if the metadata was successfully created or updated, + * {@code false} if not. + */ + @Named("account:updateMetadata") + @POST + @Fallback(FalseOnNotFoundOr404.class) + boolean updateMetadata(@BinderParam(BindAccountMetadataToHeaders.class) Map<String, String> metadata); + + /** + * Replaces the temporary URL key for the {@link Account}. + * + * @param temporaryUrlKey the temporary URL key to update. + * + * @return {@code true} if the temporary URL key was successfully updated, + * {@code false} if not. + */ + @Named("account:updateTemporaryUrlKey") + @POST + @Fallback(FalseOnNotFoundOr404.class) + boolean updateTemporaryUrlKey(@HeaderParam(ACCOUNT_TEMPORARY_URL_KEY) String temporaryUrlKey); + + /** + * Deletes metadata from the {@link Account}. + * + * @param metadata the metadata to delete. + * + * @return {@code true} if the metadata was successfully deleted, + * {@code false} if not. + */ + @Named("account:deleteMetadata") + @POST + @Fallback(FalseOnNotFoundOr404.class) + boolean deleteMetadata(@BinderParam(BindRemoveAccountMetadataToHeaders.class) Map<String, String> metadata); + +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/8505539a/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/features/BulkApi.java ---------------------------------------------------------------------- diff --git a/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/features/BulkApi.java b/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/features/BulkApi.java new file mode 100644 index 0000000..b62322f --- /dev/null +++ b/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/features/BulkApi.java @@ -0,0 +1,105 @@ +/* + * 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.jclouds.openstack.swift.v1.features; + +import static com.google.common.collect.Iterables.transform; +import static com.google.common.net.UrlEscapers.urlFragmentEscaper; +import static javax.ws.rs.core.MediaType.APPLICATION_JSON; +import static javax.ws.rs.core.MediaType.TEXT_PLAIN; + +import javax.inject.Named; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.QueryParam; + +import org.jclouds.http.HttpRequest; +import org.jclouds.io.Payload; +import org.jclouds.io.Payloads; +import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest; +import org.jclouds.openstack.swift.v1.binders.SetPayload; +import org.jclouds.openstack.swift.v1.domain.BulkDeleteResponse; +import org.jclouds.openstack.swift.v1.domain.ExtractArchiveResponse; +import org.jclouds.rest.Binder; +import org.jclouds.rest.annotations.BinderParam; +import org.jclouds.rest.annotations.QueryParams; +import org.jclouds.rest.annotations.RequestFilters; + +import com.google.common.annotations.Beta; +import com.google.common.base.Joiner; + +/** + * Provides access to the OpenStack Object Storage (Swift) Bulk API features. + * <p/> + * This API is new to jclouds and hence is in Beta. That means we need people to use it and give us feedback. Based + * on that feedback, minor changes to the interfaces may happen. This code will replace + * org.jclouds.openstack.swift.SwiftClient in jclouds 2.0 and it is recommended you adopt it sooner than later. + */ +@Beta +@RequestFilters(AuthenticateRequest.class) +@Consumes(APPLICATION_JSON) +public interface BulkApi { + + /** + * Extracts a tar archive at the path specified as {@code path}. + * + * @param path + * the path to extract under. + * @param payload + * the {@link Payload payload} archive. + * @param format + * one of {@code tar}, {@code tar.gz}, or {@code tar.bz2} + * + * @return {@link BulkDeleteResponse#getErrors()} are empty on success. + */ + @Named("bulk:extractArchive") + @PUT + @Path("/{path}") + ExtractArchiveResponse extractArchive(@PathParam("path") String path, + @BinderParam(SetPayload.class) Payload payload, @QueryParam("extract-archive") String format); + + /** + * Deletes multiple objects or containers, if present. + * + * @param paths + * format of {@code container}, for an empty container, or + * {@code container/object} for an object. + * + * @return {@link BulkDeleteResponse#getErrors()} are empty on success. + */ + @Named("bulk:delete") + @DELETE + @QueryParams(keys = "bulk-delete") + BulkDeleteResponse bulkDelete(@BinderParam(UrlEncodeAndJoinOnNewline.class) Iterable<String> paths); + + // NOTE: this cannot be tested on MWS and is also brittle, as it relies on + // sending a body on DELETE. + // https://bugs.launchpad.net/swift/+bug/1232787 + static class UrlEncodeAndJoinOnNewline implements Binder { + @SuppressWarnings("unchecked") + @Override + public <R extends HttpRequest> R bindToRequest(R request, Object input) { + String encodedAndNewlineDelimited = Joiner.on('\n').join( + transform(Iterable.class.cast(input), urlFragmentEscaper().asFunction())); + Payload payload = Payloads.newStringPayload(encodedAndNewlineDelimited); + payload.getContentMetadata().setContentType(TEXT_PLAIN); + return (R) request.toBuilder().payload(payload).build(); + } + } +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/8505539a/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/features/ContainerApi.java ---------------------------------------------------------------------- diff --git a/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/features/ContainerApi.java b/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/features/ContainerApi.java new file mode 100644 index 0000000..4cbac0d --- /dev/null +++ b/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/features/ContainerApi.java @@ -0,0 +1,215 @@ +/* + * 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.jclouds.openstack.swift.v1.features; + +import static javax.ws.rs.core.MediaType.APPLICATION_JSON; +import static org.jclouds.openstack.swift.v1.SwiftFallbacks.TrueOn404FalseOn409; + +import java.util.Map; + +import javax.inject.Named; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.HEAD; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; + +import org.jclouds.Fallbacks.EmptyFluentIterableOnNotFoundOr404; +import org.jclouds.Fallbacks.FalseOnNotFoundOr404; +import org.jclouds.Fallbacks.NullOnNotFoundOr404; +import org.jclouds.javax.annotation.Nullable; +import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest; +import org.jclouds.openstack.swift.v1.binders.BindMetadataToHeaders.BindContainerMetadataToHeaders; +import org.jclouds.openstack.swift.v1.binders.BindMetadataToHeaders.BindRemoveContainerMetadataToHeaders; +import org.jclouds.openstack.swift.v1.domain.Container; +import org.jclouds.openstack.swift.v1.functions.FalseOnAccepted; +import org.jclouds.openstack.swift.v1.functions.ParseContainerFromHeaders; +import org.jclouds.openstack.swift.v1.options.CreateContainerOptions; +import org.jclouds.openstack.swift.v1.options.ListContainerOptions; +import org.jclouds.openstack.swift.v1.options.UpdateContainerOptions; +import org.jclouds.rest.annotations.BinderParam; +import org.jclouds.rest.annotations.Fallback; +import org.jclouds.rest.annotations.RequestFilters; +import org.jclouds.rest.annotations.ResponseParser; + +import com.google.common.annotations.Beta; +import com.google.common.collect.FluentIterable; + +/** + * Provides access to the OpenStack Object Storage (Swift) Container API features. + * <p/> + * This API is new to jclouds and hence is in Beta. That means we need people to use it and give us feedback. Based + * on that feedback, minor changes to the interfaces may happen. This code will replace + * {@code org.jclouds.openstack.swift.SwiftClient} in jclouds 2.0 and it is recommended you adopt it sooner than later. + */ +@Beta +@RequestFilters(AuthenticateRequest.class) +@Consumes(APPLICATION_JSON) +public interface ContainerApi { + + /** + * Lists up to 10,000 containers. + * + * <h3>NOTE</h3> + * This method returns a list of {@link Container} objects <b>without</b> metadata. To retrieve + * the {@link Container} metadata, use the {@link #get(String)} method. + * <p/> + * + * @return a list of {@link Container containers} ordered by name. + */ + @Named("container:list") + @GET + @Fallback(EmptyFluentIterableOnNotFoundOr404.class) + FluentIterable<Container> list(); + + /** + * Lists containers with the supplied {@link ListContainerOptions}. + * + * <h3>NOTE</h3> + * This method returns a list of {@link Container} objects <b>without</b> metadata. To retrieve + * the {@link Container} metadata, use the {@link #get(String)} method. + * <p/> + * + * @param options + * the options to control the output list. + * + * @return a list of {@link Container containers} ordered by name. + */ + @Named("container:list") + @GET + @Fallback(EmptyFluentIterableOnNotFoundOr404.class) + FluentIterable<Container> list(ListContainerOptions options); + + /** + * Creates a container, if not already present. + * + * @param containerName + * corresponds to {@link Container#getName()}. + * + * @return {@code true} if the container was created, {@code false} if the container already existed. + */ + @Named("container:create") + @PUT + @Path("/{containerName}") + @ResponseParser(FalseOnAccepted.class) + boolean create(@PathParam("containerName") String containerName); + + /** + * Creates a container, if not already present. + * + * @param containerName + * corresponds to {@link Container#getName()}. + * @param options + * the options to use when creating the container. + * + * @return {@code true} if the container was created, {@code false} if the container already existed. + */ + @Named("container:create") + @PUT + @Path("/{containerName}") + @ResponseParser(FalseOnAccepted.class) + boolean create(@PathParam("containerName") String containerName, CreateContainerOptions options); + + /** + * Gets the {@link Container}. + * + * @param containerName + * corresponds to {@link Container#getName()}. + * + * @return the {@link Container}, or {@code null} if not found. + */ + @Named("container:get") + @HEAD + @Path("/{containerName}") + @ResponseParser(ParseContainerFromHeaders.class) + @Fallback(NullOnNotFoundOr404.class) + @Nullable + Container get(@PathParam("containerName") String containerName); + + /** + * Updates the {@link Container}. + * + * @param containerName + * the container name corresponding to {@link Container#getName()}. + * @param options + * the container options to update. + * + * @return {@code true} if the container metadata was successfully created or updated, + * {@code false} if not. + */ + @Named("container:update") + @POST + @Path("/{containerName}") + @Fallback(FalseOnNotFoundOr404.class) + boolean update(@PathParam("containerName") String containerName, UpdateContainerOptions options); + + /** + * Creates or updates the {@link Container} metadata. + * + * @param containerName + * the container name corresponding to {@link Container#getName()}. + * @param metadata + * the container metadata to create or update. + * + * @return {@code true} if the container metadata was successfully created or updated, + * {@code false} if not. + */ + @Named("container:updateMetadata") + @POST + @Path("/{containerName}") + @Fallback(FalseOnNotFoundOr404.class) + boolean updateMetadata(@PathParam("containerName") String containerName, + @BinderParam(BindContainerMetadataToHeaders.class) Map<String, String> metadata); + + /** + * Deletes {@link Container} metadata. + * + * @param containerName + * corresponds to {@link Container#getName()}. + * @param metadata + * the container metadata to delete. + * + * @return {@code true} if the container metadata was successfully deleted, + * {@code false} if not. + */ + @Named("container:deleteMetadata") + @POST + @Path("/{containerName}") + @Fallback(FalseOnNotFoundOr404.class) + boolean deleteMetadata(@PathParam("containerName") String containerName, + @BinderParam(BindRemoveContainerMetadataToHeaders.class) Map<String, String> metadata); + + /** + * Deletes a {@link Container}, if empty. + * + * @param containerName + * corresponds to {@link Container#getName()}. + * + * @return {@code true} if the container was deleted or not present. + * + * @throws IllegalStateException if the container was not empty. + */ + @Named("container:deleteIfEmpty") + @DELETE + @Path("/{containerName}") + @Fallback(TrueOn404FalseOn409.class) + boolean deleteIfEmpty(@PathParam("containerName") String containerName) throws IllegalStateException; + +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/8505539a/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/features/ObjectApi.java ---------------------------------------------------------------------- diff --git a/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/features/ObjectApi.java b/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/features/ObjectApi.java new file mode 100644 index 0000000..4d4d603 --- /dev/null +++ b/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/features/ObjectApi.java @@ -0,0 +1,265 @@ +/* + * 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.jclouds.openstack.swift.v1.features; + +import static com.google.common.net.HttpHeaders.EXPECT; +import static javax.ws.rs.core.MediaType.APPLICATION_JSON; +import static org.jclouds.openstack.swift.v1.reference.SwiftHeaders.OBJECT_COPY_FROM; + +import java.util.Map; + +import javax.inject.Named; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.HEAD; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; + +import org.jclouds.Fallbacks.FalseOnNotFoundOr404; +import org.jclouds.Fallbacks.NullOnNotFoundOr404; +import org.jclouds.Fallbacks.VoidOnNotFoundOr404; +import org.jclouds.blobstore.BlobStoreFallbacks.FalseOnContainerNotFound; +import org.jclouds.http.options.GetOptions; +import org.jclouds.io.Payload; +import org.jclouds.javax.annotation.Nullable; +import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest; +import org.jclouds.openstack.swift.v1.binders.BindMetadataToHeaders.BindObjectMetadataToHeaders; +import org.jclouds.openstack.swift.v1.binders.BindMetadataToHeaders.BindRemoveObjectMetadataToHeaders; +import org.jclouds.openstack.swift.v1.binders.SetPayload; +import org.jclouds.openstack.swift.v1.domain.ObjectList; +import org.jclouds.openstack.swift.v1.domain.SwiftObject; +import org.jclouds.openstack.swift.v1.functions.ETagHeader; +import org.jclouds.openstack.swift.v1.functions.ParseObjectFromResponse; +import org.jclouds.openstack.swift.v1.functions.ParseObjectListFromResponse; +import org.jclouds.openstack.swift.v1.options.ListContainerOptions; +import org.jclouds.openstack.swift.v1.options.PutOptions; +import org.jclouds.rest.annotations.BinderParam; +import org.jclouds.rest.annotations.Fallback; +import org.jclouds.rest.annotations.Headers; +import org.jclouds.rest.annotations.RequestFilters; +import org.jclouds.rest.annotations.ResponseParser; + +import com.google.common.annotations.Beta; + +/** + * Provides access to the OpenStack Object Storage (Swift) Object API features. + * <p/> + * This API is new to jclouds and hence is in Beta. That means we need people to use it and give us feedback. Based + * on that feedback, minor changes to the interfaces may happen. This code will replace + * org.jclouds.openstack.swift.SwiftClient in jclouds 2.0 and it is recommended you adopt it sooner than later. + */ +@Beta +@RequestFilters(AuthenticateRequest.class) +@Consumes(APPLICATION_JSON) +public interface ObjectApi { + + /** + * Lists up to 10,000 objects. + * + * @return an {@link ObjectList} of {@link SwiftObject} ordered by name or {@code null}. + */ + @Named("object:list") + @GET + @ResponseParser(ParseObjectListFromResponse.class) + @Fallback(NullOnNotFoundOr404.class) + @Nullable + ObjectList list(); + + /** + * Lists up to 10,000 objects. To control a large list of containers beyond + * 10,000 objects, use the {@code marker} and {@code endMarker} parameters in the + * {@link ListContainerOptions} class. + * + * @param options + * the {@link ListContainerOptions} for controlling the returned list. + * + * @return an {@link ObjectList} of {@link SwiftObject} ordered by name or {@code null}. + */ + @Named("object:list") + @GET + @ResponseParser(ParseObjectListFromResponse.class) + @Fallback(NullOnNotFoundOr404.class) + @Nullable + ObjectList list(ListContainerOptions options); + + /** + * Creates or updates a {@link SwiftObject}. + * + * @param objectName + * corresponds to {@link SwiftObject#getName()}. + * @param payload + * corresponds to {@link SwiftObject#getPayload()}. + * + * @return {@link SwiftObject#getETag()} of the object. + */ + @Named("object:put") + @PUT + @Path("/{objectName}") + @Headers(keys = EXPECT, values = "100-continue") + @ResponseParser(ETagHeader.class) + String put(@PathParam("objectName") String objectName, @BinderParam(SetPayload.class) Payload payload); + + /** + * Creates or updates a {@link SwiftObject}. + * + * @param objectName + * corresponds to {@link SwiftObject#getName()}. + * @param payload + * corresponds to {@link SwiftObject#getPayload()}. + * @param options + * {@link PutOptions options} to control creating the {@link SwiftObject}. + * + * @return {@link SwiftObject#getETag()} of the object. + */ + @Named("object:put") + @PUT + @Path("/{objectName}") + @Headers(keys = EXPECT, values = "100-continue") + @ResponseParser(ETagHeader.class) + String put(@PathParam("objectName") String objectName, @BinderParam(SetPayload.class) Payload payload, + PutOptions options); + + /** + * Gets the {@link SwiftObject} metadata without its {@link Payload#openStream() body}. + * + * @param objectName + * corresponds to {@link SwiftObject#getName()}. + * + * @return the {@link SwiftObject} or {@code null}, if not found. + */ + @Named("object:getWithoutBody") + @HEAD + @Path("/{objectName}") + @ResponseParser(ParseObjectFromResponse.class) + @Fallback(NullOnNotFoundOr404.class) + @Nullable + SwiftObject getWithoutBody(@PathParam("objectName") String objectName); + + /** + * Gets the {@link SwiftObject} including its {@link Payload#openStream() body}. + * + * @param objectName + * corresponds to {@link SwiftObject#getName()}. + * + * @return the {@link SwiftObject} or {@code null}, if not found. + */ + @Named("object:get") + @GET + @Path("/{objectName}") + @ResponseParser(ParseObjectFromResponse.class) + @Fallback(NullOnNotFoundOr404.class) + @Nullable + SwiftObject get(@PathParam("objectName") String objectName); + + /** + * Gets the {@link SwiftObject} including its {@link Payload#openStream() body}. + * + * @param objectName + * corresponds to {@link SwiftObject#getName()}. + * @param options + * options to control the download. + * + * @return the {@link SwiftObject} or {@code null}, if not found. + */ + @Named("object:get") + @GET + @Path("/{objectName}") + @ResponseParser(ParseObjectFromResponse.class) + @Fallback(NullOnNotFoundOr404.class) + @Nullable + SwiftObject get(@PathParam("objectName") String objectName, GetOptions options); + + /** + * Creates or updates the metadata for a {@link SwiftObject}. + * + * @param objectName + * corresponds to {@link SwiftObject#getName()}. + * @param metadata + * the metadata to create or update. + * + * @return {@code true} if the metadata was successfully created or updated, + * {@code false} if not. + */ + @Named("object:updateMetadata") + @POST + @Path("/{objectName}") + @Produces("") + @Fallback(FalseOnNotFoundOr404.class) + boolean updateMetadata(@PathParam("objectName") String objectName, + @BinderParam(BindObjectMetadataToHeaders.class) Map<String, String> metadata); + + /** + * Deletes the metadata from a {@link SwiftObject}. + * + * @param objectName + * corresponds to {@link SwiftObject#getName()}. + * @param metadata + * corresponds to {@link SwiftObject#getMetadata()}. + * + * @return {@code true} if the metadata was successfully deleted, + * {@code false} if not. + */ + @Named("object:deleteMetadata") + @POST + @Path("/{objectName}") + @Fallback(FalseOnNotFoundOr404.class) + boolean deleteMetadata(@PathParam("objectName") String objectName, + @BinderParam(BindRemoveObjectMetadataToHeaders.class) Map<String, String> metadata); + + /** + * Deletes an object, if present. + * + * @param objectName + * corresponds to {@link SwiftObject#getName()}. + */ + @Named("object:delete") + @DELETE + @Path("/{objectName}") + @Fallback(VoidOnNotFoundOr404.class) + void delete(@PathParam("objectName") String objectName); + + /** + * Copies an object from one container to another. + * + * <h3>NOTE</h3> + * This is a server side copy. + * + * @param destinationObject + * the destination object name. + * @param sourceContainer + * the source container name. + * @param sourceObject + * the source object name. + * + * @return {@code true} if the object was successfully copied, {@code false} if not. + * + * @throws org.jclouds.openstack.swift.v1.CopyObjectException if the source or destination container do not exist. + */ + @Named("object:copy") + @PUT + @Path("/{destinationObject}") + @Headers(keys = OBJECT_COPY_FROM, values = "/{sourceContainer}/{sourceObject}") + @Fallback(FalseOnContainerNotFound.class) + boolean copy(@PathParam("destinationObject") String destinationObject, + @PathParam("sourceContainer") String sourceContainer, + @PathParam("sourceObject") String sourceObject); + +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/8505539a/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/features/StaticLargeObjectApi.java ---------------------------------------------------------------------- diff --git a/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/features/StaticLargeObjectApi.java b/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/features/StaticLargeObjectApi.java new file mode 100644 index 0000000..51ba30d --- /dev/null +++ b/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/features/StaticLargeObjectApi.java @@ -0,0 +1,90 @@ +/* + * 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.jclouds.openstack.swift.v1.features; + +import static javax.ws.rs.core.MediaType.APPLICATION_JSON; + +import java.util.List; +import java.util.Map; + +import javax.inject.Named; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; + +import org.jclouds.Fallbacks.VoidOnNotFoundOr404; +import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest; +import org.jclouds.openstack.swift.v1.binders.BindMetadataToHeaders.BindObjectMetadataToHeaders; +import org.jclouds.openstack.swift.v1.domain.Segment; +import org.jclouds.openstack.swift.v1.functions.ETagHeader; +import org.jclouds.rest.annotations.BinderParam; +import org.jclouds.rest.annotations.Fallback; +import org.jclouds.rest.annotations.QueryParams; +import org.jclouds.rest.annotations.RequestFilters; +import org.jclouds.rest.annotations.ResponseParser; +import org.jclouds.rest.binders.BindToJsonPayload; + +import com.google.common.annotations.Beta; + +/** + * Provides access to the OpenStack Object Storage (Swift) Static Large Object API features. + * <p/> + * This API is new to jclouds and hence is in Beta. That means we need people to use it and give us feedback. Based + * on that feedback, minor changes to the interfaces may happen. This code will replace + * org.jclouds.openstack.swift.SwiftClient in jclouds 2.0 and it is recommended you adopt it sooner than later. + */ +@Beta +@RequestFilters(AuthenticateRequest.class) +@Consumes(APPLICATION_JSON) +@Path("/{objectName}") +public interface StaticLargeObjectApi { + + /** + * Creates or updates a static large object's manifest. + * + * @param objectName + * corresponds to {@link SwiftObject#getName()}. + * @param segments + * ordered parts which will be concatenated upon download. + * @param metadata + * corresponds to {@link SwiftObject#getMetadata()}. + * + * @return {@link SwiftObject#getEtag()} of the object, which is the MD5 + * checksum of the concatenated ETag values of the {@code segments}. + */ + @Named("staticLargeObject:replaceManifest") + @PUT + @ResponseParser(ETagHeader.class) + @QueryParams(keys = "multipart-manifest", values = "put") + String replaceManifest(@PathParam("objectName") String objectName, + @BinderParam(BindToJsonPayload.class) List<Segment> segments, + @BinderParam(BindObjectMetadataToHeaders.class) Map<String, String> metadata); + + /** + * Deletes a static large object, if present, including all of its segments. + * + * @param objectName + * corresponds to {@link SwiftObject#getName()}. + */ + @Named("staticLargeObject:delete") + @DELETE + @Fallback(VoidOnNotFoundOr404.class) + @QueryParams(keys = "multipart-manifest", values = "delete") + void delete(@PathParam("objectName") String objectName); +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/8505539a/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/functions/ETagHeader.java ---------------------------------------------------------------------- diff --git a/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/functions/ETagHeader.java b/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/functions/ETagHeader.java new file mode 100644 index 0000000..25a749b --- /dev/null +++ b/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/functions/ETagHeader.java @@ -0,0 +1,32 @@ +/* + * 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.jclouds.openstack.swift.v1.functions; + +import static com.google.common.net.HttpHeaders.ETAG; + +import org.jclouds.http.HttpResponse; + +import com.google.common.base.Function; + +public class ETagHeader implements Function<HttpResponse, String> { + + @Override + public String apply(HttpResponse from) { + String etag = from.getFirstHeaderOrNull(ETAG); + return etag != null ? etag.replace("\"", "") : null; + } +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/8505539a/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/functions/EntriesWithoutMetaPrefix.java ---------------------------------------------------------------------- diff --git a/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/functions/EntriesWithoutMetaPrefix.java b/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/functions/EntriesWithoutMetaPrefix.java new file mode 100644 index 0000000..473da3e --- /dev/null +++ b/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/functions/EntriesWithoutMetaPrefix.java @@ -0,0 +1,48 @@ +/* + * 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.jclouds.openstack.swift.v1.functions; + +import java.util.Map; +import java.util.Map.Entry; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Multimap; + +/** + * Extracts entries whose keys start with {@code .*-Meta-}. + * + * @param from + * a {@link Multimap} containing the prefixed headers. + * + * @return the extracted metadata without the prefixed keys. + */ +public enum EntriesWithoutMetaPrefix implements Function<Multimap<String, String>, Map<String, String>> { + INSTANCE; + + @Override + public Map<String, String> apply(Multimap<String, String> arg0) { + ImmutableMap.Builder<String, String> metadata = ImmutableMap.builder(); + for (Entry<String, String> header : arg0.entries()) { + int index = header.getKey().indexOf("-Meta-"); + if (index != -1) { + metadata.put(header.getKey().substring(index + 6), header.getValue()); + } + } + return metadata.build(); + } +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/8505539a/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/functions/FalseOnAccepted.java ---------------------------------------------------------------------- diff --git a/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/functions/FalseOnAccepted.java b/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/functions/FalseOnAccepted.java new file mode 100644 index 0000000..68da524 --- /dev/null +++ b/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/functions/FalseOnAccepted.java @@ -0,0 +1,30 @@ +/* + * 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.jclouds.openstack.swift.v1.functions; + +import org.jclouds.http.HttpResponse; + +import com.google.common.base.Function; + +/** Returns {@code false} on HTTP 202 {@code Accepted}. */ +public class FalseOnAccepted implements Function<HttpResponse, Boolean> { + + @Override + public Boolean apply(HttpResponse from) { + return from.getStatusCode() == 202 ? false : true; + } +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/8505539a/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/functions/MetadataFromHeaders.java ---------------------------------------------------------------------- diff --git a/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/functions/MetadataFromHeaders.java b/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/functions/MetadataFromHeaders.java new file mode 100644 index 0000000..cdd49f1 --- /dev/null +++ b/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/functions/MetadataFromHeaders.java @@ -0,0 +1,31 @@ +/* + * 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.jclouds.openstack.swift.v1.functions; + +import java.util.Map; + +import org.jclouds.http.HttpResponse; + +import com.google.common.base.Function; + +/** Extracts metadata entries from http response headers. */ +public class MetadataFromHeaders implements Function<HttpResponse, Map<String, String>> { + @Override + public Map<String, String> apply(HttpResponse from) { + return EntriesWithoutMetaPrefix.INSTANCE.apply(from.getHeaders()); + } +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/8505539a/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/functions/ParseAccountFromHeaders.java ---------------------------------------------------------------------- diff --git a/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/functions/ParseAccountFromHeaders.java b/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/functions/ParseAccountFromHeaders.java new file mode 100644 index 0000000..9debe67 --- /dev/null +++ b/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/functions/ParseAccountFromHeaders.java @@ -0,0 +1,38 @@ +/* + * 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.jclouds.openstack.swift.v1.functions; + +import static org.jclouds.openstack.swift.v1.reference.SwiftHeaders.ACCOUNT_BYTES_USED; +import static org.jclouds.openstack.swift.v1.reference.SwiftHeaders.ACCOUNT_CONTAINER_COUNT; +import static org.jclouds.openstack.swift.v1.reference.SwiftHeaders.ACCOUNT_OBJECT_COUNT; + +import org.jclouds.http.HttpResponse; +import org.jclouds.openstack.swift.v1.domain.Account; + +import com.google.common.base.Function; + +public class ParseAccountFromHeaders implements Function<HttpResponse, Account> { + + @Override + public Account apply(HttpResponse from) { + return Account.builder() + .bytesUsed(Long.parseLong(from.getFirstHeaderOrNull(ACCOUNT_BYTES_USED))) + .containerCount(Long.parseLong(from.getFirstHeaderOrNull(ACCOUNT_CONTAINER_COUNT))) + .objectCount(Long.parseLong(from.getFirstHeaderOrNull(ACCOUNT_OBJECT_COUNT))) + .metadata(EntriesWithoutMetaPrefix.INSTANCE.apply(from.getHeaders())).build(); + } +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/8505539a/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/functions/ParseContainerFromHeaders.java ---------------------------------------------------------------------- diff --git a/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/functions/ParseContainerFromHeaders.java b/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/functions/ParseContainerFromHeaders.java new file mode 100644 index 0000000..d616351 --- /dev/null +++ b/apis/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/functions/ParseContainerFromHeaders.java @@ -0,0 +1,54 @@ +/* + * 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.jclouds.openstack.swift.v1.functions; + +import static org.jclouds.openstack.swift.v1.reference.SwiftHeaders.CONTAINER_ACL_ANYBODY_READ; +import static org.jclouds.openstack.swift.v1.reference.SwiftHeaders.CONTAINER_BYTES_USED; +import static org.jclouds.openstack.swift.v1.reference.SwiftHeaders.CONTAINER_OBJECT_COUNT; +import static org.jclouds.openstack.swift.v1.reference.SwiftHeaders.CONTAINER_READ; + +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.jclouds.openstack.swift.v1.domain.Container; +import org.jclouds.rest.InvocationContext; +import org.jclouds.rest.internal.GeneratedHttpRequest; + +import com.google.common.base.Function; + +public class ParseContainerFromHeaders implements Function<HttpResponse, Container>, + InvocationContext<ParseContainerFromHeaders> { + + String name; + + @Override + public Container apply(HttpResponse from) { + Container c = + Container.builder() + .name(name) + .bytesUsed(Long.parseLong(from.getFirstHeaderOrNull(CONTAINER_BYTES_USED))) + .objectCount(Long.parseLong(from.getFirstHeaderOrNull(CONTAINER_OBJECT_COUNT))) + .anybodyRead(CONTAINER_ACL_ANYBODY_READ.equals(from.getFirstHeaderOrNull(CONTAINER_READ))) + .metadata(EntriesWithoutMetaPrefix.INSTANCE.apply(from.getHeaders())).build(); + return c; + } + + @Override + public ParseContainerFromHeaders setContext(HttpRequest request) { + this.name = GeneratedHttpRequest.class.cast(request).getInvocation().getArgs().get(0).toString(); + return this; + } +}
