/blobstore/src/main/java/org/jboss/capedwarf/blobstore/JBossBlobstoreService.java

https://github.com/luksa/capedwarf-blue · Java · 182 lines · 129 code · 27 blank · 26 comment · 14 complexity · 3ab3d600eab2aba2e94a18545d534a78 MD5 · raw file

  1. /*
  2. * JBoss, Home of Professional Open Source.
  3. * Copyright 2011, Red Hat, Inc., and individual contributors
  4. * as indicated by the @author tags. See the copyright.txt file in the
  5. * distribution for a full listing of individual contributors.
  6. *
  7. * This is free software; you can redistribute it and/or modify it
  8. * under the terms of the GNU Lesser General Public License as
  9. * published by the Free Software Foundation; either version 2.1 of
  10. * the License, or (at your option) any later version.
  11. *
  12. * This software is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with this software; if not, write to the Free
  19. * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  20. * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
  21. */
  22. package org.jboss.capedwarf.blobstore;
  23. import com.google.appengine.api.blobstore.*;
  24. import com.google.appengine.api.files.AppEngineFile;
  25. import com.google.appengine.api.files.FileServiceFactory;
  26. import org.jboss.capedwarf.common.io.IOUtils;
  27. import org.jboss.capedwarf.common.servlet.ServletUtils;
  28. import org.jboss.capedwarf.files.JBossFileService;
  29. import javax.servlet.ServletException;
  30. import javax.servlet.http.HttpServletRequest;
  31. import javax.servlet.http.HttpServletResponse;
  32. import javax.servlet.http.Part;
  33. import java.io.FileNotFoundException;
  34. import java.io.IOException;
  35. import java.io.InputStream;
  36. import java.io.OutputStream;
  37. import java.util.Enumeration;
  38. import java.util.HashMap;
  39. import java.util.List;
  40. import java.util.Map;
  41. /**
  42. * @author <a href="mailto:ales.justin@jboss.org">Ales Justin</a>
  43. * @author <a href="mailto:marko.luksa@gmail.com">Marko Luksa</a>
  44. */
  45. public class JBossBlobstoreService implements BlobstoreService {
  46. private static final String SERVE_HEADER = "X-AppEngine-BlobKey";
  47. private static final String UPLOADED_BLOBKEY_ATTR = "com.google.appengine.api.blobstore.upload.blobkeys";
  48. private static final String BLOB_RANGE_HEADER = "X-AppEngine-BlobRange";
  49. public String createUploadUrl(String successPath) {
  50. return createUploadUrl(successPath, UploadOptions.Builder.withDefaults());
  51. }
  52. public String createUploadUrl(String successPath, UploadOptions uploadOptions) {
  53. return UploadServlet.createUploadUrl(successPath, uploadOptions);
  54. }
  55. public void delete(BlobKey... blobKeys) {
  56. getFileService().delete(blobKeys);
  57. }
  58. public void serve(BlobKey blobKey, HttpServletResponse response) throws IOException {
  59. serve(blobKey, (ByteRange) null, response);
  60. }
  61. public void serve(BlobKey blobKey, String rangeHeader, HttpServletResponse response) throws IOException {
  62. serve(blobKey, ByteRange.parse(rangeHeader), response);
  63. }
  64. public void serve(BlobKey blobKey, ByteRange byteRange, HttpServletResponse response) throws IOException {
  65. assertNotCommited(response);
  66. try {
  67. InputStream in = getStream(blobKey);
  68. try {
  69. response.setStatus(HttpServletResponse.SC_OK);
  70. setHeaders(response, blobKey, byteRange);
  71. copyStream(in, response.getOutputStream(), byteRange);
  72. } finally {
  73. in.close();
  74. }
  75. } catch (FileNotFoundException e) {
  76. response.setStatus(HttpServletResponse.SC_NOT_FOUND);
  77. }
  78. }
  79. private void assertNotCommited(HttpServletResponse response) {
  80. if (response.isCommitted()) {
  81. throw new IllegalStateException("Response was already committed.");
  82. }
  83. }
  84. private void setHeaders(HttpServletResponse response, BlobKey blobKey, ByteRange byteRange) {
  85. response.setHeader(SERVE_HEADER, blobKey.getKeyString());
  86. if (byteRange != null) {
  87. response.setHeader(BLOB_RANGE_HEADER, byteRange.toString());
  88. }
  89. }
  90. private void copyStream(InputStream in, OutputStream out, ByteRange range) throws IOException {
  91. if (range == null) {
  92. IOUtils.copyStream(in, out);
  93. } else {
  94. if (range.hasEnd()) {
  95. long length = range.getEnd() + 1 - range.getStart(); // end is inclusive, hence +1
  96. IOUtils.copyStream(in, out, range.getStart(), length);
  97. } else {
  98. IOUtils.copyStream(in, out, range.getStart());
  99. }
  100. }
  101. }
  102. public byte[] fetchData(BlobKey blobKey, long start, long end) {
  103. try {
  104. InputStream stream = getStream(blobKey);
  105. return IOUtils.toBytes(stream, start, end, true);
  106. } catch (IOException e) {
  107. throw new IllegalStateException(e);
  108. }
  109. }
  110. @SuppressWarnings("unchecked")
  111. public ByteRange getByteRange(HttpServletRequest request) {
  112. Enumeration<String> rangeHeaders = request.getHeaders("range");
  113. if (!rangeHeaders.hasMoreElements()) {
  114. return null;
  115. }
  116. String rangeHeader = rangeHeaders.nextElement();
  117. if (rangeHeaders.hasMoreElements()) {
  118. throw new UnsupportedRangeFormatException("Cannot accept multiple range headers.");
  119. }
  120. return ByteRange.parse(rangeHeader);
  121. }
  122. public void storeUploadedBlobs(HttpServletRequest request) throws IOException, ServletException {
  123. Map<String, BlobKey> map = new HashMap<String, BlobKey>();
  124. for (Part part : request.getParts()) {
  125. if (ServletUtils.isFile(part)) {
  126. BlobKey blobKey = storeUploadedBlob(part);
  127. map.put(part.getName(), blobKey);
  128. }
  129. }
  130. request.setAttribute(UPLOADED_BLOBKEY_ATTR, map);
  131. }
  132. private BlobKey storeUploadedBlob(Part part) throws IOException {
  133. JBossFileService fileService = getFileService();
  134. // TODO -- this was changed due to new GAE API, check it?
  135. AppEngineFile file = fileService.createNewBlobFile(part.getContentType(), ServletUtils.getFileName(part));
  136. return fileService.getBlobKey(file);
  137. }
  138. @SuppressWarnings("unchecked")
  139. public Map<String, BlobKey> getUploadedBlobs(HttpServletRequest request) {
  140. Map<String, BlobKey> map = (Map<String, BlobKey>) request.getAttribute(UPLOADED_BLOBKEY_ATTR);
  141. if (map == null) {
  142. throw new IllegalStateException("Must be called from a blob upload callback request.");
  143. }
  144. return map;
  145. }
  146. public Map<String, List<BlobKey>> getUploads(HttpServletRequest httpServletRequest) {
  147. return new HashMap<String, List<BlobKey>>(); // TODO
  148. }
  149. public InputStream getStream(BlobKey blobKey) throws FileNotFoundException {
  150. return getFileService().getStream(blobKey);
  151. }
  152. private JBossFileService getFileService() {
  153. return (JBossFileService) FileServiceFactory.getFileService();
  154. }
  155. }