View Javadoc

1   /**
2    *
3    * Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
4    *
5    * ====================================================================
6    * Licensed under the Apache License, Version 2.0 (the "License");
7    * you may not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    *
10   * http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   * ====================================================================
18   */
19  package org.jclouds.blobstore.internal;
20  
21  import static com.google.common.collect.Iterables.transform;
22  import static com.google.common.collect.Lists.newArrayList;
23  import static org.jclouds.io.Payloads.newPayload;
24  
25  import java.io.File;
26  import java.io.IOException;
27  import java.io.InputStream;
28  import java.util.Collection;
29  import java.util.Map;
30  
31  import javax.inject.Inject;
32  import javax.inject.Provider;
33  
34  import org.jclouds.blobstore.BlobMap;
35  import org.jclouds.blobstore.BlobStore;
36  import org.jclouds.blobstore.InputStreamMap;
37  import org.jclouds.blobstore.domain.Blob;
38  import org.jclouds.blobstore.domain.BlobBuilder;
39  import org.jclouds.blobstore.options.ListContainerOptions;
40  import org.jclouds.blobstore.strategy.ContainsValueInListStrategy;
41  import org.jclouds.blobstore.strategy.GetBlobsInListStrategy;
42  import org.jclouds.blobstore.strategy.PutBlobsStrategy;
43  import org.jclouds.blobstore.strategy.internal.ListContainerAndRecurseThroughFolders;
44  import org.jclouds.crypto.Crypto;
45  import org.jclouds.io.Payload;
46  import org.jclouds.io.Payloads;
47  import org.jclouds.io.payloads.ByteArrayPayload;
48  import org.jclouds.io.payloads.FilePayload;
49  import org.jclouds.io.payloads.InputStreamPayload;
50  import org.jclouds.io.payloads.StringPayload;
51  
52  import com.google.common.annotations.VisibleForTesting;
53  import com.google.common.base.Function;
54  import com.google.common.base.Throwables;
55  
56  /**
57   * Map representation of a live connection to a BlobStore. All put operations will result in ETag
58   * calculation. If this is not desired, use {@link BlobMap} instead.
59   * 
60   * @author Adrian Cole
61   * 
62   * @see BlobStore
63   * @see InputStreamMap
64   * @see BaseBlobMap
65   */
66  public class InputStreamMapImpl extends BaseBlobMap<InputStream> implements InputStreamMap {
67     protected final Crypto crypto;
68  
69     @Inject
70     public InputStreamMapImpl(BlobStore connection, Provider<BlobBuilder> blobBuilders,
71           GetBlobsInListStrategy getAllBlobs, ListContainerAndRecurseThroughFolders listStrategy,
72           ContainsValueInListStrategy containsValueStrategy, PutBlobsStrategy putBlobsStrategy, String containerName,
73           ListContainerOptions options, Crypto crypto) {
74        super(connection, getAllBlobs, containsValueStrategy, putBlobsStrategy, listStrategy, containerName, options);
75        this.crypto = crypto;
76     }
77  
78     @Override
79     public InputStream get(Object o) {
80        String realKey = prefixer.apply(o.toString());
81        Blob blob = blobstore.getBlob(containerName, realKey);
82        return getInputStreamOrNull(blob);
83     }
84  
85     private InputStream getInputStreamOrNull(Blob blob) {
86        return blob != null ? blob.getPayload() != null ? blob.getPayload().getInput() : null : null;
87     }
88  
89     @Override
90     public InputStream remove(Object o) {
91        InputStream old = get(o);
92        String realKey = prefixer.apply(o.toString());
93        blobstore.removeBlob(containerName, realKey);
94        return old;
95     }
96  
97     @Override
98     public Collection<InputStream> values() {
99        return newArrayList(transform(getAllBlobs.execute(containerName, options), new Function<Blob, InputStream>() {
100          public InputStream apply(Blob from) {
101             return getInputStreamOrNull(from);
102          }
103       }));
104    }
105 
106    @Override
107    public void putAll(Map<? extends String, ? extends InputStream> map) {
108       putAllInternal(map);
109    }
110 
111    @Override
112    public void putAllBytes(Map<? extends String, ? extends byte[]> map) {
113       putAllInternal(map);
114    }
115 
116    @Override
117    public void putAllFiles(Map<? extends String, ? extends File> map) {
118       putAllInternal(map);
119    }
120 
121    @Override
122    public void putAllStrings(Map<? extends String, ? extends String> map) {
123       putAllInternal(map);
124    }
125 
126    /**
127     * submits requests to add all objects and collects the results later. All values will have eTag
128     * calculated first. As a side-effect of this, the content will be copied into a byte [].
129     * 
130     * @see S3Client#put(String, Blob)
131     */
132    @VisibleForTesting
133    void putAllInternal(Map<? extends String, ? extends Object> map) {
134       putBlobsStrategy.execute(containerName,
135             transform(map.entrySet(), new Function<Map.Entry<? extends String, ? extends Object>, Blob>() {
136                @Override
137                public Blob apply(Map.Entry<? extends String, ? extends Object> from) {
138                   String name = from.getKey();
139                   Object value = from.getValue();
140                   return newBlobWithMD5(name, value);
141                }
142 
143             }));
144    }
145 
146    @VisibleForTesting
147    Blob newBlobWithMD5(String name, Object value) {
148       Blob blob = blobstore.blobBuilder(prefixer.apply(name)).payload(newPayload(value)).build();
149       try {
150          Payloads.calculateMD5(blob, crypto.md5());
151       } catch (IOException e) {
152          Throwables.propagate(e);
153       }
154       return blob;
155    }
156 
157    @Override
158    public InputStream putString(String key, String value) {
159       return putInternal(key, new StringPayload(value));
160    }
161 
162    @Override
163    public InputStream putFile(String key, File value) {
164       return putInternal(key, new FilePayload(value));
165    }
166 
167    @Override
168    public InputStream putBytes(String key, byte[] value) {
169       return putInternal(key, new ByteArrayPayload(value));
170    }
171 
172    @Override
173    public InputStream put(String key, InputStream value) {
174       return putInternal(key, new InputStreamPayload(value));
175    }
176 
177    /**
178     * calculates eTag before adding the object to s3. As a side-effect of this, the content will be
179     * copied into a byte []. *
180     * 
181     * @see S3Client#put(String, Blob)
182     */
183    @VisibleForTesting
184    InputStream putInternal(String name, Payload payload) {
185       InputStream returnVal = containsKey(name) ? get(name) : null;
186       Blob blob = newBlobWithMD5(name, payload);
187       blobstore.putBlob(containerName, blob);
188       return returnVal;
189    }
190 
191 }