diff options
author | Kristóf Marussy <kristof@marussy.com> | 2021-10-07 16:26:05 +0200 |
---|---|---|
committer | Kristóf Marussy <kristof@marussy.com> | 2021-10-07 16:26:05 +0200 |
commit | 814295eecc10b7a87694b25c347d0821e3502c92 (patch) | |
tree | 96101ca9981cdbf518effc358c95357a4e9f3503 /language-web/src | |
parent | ci(web): no typescript 4.4 features in Sonar (diff) | |
download | refinery-814295eecc10b7a87694b25c347d0821e3502c92.tar.gz refinery-814295eecc10b7a87694b25c347d0821e3502c92.tar.zst refinery-814295eecc10b7a87694b25c347d0821e3502c92.zip |
chore(web): bump Jetty version
Requred vendoring org.eclipse.xtext.web.servlet as
tools.refinery.language.web.xtext due to the javax -> jakarta package
name change:
https://www.eclipse.org/lists/jetty-announce/msg00149.html
Diffstat (limited to 'language-web/src')
6 files changed, 383 insertions, 35 deletions
diff --git a/language-web/src/main/java/tools/refinery/language/web/CacheControlFilter.java b/language-web/src/main/java/tools/refinery/language/web/CacheControlFilter.java index e39ce54c..cf4c00fa 100644 --- a/language-web/src/main/java/tools/refinery/language/web/CacheControlFilter.java +++ b/language-web/src/main/java/tools/refinery/language/web/CacheControlFilter.java | |||
@@ -3,14 +3,14 @@ package tools.refinery.language.web; | |||
3 | import java.io.IOException; | 3 | import java.io.IOException; |
4 | import java.util.regex.Pattern; | 4 | import java.util.regex.Pattern; |
5 | 5 | ||
6 | import javax.servlet.Filter; | 6 | import jakarta.servlet.Filter; |
7 | import javax.servlet.FilterChain; | 7 | import jakarta.servlet.FilterChain; |
8 | import javax.servlet.FilterConfig; | 8 | import jakarta.servlet.FilterConfig; |
9 | import javax.servlet.ServletException; | 9 | import jakarta.servlet.ServletException; |
10 | import javax.servlet.ServletRequest; | 10 | import jakarta.servlet.ServletRequest; |
11 | import javax.servlet.ServletResponse; | 11 | import jakarta.servlet.ServletResponse; |
12 | import javax.servlet.http.HttpServletRequest; | 12 | import jakarta.servlet.http.HttpServletRequest; |
13 | import javax.servlet.http.HttpServletResponse; | 13 | import jakarta.servlet.http.HttpServletResponse; |
14 | 14 | ||
15 | public class CacheControlFilter implements Filter { | 15 | public class CacheControlFilter implements Filter { |
16 | 16 | ||
diff --git a/language-web/src/main/java/tools/refinery/language/web/ProblemServlet.java b/language-web/src/main/java/tools/refinery/language/web/ProblemServlet.java index d249525f..49457002 100644 --- a/language-web/src/main/java/tools/refinery/language/web/ProblemServlet.java +++ b/language-web/src/main/java/tools/refinery/language/web/ProblemServlet.java | |||
@@ -3,29 +3,27 @@ | |||
3 | */ | 3 | */ |
4 | package tools.refinery.language.web; | 4 | package tools.refinery.language.web; |
5 | 5 | ||
6 | import javax.servlet.ServletException; | ||
7 | |||
8 | import org.eclipse.xtext.util.DisposableRegistry; | 6 | import org.eclipse.xtext.util.DisposableRegistry; |
9 | import org.eclipse.xtext.web.servlet.XtextServlet; | 7 | |
8 | import jakarta.servlet.ServletException; | ||
9 | import tools.refinery.language.web.xtext.XtextServlet; | ||
10 | 10 | ||
11 | /** | 11 | /** |
12 | * Deploy this class into a servlet container to enable DSL-specific services. | 12 | * Deploy this class into a servlet container to enable DSL-specific services. |
13 | */ | 13 | */ |
14 | public class ProblemServlet extends XtextServlet { | 14 | public class ProblemServlet extends XtextServlet { |
15 | 15 | ||
16 | private static final long serialVersionUID = 1L; | 16 | private static final long serialVersionUID = -9204695886561362912L; |
17 | 17 | ||
18 | // Xtext requires a mutable servlet instance field. | 18 | private transient DisposableRegistry disposableRegistry; |
19 | @SuppressWarnings("squid:S2226") | 19 | |
20 | private DisposableRegistry disposableRegistry; | ||
21 | |||
22 | @Override | 20 | @Override |
23 | public void init() throws ServletException { | 21 | public void init() throws ServletException { |
24 | super.init(); | 22 | super.init(); |
25 | var injector = new ProblemWebSetup().createInjectorAndDoEMFRegistration(); | 23 | var injector = new ProblemWebSetup().createInjectorAndDoEMFRegistration(); |
26 | this.disposableRegistry = injector.getInstance(DisposableRegistry.class); | 24 | this.disposableRegistry = injector.getInstance(DisposableRegistry.class); |
27 | } | 25 | } |
28 | 26 | ||
29 | @Override | 27 | @Override |
30 | public void destroy() { | 28 | public void destroy() { |
31 | if (disposableRegistry != null) { | 29 | if (disposableRegistry != null) { |
@@ -34,5 +32,5 @@ public class ProblemServlet extends XtextServlet { | |||
34 | } | 32 | } |
35 | super.destroy(); | 33 | super.destroy(); |
36 | } | 34 | } |
37 | 35 | ||
38 | } | 36 | } |
diff --git a/language-web/src/main/java/tools/refinery/language/web/ServerLauncher.java b/language-web/src/main/java/tools/refinery/language/web/ServerLauncher.java index c6ee94dc..c253422b 100644 --- a/language-web/src/main/java/tools/refinery/language/web/ServerLauncher.java +++ b/language-web/src/main/java/tools/refinery/language/web/ServerLauncher.java | |||
@@ -11,16 +11,17 @@ import java.net.URISyntaxException; | |||
11 | import java.util.EnumSet; | 11 | import java.util.EnumSet; |
12 | import java.util.Set; | 12 | import java.util.Set; |
13 | 13 | ||
14 | import javax.servlet.DispatcherType; | ||
15 | import javax.servlet.SessionTrackingMode; | ||
16 | |||
17 | import org.eclipse.jetty.server.Server; | 14 | import org.eclipse.jetty.server.Server; |
18 | import org.eclipse.jetty.server.session.SessionHandler; | 15 | import org.eclipse.jetty.server.session.SessionHandler; |
19 | import org.eclipse.jetty.servlet.DefaultServlet; | 16 | import org.eclipse.jetty.servlet.DefaultServlet; |
20 | import org.eclipse.jetty.servlet.ServletContextHandler; | 17 | import org.eclipse.jetty.servlet.ServletContextHandler; |
21 | import org.eclipse.jetty.servlet.ServletHolder; | 18 | import org.eclipse.jetty.servlet.ServletHolder; |
22 | import org.eclipse.jetty.util.log.Slf4jLog; | ||
23 | import org.eclipse.jetty.util.resource.Resource; | 19 | import org.eclipse.jetty.util.resource.Resource; |
20 | import org.slf4j.Logger; | ||
21 | import org.slf4j.LoggerFactory; | ||
22 | |||
23 | import jakarta.servlet.DispatcherType; | ||
24 | import jakarta.servlet.SessionTrackingMode; | ||
24 | 25 | ||
25 | public class ServerLauncher { | 26 | public class ServerLauncher { |
26 | public static final String DEFAULT_LISTEN_ADDRESS = "localhost"; | 27 | public static final String DEFAULT_LISTEN_ADDRESS = "localhost"; |
@@ -30,7 +31,7 @@ public class ServerLauncher { | |||
30 | // Use this cookie name for load balancing. | 31 | // Use this cookie name for load balancing. |
31 | public static final String SESSION_COOKIE_NAME = "JSESSIONID"; | 32 | public static final String SESSION_COOKIE_NAME = "JSESSIONID"; |
32 | 33 | ||
33 | private static final Slf4jLog LOG = new Slf4jLog(ServerLauncher.class.getName()); | 34 | private static final Logger LOG = LoggerFactory.getLogger(ServerLauncher.class); |
34 | 35 | ||
35 | private final Server server; | 36 | private final Server server; |
36 | 37 | ||
@@ -71,15 +72,8 @@ public class ServerLauncher { | |||
71 | 72 | ||
72 | public void start() throws Exception { | 73 | public void start() throws Exception { |
73 | server.start(); | 74 | server.start(); |
74 | LOG.info("Server started " + server.getURI() + "..."); | 75 | LOG.info("Server started on {}", server.getURI()); |
75 | LOG.info("Press enter to stop the server..."); | 76 | server.join(); |
76 | int key = System.in.read(); | ||
77 | if (key != -1) { | ||
78 | server.stop(); | ||
79 | } else { | ||
80 | LOG.warn("Console input is not available. " | ||
81 | + "In order to stop the server, you need to cancel process manually."); | ||
82 | } | ||
83 | } | 77 | } |
84 | 78 | ||
85 | public static void main(String[] args) { | 79 | public static void main(String[] args) { |
@@ -89,7 +83,7 @@ public class ServerLauncher { | |||
89 | var serverLauncher = new ServerLauncher(bindAddress, baseResource); | 83 | var serverLauncher = new ServerLauncher(bindAddress, baseResource); |
90 | serverLauncher.start(); | 84 | serverLauncher.start(); |
91 | } catch (Exception exception) { | 85 | } catch (Exception exception) { |
92 | LOG.warn(exception); | 86 | LOG.error("Fatal server error", exception); |
93 | System.exit(1); | 87 | System.exit(1); |
94 | } | 88 | } |
95 | } | 89 | } |
diff --git a/language-web/src/main/java/tools/refinery/language/web/xtext/HttpServiceContext.java b/language-web/src/main/java/tools/refinery/language/web/xtext/HttpServiceContext.java new file mode 100644 index 00000000..d0ba6a2d --- /dev/null +++ b/language-web/src/main/java/tools/refinery/language/web/xtext/HttpServiceContext.java | |||
@@ -0,0 +1,107 @@ | |||
1 | /** | ||
2 | * Copyright (c) 2015, 2020 itemis AG (http://www.itemis.eu) and others. | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-2.0. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | */ | ||
9 | package tools.refinery.language.web.xtext; | ||
10 | |||
11 | import java.io.IOException; | ||
12 | import java.net.URLDecoder; | ||
13 | import java.nio.charset.Charset; | ||
14 | import java.util.Collections; | ||
15 | import java.util.Enumeration; | ||
16 | import java.util.HashMap; | ||
17 | import java.util.Map; | ||
18 | import java.util.Set; | ||
19 | |||
20 | import org.eclipse.xtext.web.server.IServiceContext; | ||
21 | import org.eclipse.xtext.web.server.ISession; | ||
22 | |||
23 | import com.google.common.io.CharStreams; | ||
24 | |||
25 | import jakarta.servlet.http.HttpServletRequest; | ||
26 | |||
27 | /** | ||
28 | * Provides the parameters and metadata of an {@link HttpServletRequest}. | ||
29 | */ | ||
30 | class HttpServiceContext implements IServiceContext { | ||
31 | private final HttpServletRequest request; | ||
32 | |||
33 | private final Map<String, String> parameters = new HashMap<>(); | ||
34 | |||
35 | private HttpSessionWrapper sessionWrapper; | ||
36 | |||
37 | public HttpServiceContext(HttpServletRequest request) throws IOException { | ||
38 | this.request = request; | ||
39 | initializeParameters(); | ||
40 | } | ||
41 | |||
42 | private void initializeParameters() throws IOException { | ||
43 | initializeUrlEncodedParameters(); | ||
44 | initializeRequestParameters(); | ||
45 | if (!parameters.containsKey(IServiceContext.SERVICE_TYPE)) { | ||
46 | String substring = null; | ||
47 | if (request.getPathInfo() != null) { | ||
48 | substring = request.getPathInfo().substring(1); | ||
49 | } | ||
50 | parameters.put(IServiceContext.SERVICE_TYPE, substring); | ||
51 | } | ||
52 | } | ||
53 | |||
54 | private void initializeUrlEncodedParameters() throws IOException { | ||
55 | String[] contentType = null; | ||
56 | if (request.getContentType() != null) { | ||
57 | contentType = request.getContentType().split(";(\\s*)"); | ||
58 | } | ||
59 | if (contentType != null && "application/x-www-form-urlencoded".equals(contentType[0])) { | ||
60 | String charset = null; | ||
61 | if (contentType.length >= 2 && contentType[1].startsWith("charset=")) { | ||
62 | charset = (contentType[1]).substring("charset=".length()); | ||
63 | } else { | ||
64 | charset = Charset.defaultCharset().toString(); | ||
65 | } | ||
66 | String[] encodedParams = CharStreams.toString(request.getReader()).split("&"); | ||
67 | for (String param : encodedParams) { | ||
68 | int nameEnd = param.indexOf("="); | ||
69 | if (nameEnd > 0) { | ||
70 | String key = param.substring(0, nameEnd); | ||
71 | String value = URLDecoder.decode(param.substring(nameEnd + 1), charset); | ||
72 | parameters.put(key, value); | ||
73 | } | ||
74 | } | ||
75 | } | ||
76 | } | ||
77 | |||
78 | private void initializeRequestParameters() { | ||
79 | Enumeration<String> paramNames = request.getParameterNames(); | ||
80 | while (paramNames.hasMoreElements()) { | ||
81 | String name = paramNames.nextElement(); | ||
82 | parameters.put(name, request.getParameter(name)); | ||
83 | } | ||
84 | } | ||
85 | |||
86 | @Override | ||
87 | public Set<String> getParameterKeys() { | ||
88 | return Collections.unmodifiableSet(parameters.keySet()); | ||
89 | } | ||
90 | |||
91 | @Override | ||
92 | public String getParameter(String key) { | ||
93 | return parameters.get(key); | ||
94 | } | ||
95 | |||
96 | @Override | ||
97 | public ISession getSession() { | ||
98 | if (sessionWrapper == null) { | ||
99 | sessionWrapper = new HttpSessionWrapper(request.getSession(true)); | ||
100 | } | ||
101 | return sessionWrapper; | ||
102 | } | ||
103 | |||
104 | public HttpServletRequest getRequest() { | ||
105 | return request; | ||
106 | } | ||
107 | } | ||
diff --git a/language-web/src/main/java/tools/refinery/language/web/xtext/HttpSessionWrapper.java b/language-web/src/main/java/tools/refinery/language/web/xtext/HttpSessionWrapper.java new file mode 100644 index 00000000..8a5e19ba --- /dev/null +++ b/language-web/src/main/java/tools/refinery/language/web/xtext/HttpSessionWrapper.java | |||
@@ -0,0 +1,53 @@ | |||
1 | /** | ||
2 | * Copyright (c) 2015, 2020 itemis AG (http://www.itemis.eu) and others. | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-2.0. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | */ | ||
9 | package tools.refinery.language.web.xtext; | ||
10 | |||
11 | import org.eclipse.xtext.web.server.ISession; | ||
12 | import org.eclipse.xtext.xbase.lib.Functions.Function0; | ||
13 | |||
14 | import jakarta.servlet.http.HttpSession; | ||
15 | |||
16 | /** | ||
17 | * Provides access to the information stored in a {@link HttpSession}. | ||
18 | */ | ||
19 | record HttpSessionWrapper(HttpSession session) implements ISession { | ||
20 | @SuppressWarnings("unchecked") | ||
21 | @Override | ||
22 | public <T> T get(Object key) { | ||
23 | return (T) session.getAttribute(key.toString()); | ||
24 | } | ||
25 | |||
26 | @Override | ||
27 | public <T> T get(Object key, Function0<? extends T> factory) { | ||
28 | synchronized (session) { | ||
29 | T sessionValue = get(key); | ||
30 | if (sessionValue != null) { | ||
31 | return sessionValue; | ||
32 | } else { | ||
33 | T factoryValue = factory.apply(); | ||
34 | put(key, factoryValue); | ||
35 | return factoryValue; | ||
36 | } | ||
37 | } | ||
38 | } | ||
39 | |||
40 | @Override | ||
41 | public void put(Object key, Object value) { | ||
42 | session.setAttribute(key.toString(), value); | ||
43 | } | ||
44 | |||
45 | @Override | ||
46 | public void remove(Object key) { | ||
47 | session.removeAttribute(key.toString()); | ||
48 | } | ||
49 | |||
50 | public HttpSession getSession() { | ||
51 | return session; | ||
52 | } | ||
53 | } | ||
diff --git a/language-web/src/main/java/tools/refinery/language/web/xtext/XtextServlet.java b/language-web/src/main/java/tools/refinery/language/web/xtext/XtextServlet.java new file mode 100644 index 00000000..f39bec12 --- /dev/null +++ b/language-web/src/main/java/tools/refinery/language/web/xtext/XtextServlet.java | |||
@@ -0,0 +1,196 @@ | |||
1 | /** | ||
2 | * Copyright (c) 2015, 2020 itemis AG (http://www.itemis.eu) and others. | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-2.0. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | */ | ||
9 | package tools.refinery.language.web.xtext; | ||
10 | |||
11 | import java.io.IOException; | ||
12 | import java.util.Set; | ||
13 | |||
14 | import org.eclipse.emf.common.util.URI; | ||
15 | import org.eclipse.xtext.resource.IResourceServiceProvider; | ||
16 | import org.eclipse.xtext.web.server.IServiceContext; | ||
17 | import org.eclipse.xtext.web.server.IServiceResult; | ||
18 | import org.eclipse.xtext.web.server.IUnwrappableServiceResult; | ||
19 | import org.eclipse.xtext.web.server.InvalidRequestException; | ||
20 | import org.eclipse.xtext.web.server.XtextServiceDispatcher; | ||
21 | import org.slf4j.Logger; | ||
22 | import org.slf4j.LoggerFactory; | ||
23 | |||
24 | import com.google.common.base.Objects; | ||
25 | import com.google.common.base.Strings; | ||
26 | import com.google.gson.Gson; | ||
27 | import com.google.inject.Injector; | ||
28 | |||
29 | import jakarta.servlet.ServletException; | ||
30 | import jakarta.servlet.http.HttpServlet; | ||
31 | import jakarta.servlet.http.HttpServletRequest; | ||
32 | import jakarta.servlet.http.HttpServletResponse; | ||
33 | |||
34 | /** | ||
35 | * An HTTP servlet for publishing the Xtext services. Include this into your web | ||
36 | * server by creating a subclass that executes the standalone setups of your | ||
37 | * languages in its {@link #init()} method: | ||
38 | * | ||
39 | * <pre> | ||
40 | * @WebServlet(name = "Xtext Services", urlPatterns = "/xtext-service/*") | ||
41 | * class MyXtextServlet extends XtextServlet { | ||
42 | * override init() { | ||
43 | * super.init(); | ||
44 | * MyDslWebSetup.doSetup(); | ||
45 | * } | ||
46 | * } | ||
47 | * </pre> | ||
48 | * | ||
49 | * Use the {@code WebServlet} annotation to register your servlet. The default | ||
50 | * URL pattern for Xtext services is {@code "/xtext-service/*"}. | ||
51 | */ | ||
52 | public class XtextServlet extends HttpServlet { | ||
53 | |||
54 | private static final long serialVersionUID = 7784324070547781918L; | ||
55 | |||
56 | private static final IResourceServiceProvider.Registry SERVICE_PROVIDER_REGISTRY = IResourceServiceProvider.Registry.INSTANCE; | ||
57 | |||
58 | private static final String ENCODING = "UTF-8"; | ||
59 | |||
60 | private static final String INVALID_REQUEST_MESSAGE = "Invalid request ({}): {}"; | ||
61 | |||
62 | private final transient Logger log = LoggerFactory.getLogger(this.getClass()); | ||
63 | |||
64 | private final transient Gson gson = new Gson(); | ||
65 | |||
66 | @Override | ||
67 | protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { | ||
68 | try { | ||
69 | super.service(req, resp); | ||
70 | } catch (InvalidRequestException.ResourceNotFoundException exception) { | ||
71 | log.trace(INVALID_REQUEST_MESSAGE, req.getRequestURI(), exception.getMessage()); | ||
72 | resp.sendError(HttpServletResponse.SC_NOT_FOUND, exception.getMessage()); | ||
73 | } catch (InvalidRequestException.InvalidDocumentStateException exception) { | ||
74 | log.trace(INVALID_REQUEST_MESSAGE, req.getRequestURI(), exception.getMessage()); | ||
75 | resp.sendError(HttpServletResponse.SC_CONFLICT, exception.getMessage()); | ||
76 | } catch (InvalidRequestException.PermissionDeniedException exception) { | ||
77 | log.trace(INVALID_REQUEST_MESSAGE, req.getRequestURI(), exception.getMessage()); | ||
78 | resp.sendError(HttpServletResponse.SC_FORBIDDEN, exception.getMessage()); | ||
79 | } catch (InvalidRequestException exception) { | ||
80 | log.trace(INVALID_REQUEST_MESSAGE, req.getRequestURI(), exception.getMessage()); | ||
81 | resp.sendError(HttpServletResponse.SC_BAD_REQUEST, exception.getMessage()); | ||
82 | } | ||
83 | } | ||
84 | |||
85 | @Override | ||
86 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { | ||
87 | XtextServiceDispatcher.ServiceDescriptor service = getService(req); | ||
88 | if (!service.isHasConflict() && (service.isHasSideEffects() || hasTextInput(service))) { | ||
89 | super.doGet(req, resp); | ||
90 | } else { | ||
91 | doService(service, resp); | ||
92 | } | ||
93 | } | ||
94 | |||
95 | @Override | ||
96 | protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { | ||
97 | XtextServiceDispatcher.ServiceDescriptor service = getService(req); | ||
98 | String type = service.getContext().getParameter(IServiceContext.SERVICE_TYPE); | ||
99 | if (!service.isHasConflict() && !Objects.equal(type, "update")) { | ||
100 | super.doPut(req, resp); | ||
101 | } else { | ||
102 | doService(service, resp); | ||
103 | } | ||
104 | } | ||
105 | |||
106 | @Override | ||
107 | protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { | ||
108 | XtextServiceDispatcher.ServiceDescriptor service = getService(req); | ||
109 | String type = service.getContext().getParameter(IServiceContext.SERVICE_TYPE); | ||
110 | if (!service.isHasConflict() | ||
111 | && (!service.isHasSideEffects() && !hasTextInput(service) || Objects.equal(type, "update"))) { | ||
112 | super.doPost(req, resp); | ||
113 | } else { | ||
114 | doService(service, resp); | ||
115 | } | ||
116 | } | ||
117 | |||
118 | protected boolean hasTextInput(XtextServiceDispatcher.ServiceDescriptor service) { | ||
119 | Set<String> parameterKeys = service.getContext().getParameterKeys(); | ||
120 | return parameterKeys.contains("fullText") || parameterKeys.contains("deltaText"); | ||
121 | } | ||
122 | |||
123 | /** | ||
124 | * Retrieve the service metadata for the given request. This involves resolving | ||
125 | * the Guice injector for the respective language, querying the | ||
126 | * {@link XtextServiceDispatcher}, and checking the permission to invoke the | ||
127 | * service. | ||
128 | */ | ||
129 | protected XtextServiceDispatcher.ServiceDescriptor getService(HttpServletRequest request) throws IOException { | ||
130 | HttpServiceContext serviceContext = new HttpServiceContext(request); | ||
131 | Injector injector = getInjector(serviceContext); | ||
132 | XtextServiceDispatcher serviceDispatcher = injector.getInstance(XtextServiceDispatcher.class); | ||
133 | return serviceDispatcher.getService(serviceContext); | ||
134 | } | ||
135 | |||
136 | /** | ||
137 | * Invoke the service function of the given service descriptor and write its | ||
138 | * result to the servlet response in Json format. An exception is made for | ||
139 | * {@link IUnwrappableServiceResult}: here the document itself is written into | ||
140 | * the response instead of wrapping it into a Json object. | ||
141 | */ | ||
142 | protected void doService(XtextServiceDispatcher.ServiceDescriptor service, HttpServletResponse response) | ||
143 | throws IOException { | ||
144 | IServiceResult result = service.getService().apply(); | ||
145 | response.setStatus(HttpServletResponse.SC_OK); | ||
146 | response.setCharacterEncoding(ENCODING); | ||
147 | response.setHeader("Cache-Control", "no-cache"); | ||
148 | if (result instanceof IUnwrappableServiceResult unwrapResult && unwrapResult.getContent() != null) { | ||
149 | String contentType = null; | ||
150 | if (unwrapResult.getContentType() != null) { | ||
151 | contentType = unwrapResult.getContentType(); | ||
152 | } else { | ||
153 | contentType = "text/plain"; | ||
154 | } | ||
155 | response.setContentType(contentType); | ||
156 | response.getWriter().write(unwrapResult.getContent()); | ||
157 | } else { | ||
158 | response.setContentType("text/x-json"); | ||
159 | gson.toJson(result, response.getWriter()); | ||
160 | } | ||
161 | } | ||
162 | |||
163 | /** | ||
164 | * Resolve the Guice injector for the language associated with the given | ||
165 | * context. | ||
166 | */ | ||
167 | protected Injector getInjector(HttpServiceContext serviceContext) | ||
168 | throws InvalidRequestException.UnknownLanguageException { | ||
169 | IResourceServiceProvider resourceServiceProvider = null; | ||
170 | String parameter = serviceContext.getParameter("resource"); | ||
171 | if (parameter == null) { | ||
172 | parameter = ""; | ||
173 | } | ||
174 | URI emfURI = URI.createURI(parameter); | ||
175 | String contentType = serviceContext.getParameter("contentType"); | ||
176 | if (Strings.isNullOrEmpty(contentType)) { | ||
177 | resourceServiceProvider = SERVICE_PROVIDER_REGISTRY.getResourceServiceProvider(emfURI); | ||
178 | if (resourceServiceProvider == null) { | ||
179 | if (emfURI.toString().isEmpty()) { | ||
180 | throw new InvalidRequestException.UnknownLanguageException( | ||
181 | "Unable to identify the Xtext language: missing parameter 'resource' or 'contentType'."); | ||
182 | } else { | ||
183 | throw new InvalidRequestException.UnknownLanguageException( | ||
184 | "Unable to identify the Xtext language for resource " + emfURI + "."); | ||
185 | } | ||
186 | } | ||
187 | } else { | ||
188 | resourceServiceProvider = SERVICE_PROVIDER_REGISTRY.getResourceServiceProvider(emfURI, contentType); | ||
189 | if (resourceServiceProvider == null) { | ||
190 | throw new InvalidRequestException.UnknownLanguageException( | ||
191 | "Unable to identify the Xtext language for contentType " + contentType + "."); | ||
192 | } | ||
193 | } | ||
194 | return resourceServiceProvider.get(Injector.class); | ||
195 | } | ||
196 | } \ No newline at end of file | ||