JCLOUDS-410. Add support for ByteSource Payloads

Also deprecate byte[], File, InputSupplier<InputStream>, and String
Payloads.  Callers should instead provide a ByteSource via
ByteSource.wrap(byte[]) and Files.asByteSource(File)
This commit is contained in:
Andrew Gaul 2013-12-13 16:52:15 -08:00
parent f3dcd3fe86
commit e48d4985ea
10 changed files with 133 additions and 11 deletions

View File

@ -25,6 +25,7 @@ import java.util.Map;
import org.jclouds.blobstore.domain.internal.BlobBuilderImpl; import org.jclouds.blobstore.domain.internal.BlobBuilderImpl;
import org.jclouds.io.Payload; import org.jclouds.io.Payload;
import com.google.common.io.ByteSource;
import com.google.inject.ImplementedBy; import com.google.inject.ImplementedBy;
/** /**
@ -77,21 +78,32 @@ public interface BlobBuilder {
* *
* @param payload * @param payload
* payload you wish to construct the {@link Blob} with. * payload you wish to construct the {@link Blob} with.
* @deprecated see payload(ByteSource.wrap(byte[])
*/ */
@Deprecated
PayloadBlobBuilder payload(byte[] payload); PayloadBlobBuilder payload(byte[] payload);
/**
* @param payload payload you wish to construct the {@link Blob} with.
*/
PayloadBlobBuilder payload(ByteSource byteSource);
/** /**
* *
* @param payload * @param payload
* payload you wish to construct the {@link Blob} with. * payload you wish to construct the {@link Blob} with.
* @deprecated see payload(ByteSource.wrap(String.getBytes()))
*/ */
@Deprecated
PayloadBlobBuilder payload(String payload); PayloadBlobBuilder payload(String payload);
/** /**
* *
* @param payload * @param payload
* payload you wish to construct the {@link Blob} with. * payload you wish to construct the {@link Blob} with.
* @deprecated see payload(Files.asByteSource(File))
*/ */
@Deprecated
PayloadBlobBuilder payload(File payload); PayloadBlobBuilder payload(File payload);
/** /**

View File

@ -35,6 +35,7 @@ import org.jclouds.io.Payloads;
import org.jclouds.io.payloads.PhantomPayload; import org.jclouds.io.payloads.PhantomPayload;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.io.ByteSource;
/** /**
* @author Adrian Cole * @author Adrian Cole
@ -89,6 +90,11 @@ public class BlobBuilderImpl implements BlobBuilder {
return payload(newPayload(checkNotNull(data, "data"))); return payload(newPayload(checkNotNull(data, "data")));
} }
@Override
public PayloadBlobBuilder payload(ByteSource data) {
return payload(newPayload(checkNotNull(data, "data")));
}
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@ -161,6 +167,11 @@ public class BlobBuilderImpl implements BlobBuilder {
return builder.payload(payload); return builder.payload(payload);
} }
@Override
public PayloadBlobBuilder payload(ByteSource payload) {
return builder.payload(payload);
}
@Override @Override
public PayloadBlobBuilder payload(String payload) { public PayloadBlobBuilder payload(String payload) {
return builder.payload(payload); return builder.payload(payload);

View File

@ -33,6 +33,7 @@ import com.google.common.base.Objects;
import com.google.common.base.Objects.ToStringHelper; import com.google.common.base.Objects.ToStringHelper;
import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
import com.google.common.io.ByteSource;
/** /**
* Represents a request that can be executed within {@link HttpCommandExecutorService} * Represents a request that can be executed within {@link HttpCommandExecutorService}
@ -65,7 +66,9 @@ public class HttpMessage extends PayloadEnclosingImpl {
/** /**
* @see HttpMessage#getPayload() * @see HttpMessage#getPayload()
* @deprecated see payload(ByteSource.wrap(byte[]))
*/ */
@Deprecated
public T payload(byte [] payload) { public T payload(byte [] payload) {
this.payload = Payloads.newByteArrayPayload(checkNotNull(payload, "payload")); this.payload = Payloads.newByteArrayPayload(checkNotNull(payload, "payload"));
return self(); return self();
@ -74,6 +77,17 @@ public class HttpMessage extends PayloadEnclosingImpl {
/** /**
* @see HttpMessage#getPayload() * @see HttpMessage#getPayload()
*/ */
@Deprecated
public T payload(ByteSource payload) {
this.payload = Payloads.newByteSourcePayload(checkNotNull(payload, "payload"));
return self();
}
/**
* @see HttpMessage#getPayload()
* @deprecated see payload(Files.asByteSource(File))
*/
@Deprecated
public T payload(File payload) { public T payload(File payload) {
this.payload = Payloads.newFilePayload(checkNotNull(payload, "payload")); this.payload = Payloads.newFilePayload(checkNotNull(payload, "payload"));
return self(); return self();
@ -89,7 +103,9 @@ public class HttpMessage extends PayloadEnclosingImpl {
/** /**
* @see HttpMessage#getPayload() * @see HttpMessage#getPayload()
* @deprecated see payload(ByteSource.wrap(String.getBytes()))
*/ */
@Deprecated
public T payload(String payload) { public T payload(String payload) {
this.payload = Payloads.newStringPayload(checkNotNull(payload, "payload")); this.payload = Payloads.newStringPayload(checkNotNull(payload, "payload"));
return self(); return self();

View File

@ -64,6 +64,7 @@ import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
import com.google.common.collect.ImmutableSet.Builder; import com.google.common.collect.ImmutableSet.Builder;
import com.google.common.io.ByteSource;
import com.google.common.reflect.Invokable; import com.google.common.reflect.Invokable;
import com.google.inject.Inject; import com.google.inject.Inject;
@ -161,7 +162,7 @@ public class HttpUtils {
public static byte[] closeClientButKeepContentStream(PayloadEnclosing response) { public static byte[] closeClientButKeepContentStream(PayloadEnclosing response) {
byte[] returnVal = toByteArrayOrNull(response); byte[] returnVal = toByteArrayOrNull(response);
if (returnVal != null && !response.getPayload().isRepeatable()) { if (returnVal != null && !response.getPayload().isRepeatable()) {
Payload newPayload = Payloads.newByteArrayPayload(returnVal); Payload newPayload = Payloads.newByteSourcePayload(ByteSource.wrap(returnVal));
MutableContentMetadata fromMd = response.getPayload().getContentMetadata(); MutableContentMetadata fromMd = response.getPayload().getContentMetadata();
MutableContentMetadata toMd = newPayload.getContentMetadata(); MutableContentMetadata toMd = newPayload.getContentMetadata();
copy(fromMd, toMd); copy(fromMd, toMd);

View File

@ -24,6 +24,7 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import org.jclouds.io.payloads.ByteArrayPayload; import org.jclouds.io.payloads.ByteArrayPayload;
import org.jclouds.io.payloads.ByteSourcePayload;
import org.jclouds.io.payloads.FilePayload; import org.jclouds.io.payloads.FilePayload;
import org.jclouds.io.payloads.InputStreamPayload; import org.jclouds.io.payloads.InputStreamPayload;
import org.jclouds.io.payloads.StringPayload; import org.jclouds.io.payloads.StringPayload;
@ -31,6 +32,7 @@ import org.jclouds.io.payloads.UrlEncodedFormPayload;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
import com.google.common.io.ByteStreams; import com.google.common.io.ByteStreams;
import com.google.common.io.ByteSource;
/** /**
* *
@ -40,6 +42,10 @@ public class Payloads {
private Payloads() { private Payloads() {
} }
/**
* @deprecated see newPayload(ByteSource) or newPayload(InputStream)
*/
@Deprecated
public static Payload newPayload(Object data) { public static Payload newPayload(Object data) {
checkNotNull(data, "data"); checkNotNull(data, "data");
if (data instanceof Payload) { if (data instanceof Payload) {
@ -48,6 +54,8 @@ public class Payloads {
return newInputStreamPayload((InputStream) data); return newInputStreamPayload((InputStream) data);
} else if (data instanceof byte[]) { } else if (data instanceof byte[]) {
return newByteArrayPayload((byte[]) data); return newByteArrayPayload((byte[]) data);
} else if (data instanceof ByteSource) {
return newByteSourcePayload((ByteSource) data);
} else if (data instanceof String) { } else if (data instanceof String) {
return newStringPayload((String) data); return newStringPayload((String) data);
} else if (data instanceof File) { } else if (data instanceof File) {
@ -61,14 +69,30 @@ public class Payloads {
return new InputStreamPayload(checkNotNull(data, "data")); return new InputStreamPayload(checkNotNull(data, "data"));
} }
/**
* @deprecated see newPayload(ByteSource)
*/
@Deprecated
public static ByteArrayPayload newByteArrayPayload(byte[] data) { public static ByteArrayPayload newByteArrayPayload(byte[] data) {
return new ByteArrayPayload(checkNotNull(data, "data")); return new ByteArrayPayload(checkNotNull(data, "data"));
} }
public static ByteSourcePayload newByteSourcePayload(ByteSource data) {
return new ByteSourcePayload(checkNotNull(data, "data"));
}
/**
* @deprecated see newPayload(ByteSource)
*/
@Deprecated
public static StringPayload newStringPayload(String data) { public static StringPayload newStringPayload(String data) {
return new StringPayload(checkNotNull(data, "data")); return new StringPayload(checkNotNull(data, "data"));
} }
/**
* @deprecated see newPayload(ByteSource)
*/
@Deprecated
public static FilePayload newFilePayload(File data) { public static FilePayload newFilePayload(File data) {
return new FilePayload(checkNotNull(data, "data")); return new FilePayload(checkNotNull(data, "data"));
} }

View File

@ -24,7 +24,9 @@ import java.io.InputStream;
/** /**
* @author Adrian Cole * @author Adrian Cole
* @deprecated see ByteSourcePayload
*/ */
@Deprecated
public class ByteArrayPayload extends BasePayload<byte[]> { public class ByteArrayPayload extends BasePayload<byte[]> {
public ByteArrayPayload(byte[] content) { public ByteArrayPayload(byte[] content) {
this(content, null); this(content, null);

View File

@ -0,0 +1,56 @@
/*
* 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.io.payloads;
import static com.google.common.io.Closeables.closeQuietly;
import java.io.IOException;
import java.io.InputStream;
import com.google.common.io.ByteSource;
import com.google.common.io.Closer;
/**
* A repeatable, ByteSource-backed Payload.
*
* @author Andrew Gaul
*/
public class ByteSourcePayload extends BasePayload<ByteSource> {
private final Closer closer = Closer.create();
public ByteSourcePayload(ByteSource content) {
super(content);
}
@Override
public InputStream openStream() throws IOException {
return closer.register(content.openStream());
}
@Override
public boolean isRepeatable() {
return true;
}
/**
* if we created the stream, then it is already consumed on close.
*/
@Override
public void release() {
closeQuietly(closer);
}
}

View File

@ -26,7 +26,9 @@ import java.io.IOException;
/** /**
* @author Adrian Cole * @author Adrian Cole
* @deprecated see ByteSourcePayload
*/ */
@Deprecated
public class FilePayload extends BasePayload<File> { public class FilePayload extends BasePayload<File> {
public FilePayload(File content) { public FilePayload(File content) {

View File

@ -20,16 +20,17 @@ import static com.google.common.io.Closeables.closeQuietly;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.List;
import com.google.common.collect.Lists; import com.google.common.io.Closer;
import com.google.common.io.InputSupplier; import com.google.common.io.InputSupplier;
/** /**
* @author Adrian Cole * @author Adrian Cole
* @deprecated see ByteSourcePayload
*/ */
@Deprecated
public class InputStreamSupplierPayload extends BasePayload<InputSupplier<? extends InputStream>> { public class InputStreamSupplierPayload extends BasePayload<InputSupplier<? extends InputStream>> {
private List<InputStream> toClose = Lists.newArrayList(); private final Closer closer = Closer.create();
public InputStreamSupplierPayload(InputSupplier<? extends InputStream> content) { public InputStreamSupplierPayload(InputSupplier<? extends InputStream> content) {
super(content); super(content);
@ -40,9 +41,7 @@ public class InputStreamSupplierPayload extends BasePayload<InputSupplier<? exte
*/ */
@Override @Override
public InputStream openStream() throws IOException { public InputStream openStream() throws IOException {
InputStream returnVal = content.getInput(); return closer.register(content.getInput());
toClose.add(returnVal);
return returnVal;
} }
/** /**
@ -58,9 +57,6 @@ public class InputStreamSupplierPayload extends BasePayload<InputSupplier<? exte
*/ */
@Override @Override
public void release() { public void release() {
if (toClose.size() > 0) closeQuietly(closer);
for (InputStream content = toClose.remove(0); toClose.size() > 0; content = toClose.remove(0))
closeQuietly(content);
} }
} }

View File

@ -26,7 +26,9 @@ import com.google.common.base.Charsets;
* a different encoding, please use {@link ByteArrayPayload}. * a different encoding, please use {@link ByteArrayPayload}.
* *
* @author Adrian Cole * @author Adrian Cole
* @deprecated see ByteSourcePayload
*/ */
@Deprecated
public class StringPayload extends BasePayload<String> { public class StringPayload extends BasePayload<String> {
private final byte[] bytes; private final byte[] bytes;