@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()); }
public static synchronized void init() throws KettleException { if (initialized != null) { return; } if (KettleClientEnvironment.instance == null) { KettleClientEnvironment.instance = new KettleClientEnvironment(); } createKettleHome(); // Read the kettle.properties file before anything else // EnvUtil.environmentInit(); // Initialize the logging back-end. // KettleLogStore.init(); // Add console output so that folks see what's going on... // TODO: make this configurable... // if (!"Y".equalsIgnoreCase(System.getProperty(Const.KETTLE_DISABLE_CONSOLE_LOGGING, "N"))) { KettleLogStore.getAppender().addLoggingEventListener(new ConsoleLoggingEventListener()); } // Load value meta data plugins // PluginRegistry.addPluginType(LoggingPluginType.getInstance()); PluginRegistry.addPluginType(ValueMetaPluginType.getInstance()); PluginRegistry.addPluginType(DatabasePluginType.getInstance()); PluginRegistry.addPluginType(ExtensionPointPluginType.getInstance()); PluginRegistry.init(true); initialized = new Boolean(true); }
@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()))); }
/** * <div id="mindtouch"> * * <h1>/kettle/prepareExec</h1> * * <a name="GET"></a> * * <h2>GET</h2> * * <p>Prepares previously loaded transformation for execution. Method is used for preparing * previously uploaded transformation for execution by its name. * * <p><b>Example Request:</b><br> * * <pre function="syntax.xml"> * GET /kettle/prepareExec/?name=dummy-trans2&xml=Y * </pre> * * <h3>Parameters</h3> * * <table class="pentaho-table"> * <tbody> * <tr> * <th>name</th> * <th>description</th> * <th>type</th> * </tr> * <tr> * <td>name</td> * <td>Name of the transformation to be prepared for execution.</td> * <td>query</td> * </tr> * <tr> * <td>xml</td> * <td>Boolean flag which sets the output format required. Use <code>Y</code> to receive XML response.</td> * <td>boolean</td> * </tr> * <tr> * <td>id</td> * <td>Carte transformation ID of the transformation to be prepared for execution.</td> * <td>query, optional</td> * </tr> * </tbody> * </table> * * <h3>Response Body</h3> * * <table class="pentaho-table"> * <tbody> * <tr> * <td align="right">text:</td> * <td>HTML</td> * </tr> * <tr> * <td align="right">media types:</td> * <td>text/xml, text/html</td> * </tr> * </tbody> * </table> * * <p>Response XML or HTML containing operation result. When using xml=Y <code>result</code> field * indicates whether operation was successful (<code>OK</code>) or not (<code>ERROR</code>). * * <p><b>Example Response:</b> * * <pre function="syntax.xml"> * <?xml version="1.0" encoding="UTF-8"?> * <webresult> * <result>OK</result> * <message/> * <id/> * </webresult> * </pre> * * <h3>Status Codes</h3> * * <table class="pentaho-table"> * <tbody> * <tr> * <th>code</th> * <th>description</th> * </tr> * <tr> * <td>200</td> * <td>Request was processed.</td> * </tr> * <tr> * <td>500</td> * <td>Internal server error occurs during request processing.</td> * </tr> * </tbody> * </table> * * </div> */ 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, "PrepareExecutionTransServlet.TransPrepareExecutionRequested")); } String transName = request.getParameter("name"); String id = request.getParameter("id"); boolean useXML = "Y".equalsIgnoreCase(request.getParameter("xml")); response.setStatus(HttpServletResponse.SC_OK); PrintWriter out = response.getWriter(); if (useXML) { response.setContentType("text/xml"); out.print(XMLHandler.getXMLHeader(Const.XML_ENCODING)); } else { response.setCharacterEncoding("UTF-8"); response.setContentType("text/html;charset=UTF-8"); out.println("<HTML>"); out.println("<HEAD>"); out.println( "<TITLE>" + BaseMessages.getString(PKG, "PrepareExecutionTransServlet.TransPrepareExecution") + "</TITLE>"); out.println( "<META http-equiv=\"Refresh\" content=\"2;url=" + convertContextPath(GetTransStatusServlet.CONTEXT_PATH) + "?name=" + URLEncoder.encode(transName, "UTF-8") + "\">"); out.println("<META http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">"); out.println("</HEAD>"); out.println("<BODY>"); } try { // ID is optional... // Trans trans; CarteObjectEntry entry; if (Utils.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); } TransConfiguration transConfiguration = getTransformationMap().getConfiguration(entry); if (trans != null && transConfiguration != null) { TransExecutionConfiguration executionConfiguration = transConfiguration.getTransExecutionConfiguration(); // Set the appropriate logging, variables, arguments, replay date, ... // etc. trans.setArguments(executionConfiguration.getArgumentStrings()); trans.setReplayDate(executionConfiguration.getReplayDate()); trans.setSafeModeEnabled(executionConfiguration.isSafeModeEnabled()); trans.setGatheringMetrics(executionConfiguration.isGatheringMetrics()); trans.injectVariables(executionConfiguration.getVariables()); trans.setPreviousResult(executionConfiguration.getPreviousResult()); try { trans.prepareExecution(null); if (useXML) { out.println(WebResult.OK.getXML()); } else { out.println( "<H1>" + Encode.forHtml( BaseMessages.getString( PKG, "PrepareExecutionTransServlet.TransPrepared", transName)) + "</H1>"); out.println( "<a href=\"" + convertContextPath(GetTransStatusServlet.CONTEXT_PATH) + "?name=" + URLEncoder.encode(transName, "UTF-8") + "&id=" + URLEncoder.encode(id, "UTF-8") + "\">" + BaseMessages.getString(PKG, "TransStatusServlet.BackToTransStatusPage") + "</a><p>"); } } catch (Exception e) { String logText = KettleLogStore.getAppender() .getBuffer(trans.getLogChannel().getLogChannelId(), true) .toString(); if (useXML) { out.println( new WebResult( WebResult.STRING_ERROR, BaseMessages.getString( PKG, "PrepareExecutionTransServlet.Error.TransInitFailed", Const.CR + logText + Const.CR + Const.getStackTracker(e)))); } else { out.println( "<H1>" + Encode.forHtml( BaseMessages.getString( PKG, "PrepareExecutionTransServlet.Log.TransNotInit", transName)) + "</H1>"); out.println("<pre>"); out.println(Encode.forHtml(logText)); out.println(Encode.forHtml(Const.getStackTracker(e))); out.println("</pre>"); out.println( "<a href=\"" + convertContextPath(GetTransStatusServlet.CONTEXT_PATH) + "?name=" + URLEncoder.encode(transName, "UTF-8") + "&id=" + id + "\">" + BaseMessages.getString(PKG, "TransStatusServlet.BackToTransStatusPage") + "</a><p>"); } } } else { if (useXML) { out.println( new WebResult( WebResult.STRING_ERROR, BaseMessages.getString( PKG, "TransStatusServlet.Log.CoundNotFindSpecTrans", transName))); } else { out.println( "<H1>" + Encode.forHtml( BaseMessages.getString( PKG, "TransStatusServlet.Log.CoundNotFindTrans", transName)) + "</H1>"); out.println( "<a href=\"" + convertContextPath(GetStatusServlet.CONTEXT_PATH) + "\">" + BaseMessages.getString(PKG, "TransStatusServlet.BackToStatusPage") + "</a><p>"); } } } catch (Exception ex) { if (useXML) { out.println( new WebResult( WebResult.STRING_ERROR, BaseMessages.getString( PKG, "PrepareExecutionTransServlet.Error.UnexpectedError", Const.CR + Const.getStackTracker(ex)))); } else { out.println("<p>"); out.println("<pre>"); out.println(Encode.forHtml(Const.getStackTracker(ex))); out.println("</pre>"); } } if (!useXML) { out.println("<p>"); out.println("</BODY>"); out.println("</HTML>"); } }
/** * <div id="mindtouch"> * * <h1>/kettle/startJob</h1> * * <a name="GET"></a> * * <h2>GET</h2> * * <p>Starts the job. If the job cannot be started, an error is returned. * * <p><b>Example Request:</b><br> * * <pre function="syntax.xml"> * GET /kettle/startJob/?name=dummy_job&xml=Y * </pre> * * <h3>Parameters</h3> * * <table class="pentaho-table"> * <tbody> * <tr> * <th>name</th> * <th>description</th> * <th>type</th> * </tr> * <tr> * <td>name</td> * <td>Name of the job to be executed.</td> * <td>query</td> * </tr> * <tr> * <td>xml</td> * <td>Boolean flag which sets the output format required. Use <code>Y</code> to receive XML response.</td> * <td>boolean, optional</td> * </tr> * <tr> * <td>id</td> * <td>Carte job ID of the job to be executed. This parameter is optional when xml=Y is used.</td> * <td>query, optional</td> * </tr> * </tbody> * </table> * * <h3>Response Body</h3> * * <table class="pentaho-table"> * <tbody> * <tr> * <td align="right">text:</td> * <td>HTML</td> * </tr> * <tr> * <td align="right">media types:</td> * <td>text/xml, text/html</td> * </tr> * </tbody> * </table> * * <p>Response XML or HTML containing operation result. When using xml=Y <code>result</code> field * indicates whether operation was successful (<code>OK</code>) or not (<code>ERROR</code>). * * <p><b>Example Response:</b> * * <pre function="syntax.xml"> * <?xml version="1.0" encoding="UTF-8"?> * <webresult> * <result>OK</result> * <message>Job [dummy_job] was started.</message> * <id>abd61143-8174-4f27-9037-6b22fbd3e229</id> * </webresult> * </pre> * * <h3>Status Codes</h3> * * <table class="pentaho-table"> * <tbody> * <tr> * <th>code</th> * <th>description</th> * </tr> * <tr> * <td>200</td> * <td>Request was processed.</td> * </tr> * <tr> * <td>500</td> * <td>Internal server error occurs during request processing.</td> * </tr> * </tbody> * </table> * * </div> */ 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, "StartJobServlet.Log.StartJobRequested")); } String jobName = request.getParameter("name"); String id = request.getParameter("id"); boolean useXML = "Y".equalsIgnoreCase(request.getParameter("xml")); response.setStatus(HttpServletResponse.SC_OK); Encoder encoder = ESAPI.encoder(); PrintWriter out = response.getWriter(); if (useXML) { response.setContentType("text/xml"); response.setCharacterEncoding(Const.XML_ENCODING); out.print(XMLHandler.getXMLHeader(Const.XML_ENCODING)); } else { response.setContentType("text/html;charset=UTF-8"); out.println("<HTML>"); out.println("<HEAD>"); out.println("<TITLE>Start job</TITLE>"); out.println( "<META http-equiv=\"Refresh\" content=\"2;url=" + convertContextPath(GetStatusServlet.CONTEXT_PATH) + "?name=" + URLEncoder.encode(jobName, "UTF-8") + "\">"); out.println("<META http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">"); out.println("</HEAD>"); out.println("<BODY>"); } try { // ID is optional... // Job job; CarteObjectEntry entry; if (Const.isEmpty(id)) { // get the first job that matches... // entry = getJobMap().getFirstCarteObjectEntry(jobName); if (entry == null) { job = null; } else { id = entry.getId(); job = getJobMap().getJob(entry); } } else { // Take the ID into account! // entry = new CarteObjectEntry(jobName, id); job = getJobMap().getJob(entry); } if (job != null) { // First see if this job already ran to completion. // If so, we get an exception is we try to start() the job thread // if (job.isInitialized() && !job.isActive()) { // Re-create the job from the jobMeta // // We might need to re-connect to the repository // if (job.getRep() != null && !job.getRep().isConnected()) { if (job.getRep().getUserInfo() != null) { job.getRep() .connect( job.getRep().getUserInfo().getLogin(), job.getRep().getUserInfo().getPassword()); } else { job.getRep().connect(null, null); } } // Create a new job object to start from a sane state. Then replace // the new job in the job map // synchronized (getJobMap()) { JobConfiguration jobConfiguration = getJobMap().getConfiguration(jobName); String carteObjectId = UUID.randomUUID().toString(); SimpleLoggingObject servletLoggingObject = new SimpleLoggingObject(CONTEXT_PATH, LoggingObjectType.CARTE, null); servletLoggingObject.setContainerObjectId(carteObjectId); Job newJob = new Job(job.getRep(), job.getJobMeta(), servletLoggingObject); newJob.setLogLevel(job.getLogLevel()); // Discard old log lines from the old job // KettleLogStore.discardLines(job.getLogChannelId(), true); getJobMap().replaceJob(entry, newJob, jobConfiguration); job = newJob; } } runJob(job); String message = BaseMessages.getString(PKG, "StartJobServlet.Log.JobStarted", jobName); if (useXML) { out.println(new WebResult(WebResult.STRING_OK, message, id).getXML()); } else { out.println("<H1>" + encoder.encodeForHTML(message) + "</H1>"); out.println( "<a href=\"" + convertContextPath(GetJobStatusServlet.CONTEXT_PATH) + "?name=" + URLEncoder.encode(jobName, "UTF-8") + "&id=" + URLEncoder.encode(id, "UTF-8") + "\">" + BaseMessages.getString(PKG, "JobStatusServlet.BackToJobStatusPage") + "</a><p>"); } } else { String message = BaseMessages.getString(PKG, "StartJobServlet.Log.SpecifiedJobNotFound", jobName); if (useXML) { out.println(new WebResult(WebResult.STRING_ERROR, message)); } else { out.println("<H1>" + encoder.encodeForHTML(message) + "</H1>"); out.println( "<a href=\"" + convertContextPath(GetStatusServlet.CONTEXT_PATH) + "\">" + BaseMessages.getString(PKG, "TransStatusServlet.BackToStatusPage") + "</a><p>"); } } } catch (Exception ex) { if (useXML) { out.println( new WebResult( WebResult.STRING_ERROR, BaseMessages.getString( PKG, "StartJobServlet.Error.UnexpectedError", Const.CR + Const.getStackTracker(ex)))); } else { out.println("<p>"); out.println("<pre>"); out.println(encoder.encodeForHTML(Const.getStackTracker(ex))); out.println("</pre>"); } } if (!useXML) { out.println("<p>"); out.println("</BODY>"); out.println("</HTML>"); } }
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>"); } } }
@BeforeClass public static void setUpBeforeClass() throws Exception { KettleLogStore.init(); }
/** Storage for bean annotations info for Metadata Injection and Load/Save. */ public class BeanInjectionInfo { private static LogChannelInterface LOG = KettleLogStore.getLogChannelInterfaceFactory().create(BeanInjectionInfo.class); protected final Class<?> clazz; private final InjectionSupported clazzAnnotation; private Map<String, Property> properties = new HashMap<>(); private List<Group> groupsList = new ArrayList<>(); /** Used only for fast group search during initialize. */ private Map<String, Group> groupsMap = new HashMap<>(); public static boolean isInjectionSupported(Class<?> clazz) { InjectionSupported annotation = clazz.getAnnotation(InjectionSupported.class); return annotation != null; } public BeanInjectionInfo(Class<?> clazz) { LOG.logDebug("Collect bean injection info for " + clazz); try { this.clazz = clazz; clazzAnnotation = clazz.getAnnotation(InjectionSupported.class); if (clazzAnnotation == null) { throw new RuntimeException("Injection not supported in " + clazz); } Group gr0 = new Group(""); groupsList.add(gr0); groupsMap.put(gr0.getName(), gr0); for (String group : clazzAnnotation.groups()) { Group gr = new Group(group); groupsList.add(gr); groupsMap.put(gr.getName(), gr); } BeanLevelInfo root = new BeanLevelInfo(); root.leafClass = clazz; root.init(this); properties = Collections.unmodifiableMap(properties); groupsList = Collections.unmodifiableList(groupsList); groupsMap = null; } catch (Throwable ex) { LOG.logError( "Error bean injection info collection for " + clazz + ": " + ex.getMessage(), ex); throw ex; } } public String getLocalizationPrefix() { return clazzAnnotation.localizationPrefix(); } public Map<String, Property> getProperties() { return properties; } public List<Group> getGroups() { return groupsList; } protected void addInjectionProperty(Injection metaInj, BeanLevelInfo leaf) { if (StringUtils.isBlank(metaInj.name())) { throw new RuntimeException("Property name shouldn't be blank in the " + clazz); } String propertyName = calcPropertyName(metaInj, leaf); if (properties.containsKey(propertyName)) { throw new RuntimeException("Property '" + propertyName + "' already defined for " + clazz); } Property prop = new Property(propertyName, metaInj.group(), leaf.createCallStack()); properties.put(prop.name, prop); Group gr = groupsMap.get(metaInj.group()); if (gr == null) { throw new RuntimeException( "Group '" + metaInj.group() + "' for property '" + metaInj.name() + "' is not defined " + clazz); } gr.groupProperties.add(prop); } public String getDescription(String name) { String description = BaseMessages.getString(clazz, clazzAnnotation.localizationPrefix() + name); if (description != null && description.startsWith("!") && description.endsWith("!")) { Class baseClass = clazz.getSuperclass(); while (baseClass != null) { InjectionSupported baseAnnotation = (InjectionSupported) baseClass.getAnnotation(InjectionSupported.class); if (baseAnnotation != null) { description = BaseMessages.getString(baseClass, baseAnnotation.localizationPrefix() + name); if (description != null && !description.startsWith("!") && !description.endsWith("!")) { return description; } } baseClass = baseClass.getSuperclass(); } } return description; } private String calcPropertyName(Injection metaInj, BeanLevelInfo leaf) { String name = metaInj.name(); while (leaf != null) { if (StringUtils.isNotBlank(leaf.prefix)) { name = leaf.prefix + '.' + name; } leaf = leaf.parent; } if (!name.equals(metaInj.name()) && !metaInj.group().isEmpty()) { // group exist with prefix throw new RuntimeException("Group shouldn't be declared with prefix in " + clazz); } return name; } public class Property { private final String name; private final String groupName; protected final List<BeanLevelInfo> path; protected final int pathArraysCount; public Property(String name, String groupName, List<BeanLevelInfo> path) { this.name = name; this.groupName = groupName; this.path = path; int ac = 0; for (BeanLevelInfo level : path) { if (level.dim != BeanLevelInfo.DIMENSION.NONE) { ac++; } } pathArraysCount = ac; } public String getName() { return name; } public String getGroupName() { return groupName; } public String getDescription() { return BeanInjectionInfo.this.getDescription(name); } public Class<?> getPropertyClass() { return path.get(path.size() - 1).leafClass; } } public class Group { private final String name; protected final List<Property> groupProperties = new ArrayList<>(); public Group(String name) { this.name = name; } public String getName() { return name; } public List<Property> getGroupProperties() { return Collections.unmodifiableList(groupProperties); } public String getDescription() { return BeanInjectionInfo.this.getDescription(name); } } }
public Result execute(Result result, int nr) throws KettleException { FileLoggingEventListener loggingEventListener = null; LogLevel shellLogLevel = parentJob.getLogLevel(); if (setLogfile) { String realLogFilename = environmentSubstitute(getLogFilename()); // We need to check here the log filename // if we do not have one, we must fail if (Const.isEmpty(realLogFilename)) { logError(BaseMessages.getString(PKG, "JobEntryShell.Exception.LogFilenameMissing")); result.setNrErrors(1); result.setResult(false); return result; } try { loggingEventListener = new FileLoggingEventListener(getLogChannelId(), realLogFilename, setAppendLogfile); KettleLogStore.getAppender().addLoggingEventListener(loggingEventListener); } catch (KettleException e) { logError( BaseMessages.getString( PKG, "JobEntryShell.Error.UnableopenAppenderFile", getLogFilename(), e.toString())); logError(Const.getStackTracker(e)); result.setNrErrors(1); result.setResult(false); return result; } shellLogLevel = logFileLevel; } log.setLogLevel(shellLogLevel); result.setEntryNr(nr); // "Translate" the arguments for later String[] substArgs = null; if (arguments != null) { substArgs = new String[arguments.length]; for (int idx = 0; idx < arguments.length; idx++) { substArgs[idx] = environmentSubstitute(arguments[idx]); } } int iteration = 0; String[] args = substArgs; RowMetaAndData resultRow = null; boolean first = true; List<RowMetaAndData> rows = result.getRows(); if (log.isDetailed()) { logDetailed( BaseMessages.getString( PKG, "JobEntryShell.Log.FoundPreviousRows", "" + (rows != null ? rows.size() : 0))); } while ((first && !execPerRow) || (execPerRow && rows != null && iteration < rows.size() && result.getNrErrors() == 0)) { first = false; if (rows != null && execPerRow) { resultRow = rows.get(iteration); } else { resultRow = null; } List<RowMetaAndData> cmdRows = null; if (execPerRow) { // Execute for each input row if (argFromPrevious) { // Copy the input row to the (command line) arguments if (resultRow != null) { args = new String[resultRow.size()]; for (int i = 0; i < resultRow.size(); i++) { args[i] = resultRow.getString(i, null); } } } else { // Just pass a single row List<RowMetaAndData> newList = new ArrayList<RowMetaAndData>(); newList.add(resultRow); cmdRows = newList; } } else { if (argFromPrevious) { // Only put the first Row on the arguments args = null; if (resultRow != null) { args = new String[resultRow.size()]; for (int i = 0; i < resultRow.size(); i++) { args[i] = resultRow.getString(i, null); } } else { cmdRows = rows; } } else { // Keep it as it was... cmdRows = rows; } } executeShell(result, cmdRows, args); iteration++; } if (setLogfile) { if (loggingEventListener != null) { KettleLogStore.getAppender().removeLoggingEventListener(loggingEventListener); loggingEventListener.close(); ResultFile resultFile = new ResultFile( ResultFile.FILE_TYPE_LOG, loggingEventListener.getFile(), parentJob.getJobname(), getName()); result.getResultFiles().put(resultFile.getFile().toString(), resultFile); } } return result; }