1 // Copyright 2009 Google Inc. All Rights Reserved.
3 package com
.google
.appengine
.api
.blobstore
;
5 import com
.google
.appengine
.api
.NamespaceManager
;
6 import com
.google
.appengine
.api
.blobstore
.BlobKey
;
7 import com
.google
.appengine
.api
.datastore
.DatastoreService
;
8 import com
.google
.appengine
.api
.datastore
.DatastoreServiceFactory
;
9 import com
.google
.appengine
.api
.datastore
.Entity
;
10 import com
.google
.appengine
.api
.datastore
.EntityNotFoundException
;
11 import com
.google
.appengine
.api
.datastore
.Key
;
12 import com
.google
.appengine
.api
.datastore
.KeyFactory
;
13 import com
.google
.appengine
.api
.datastore
.Query
;
15 import java
.util
.Date
;
16 import java
.util
.Iterator
;
19 * {@code BlobInfoFactory} provides a trivial interface for retrieving
20 * {@link BlobInfo} metadata.
22 * <p>BlobInfo metadata is stored in read-only {@code __BlobInfo__}
23 * entities in the datastore. This class provides an easy way to
24 * access these entities. For more complex queries, you can use the
28 public class BlobInfoFactory
{
29 public static final String KIND
= "__BlobInfo__";
30 public static final String CONTENT_TYPE
= "content_type";
31 public static final String CREATION
= "creation";
32 public static final String FILENAME
= "filename";
33 public static final String SIZE
= "size";
34 public static final String MD5_HASH
= "md5_hash";
36 private final DatastoreService datastoreService
;
39 * Creates a {@code BlobInfoFactory} that uses the default
40 * implementation of {@link DatastoreService}.
42 public BlobInfoFactory() {
43 this(DatastoreServiceFactory
.getDatastoreService());
47 * Creates a {@code BlobInfoFactory} with the specified
48 * implementation of {@link DatastoreService}.
50 public BlobInfoFactory(DatastoreService datastoreService
) {
51 this.datastoreService
= datastoreService
;
55 * Loads the {@link BlobInfo} metadata for {@code blobKey}. Returns
56 * {@code null} if no matching blob is found.
58 public BlobInfo
loadBlobInfo(BlobKey blobKey
) {
60 return createBlobInfo(datastoreService
.get(getMetadataKeyForBlobKey(blobKey
)));
61 } catch (EntityNotFoundException ex
) {
67 * Queries for {@link BlobInfo} instances, beginning with the {@link
68 * BlobKey} that appears first in lexicographic order.
70 public Iterator
<BlobInfo
> queryBlobInfos() {
71 return queryBlobInfosAfter(null);
75 * Queries for {@link BlobInfo} instances, beginning at the blob
76 * following {@code previousBlob} in lexicographic order. If {@code
77 * previousBlob} is null, the first blob will be returned.
79 * <p>This is useful for displaying discrete pages of blobs.
81 public Iterator
<BlobInfo
> queryBlobInfosAfter(BlobKey previousBlob
) {
82 String origNamespace
= NamespaceManager
.get();
85 NamespaceManager
.set("");
86 query
= new Query(KIND
, null);
88 NamespaceManager
.set(origNamespace
);
91 if (previousBlob
!= null) {
92 query
.addFilter(Entity
.KEY_RESERVED_PROPERTY
,
93 Query
.FilterOperator
.GREATER_THAN
,
94 getMetadataKeyForBlobKey(previousBlob
));
97 final Iterator
<Entity
> parent
= datastoreService
.prepare(query
).asIterator();
99 return new Iterator
<BlobInfo
>() {
100 public boolean hasNext() {
101 return parent
.hasNext();
104 public BlobInfo
next() {
105 return createBlobInfo(parent
.next());
108 public void remove() {
109 throw new UnsupportedOperationException();
115 * Creates a {@link BlobInfo} by extracting content from the
116 * specified {@link Entity}.
118 public BlobInfo
createBlobInfo(Entity entity
) {
119 if (entity
.hasProperty(MD5_HASH
)) {
121 new BlobKey(entity
.getKey().getName()),
122 (String
) entity
.getProperty(CONTENT_TYPE
),
123 (Date
) entity
.getProperty(CREATION
),
124 (String
) entity
.getProperty(FILENAME
),
125 (Long
) entity
.getProperty(SIZE
),
126 (String
) entity
.getProperty(MD5_HASH
));
129 new BlobKey(entity
.getKey().getName()),
130 (String
) entity
.getProperty(CONTENT_TYPE
),
131 (Date
) entity
.getProperty(CREATION
),
132 (String
) entity
.getProperty(FILENAME
),
133 (Long
) entity
.getProperty(SIZE
));
137 private Key
getMetadataKeyForBlobKey(BlobKey blobKey
) {
138 String origNamespace
= NamespaceManager
.get();
140 NamespaceManager
.set("");
141 return KeyFactory
.createKey(null, KIND
, blobKey
.getKeyString());
143 NamespaceManager
.set(origNamespace
);