@Test @PrepareForTest({Encode.class}) public void testStartExecutionTransServletEscapesHtmlWhenTransFound() throws ServletException, IOException { KettleLogStore.init(); HttpServletRequest mockHttpServletRequest = mock(HttpServletRequest.class); HttpServletResponse mockHttpServletResponse = mock(HttpServletResponse.class); Trans mockTrans = mock(Trans.class); TransMeta mockTransMeta = mock(TransMeta.class); LogChannelInterface mockChannelInterface = mock(LogChannelInterface.class); StringWriter out = new StringWriter(); PrintWriter printWriter = new PrintWriter(out); PowerMockito.spy(Encode.class); when(mockHttpServletRequest.getContextPath()) .thenReturn(StartExecutionTransServlet.CONTEXT_PATH); when(mockHttpServletRequest.getParameter(anyString())) .thenReturn(ServletTestUtils.BAD_STRING_TO_TEST); when(mockHttpServletResponse.getWriter()).thenReturn(printWriter); when(mockTransformationMap.getTransformation(any(CarteObjectEntry.class))) .thenReturn(mockTrans); when(mockTrans.getLogChannel()).thenReturn(mockChannelInterface); when(mockTrans.isReadyToStart()).thenReturn(true); when(mockTrans.getLogChannelId()).thenReturn("test"); when(mockTrans.getTransMeta()).thenReturn(mockTransMeta); when(mockTransMeta.getMaximum()).thenReturn(new Point(10, 10)); startExecutionTransServlet.doGet(mockHttpServletRequest, mockHttpServletResponse); assertFalse(ServletTestUtils.hasBadText(ServletTestUtils.getInsideOfTag("H1", out.toString()))); PowerMockito.verifyStatic(atLeastOnce()); Encode.forHtml(anyString()); }
@Test public void testLogging() throws Exception { when(serviceTrans.getTransMeta()).thenReturn(transMeta); TransMeta genTransMeta = mock(TransMeta.class); when(genTrans.getTransMeta()).thenReturn(genTransMeta); new DataServiceExecutor.Builder( new SQL("SELECT * FROM " + DATA_SERVICE_NAME), dataService, context) .serviceTrans(serviceTrans) .genTrans(genTrans) .prepareExecution(false) .logLevel(LogLevel.DETAILED) .build(); verify(serviceTrans).setLogLevel(LogLevel.DETAILED); verify(transMeta).setLogLevel(LogLevel.DETAILED); verify(genTrans).setLogLevel(LogLevel.DETAILED); verify(genTransMeta).setLogLevel(LogLevel.DETAILED); }
@Test public void testStopTransServletEscapesHtmlWhenTransFound() throws ServletException, IOException { KettleLogStore.init(); HttpServletRequest mockHttpServletRequest = mock(HttpServletRequest.class); HttpServletResponse mockHttpServletResponse = mock(HttpServletResponse.class); Trans mockTrans = mock(Trans.class); TransMeta mockTransMeta = mock(TransMeta.class); LogChannelInterface mockChannelInterface = mock(LogChannelInterface.class); StringWriter out = new StringWriter(); PrintWriter printWriter = new PrintWriter(out); when(mockHttpServletRequest.getContextPath()).thenReturn(StopTransServlet.CONTEXT_PATH); when(mockHttpServletRequest.getParameter(anyString())).thenReturn(ServletTestUtils.BAD_STRING); when(mockHttpServletResponse.getWriter()).thenReturn(printWriter); when(mockTransformationMap.getTransformation(any(CarteObjectEntry.class))) .thenReturn(mockTrans); when(mockTrans.getLogChannel()).thenReturn(mockChannelInterface); when(mockTrans.getLogChannelId()).thenReturn("test"); when(mockTrans.getTransMeta()).thenReturn(mockTransMeta); when(mockTransMeta.getMaximum()).thenReturn(new Point(10, 10)); stopTransServlet.doGet(mockHttpServletRequest, mockHttpServletResponse); assertFalse(ServletTestUtils.hasBadText(ServletTestUtils.getInsideOfTag("H1", out.toString()))); }
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { if (isJettyMode() && !request.getContextPath().startsWith(CONTEXT_PATH)) { return; } if (log.isDebug()) { logDebug(BaseMessages.getString(PKG, "TransStatusServlet.Log.TransStatusRequested")); } String transName = request.getParameter("name"); String id = request.getParameter("id"); boolean useXML = "Y".equalsIgnoreCase(request.getParameter("xml")); int startLineNr = Const.toInt(request.getParameter("from"), 0); response.setStatus(HttpServletResponse.SC_OK); if (useXML) { response.setContentType("text/xml"); response.setCharacterEncoding(Const.XML_ENCODING); } else { response.setCharacterEncoding("UTF-8"); response.setContentType("text/html;charset=UTF-8"); } PrintWriter out = response.getWriter(); // ID is optional... // Trans trans; CarteObjectEntry entry; if (Const.isEmpty(id)) { // get the first transformation that matches... // entry = getTransformationMap().getFirstCarteObjectEntry(transName); if (entry == null) { trans = null; } else { id = entry.getId(); trans = getTransformationMap().getTransformation(entry); } } else { // Take the ID into account! // entry = new CarteObjectEntry(transName, id); trans = getTransformationMap().getTransformation(entry); } Encoder encoder = ESAPI.encoder(); if (trans != null) { String status = trans.getStatus(); int lastLineNr = KettleLogStore.getLastBufferLineNr(); String logText = KettleLogStore.getAppender() .getBuffer(trans.getLogChannel().getLogChannelId(), false, startLineNr, lastLineNr) .toString(); if (useXML) { response.setContentType("text/xml"); response.setCharacterEncoding(Const.XML_ENCODING); out.print(XMLHandler.getXMLHeader(Const.XML_ENCODING)); SlaveServerTransStatus transStatus = new SlaveServerTransStatus(transName, entry.getId(), status); transStatus.setFirstLoggingLineNr(startLineNr); transStatus.setLastLoggingLineNr(lastLineNr); for (int i = 0; i < trans.nrSteps(); i++) { StepInterface baseStep = trans.getRunThread(i); if ((baseStep.isRunning()) || baseStep.getStatus() != StepExecutionStatus.STATUS_EMPTY) { StepStatus stepStatus = new StepStatus(baseStep); transStatus.getStepStatusList().add(stepStatus); } } // The log can be quite large at times, we are going to put a base64 encoding around a // compressed stream // of bytes to handle this one. String loggingString = HttpUtil.encodeBase64ZippedString(logText); transStatus.setLoggingString(loggingString); // Also set the result object... // transStatus.setResult(trans.getResult()); // Is the transformation paused? // transStatus.setPaused(trans.isPaused()); // Send the result back as XML // try { out.println(transStatus.getXML()); } catch (KettleException e) { throw new ServletException("Unable to get the transformation status in XML format", e); } } else { response.setContentType("text/html;charset=UTF-8"); out.println("<HTML>"); out.println("<HEAD>"); out.println( "<TITLE>" + BaseMessages.getString(PKG, "TransStatusServlet.KettleTransStatus") + "</TITLE>"); out.println( "<META http-equiv=\"Refresh\" content=\"10;url=" + convertContextPath(CONTEXT_PATH) + "?name=" + URLEncoder.encode(transName, "UTF-8") + "&id=" + URLEncoder.encode(id, "UTF-8") + "\">"); out.println("<META http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">"); out.println("</HEAD>"); out.println("<BODY>"); out.println( "<H1>" + encoder.encodeForHTML( BaseMessages.getString(PKG, "TransStatusServlet.TopTransStatus", transName)) + "</H1>"); try { out.println("<table border=\"1\">"); out.print( "<tr> <th>" + BaseMessages.getString(PKG, "TransStatusServlet.TransName") + "</th> <th>" + BaseMessages.getString(PKG, "TransStatusServlet.CarteObjectId") + "</th> <th>" + BaseMessages.getString(PKG, "TransStatusServlet.TransStatus") + "</th> </tr>"); out.print("<tr>"); out.print("<td>" + encoder.encodeForHTML(transName) + "</td>"); out.print("<td>" + encoder.encodeForHTML(id) + "</td>"); out.print("<td>" + encoder.encodeForHTML(status) + "</td>"); out.print("</tr>"); out.print("</table>"); out.print("<p>"); // Get the transformation image // // out.print("<a href=\"" + convertContextPath(GetTransImageServlet.CONTEXT_PATH) + // "?name=" + // URLEncoder.encode(transName, "UTF-8") + "&id="+id+"\">" // + BaseMessages.getString(PKG, "TransStatusServlet.GetTransImage") + "</a>"); Point max = trans.getTransMeta().getMaximum(); max.x += 20; max.y += 20; out.print( "<iframe height=\"" + max.y + "\" width=\"" + max.x + "\" seamless src=\"" + convertContextPath(GetTransImageServlet.CONTEXT_PATH) + "?name=" + URLEncoder.encode(transName, "UTF-8") + "&id=" + URLEncoder.encode(id, "UTF-8") + "\"></iframe>"); out.print("<p>"); if ((trans.isFinished() && trans.isRunning()) || (!trans.isRunning() && !trans.isPreparing() && !trans.isInitializing())) { out.print( "<a href=\"" + convertContextPath(StartTransServlet.CONTEXT_PATH) + "?name=" + URLEncoder.encode(transName, "UTF-8") + "&id=" + URLEncoder.encode(id, "UTF-8") + "\">" + BaseMessages.getString(PKG, "TransStatusServlet.StartTrans") + "</a>"); out.print("<p>"); out.print( "<a href=\"" + convertContextPath(PrepareExecutionTransServlet.CONTEXT_PATH) + "?name=" + URLEncoder.encode(transName, "UTF-8") + "&id=" + URLEncoder.encode(id, "UTF-8") + "\">" + BaseMessages.getString(PKG, "TransStatusServlet.PrepareTrans") + "</a><br>"); } else if (trans.isRunning()) { out.print( "<a href=\"" + convertContextPath(PauseTransServlet.CONTEXT_PATH) + "?name=" + URLEncoder.encode(transName, "UTF-8") + "&id=" + URLEncoder.encode(id, "UTF-8") + "\">" + BaseMessages.getString(PKG, "PauseStatusServlet.PauseResumeTrans") + "</a><br>"); out.print( "<a href=\"" + convertContextPath(StopTransServlet.CONTEXT_PATH) + "?name=" + URLEncoder.encode(transName, "UTF-8") + "&id=" + URLEncoder.encode(id, "UTF-8") + "\">" + BaseMessages.getString(PKG, "TransStatusServlet.StopTrans") + "</a>"); out.print("<p>"); } out.print( "<a href=\"" + convertContextPath(CleanupTransServlet.CONTEXT_PATH) + "?name=" + URLEncoder.encode(transName, "UTF-8") + "&id=" + URLEncoder.encode(id, "UTF-8") + "\">" + BaseMessages.getString(PKG, "TransStatusServlet.CleanupTrans") + "</a>"); out.print("<p>"); out.println("<table border=\"1\">"); out.print( "<tr> <th>" + BaseMessages.getString(PKG, "TransStatusServlet.Stepname") + "</th> <th>" + BaseMessages.getString(PKG, "TransStatusServlet.CopyNr") + "</th> <th>" + BaseMessages.getString(PKG, "TransStatusServlet.Read") + "</th> <th>" + BaseMessages.getString(PKG, "TransStatusServlet.Written") + "</th> <th>" + BaseMessages.getString(PKG, "TransStatusServlet.Input") + "</th> <th>" + BaseMessages.getString(PKG, "TransStatusServlet.Output") + "</th> " + "<th>" + BaseMessages.getString(PKG, "TransStatusServlet.Updated") + "</th> <th>" + BaseMessages.getString(PKG, "TransStatusServlet.Rejected") + "</th> <th>" + BaseMessages.getString(PKG, "TransStatusServlet.Errors") + "</th> <th>" + BaseMessages.getString(PKG, "TransStatusServlet.Active") + "</th> <th>" + BaseMessages.getString(PKG, "TransStatusServlet.Time") + "</th> " + "<th>" + BaseMessages.getString(PKG, "TransStatusServlet.Speed") + "</th> <th>" + BaseMessages.getString(PKG, "TransStatusServlet.prinout") + "</th> </tr>"); for (int i = 0; i < trans.nrSteps(); i++) { StepInterface step = trans.getRunThread(i); if ((step.isRunning()) || step.getStatus() != StepExecutionStatus.STATUS_EMPTY) { StepStatus stepStatus = new StepStatus(step); boolean snif = false; if (step.isRunning() && !step.isStopped() && !step.isPaused()) { snif = true; String sniffLink = " <a href=\"" + convertContextPath(SniffStepServlet.CONTEXT_PATH) + "?trans=" + URLEncoder.encode(transName, "UTF-8") + "&id=" + URLEncoder.encode(id, "UTF-8") + "&lines=50" + "©nr=" + step.getCopy() + "&type=" + SniffStepServlet.TYPE_OUTPUT + "&step=" + URLEncoder.encode(step.getStepname(), "UTF-8") + "\">" + encoder.encodeForHTML(stepStatus.getStepname()) + "</a>"; stepStatus.setStepname(sniffLink); } out.print(stepStatus.getHTMLTableRow(snif)); } } out.println("</table>"); out.println("<p>"); out.print( "<a href=\"" + convertContextPath(GetTransStatusServlet.CONTEXT_PATH) + "?name=" + URLEncoder.encode(transName, "UTF-8") + "&id=" + URLEncoder.encode(id, "UTF-8") + "&xml=y\">" + BaseMessages.getString(PKG, "TransStatusServlet.ShowAsXml") + "</a><br>"); out.print( "<a href=\"" + convertContextPath(GetStatusServlet.CONTEXT_PATH) + "\">" + BaseMessages.getString(PKG, "TransStatusServlet.BackToStatusPage") + "</a><br>"); out.print( "<p><a href=\"" + convertContextPath(GetTransStatusServlet.CONTEXT_PATH) + "?name=" + URLEncoder.encode(transName, "UTF-8") + "&id=" + URLEncoder.encode(id, "UTF-8") + "\">" + BaseMessages.getString(PKG, "TransStatusServlet.Refresh") + "</a>"); // Put the logging below that. out.println("<p>"); out.println( "<textarea id=\"translog\" cols=\"120\" rows=\"20\" " + "wrap=\"off\" name=\"Transformation log\" readonly=\"readonly\">" + encoder.encodeForHTML(logText) + "</textarea>"); out.println("<script type=\"text/javascript\"> "); out.println(" translog.scrollTop=translog.scrollHeight; "); out.println("</script> "); out.println("<p>"); } catch (Exception ex) { out.println("<p>"); out.println("<pre>"); out.println(encoder.encodeForHTML(Const.getStackTracker(ex))); out.println("</pre>"); } out.println("<p>"); out.println("</BODY>"); out.println("</HTML>"); } } else { if (useXML) { out.println( new WebResult( WebResult.STRING_ERROR, BaseMessages.getString( PKG, "TransStatusServlet.Log.CoundNotFindSpecTrans", transName))); } else { out.println( "<H1>" + encoder.encodeForHTML( BaseMessages.getString( PKG, "TransStatusServlet.Log.CoundNotFindTrans", transName)) + "</H1>"); out.println( "<a href=\"" + convertContextPath(GetStatusServlet.CONTEXT_PATH) + "\">" + BaseMessages.getString(PKG, "TransStatusServlet.BackToStatusPage") + "</a><p>"); } } }
/** Create a copy of {@code trans} */ public static Trans recreateTrans(Trans trans) { return new Trans(trans.getTransMeta(), trans.getParent()); }
@Test public void testExecuteQuery() throws Exception { SQL sql = new SQL("SELECT * FROM " + DATA_SERVICE_NAME); StepInterface serviceStep = serviceTrans.findRunThread(DATA_SERVICE_STEP); StepInterface resultStep = genTrans.findRunThread(RESULT_STEP_NAME); when(serviceTrans.getTransMeta().listParameters()).thenReturn(new String[0]); PushDownOptimizationMeta optimization = mock(PushDownOptimizationMeta.class); when(optimization.isEnabled()).thenReturn(true); dataService.getPushDownOptimizationMeta().add(optimization); IMetaStore metastore = mock(IMetaStore.class); DataServiceExecutor executor = new DataServiceExecutor.Builder(sql, dataService, context) .serviceTrans(serviceTrans) .sqlTransGenerator(sqlTransGenerator) .genTrans(genTrans) .metastore(metastore) .build(); ArgumentCaptor<String> objectIds = ArgumentCaptor.forClass(String.class); verify(serviceTrans).setContainerObjectId(objectIds.capture()); when(serviceTrans.getContainerObjectId()).thenReturn(objectIds.getValue()); verify(genTrans).setContainerObjectId(objectIds.capture()); when(genTrans.getContainerObjectId()).thenReturn(objectIds.getValue()); verify(serviceTrans).setMetaStore(metastore); verify(genTrans).setMetaStore(metastore); RowProducer sqlTransRowProducer = mock(RowProducer.class); when(genTrans.addRowProducer(INJECTOR_STEP_NAME, 0)).thenReturn(sqlTransRowProducer); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); // Start Execution executor.executeQuery(new DataOutputStream(outputStream)); // Check header was written assertThat(outputStream.size(), greaterThan(0)); outputStream.reset(); InOrder genTransStartup = inOrder(genTrans, resultStep); InOrder serviceTransStartup = inOrder(optimization, serviceTrans, serviceStep); ArgumentCaptor<RowListener> listenerArgumentCaptor = ArgumentCaptor.forClass(RowListener.class); ArgumentCaptor<StepListener> resultStepListener = ArgumentCaptor.forClass(StepListener.class); ArgumentCaptor<TransListener> transListenerCaptor = ArgumentCaptor.forClass(TransListener.class); genTransStartup.verify(genTrans).addTransListener(transListenerCaptor.capture()); genTransStartup.verify(genTrans).addRowProducer(INJECTOR_STEP_NAME, 0); genTransStartup.verify(resultStep).addStepListener(resultStepListener.capture()); genTransStartup.verify(resultStep).addRowListener(listenerArgumentCaptor.capture()); RowListener clientRowListener = listenerArgumentCaptor.getValue(); genTransStartup.verify(genTrans).startThreads(); serviceTransStartup.verify(optimization).activate(executor); serviceTransStartup.verify(serviceStep).addRowListener(listenerArgumentCaptor.capture()); serviceTransStartup.verify(serviceTrans).startThreads(); // Verify linkage RowListener serviceRowListener = listenerArgumentCaptor.getValue(); assertNotNull(serviceRowListener); // Push row from service to sql Trans RowMetaInterface rowMeta = genTrans.getTransMeta().getStepFields(RESULT_STEP_NAME); Object[] data; for (int i = 0; i < 50; i++) { data = new Object[] {i}; Object[] dataClone = {i}; when(rowMeta.cloneRow(data)).thenReturn(dataClone); serviceRowListener.rowWrittenEvent(rowMeta, data); verify(sqlTransRowProducer) .putRowWait( same(rowMeta), and(eq(dataClone), not(same(data))), any(Long.class), any(TimeUnit.class)); verify(rowMeta).cloneRow(data); } doReturn(true).when(serviceTrans).isRunning(); resultStepListener.getValue().stepFinished(genTrans, resultStep.getStepMeta(), resultStep); verify(serviceTrans).stopAll(); // Verify Service Trans finished ArgumentCaptor<StepListener> serviceStepListener = ArgumentCaptor.forClass(StepListener.class); verify(serviceStep).addStepListener(serviceStepListener.capture()); serviceStepListener .getValue() .stepFinished(serviceTrans, serviceStep.getStepMeta(), serviceStep); verify(sqlTransRowProducer).finished(); // Push row from service to sql Trans for (int i = 0; i < 50; i++) { Object[] row = {i}; clientRowListener.rowWrittenEvent(rowMeta, row); } transListenerCaptor.getValue().transFinished(genTrans); InOrder writeRows = inOrder(rowMeta); ArgumentCaptor<DataOutputStream> streamCaptor = ArgumentCaptor.forClass(DataOutputStream.class); writeRows.verify(rowMeta).writeMeta(streamCaptor.capture()); DataOutputStream dataOutputStream = streamCaptor.getValue(); writeRows .verify(rowMeta, times(50)) .writeData(same(dataOutputStream), argThat(arrayWithSize(1))); writeRows.verifyNoMoreInteractions(); executor.waitUntilFinished(); verify(serviceTrans).waitUntilFinished(); verify(genTrans).waitUntilFinished(); }