| /******************************************************************************* |
| * Copyright (c) 2000, 2013 IBM Corporation and others. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| * Matt Conway - Patch for Bug 28052 |
| *******************************************************************************/ |
| |
| package org.eclipse.ant.internal.launching.runtime.logger; |
| |
| import java.io.BufferedReader; |
| import java.io.IOException; |
| import java.io.StringReader; |
| |
| import org.apache.tools.ant.BuildEvent; |
| import org.apache.tools.ant.Location; |
| import org.apache.tools.ant.Project; |
| import org.apache.tools.ant.Target; |
| import org.eclipse.ant.internal.core.AbstractEclipseBuildLogger; |
| import org.eclipse.ant.internal.core.IAntCoreConstants; |
| import org.eclipse.ant.internal.launching.AntLaunch; |
| import org.eclipse.ant.internal.launching.AntLaunching; |
| import org.eclipse.ant.internal.launching.AntLaunchingUtil; |
| import org.eclipse.ant.internal.launching.debug.AntDebugState; |
| import org.eclipse.ant.internal.launching.launchConfigurations.AntProcess; |
| import org.eclipse.ant.internal.launching.launchConfigurations.AntStreamMonitor; |
| import org.eclipse.ant.internal.launching.launchConfigurations.AntStreamsProxy; |
| import org.eclipse.core.runtime.OperationCanceledException; |
| import org.eclipse.debug.core.DebugPlugin; |
| import org.eclipse.debug.core.model.IProcess; |
| import org.eclipse.jface.text.IRegion; |
| import org.eclipse.jface.text.Region; |
| |
| public class AntProcessBuildLogger extends NullBuildLogger { |
| |
| private long fStartTime; |
| |
| /** |
| * Associated process - discovered as needed to log messages |
| */ |
| private AntProcess fProcess = null; |
| |
| protected void logMessage(String message, BuildEvent event, int overridePriority) { |
| int priority = overridePriority; |
| if (priority == -1) { |
| priority = event.getPriority(); |
| } |
| |
| if (priority > getMessageOutputLevel()) { |
| return; |
| } |
| AntProcess antProcess = getAntProcess(fProcessId); |
| if (antProcess == null) { |
| return; |
| } |
| |
| StringBuffer fullMessage = new StringBuffer(); |
| if (!loggingToLogFile()) { |
| fullMessage.append(System.getProperty("line.separator")); //$NON-NLS-1$ |
| } |
| if (event.getException() == null && event.getTask() != null && !fEmacsMode) { |
| adornMessage(event, fullMessage); |
| } else { |
| fullMessage.append(message); |
| } |
| message = fullMessage.toString(); |
| |
| if (loggingToLogFile()) { |
| logMessageToLogFile(message, priority); |
| } else { |
| AntStreamMonitor monitor = getMonitor(priority); |
| monitor.append(message); |
| } |
| } |
| |
| /** |
| * Builds a right justified task prefix for the given build event, placing it in the given string buffer. Creates the hyperlinks for the task |
| * prefix. |
| * |
| * @param event |
| * build event |
| * @param fullMessage |
| * buffer to place task prefix in |
| */ |
| private void adornMessage(BuildEvent event, StringBuffer fullMessage) { |
| String name = event.getTask().getTaskName(); |
| if (name == null) { |
| name = "null"; //$NON-NLS-1$ |
| } |
| Location location = event.getTask().getLocation(); |
| StringBuffer column = new StringBuffer(); |
| int size = AntLaunching.LEFT_COLUMN_SIZE - (name.length() + 3); |
| for (int i = 0; i < size; i++) { |
| column.append(' '); |
| } |
| StringBuilder labelBuff = new StringBuilder(); |
| labelBuff.append('['); |
| labelBuff.append(name); |
| labelBuff.append("] "); //$NON-NLS-1$ |
| |
| int offset = Math.max(size, 0) + 1; |
| String label = labelBuff.toString(); |
| if (event.getMessage() == null) { |
| return; |
| } |
| try { |
| BufferedReader r = new BufferedReader(new StringReader(event.getMessage())); |
| String line = r.readLine(); |
| fullMessage.append(column); |
| appendAndLink(fullMessage, location, label, offset, line); |
| line = r.readLine(); |
| while (line != null) { |
| fullMessage.append(System.getProperty("line.separator")); //$NON-NLS-1$ |
| fullMessage.append(column); |
| appendAndLink(fullMessage, location, label, offset, line); |
| line = r.readLine(); |
| } |
| } |
| catch (IOException e) { |
| if (event.getMessage() != null) { |
| fullMessage.append(label).append(event.getMessage()); |
| } |
| } |
| } |
| |
| private void appendAndLink(StringBuffer fullMessage, Location location, String label, int offset, String line) { |
| fullMessage.append(label); |
| fullMessage.append(line); |
| if (location != null) { |
| String newLine = (label + line).trim(); |
| IRegion region = new Region(offset, label.length() - 3); // only |
| // want |
| // the |
| // name |
| // length |
| // "[name] " |
| AntProcess antProcess = getAntProcess(fProcessId); |
| AntLaunch antLaunch = (AntLaunch) antProcess.getLaunch(); |
| antLaunch.addLinkDescriptor(newLine, location.getFileName(), location.getLineNumber(), region.getOffset(), region.getLength()); |
| } |
| } |
| |
| private AntStreamMonitor getMonitor(int priority) { |
| AntStreamsProxy proxy = (AntStreamsProxy) fProcess.getStreamsProxy(); |
| AntStreamMonitor monitor = null; |
| switch (priority) { |
| case Project.MSG_INFO: |
| monitor = (AntStreamMonitor) proxy.getOutputStreamMonitor(); |
| break; |
| case Project.MSG_ERR: |
| monitor = (AntStreamMonitor) proxy.getErrorStreamMonitor(); |
| break; |
| case Project.MSG_DEBUG: |
| monitor = (AntStreamMonitor) proxy.getDebugStreamMonitor(); |
| break; |
| case Project.MSG_WARN: |
| monitor = (AntStreamMonitor) proxy.getWarningStreamMonitor(); |
| break; |
| case Project.MSG_VERBOSE: |
| monitor = (AntStreamMonitor) proxy.getVerboseStreamMonitor(); |
| break; |
| default: |
| break; |
| } |
| return monitor; |
| } |
| |
| private void logMessageToLogFile(String message, int priority) { |
| if (priority == Project.MSG_ERR) { |
| getErrorPrintStream().println(message); |
| } else { |
| getOutputPrintStream().println(message); |
| } |
| } |
| |
| /** |
| * Returns the associated Ant process, finding it if necessary, if not already found. |
| */ |
| protected AntProcess getAntProcess(String processId) { |
| if (fProcess == null && processId != null) { |
| for (IProcess process : DebugPlugin.getDefault().getLaunchManager().getProcesses()) { |
| if (process instanceof AntProcess && processId.equals(process.getAttribute(AbstractEclipseBuildLogger.ANT_PROCESS_ID))) { |
| fProcess = (AntProcess) process; |
| break; |
| } |
| } |
| } |
| return fProcess; |
| } |
| |
| @Override |
| public void buildStarted(BuildEvent event) { |
| fStartTime = System.currentTimeMillis(); |
| } |
| |
| @Override |
| public void buildFinished(BuildEvent event) { |
| String message = handleException(event); |
| if (message != null) { |
| try { |
| BufferedReader r = new BufferedReader(new StringReader(message)); |
| String line = r.readLine(); |
| logMessage(line, event, Project.MSG_ERR); |
| line = r.readLine(); |
| AntProcess antProcess = getAntProcess(fProcessId); |
| while (line != null) { |
| logMessage(line, event, Project.MSG_ERR); |
| if (!message.startsWith("Total time:")) { //$NON-NLS-1$ |
| AntLaunchingUtil.linkBuildFailedMessage(line, antProcess); |
| } |
| line = r.readLine(); |
| } |
| logMessage(IAntCoreConstants.EMPTY_STRING, event, Project.MSG_ERR); |
| } |
| catch (IOException e) { |
| // do nothing |
| } |
| } |
| fHandledException = null; |
| if (!(event.getException() instanceof OperationCanceledException)) { |
| logMessage(getTimeString(System.currentTimeMillis() - fStartTime), event, fMessageOutputLevel); |
| } |
| fProcess = null; |
| event.getProject().removeBuildListener(this); |
| } |
| |
| private String getTimeString(long milliseconds) { |
| long seconds = milliseconds / 1000; |
| long minutes = seconds / 60; |
| seconds = seconds % 60; |
| |
| StringBuilder result = new StringBuilder(RuntimeMessages.AntProcessBuildLogger_Total_time); |
| if (minutes > 0) { |
| result.append(minutes); |
| if (minutes > 1) { |
| result.append(RuntimeMessages.AntProcessBuildLogger__minutes_2); |
| } else { |
| result.append(RuntimeMessages.AntProcessBuildLogger__minute_3); |
| } |
| } |
| if (seconds > 0) { |
| if (minutes > 0) { |
| result.append(' '); |
| } |
| result.append(seconds); |
| |
| if (seconds > 1) { |
| result.append(RuntimeMessages.AntProcessBuildLogger__seconds_4); |
| } else { |
| result.append(RuntimeMessages.AntProcessBuildLogger__second_5); |
| } |
| } |
| if (seconds == 0 && minutes == 0) { |
| result.append(milliseconds); |
| result.append(RuntimeMessages.AntProcessBuildLogger__milliseconds_6); |
| } |
| |
| result.append(System.getProperty("line.separator")); //$NON-NLS-1$ |
| return result.toString(); |
| } |
| |
| @Override |
| public void messageLogged(BuildEvent event) { |
| if (event.getPriority() > getMessageOutputLevel()) { |
| return; |
| } |
| if (event.getMessage() != null && event.getMessage().length() > 0) { |
| logMessage(event.getMessage(), event, -1); |
| } |
| } |
| |
| @Override |
| public void targetStarted(BuildEvent event) { |
| if (Project.MSG_INFO > getMessageOutputLevel()) { |
| return; |
| } |
| Target target = event.getTarget(); |
| StringBuilder msg = new StringBuilder(System.getProperty("line.separator")); //$NON-NLS-1$ |
| String targetName = target.getName(); |
| msg.append(targetName); |
| msg.append(':'); |
| String message = msg.toString(); |
| Location location = AntDebugState.getLocation(target); |
| if (location != null && location != Location.UNKNOWN_LOCATION) { |
| IRegion region = new Region(0, targetName.length()); |
| AntProcess antProcess = getAntProcess(fProcessId); |
| AntLaunch antLaunch = (AntLaunch) antProcess.getLaunch(); |
| antLaunch.addLinkDescriptor(message, location.getFileName(), location.getLineNumber(), region.getOffset(), region.getLength()); |
| } |
| logMessage(message, event, Project.MSG_INFO); |
| } |
| |
| private boolean loggingToLogFile() { |
| // check if user has designated to log to a log file |
| return getErrorPrintStream() != null && getErrorPrintStream() != System.err; |
| } |
| } |