Skip to content

Commit 25b3113

Browse files
ischindlmerks
authored andcommitted
try to unify POST processing in servlets
1 parent 9f992ed commit 25b3113

File tree

3 files changed

+253
-387
lines changed

3 files changed

+253
-387
lines changed

viewer/org.eclipse.birt.report.viewer/birt/WEB-INF/classes/org/eclipse/birt/report/servlet/BaseReportEngineServlet.java

Lines changed: 238 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -14,24 +14,37 @@
1414
package org.eclipse.birt.report.servlet;
1515

1616
import java.io.IOException;
17-
18-
import jakarta.servlet.ServletConfig;
19-
import jakarta.servlet.ServletException;
20-
import jakarta.servlet.ServletRequest;
21-
import jakarta.servlet.ServletResponse;
22-
import jakarta.servlet.http.HttpServlet;
23-
import jakarta.servlet.http.HttpServletRequest;
24-
import jakarta.servlet.http.HttpServletResponse;
17+
import java.io.PrintWriter;
18+
import java.io.StringWriter;
19+
import java.nio.charset.StandardCharsets;
2520

2621
import org.eclipse.birt.core.exception.BirtException;
2722
import org.eclipse.birt.report.IBirtConstants;
23+
import org.eclipse.birt.report.context.BirtContext;
2824
import org.eclipse.birt.report.context.IContext;
25+
import org.eclipse.birt.report.exception.ViewerException;
2926
import org.eclipse.birt.report.presentation.aggregation.IFragment;
3027
import org.eclipse.birt.report.resource.BirtResources;
28+
import org.eclipse.birt.report.resource.ResourceConstants;
29+
import org.eclipse.birt.report.service.BirtReportServiceFactory;
3130
import org.eclipse.birt.report.session.IViewingSession;
3231
import org.eclipse.birt.report.session.ViewingSessionUtil;
32+
import org.eclipse.birt.report.soapengine.api.GetUpdatedObjects;
33+
import org.eclipse.birt.report.soapengine.api.GetUpdatedObjectsResponse;
34+
import org.eclipse.birt.report.soapengine.endpoint.BirtSoapBindingImpl;
35+
import org.eclipse.birt.report.soapengine.endpoint.BirtSoapException;
36+
import org.eclipse.birt.report.utility.BirtUtility;
3337
import org.eclipse.birt.report.utility.ParameterAccessor;
3438

39+
import jakarta.servlet.ServletConfig;
40+
import jakarta.servlet.ServletException;
41+
import jakarta.servlet.ServletOutputStream;
42+
import jakarta.servlet.ServletRequest;
43+
import jakarta.servlet.ServletResponse;
44+
import jakarta.servlet.http.HttpServlet;
45+
import jakarta.servlet.http.HttpServletRequest;
46+
import jakarta.servlet.http.HttpServletResponse;
47+
3548
/**
3649
* Jakarta-compatible BaseReportEngineServlet (Axis-free).
3750
*/
@@ -52,16 +65,8 @@ public abstract class BaseReportEngineServlet extends HttpServlet {
5265

5366
protected abstract void __init(ServletConfig config);
5467

55-
protected abstract boolean __authenticate(HttpServletRequest request, HttpServletResponse response);
56-
57-
protected abstract IContext __getContext(HttpServletRequest request, HttpServletResponse response)
58-
throws BirtException;
59-
6068
protected abstract void __doGet(IContext context) throws ServletException, IOException, BirtException;
6169

62-
protected abstract void __handleNonSoapException(HttpServletRequest request, HttpServletResponse response,
63-
Exception exception) throws ServletException, IOException;
64-
6570
/**
6671
* Check version.
6772
*
@@ -71,6 +76,30 @@ public static boolean isOpenSource() {
7176
return openSource;
7277
}
7378

79+
/**
80+
* Init context.
81+
*
82+
* @param request incoming http request
83+
* @param response http response
84+
* @exception BirtException
85+
* @return IContext
86+
*/
87+
protected IContext __getContext(HttpServletRequest request, HttpServletResponse response) throws BirtException {
88+
BirtReportServiceFactory.getReportService().setContext(getServletContext(), null);
89+
return new BirtContext(request, response);
90+
}
91+
92+
/**
93+
* Local authentication.
94+
*
95+
* @param request incoming http request
96+
* @param response http response
97+
* @return
98+
*/
99+
protected boolean __authenticate(HttpServletRequest request, HttpServletResponse response) {
100+
return true;
101+
}
102+
74103
/**
75104
* Servlet init.
76105
*
@@ -100,6 +129,22 @@ public void service(ServletRequest req, ServletResponse res) throws ServletExcep
100129
super.service(req, res);
101130
}
102131

132+
/**
133+
* Process exception for non soap request.
134+
*
135+
* @param request incoming http request
136+
* @param response http response
137+
* @param exception
138+
* @throws ServletException
139+
* @throws IOException
140+
*/
141+
public void __handleNonSoapException(HttpServletRequest request, HttpServletResponse response,
142+
Exception exception) throws ServletException, IOException {
143+
exception.printStackTrace();
144+
response.setContentType("text/html; charset=utf-8"); //$NON-NLS-1$
145+
BirtUtility.appendErrorMessage(response.getOutputStream(), exception);
146+
}
147+
103148
/**
104149
* Handle HTTP GET method.
105150
*
@@ -130,9 +175,6 @@ public void doGet(HttpServletRequest request, HttpServletResponse response) thro
130175
}
131176
} finally {
132177
session.unlock();
133-
if (!session.isLocked() && !__getContext(request, response).getBean().isShowParameterPage()) {
134-
session.invalidate();
135-
}
136178
}
137179
} catch (BirtException e) {
138180
__handleNonSoapException(request, response, e);
@@ -150,6 +192,182 @@ public void doGet(HttpServletRequest request, HttpServletResponse response) thro
150192
*/
151193
@Override
152194
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
153-
doGet(request, response);
195+
if (!__authenticate(request, response)) {
196+
return;
197+
}
198+
199+
// create SOAP URL with post parameters
200+
StringBuilder builder = new StringBuilder();
201+
for (String paramName : request.getParameterMap().keySet()) {
202+
if (paramName != null && paramName.startsWith("__")) //$NON-NLS-1$
203+
{
204+
String paramValue = ParameterAccessor.urlEncode(ParameterAccessor.getParameter(request, paramName),
205+
ParameterAccessor.UTF_8_ENCODE);
206+
builder.append("&" + paramName + "=" + paramValue); //$NON-NLS-1$//$NON-NLS-2$
207+
}
208+
}
209+
String soapURL = request.getRequestURL().toString();
210+
if (ParameterAccessor.getBaseURL() != null) {
211+
soapURL = ParameterAccessor.getBaseURL() + request.getContextPath() + request.getServletPath();
212+
}
213+
214+
builder.deleteCharAt(0);
215+
soapURL += "?" + builder.toString(); //$NON-NLS-1$
216+
217+
request.setAttribute("SoapURL", soapURL); //$NON-NLS-1$
218+
219+
String requestType = request.getHeader(ParameterAccessor.HEADER_REQUEST_TYPE);
220+
boolean isSoapRequest = ParameterAccessor.HEADER_REQUEST_TYPE_SOAP.equalsIgnoreCase(requestType);
221+
// refresh the current BIRT viewing session by accessing it
222+
IViewingSession session;
223+
224+
// init context
225+
IContext context = null;
226+
try {
227+
session = ViewingSessionUtil.getSession(request);
228+
if (session == null && !isSoapRequest) {
229+
if (ViewingSessionUtil.getSessionId(request) == null) {
230+
session = ViewingSessionUtil.createSession(request);
231+
} else {
232+
// if session id passed through the URL, it means this request
233+
// was expected to run using a session that has already expired
234+
throw new ViewerException(
235+
BirtResources.getMessage(ResourceConstants.GENERAL_ERROR_NO_VIEWING_SESSION));
236+
}
237+
}
238+
context = __getContext(request, response);
239+
} catch (BirtException e) {
240+
// throw exception
241+
__handleNonSoapException(request, response, e);
242+
return;
243+
}
244+
245+
try {
246+
if (session != null) {
247+
session.lock();
248+
}
249+
__doPost(context);
250+
251+
if (isSoapRequest) {
252+
soapService(request, response);
253+
} else {
254+
try {
255+
if (context.getBean().getException() != null) {
256+
__handleNonSoapException(request, response, context.getBean().getException());
257+
} else {
258+
__doGet(context);
259+
}
260+
} catch (BirtException e) {
261+
__handleNonSoapException(request, response, e);
262+
}
263+
}
264+
} catch (BirtException e) {
265+
__handleNonSoapException(request, response, e);
266+
} finally {
267+
if (session != null && !session.isExpired()) {
268+
session.unlock();
269+
}
270+
}
271+
}
272+
273+
/**
274+
* @param request
275+
* @param response
276+
* @throws IOException
277+
*/
278+
public void soapService(HttpServletRequest request, HttpServletResponse response) throws IOException {
279+
try {
280+
GetUpdatedObjects requestObj = BirtSoapParser.parseGetUpdatedObjects(request);
281+
282+
BirtSoapBindingImpl binding = new BirtSoapBindingImpl();
283+
GetUpdatedObjectsResponse responseObj = binding.getUpdatedObjects(requestObj);
284+
BirtSoapMarshaller.marshalResponse(responseObj, response);
285+
} catch (BirtSoapException e) {
286+
writeSoapFault(e.getFaultCode(), e.getMessage(), e, response);
287+
} catch (Exception e) {
288+
writeSoapFault("Soap error", e.getMessage(), e, response);
289+
}
290+
}
291+
292+
/**
293+
* Function for possible extensions
294+
*
295+
* @param context
296+
*/
297+
public void __doPost(IContext context) throws BirtException {
298+
}
299+
300+
/**
301+
* Function can be replaced by apache common-text or google guava, but no one is
302+
* as dependency of BIRT Just now this looks like easiest way to do what we
303+
* need.
304+
*
305+
* @param s
306+
* @return
307+
*/
308+
private static String escape(String s) {
309+
if (s == null) {
310+
return "";
311+
}
312+
313+
StringBuilder out = new StringBuilder(s.length() + 16);
314+
for (int i = 0; i < s.length(); i++) {
315+
char c = s.charAt(i);
316+
switch (c) {
317+
case '&' -> out.append("&amp;");
318+
case '<' -> out.append("&lt;");
319+
case '>' -> out.append("&gt;");
320+
case '"' -> out.append("&quot;");
321+
case '\'' -> out.append("&apos;");
322+
default -> out.append(c);
323+
}
324+
}
325+
return out.toString();
326+
}
327+
328+
/**
329+
* @param faultCode
330+
* @param faultMessage
331+
* @param exception
332+
* @param resp
333+
* @throws IOException
334+
*/
335+
public void writeSoapFault(String faultCode, String faultMessage, Throwable exception, HttpServletResponse resp)
336+
throws IOException {
337+
338+
resp.reset();
339+
resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
340+
resp.setContentType("text/xml;charset=UTF-8");
341+
342+
StringBuilder detailXml = new StringBuilder();
343+
if (exception != null) {
344+
// Separate stack trace to "chunks" by exceptions
345+
Throwable current = exception;
346+
// log into server log
347+
current.printStackTrace();
348+
while (current != null) {
349+
StringWriter sw = new StringWriter();
350+
PrintWriter pw = new PrintWriter(sw);
351+
current.printStackTrace(pw);
352+
pw.flush();
353+
detailXml.append("<string>").append(escape(sw.toString())).append("</string>");
354+
pw.close();
355+
current = current.getCause();
356+
}
357+
}
358+
359+
String faultXml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
360+
+ "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\">" + "<soapenv:Body>"
361+
+ "<soapenv:Fault>" + "<faultcode>" + escape(faultCode) + "</faultcode>" + "<faultstring>"
362+
+ escape(faultMessage) + "</faultstring>"
363+
+ (detailXml.length() > 0 ? "<detail>" + detailXml + "</detail>" : "") + "</soapenv:Fault>"
364+
+ "</soapenv:Body>" + "</soapenv:Envelope>";
365+
366+
byte[] bytes = faultXml.getBytes(StandardCharsets.UTF_8);
367+
resp.setContentLength(bytes.length);
368+
369+
try (ServletOutputStream out = resp.getOutputStream()) {
370+
out.write(bytes);
371+
}
154372
}
155373
}

0 commit comments

Comments
 (0)