/* * This program is free software; you can redistribute it and/or modify it under the * terms of the GNU General Public License, version 2 as published by the Free Software * Foundation. * * You should have received a copy of the GNU General Public License along with this * program; if not, you can obtain a copy at http://www.gnu.org/licenses/gpl-2.0.html * or from the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. */ package org.pentaho.platform.engine.services; import java.io.CharArrayWriter; import java.io.IOException; import java.io.PrintWriter; import java.text.DateFormat; import java.text.NumberFormat; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.Stack; import org.apache.commons.lang.StringEscapeUtils; import org.apache.commons.lang.StringUtils; import org.pentaho.commons.connection.IPentahoResultSet; import org.pentaho.platform.api.engine.ActionSequenceException; import org.pentaho.platform.api.engine.IMessageFormatter; import org.pentaho.platform.api.engine.IRuntimeContext; import org.pentaho.platform.api.repository.ISolutionRepository; import org.pentaho.platform.api.util.IVersionHelper; import org.pentaho.platform.engine.core.system.PentahoSystem; import org.pentaho.platform.engine.services.messages.Messages; import org.pentaho.platform.engine.services.runtime.ParameterManager.ReturnParameter; import org.pentaho.platform.util.messages.LocaleHelper; public class MessageFormatter implements IMessageFormatter { public static final String HTML_MIME_TYPE = "text/html"; //$NON-NLS-1$ public static final String TEXT_MIME_TYPE = "text/plain"; //$NON-NLS-1$ public static final int MAX_RESULT_THRESHOLD = 100; DateFormat dateFormat = LocaleHelper.getFullDateFormat(true, true); public void formatErrorMessage(final String mimeType, final String title, final String message, final StringBuffer messageBuffer) { ArrayList messages = new ArrayList(1); messages.add(message); formatErrorMessage(mimeType, title, messages, messageBuffer); } /** * If PentahoMessenger.getUserString("ERROR") returns the string: * "Error: {0} ({1})" (which is the case for English) * Find the substring before the first "{". In this case, that * would be: "Error: ". * Return the first string in the messages list that contains * the string "Error: ". If no string in the list contains * "Error: ", return null; * @param messages * @return */ public String getFirstError(final List messages) { // returns something like: "Error: {0} ({1})" String errorStart = PentahoMessenger.getUserString("ERROR"); //$NON-NLS-1$ if (errorStart != null) { int pos = errorStart.indexOf('{'); if (pos != -1) { errorStart = errorStart.substring(0, pos); } Iterator messageIterator = messages.iterator(); while (messageIterator.hasNext()) { String message = (String) messageIterator.next(); if (message.indexOf(errorStart) == 0) { message = StringEscapeUtils.escapeHtml(message); // Escape this to prevent CSS (PPP-1595) return message; } } } return null; } public void formatErrorMessage(final String mimeType, final String title, final List messages, final StringBuffer messageBuffer) { // TODO make this template or XSL based // String product = VersionHelper.getVersionInfo().getProductID(); // String version = VersionHelper.getVersionInfo().getVersionNumber(); if ("text/html".equals(mimeType)) { //$NON-NLS-1$ messageBuffer .append("<html><head><title>") //$NON-NLS-1$ .append(Messages.getInstance().getString("MessageFormatter.ERROR_PAGE_TITLE")) //$NON-NLS-1$ .append( "</title><link rel=\"stylesheet\" type=\"text/css\" href=\"/pentaho-style/active/default.css\"></head>") //$NON-NLS-1$ .append("<body dir=\"").append(LocaleHelper.getTextDirection()).append("\"><table cellspacing=\"10\"><tr><td class=\"portlet-section\" colspan=\"3\">") //$NON-NLS-1$ //$NON-NLS-2$ .append(title).append("<hr size=\"1\"/></td></tr><tr><td class=\"portlet-font\" valign=\"top\">"); //$NON-NLS-1$ Iterator messageIterator = messages.iterator(); String errorStart = PentahoMessenger.getUserString("ERROR"); //$NON-NLS-1$ int pos = errorStart.indexOf('{'); if (pos != -1) { errorStart = errorStart.substring(0, pos); } String firstMessage = getFirstError(messages); if (firstMessage != null) { messageBuffer.append("<span style=\"color:red\">").append(firstMessage).append("</span><p/>"); //$NON-NLS-1$ //$NON-NLS-2$ } messageIterator = messages.iterator(); while (messageIterator.hasNext()) { messageBuffer.append(StringEscapeUtils.escapeHtml((String) messageIterator.next())).append("<br/>"); //$NON-NLS-1$ } messageBuffer.append("</td></tr></table><p>"); //$NON-NLS-1$ if (PentahoSystem.getObjectFactory().objectDefined(IVersionHelper.class.getSimpleName())) { IVersionHelper versionHelper = PentahoSystem.get(IVersionHelper.class, null); messageBuffer .append("  " + Messages.getInstance().getString("MessageFormatter.USER_SERVER_VERSION", versionHelper.getVersionInformation(PentahoSystem.class))); //$NON-NLS-1$ //$NON-NLS-2$ } messageBuffer.append("</body></html>"); //$NON-NLS-1$ } else { // TODO support other mime types } } public void formatFailureMessage(final String mimeType, final IRuntimeContext context, final StringBuffer messageBuffer, final List defaultMessages) { // TODO handle error messages from the runtime context if ((context == null) && (defaultMessages == null)) { // something went badly wrong formatErrorMessage( mimeType, Messages.getInstance().getString("MessageFormatter.ERROR_0001_REQUEST_FAILED"), Messages.getInstance().getString("MessageFormatter.ERROR_0002_COULD_NOT_PROCESS"), messageBuffer); //$NON-NLS-1$ //$NON-NLS-2$ } else { if (context == null) { formatErrorMessage(mimeType, "Failed", defaultMessages, messageBuffer); //$NON-NLS-1$ } else { // By convention, if the solution engine encounters an exception while trying to execute and xaction, // the engine will stick the caught exception in the runtime context messages. Here we're looking through // the messages to see if an an action sequence exception was caught and stored with the messages. // If so we'll format and return an exception message. ActionSequenceException theFailureException = null; List theMessages = context.getMessages(); for (Object msg : theMessages) { if (msg instanceof ActionSequenceException) { theFailureException = (ActionSequenceException) msg; break; } } if (theFailureException != null) { formatExceptionMessage(mimeType, theFailureException, messageBuffer); } else { formatErrorMessage(mimeType, "Failed", theMessages, messageBuffer); //$NON-NLS-1$ } } } } public void formatExceptionMessage(String mimeType, ActionSequenceException exception, StringBuffer messageBuffer) { if ("text/html".equals(mimeType)) { //$NON-NLS-1$ ISolutionRepository repository = PentahoSystem.get(ISolutionRepository.class); String templateFile = null; String templatePath = "system/ui/templates/viewActionErrorTemplate.html"; //$NON-NLS-1$ try { templateFile = repository.getResourceAsString(templatePath, ISolutionRepository.ACTION_EXECUTE); } catch (IOException e) { messageBuffer.append(Messages.getInstance().getErrorString("MessageFormatter.RESPONSE_ERROR_HEADING", templatePath)); //$NON-NLS-1$ e.printStackTrace(); } //NOTE: StringUtils.replace is used here instead of String.replaceAll because since the latter uses regex, the replacment //text can cause exceptions if '$' or other special characters are present. We cannot guarantee that the replacement //text does not have these characters, so a non-regex replacer was used. //TODO: there is a bit of extraneous String object creation here. If performance becomes an issue, there are more efficient //ways of doing mass replacements of text, such as using StringBuilder.replace //%ERROR_HEADING% templateFile = StringUtils.replace(templateFile, "%ERROR_HEADING%", Messages.getInstance() //$NON-NLS-1$ .getString("MessageFormatter.RESPONSE_ERROR_HEADING")); //$NON-NLS-1$ //%EXCEPTION_MSG% templateFile = StringUtils.replace(templateFile, "%EXCEPTION_MSG%", StringEscapeUtils.escapeHtml(exception //$NON-NLS-1$ .getMessage() == null ? "" : exception.getMessage())); //$NON-NLS-1$ templateFile = StringUtils.replace(templateFile, "%EXCEPTION_MSG_LABEL%", Messages.getInstance() //$NON-NLS-1$ .getString("MessageFormatter.RESPONSE_EXCEPTION_MSG_LABEL")); //$NON-NLS-1$ //%EXCEPTION_TIME% templateFile = StringUtils.replace(templateFile, "%EXCEPTION_TIME%", StringEscapeUtils.escapeHtml(dateFormat //$NON-NLS-1$ .format(exception.getDate()))); templateFile = StringUtils.replace(templateFile, "%EXCEPTION_TIME_LABEL%", Messages.getInstance() //$NON-NLS-1$ .getString("MessageFormatter.RESPONSE_EXCEPTION_TIME_LABEL")); //$NON-NLS-1$ //%EXCEPTION_TYPE% templateFile = StringUtils.replace(templateFile, "%EXCEPTION_TYPE%", StringEscapeUtils.escapeHtml(exception //$NON-NLS-1$ .getClass().getSimpleName())); templateFile = StringUtils.replace(templateFile, "%EXCEPTION_TYPE_LABEL%", Messages.getInstance() //$NON-NLS-1$ .getString("MessageFormatter.RESPONSE_EXCEPTION_TYPE_LABEL")); //$NON-NLS-1$ //%SESSION_ID% templateFile = StringUtils.replace(templateFile, "%SESSION_ID%", StringEscapeUtils.escapeHtml(exception //$NON-NLS-1$ .getSessionId() == null ? "" : exception.getSessionId())); //$NON-NLS-1$ templateFile = StringUtils.replace(templateFile, "%SESSION_ID_LABEL%", Messages.getInstance() //$NON-NLS-1$ .getString("MessageFormatter.RESPONSE_EXCEPTION_SESSION_ID_LABEL")); //$NON-NLS-1$ //%INSTANCE_ID% templateFile = StringUtils.replace(templateFile, "%INSTANCE_ID%", StringEscapeUtils.escapeHtml(exception //$NON-NLS-1$ .getInstanceId() == null ? "" : exception.getInstanceId())); //$NON-NLS-1$ templateFile = StringUtils.replace(templateFile, "%INSTANCE_ID_LABEL%", Messages.getInstance() //$NON-NLS-1$ .getString("MessageFormatter.RESPONSE_EXCEPTION_INSTANCE_ID_LABEL")); //$NON-NLS-1$ //%ACTION_SEQUENCE% templateFile = StringUtils.replace(templateFile, "%ACTION_SEQUENCE%", StringEscapeUtils.escapeHtml(exception //$NON-NLS-1$ .getActionSequenceName() == null ? "" : exception.getActionSequenceName())); //$NON-NLS-1$ templateFile = StringUtils.replace(templateFile, "%ACTION_SEQUENCE_LABEL%", Messages.getInstance() //$NON-NLS-1$ .getString("MessageFormatter.RESPONSE_EXCEPTION_ACTION_SEQUENCE_LABEL")); //$NON-NLS-1$ //%ACTION_SEQUENCE_EXECUTION_STACK% CharArrayWriter charWriter = new CharArrayWriter(); PrintWriter printWriter = new PrintWriter(charWriter); exception.printActionExecutionStack(printWriter); templateFile = StringUtils.replace(templateFile, "%ACTION_SEQUENCE_EXECUTION_STACK%", StringEscapeUtils.escapeHtml(charWriter //$NON-NLS-1$ .toString())); templateFile = StringUtils.replace(templateFile, "%ACTION_SEQUENCE_EXECUTION_STACK_LABEL%", Messages.getInstance() //$NON-NLS-1$ .getString("MessageFormatter.RESPONSE_EXCEPTION_ACTION_SEQUENCE_EXECUTION_STACK_LABEL")); //$NON-NLS-1$ //%ACTION_CLASS% templateFile = StringUtils.replace(templateFile, "%ACTION_CLASS%", StringEscapeUtils.escapeHtml(exception //$NON-NLS-1$ .getActionClass() == null ? "" : exception.getActionClass())); //$NON-NLS-1$ templateFile = StringUtils.replace(templateFile, "%ACTION_CLASS_LABEL%", Messages.getInstance() //$NON-NLS-1$ .getString("MessageFormatter.RESPONSE_EXCEPTION_ACTION_CLASS_LABEL")); //$NON-NLS-1$ //%ACTION_DESC% templateFile = StringUtils.replace(templateFile, "%ACTION_DESC%", StringEscapeUtils.escapeHtml(exception //$NON-NLS-1$ .getStepDescription() == null ? "" : exception.getStepDescription())); //$NON-NLS-1$ templateFile = StringUtils.replace(templateFile, "%ACTION_DESC_LABEL%", Messages.getInstance() //$NON-NLS-1$ .getString("MessageFormatter.RESPONSE_EXCEPTION_ACTION_DESC_LABEL")); //$NON-NLS-1$ //%STEP_NUM% templateFile = StringUtils.replace(templateFile, "%STEP_NUM%", StringEscapeUtils.escapeHtml(exception //$NON-NLS-1$ .getStepNumber() == null ? Messages.getInstance().getString("MessageFormatter.EXCEPTION_FIELD_NOT_APPLICABLE") : exception.getStepNumber().toString())); //$NON-NLS-1$ templateFile = StringUtils.replace(templateFile, "%STEP_NUM_LABEL%", Messages.getInstance() //$NON-NLS-1$ .getString("MessageFormatter.RESPONSE_EXCEPTION_STEP_NUM_LABEL")); //$NON-NLS-1$ //%STEP_NUM% templateFile = StringUtils.replace(templateFile, "%LOOP_INDEX%", StringEscapeUtils.escapeHtml(exception //$NON-NLS-1$ .getLoopIndex() == null ? Messages.getInstance().getString("MessageFormatter.EXCEPTION_FIELD_NOT_APPLICABLE") : exception.getLoopIndex().toString())); //$NON-NLS-1$ templateFile = StringUtils.replace(templateFile, "%LOOP_INDEX_LABEL%", Messages.getInstance() //$NON-NLS-1$ .getString("MessageFormatter.RESPONSE_EXCEPTION_LOOP_INDEX_LABEL")); //$NON-NLS-1$ //%STACK_TRACE% charWriter = new CharArrayWriter(); printWriter = new PrintWriter(charWriter); exception.printStackTrace(printWriter); templateFile = StringUtils.replace(templateFile, "%STACK_TRACE%", StringEscapeUtils.escapeHtml(charWriter //$NON-NLS-1$ .toString())); templateFile = StringUtils.replace(templateFile, "%STACK_TRACE_LABEL%", Messages.getInstance() //$NON-NLS-1$ .getString("MessageFormatter.RESPONSE_EXCEPTION_STACK_TRACE_LABEL")); //$NON-NLS-1$ //%EXCEPTION_MESSAGES% Stack<String> causes = new Stack<String>(); buildCauses(causes, exception); charWriter = new CharArrayWriter(); printWriter = new PrintWriter(charWriter); while(!causes.empty()) { printWriter.println(causes.pop()); } templateFile = StringUtils.replace(templateFile, "%EXCEPTION_MESSAGES%", StringEscapeUtils.escapeHtml(charWriter //$NON-NLS-1$ .toString())); templateFile = StringUtils.replace(templateFile, "%EXCEPTION_MESSAGES_LABEL%", Messages.getInstance() //$NON-NLS-1$ .getString("MessageFormatter.RESPONSE_EXCEPTION_MESSAGES_LABEL")); //$NON-NLS-1$ //%SERVER_INFO% (if available) if (PentahoSystem.getObjectFactory().objectDefined(IVersionHelper.class.getSimpleName())) { IVersionHelper versionHelper = PentahoSystem.get(IVersionHelper.class); templateFile = StringUtils.replace(templateFile, "%SERVER_INFO%", Messages.getInstance().getString( //$NON-NLS-1$ "MessageFormatter.USER_SERVER_VERSION", versionHelper.getVersionInformation(PentahoSystem.class))); //$NON-NLS-1$ } messageBuffer.append(templateFile); } } private static void buildCauses(Stack<String> causes, Throwable cause) { if (cause != null) { causes.push(cause.getClass().getSimpleName() +": "+((cause.getMessage() != null)?cause.getMessage():"")); //$NON-NLS-1$//$NON-NLS-2$ buildCauses(causes, cause.getCause()); } } public void formatFailureMessage(final String mimeType, final IRuntimeContext context, final StringBuffer messageBuffer) { formatFailureMessage(mimeType, context, messageBuffer, null); } @SuppressWarnings("deprecation") public void formatResultSetAsHTMLRows(final IPentahoResultSet resultSet, final StringBuffer messageBuffer) { boolean hasColumnHeaders = false; boolean hasRowHeaders = false; Object[][] columnHeaders = null; Object[][] rowHeaders = null; if (resultSet.getMetaData() != null) { columnHeaders = resultSet.getMetaData().getColumnHeaders(); rowHeaders = resultSet.getMetaData().getRowHeaders(); hasColumnHeaders = columnHeaders != null; hasRowHeaders = rowHeaders != null; if (hasColumnHeaders) { for (Object[] element : columnHeaders) { messageBuffer.append("<tr>"); //$NON-NLS-1$ if (hasRowHeaders) { for (int indent = 0; indent < rowHeaders[0].length; indent++) { messageBuffer.append("<th></th>"); //$NON-NLS-1$ } } for (int column = 0; column < element.length; column++) { messageBuffer.append("<th>").append(element[column]).append("</th>"); //$NON-NLS-1$//$NON-NLS-2$ } messageBuffer.append("</tr>"); //$NON-NLS-1$ } } } Object[] dataRow = resultSet.next(); int currentRow = 0; while ((dataRow != null) && (currentRow < MessageFormatter.MAX_RESULT_THRESHOLD)) { messageBuffer.append("<tr>"); //$NON-NLS-1$ if (hasRowHeaders) { for (int rowHeaderCol = rowHeaders[currentRow].length - 1; rowHeaderCol >= 0; rowHeaderCol--) { messageBuffer.append("<th>").append(rowHeaders[currentRow][rowHeaderCol].toString()).append("</th>"); //$NON-NLS-1$//$NON-NLS-2$ } } NumberFormat nf = NumberFormat.getInstance(); for (Object element : dataRow) { if (element != null) { Object value = element; if (value instanceof Number) { Number numVal = (Number) value; value = nf.format(numVal); messageBuffer.append("<td align=\"right\">").append(value.toString()).append("</td>"); //$NON-NLS-1$//$NON-NLS-2$ } else { messageBuffer.append("<td>").append(value.toString()).append("</td>"); //$NON-NLS-1$ //$NON-NLS-2$ } } else { messageBuffer.append("<td>---</td>"); //$NON-NLS-1$ } } messageBuffer.append("</tr>"); //$NON-NLS-1$ dataRow = resultSet.next(); currentRow++; } } public void formatSuccessMessage(final String mimeType, final IRuntimeContext context, final StringBuffer messageBuffer, final boolean doMessages) { formatSuccessMessage(mimeType, context, messageBuffer, doMessages, true); } @SuppressWarnings("deprecation") public void formatSuccessMessage(final String mimeType, final IRuntimeContext context, final StringBuffer messageBuffer, final boolean doMessages, final boolean doWrapper) { if (context == null) { // something went badly wrong formatFailureMessage(mimeType, context, messageBuffer); } else if (mimeType.equalsIgnoreCase(MessageFormatter.HTML_MIME_TYPE)) { // TODO make this template or XSL based if (doWrapper) { messageBuffer .append("<html><head><title>") //$NON-NLS-1$ .append(Messages.getInstance().getString("MessageFormatter.USER_START_ACTION")) //$NON-NLS-1$ .append( "</title><link rel=\"stylesheet\" type=\"text/css\" href=\"/pentaho-style/active/default.css\"></head>") //$NON-NLS-1$ .append("<body dir=\"").append(LocaleHelper.getTextDirection()).append("\"><table cellspacing=\"10\"><tr><td class=\"portlet-section\" colspan=\"3\">") //$NON-NLS-1$ //$NON-NLS-2$ .append(Messages.getInstance().getString("MessageFormatter.USER_ACTION_SUCCESSFUL")) //$NON-NLS-1$ .append("<hr size=\"1\"/></td></tr><tr><td class=\"portlet-font\" valign=\"top\">"); //$NON-NLS-1$ } // hmm do we need this to be ordered? Set outputNames = context.getOutputNames(); Iterator outputNameIterator = outputNames.iterator(); while (outputNameIterator.hasNext()) { String outputName = (String) outputNameIterator.next(); Object value = context.getOutputParameter(outputName).getValue(); if (value == null) { value = ""; //$NON-NLS-1$ } else if (value instanceof IPentahoResultSet) { formatResultSetAsHTMLRows((IPentahoResultSet) value, messageBuffer); } else { // Temporary fix for BISERVER-3348 ReturnParameter rpm = (ReturnParameter) context.getParameterManager().getReturnParameters().get(outputName); if ((rpm != null) && ("response".equalsIgnoreCase(rpm.destinationName)) //$NON-NLS-1$ && ("header".equalsIgnoreCase(rpm.destinationParameter))) { //$NON-NLS-1$ // we don't want to output response header parameters to the browser... } else { if (doWrapper) { messageBuffer.append(outputName).append("="); //$NON-NLS-1$ } messageBuffer.append(value.toString()); if (doWrapper) { messageBuffer.append("<br/>"); //$NON-NLS-1$ } } } } if (doMessages) { if (doWrapper) { messageBuffer.append("<p><br size=\"1\">"); //$NON-NLS-1$ } List messages = context.getMessages(); Iterator messageIterator = messages.iterator(); while (messageIterator.hasNext()) { messageBuffer.append((String) messageIterator.next()); if (doWrapper) { messageBuffer.append("<br/>"); //$NON-NLS-1$ } } } if (doWrapper) { messageBuffer.append("</td></tr></table></body></html>"); //$NON-NLS-1$ } } else if (mimeType.equalsIgnoreCase(MessageFormatter.TEXT_MIME_TYPE)) { messageBuffer.append(Messages.getInstance().getString("MessageFormatter.USER_START_ACTION" + "\n")) //$NON-NLS-1$ //$NON-NLS-2$ .append(Messages.getInstance().getString("MessageFormatter.USER_ACTION_SUCCESSFUL" + "\n")); //$NON-NLS-1$ //$NON-NLS-2$ // hmm do we need this to be ordered? Set outputNames = context.getOutputNames(); Iterator outputNameIterator = outputNames.iterator(); while (outputNameIterator.hasNext()) { String outputName = (String) outputNameIterator.next(); Object value = context.getOutputParameter(outputName).getValue(); if (value == null) { value = ""; //$NON-NLS-1$ } else if (value instanceof IPentahoResultSet) { IPentahoResultSet resultSet = (IPentahoResultSet) value; Object[][] columnHeaders = resultSet.getMetaData().getColumnHeaders(); Object[][] rowHeaders = resultSet.getMetaData().getRowHeaders(); boolean hasColumnHeaders = columnHeaders != null; boolean hasRowHeaders = rowHeaders != null; if (hasColumnHeaders) { for (Object[] element : columnHeaders) { for (int column = 0; column < element.length; column++) { if (hasRowHeaders) { for (int indent = 0; indent < rowHeaders[0].length; indent++) { messageBuffer.append("\t"); //$NON-NLS-1$ } } messageBuffer.append(element[column]).append("\t"); //$NON-NLS-1$ } messageBuffer.append("\n"); //$NON-NLS-1$ } } int headerRow = 0; Object[] dataRow = resultSet.next(); int currentRow = 0; while ((dataRow != null) && (currentRow < MessageFormatter.MAX_RESULT_THRESHOLD)) { if (hasRowHeaders) { for (int rowHeaderCol = 0; rowHeaderCol < rowHeaders[headerRow].length; rowHeaderCol++) { messageBuffer.append(rowHeaders[headerRow][rowHeaderCol].toString()).append("\t"); //$NON-NLS-1$ } } for (Object element : dataRow) { messageBuffer.append(element.toString()).append("\t"); //$NON-NLS-1$ } dataRow = resultSet.next(); currentRow++; } } else { // Temporary fix for BISERVER-3348 ReturnParameter rpm = (ReturnParameter) context.getParameterManager().getReturnParameters().get(outputName); if ((rpm != null) && ("response".equalsIgnoreCase(rpm.destinationName)) //$NON-NLS-1$ && ("header".equalsIgnoreCase(rpm.destinationParameter))) { //$NON-NLS-1$ // we don't want to output response header parameters to the browser... } else { messageBuffer.append(outputName).append("=").append(value.toString()).append("\n"); //$NON-NLS-1$ //$NON-NLS-2$ } } } if (doMessages) { List messages = context.getMessages(); Iterator messageIterator = messages.iterator(); while (messageIterator.hasNext()) { messageBuffer.append((String) messageIterator.next()).append("\n"); //$NON-NLS-1$ } } } } }