1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.apache.struts2.rest;
23
24 import com.opensymphony.xwork2.ModelDriven;
25 import com.opensymphony.xwork2.config.entities.ActionConfig;
26 import com.opensymphony.xwork2.inject.Container;
27 import com.opensymphony.xwork2.inject.Inject;
28 import org.apache.struts2.ServletActionContext;
29 import org.apache.struts2.rest.handler.ContentTypeHandler;
30
31 import javax.servlet.http.HttpServletRequest;
32 import javax.servlet.http.HttpServletResponse;
33 import static javax.servlet.http.HttpServletResponse.SC_NOT_MODIFIED;
34 import static javax.servlet.http.HttpServletResponse.SC_OK;
35 import java.io.ByteArrayOutputStream;
36 import java.io.IOException;
37 import java.io.StringWriter;
38 import java.util.HashMap;
39 import java.util.Map;
40 import java.util.Set;
41
42 /***
43 * Manages {@link ContentTypeHandler} instances and uses them to
44 * process results
45 */
46 public class ContentTypeHandlerManager {
47
48 Map<String,ContentTypeHandler> handlers = new HashMap<String,ContentTypeHandler>();
49 String defaultExtension;
50 public static final String STRUTS_REST_HANDLER_OVERRIDE_PREFIX = "struts.rest.handlerOverride.";
51
52 @Inject("struts.rest.defaultExtension")
53 public void setDefaultExtension(String name) {
54 this.defaultExtension = name;
55 }
56
57 @Inject
58 public void setContainer(Container container) {
59 Set<String> names = container.getInstanceNames(ContentTypeHandler.class);
60 for (String name : names) {
61 ContentTypeHandler handler = container.getInstance(ContentTypeHandler.class, name);
62
63
64 String overrideName = container.getInstance(String.class, STRUTS_REST_HANDLER_OVERRIDE_PREFIX +handler.getExtension());
65 if (overrideName != null) {
66 if (!handlers.containsKey(handler.getExtension())) {
67 handler = container.getInstance(ContentTypeHandler.class, overrideName);
68 } else {
69
70 continue;
71 }
72 }
73 this.handlers.put(handler.getExtension(), handler);
74 }
75 }
76
77 /***
78 * Gets the handler for the request by looking at the extension
79 * @param req The request
80 * @return The appropriate handler
81 */
82 public ContentTypeHandler getHandlerForRequest(HttpServletRequest req) {
83 String extension = findExtension(req.getRequestURI());
84 if (extension == null) {
85 extension = defaultExtension;
86 }
87 return handlers.get(extension);
88 }
89
90 /***
91 * Handles the result using handlers to generate content type-specific content
92 *
93 * @param actionConfig The action config for the current request
94 * @param methodResult The object returned from the action method
95 * @param target The object to return, usually the action object
96 * @return The new result code to process
97 * @throws IOException If unable to write to the response
98 */
99 public String handleResult(ActionConfig actionConfig, Object methodResult, Object target)
100 throws IOException {
101 String resultCode = null;
102 HttpServletRequest req = ServletActionContext.getRequest();
103 HttpServletResponse res = ServletActionContext.getResponse();
104 if (target instanceof ModelDriven) {
105 target = ((ModelDriven)target).getModel();
106 }
107
108 boolean statusNotOk = false;
109 if (methodResult instanceof HttpHeaders) {
110 HttpHeaders info = (HttpHeaders) methodResult;
111 resultCode = info.apply(req, res, target);
112 if (info.getStatus() != SC_OK) {
113
114
115 if (info.getStatus() == SC_NOT_MODIFIED) {
116 target = null;
117 } else {
118 statusNotOk = true;
119 }
120
121 }
122 } else {
123 resultCode = (String) methodResult;
124 }
125
126
127 if (!statusNotOk && !"get".equalsIgnoreCase(req.getMethod())) {
128 target = null;
129 }
130
131 ContentTypeHandler handler = getHandlerForRequest(req);
132 if (handler != null) {
133 String extCode = resultCode+"-"+handler.getExtension();
134 if (actionConfig.getResults().get(extCode) != null) {
135 resultCode = extCode;
136 } else {
137 StringWriter writer = new StringWriter();
138 resultCode = handler.fromObject(target, resultCode, writer);
139 String text = writer.toString();
140 if (text.length() > 0) {
141 byte[] data = text.getBytes("UTF-8");
142 res.setContentLength(data.length);
143 res.setContentType(handler.getContentType());
144 res.getOutputStream().write(data);
145 res.getOutputStream().close();
146 }
147 }
148 }
149 return resultCode;
150
151 }
152
153 /***
154 * Finds the extension in the url
155 *
156 * @param url The url
157 * @return The extension
158 */
159 protected String findExtension(String url) {
160 int dotPos = url.lastIndexOf('.');
161 int slashPos = url.lastIndexOf('/');
162 if (dotPos > slashPos && dotPos > -1) {
163 return url.substring(dotPos+1);
164 }
165 return null;
166 }
167 }