1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.cache.browser.app.action;
35
36 import info.magnolia.cache.browser.app.CacheKeyItem;
37 import info.magnolia.cache.browser.rest.client.CacheService;
38 import info.magnolia.cache.browser.rest.endpoint.CacheEndpoint;
39 import info.magnolia.i18nsystem.SimpleTranslator;
40 import info.magnolia.ui.api.action.ActionExecutionException;
41 import info.magnolia.ui.api.context.UiContext;
42
43 import java.io.ByteArrayInputStream;
44 import java.io.ByteArrayOutputStream;
45 import java.io.IOException;
46 import java.io.InputStream;
47 import java.util.HashMap;
48 import java.util.List;
49 import java.util.Map;
50 import java.util.zip.ZipEntry;
51 import java.util.zip.ZipOutputStream;
52
53 import javax.ws.rs.ClientErrorException;
54
55 import org.apache.commons.io.IOUtils;
56 import org.apache.commons.lang3.StringUtils;
57 import com.fasterxml.jackson.databind.JsonNode;
58
59 import com.cedarsoftware.util.io.JsonWriter;
60 import com.vaadin.server.Page;
61 import com.vaadin.server.StreamResource;
62 import com.vaadin.v7.data.Item;
63
64
65
66
67 public class DownloadCacheContentAction extends AbstractMultiItemAction<DownloadCacheContentActionDefinition> {
68
69 private static final String DEFAULT_NAME = "untitled";
70 private static final String CONTENT_TYPE = "application/octet-stream";
71 private Map<String, byte[]> cacheContents = new HashMap<>();
72
73 public DownloadCacheContentAction(DownloadCacheContentActionDefinition definition, Item relatedItem, UiContext uiContext, SimpleTranslator i18n) {
74 super(definition, relatedItem, uiContext, i18n);
75 }
76
77 public DownloadCacheContentAction(DownloadCacheContentActionDefinition definition, List<Item> relatedItems, UiContext uiContext, SimpleTranslator i18n) {
78 super(definition, relatedItems, uiContext, i18n);
79 }
80
81 @Override
82 public void execute() throws ActionExecutionException {
83 super.execute();
84 if (cacheContents.size() == 1) {
85 Map.Entry<String, byte[]> entry = cacheContents.entrySet().iterator().next();
86 downloadFile(entry.getKey(), entry.getValue());
87 } else if (cacheContents.size() > 1) {
88 try {
89 zipAndDownloadFile(cacheContents);
90 } catch (IOException e) {
91 throw new ActionExecutionException(e.getMessage());
92 }
93 }
94 }
95
96 @Override
97 protected void executeOnItem(Item item) throws Exception {
98 if (item instanceof CacheKeyItem) {
99 CacheKeyItem cacheKeyItem = (CacheKeyItem) item;
100 if (cacheKeyItem.getCacheServices().size() > 0) {
101 for (Map.Entry<String, CacheService> entry : cacheKeyItem.getCacheServices().entrySet()) {
102 String location = entry.getKey();
103 CacheService cacheService = entry.getValue();
104 JsonNode jsonNode;
105 try {
106 jsonNode = cacheService.getCacheContent(cacheKeyItem.getCacheName(), JsonWriter.objectToJson(cacheKeyItem.getItemId()));
107 } catch (ClientErrorException e) {
108 JsonNode errorNode = (JsonNode) e.getResponse().getEntity();
109 throw new ActionExecutionException(errorNode.get(CacheEndpoint.PROPERTY_ERROR_MESSAGE).textValue());
110 }
111 if (jsonNode.has(CacheEndpoint.PROPERTY_UNSUPPORTED_CACHED_ENTRY_TYPE)) {
112 throw new ActionExecutionException(jsonNode.get(CacheEndpoint.PROPERTY_UNSUPPORTED_CACHED_ENTRY_TYPE).textValue());
113 }
114 String originalUrl = jsonNode.get(CacheEndpoint.PROPERTY_ORIGINAL_URL).textValue();
115 byte[] data = jsonNode.get(CacheEndpoint.PROPERTY_PLAIN_CONTENT).binaryValue();
116 String name = StringUtils.substringAfterLast(originalUrl, "/");
117 if (StringUtils.isBlank(name) || "/".equals(name)) {
118 name = DEFAULT_NAME;
119 }
120 name = location + "_" + name;
121 cacheContents.put(name, data);
122 }
123 }
124 }
125 }
126
127 @Override
128 protected String getSuccessMessageKey() {
129 return null;
130 }
131
132 @Override
133 protected String getFailureMessageKey() {
134 return "cache-browser-app.actions.download.error";
135 }
136
137 @Override
138 protected String itemToString(Item item) {
139 if (item instanceof CacheKeyItem) {
140 return ((CacheKeyItem) item).getItemId().toString();
141 }
142 return null;
143 }
144
145 protected void zipAndDownloadFile(Map<String, byte[]> cacheContents) throws IOException {
146 ByteArrayOutputStream baos = new ByteArrayOutputStream();
147 ZipOutputStream zos = new ZipOutputStream(baos);
148 for (Map.Entry<String, byte[]> entry : cacheContents.entrySet()) {
149 String name = entry.getKey();
150 byte[] data = entry.getValue();
151 ZipEntry zipEntry = new ZipEntry(name);
152 zipEntry.setSize(data.length);
153 zos.putNextEntry(zipEntry);
154 zos.write(data);
155 zos.closeEntry();
156 }
157 IOUtils.closeQuietly(zos);
158 downloadFile("cacheContent.zip", baos.toByteArray());
159 }
160
161 protected void downloadFile(String fileName, final byte[] data) {
162 StreamResource.StreamSource source = new StreamResource.StreamSource() {
163 @Override
164 public InputStream getStream() {
165 return new ByteArrayInputStream(data);
166 }
167 };
168 fileName = fileName.replaceAll("[^a-zA-Z0-9\\.]+", "-");
169 StreamResource resource = new StreamResource(source, fileName);
170
171
172
173 resource.setCacheTime(-1);
174 resource.getStream().setParameter("Content-Disposition", String.format("attachment; filename=\"%s\"", fileName));
175 resource.setMIMEType(CONTENT_TYPE);
176
177 Page.getCurrent().open(resource, null, false);
178 }
179 }