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.imaging;
35
36 import info.magnolia.context.MgnlContext;
37 import info.magnolia.imaging.util.PathSplitter;
38 import info.magnolia.init.MagnoliaConfigurationProperties;
39 import info.magnolia.objectfactory.Components;
40
41 import java.io.IOException;
42 import java.io.OutputStream;
43 import java.util.concurrent.ExecutorService;
44 import java.util.concurrent.Executors;
45
46 import javax.inject.Inject;
47 import javax.inject.Provider;
48 import javax.servlet.AsyncContext;
49 import javax.servlet.ServletException;
50 import javax.servlet.ServletResponse;
51 import javax.servlet.http.HttpServlet;
52 import javax.servlet.http.HttpServletRequest;
53 import javax.servlet.http.HttpServletResponse;
54
55 import org.slf4j.Logger;
56 import org.slf4j.LoggerFactory;
57
58 import com.google.common.net.MediaType;
59
60
61
62
63 public class ImagingServlet extends HttpServlet {
64 private static final Logger log = LoggerFactory.getLogger(ImagingServlet.class);
65 private final Imaging imaging;
66 private final Provider<ImagingModule> imagingModuleProvider;
67 private ExecutorService workers;
68
69
70 @Inject
71 public ImagingServlet(Imaging imaging, Provider<ImagingModule> imagingModuleProvider, MagnoliaConfigurationProperties mcp) {
72 this.imaging = imaging;
73 this.imagingModuleProvider = imagingModuleProvider;
74 int workersCount = 4;
75 if (mcp.hasProperty("imaging.workers.count")) {
76 try {
77 workersCount = Integer.parseInt(mcp.getProperty("imaging.workers.count"));
78 } catch (NumberFormatException e) {
79 log.error("Failed to parse the number of imaging workers, falling back to 4");
80 }
81 }
82 this.workers = Executors.newFixedThreadPool(workersCount);
83 }
84
85
86
87
88 @Deprecated
89 public ImagingServlet(Imaging imaging, Provider<ImagingModule> imagingModuleProvider) {
90 this(imaging, imagingModuleProvider, Components.getComponent(MagnoliaConfigurationProperties.class));
91 }
92
93
94
95
96 @Deprecated
97 public ImagingServlet(final ImagingModule imagingModule) {
98 this.imaging = Components.getComponent(Imaging.class);
99 this.imagingModuleProvider = new Provider<ImagingModule>() {
100 @Override
101 public ImagingModule get() {
102 return Components.getComponent(ImagingModule.class);
103 }
104 };
105 }
106
107
108 @Override
109 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
110 AsyncContext asyncContext = request.startAsync();
111 log.debug("Requesting {}", request.getRequestURI());
112 workers.submit(() -> {
113 MgnlContext.doInSystemContext(new MgnlContext.VoidOp() {
114
115 @Override
116 public void doExec() {
117 try {
118 String generatorName = getImageGeneratorName(request);
119 imaging.generate(generatorName, request, new ServletImageResponse(asyncContext.getResponse()));
120 log.debug("Generated image for {}", request.getRequestURI());
121 asyncContext.getResponse().flushBuffer();
122 } catch (IllegalArgumentException | ImagingRuntimeException | ImagingException e) {
123 log.warn("Because of incorrect arguments the image couldn't be found", e);
124 sendError(asyncContext, HttpServletResponse.SC_NOT_FOUND, "");
125 } catch (IOException e) {
126
127
128 log.debug("Unable to spool resource due to a {} exception", e.getClass().getName());
129 if (!asyncContext.getResponse().isCommitted()) {
130 sendError(asyncContext, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "");
131 }
132 } finally {
133 asyncContext.complete();
134 }
135 }
136 });
137
138 });
139 }
140
141
142 private void sendError(AsyncContext asyncContext, int statusCode, String message) {
143 if(asyncContext.getResponse() instanceof HttpServletResponse)
144 try {
145 ((HttpServletResponse) asyncContext.getResponse()).sendError(statusCode, message);
146 } catch (IOException e) {
147 e.printStackTrace();
148 }
149 }
150
151
152
153
154
155 protected String getImageGeneratorName(HttpServletRequest request) {
156 final String pathInfo = request.getPathInfo();
157 return new PathSplitter(pathInfo).skipTo(0);
158 }
159
160 protected ImageGenerator getGenerator(String generatorName) {
161 final ImagingModule module = getImagingModule();
162 return module.getGenerators().get(generatorName);
163 }
164
165 protected ImagingModule getImagingModule() {
166 return imagingModuleProvider.get();
167 }
168
169 private static class ServletImageResponse implements ImageResponse {
170 private final ServletResponse response;
171
172 public ServletImageResponse(ServletResponse response) {
173 this.response = response;
174 }
175
176 @Override
177 public void setMediaType(MediaType mediaType) throws IOException {
178 response.setContentType(mediaType.toString());
179 }
180
181 @Override
182 public OutputStream getOutputStream() throws IOException {
183 return response.getOutputStream();
184 }
185 }
186 }