1414package org .eclipse .birt .report .servlet ;
1515
1616import 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
2621import org .eclipse .birt .core .exception .BirtException ;
2722import org .eclipse .birt .report .IBirtConstants ;
23+ import org .eclipse .birt .report .context .BirtContext ;
2824import org .eclipse .birt .report .context .IContext ;
25+ import org .eclipse .birt .report .exception .ViewerException ;
2926import org .eclipse .birt .report .presentation .aggregation .IFragment ;
3027import org .eclipse .birt .report .resource .BirtResources ;
28+ import org .eclipse .birt .report .resource .ResourceConstants ;
29+ import org .eclipse .birt .report .service .BirtReportServiceFactory ;
3130import org .eclipse .birt .report .session .IViewingSession ;
3231import 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 ;
3337import 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 ("&" );
318+ case '<' -> out .append ("<" );
319+ case '>' -> out .append (">" );
320+ case '"' -> out .append (""" );
321+ case '\'' -> out .append ("'" );
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