/**
* Copyright 2015 ArcBees Inc.
*
* Licensed 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 com.arcbees.gaestudio.testutil;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.io.IOUtils;
import org.mockito.ArgumentCaptor;
import com.google.appengine.api.blobstore.BlobKey;
import com.google.appengine.api.blobstore.BlobstoreService;
import com.google.appengine.api.blobstore.dev.UploadBlobServlet;
import com.google.appengine.tools.development.ApiProxyLocalFactory;
import com.google.appengine.tools.development.LocalServerEnvironment;
import com.google.inject.Inject;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
public class BlobGenerator {
private static final String BLOB_KEYS = "com.google.appengine.api.blobstore.upload.blobkeys";
private static final String MULTI_PART_BOUNDARY =
"multipart/form-data; boundary=----WebKitFormBoundary8wvYWW5KwfiI9Lzk";
private final BlobstoreService blobstoreService;
@Inject
BlobGenerator(BlobstoreService blobstoreService) {
this.blobstoreService = blobstoreService;
}
public BlobKey storeBlobFromFile(String path) throws IOException, ServletException {
UploadBlobServlet uploadBlobServlet = new UploadBlobServlet();
HttpServletRequest request = mockHttpServletRequest();
ServletConfig servletConfig = mockServletConfig();
writeDataToRequest(path, request);
uploadBlobServlet.init(servletConfig);
uploadBlobServlet.doPost(request, mock(HttpServletResponse.class));
return extractBlobKey(request);
}
private HttpServletRequest mockHttpServletRequest() {
String uploadUrl = blobstoreService.createUploadUrl("/upload");
uploadUrl = uploadUrl.substring(uploadUrl.lastIndexOf("/"));
HttpServletRequest request = mock(HttpServletRequest.class, RETURNS_DEEP_STUBS);
when(request.getPathInfo()).thenReturn(uploadUrl);
when(request.getContentType()).thenReturn(MULTI_PART_BOUNDARY);
return request;
}
private ServletConfig mockServletConfig() {
ServletConfig servletConfig = mock(ServletConfig.class);
ServletContext servletContext = mock(ServletContext.class, RETURNS_DEEP_STUBS);
when(servletContext.getAttribute(eq("com.google.appengine.devappserver.ApiProxyLocal")))
.thenReturn(new ApiProxyLocalFactory().create(mock(LocalServerEnvironment.class, RETURNS_DEEP_STUBS)));
when(servletConfig.getServletContext()).thenReturn(servletContext);
return servletConfig;
}
private void writeDataToRequest(String path, HttpServletRequest request) throws IOException {
InputStream stream = getClass().getResourceAsStream(path);
ByteArrayOutputStream out = new ByteArrayOutputStream();
out.write(("------WebKitFormBoundary8wvYWW5KwfiI9Lzk\n" +
"Content-Disposition: form-data; name=\"fileUpload\"; filename=\"filename\"\n" +
"Content-Type: application/octet-stream\n\n").getBytes());
IOUtils.copy(stream, out);
out.write("\n\n------WebKitFormBoundary8wvYWW5KwfiI9Lzk".getBytes());
when(request.getInputStream()).thenReturn(
new ServletInputStreamImpl(new ByteArrayInputStream(out.toByteArray())));
}
private BlobKey extractBlobKey(HttpServletRequest request) {
ArgumentCaptor<Map> requestCaptor = ArgumentCaptor.forClass(Map.class);
verify(request).setAttribute(eq(BLOB_KEYS), requestCaptor.capture());
Map<String, List<String>> uploads = requestCaptor.getValue();
for (List<String> blobKeys : uploads.values()) {
return new BlobKey(blobKeys.get(0));
}
return null;
}
private static class ServletInputStreamImpl extends ServletInputStream {
private final InputStream inputStream;
ServletInputStreamImpl(InputStream inputStream) {
this.inputStream = inputStream;
}
@Override
public int read() throws IOException {
return inputStream.read();
}
}
}