| /******************************************************************************* |
| * Copyright (c) 2000, 2003 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Common Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/cpl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| * Matt Conway - Patch for Bug 28052 |
| *******************************************************************************/ |
| |
| package org.eclipse.ant.ui.internal.antsupport.logger; |
| |
| import java.io.File; |
| import java.text.MessageFormat; |
| |
| import org.apache.tools.ant.BuildEvent; |
| import org.apache.tools.ant.BuildException; |
| import org.apache.tools.ant.Location; |
| import org.apache.tools.ant.Project; |
| import org.apache.tools.ant.Task; |
| import org.apache.tools.ant.util.FileUtils; |
| import org.eclipse.ant.core.AntSecurityException; |
| import org.eclipse.ant.ui.internal.launchConfigurations.AntProcess; |
| import org.eclipse.ant.ui.internal.launchConfigurations.AntStreamMonitor; |
| import org.eclipse.ant.ui.internal.launchConfigurations.AntStreamsProxy; |
| import org.eclipse.ant.ui.internal.launchConfigurations.TaskLinkManager; |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.resources.ResourcesPlugin; |
| import org.eclipse.core.runtime.IPath; |
| import org.eclipse.core.runtime.OperationCanceledException; |
| import org.eclipse.core.runtime.Path; |
| import org.eclipse.debug.core.DebugPlugin; |
| import org.eclipse.debug.core.model.IProcess; |
| import org.eclipse.debug.ui.console.FileLink; |
| import org.eclipse.debug.ui.console.IConsoleHyperlink; |
| import org.eclipse.jface.text.Region; |
| import org.eclipse.ant.ui.internal.antsupport.AntSupportMessages; |
| |
| /** |
| */ |
| public class AntProcessBuildLogger extends NullBuildLogger { |
| |
| private File fBuildFileParent= null; |
| private long fStartTime; |
| |
| /** |
| * Size of left-hand column for right-justified task name. |
| * @see #logMessage(String, BuildEvent, -1) |
| */ |
| public static final int LEFT_COLUMN_SIZE = 15; |
| |
| /** |
| * 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(event.getProject().getUserProperty(AntProcess.ATTR_ANT_PROCESS_ID)); |
| if (antProcess == null) { |
| return; |
| } |
| |
| AntStreamMonitor monitor = getMonitor(priority); |
| |
| if (event.getTarget() == null) { |
| // look for "Buildfile:" message |
| if (message.startsWith("Buildfile:")) { //$NON-NLS-1$ |
| String fileName = message.substring(10).trim(); |
| IFile file = getFileForLocation(fileName); |
| if (file != null) { |
| FileLink link = new FileLink(file, null, -1, -1, -1); |
| TaskLinkManager.addTaskHyperlink(fProcess, link, new Region(11 + System.getProperty("line.separator").length(), fileName.length()), fileName); //$NON-NLS-1$ |
| fBuildFileParent= file.getLocation().toFile().getParentFile(); |
| } |
| } |
| } |
| |
| StringBuffer fullMessage= new StringBuffer(System.getProperty("line.separator")); //$NON-NLS-1$ |
| |
| if (event.getTask() != null && !fEmacsMode) { |
| getAdornedMessage(event, fullMessage); |
| } |
| fullMessage.append(message); |
| message= fullMessage.toString(); |
| |
| monitor.append(message); |
| logMessageToLogFile(message, priority); |
| |
| } |
| |
| /** |
| * Builds a right justified task prefix for the given build event, placing it |
| * in the given string buffer. Creates a hyperlink for the task prefix. |
| * |
| * @param event build event |
| * @param fullMessage buffer to place task prefix in |
| */ |
| private void getAdornedMessage(BuildEvent event, StringBuffer fullMessage) { |
| String name = event.getTask().getTaskName(); |
| if (name == null) { |
| name = "null"; //$NON-NLS-1$ |
| } |
| int size = LEFT_COLUMN_SIZE - (name.length() + 3); |
| for (int i = 0; i < size; i++) { |
| fullMessage.append(' '); |
| } |
| fullMessage.append('['); |
| fullMessage.append(name); |
| fullMessage.append("] "); //$NON-NLS-1$ |
| int offset = Math.max(size, 0) + 1; |
| int length = LEFT_COLUMN_SIZE - size - 3; |
| IConsoleHyperlink taskLink = getTaskLink(event); |
| if (taskLink != null) { |
| TaskLinkManager.addTaskHyperlink(fProcess, taskLink, new Region(offset, length), name); |
| } |
| } |
| |
| 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; |
| } |
| return monitor; |
| } |
| |
| private void logMessageToLogFile(String message, int priority) { |
| if (priority == Project.MSG_ERR) { |
| if (getErrorPrintStream() != null && getErrorPrintStream() != System.err) { |
| //user has designated to log to a logfile |
| getErrorPrintStream().println(message); |
| } |
| } else { |
| if (getOutputPrintStream() != null && getOutputPrintStream() != System.out) { |
| //user has designated to log to a logfile |
| getOutputPrintStream().println(message); |
| } |
| } |
| } |
| |
| /** |
| * Returns a hyperlink for the given task, or <code>null</code> if unable to |
| * parse a valid location for the task. The link is set to exist at the specified |
| * offset and length. |
| * |
| * @return hyper link, or <code>null</code> |
| */ |
| private IConsoleHyperlink getTaskLink(BuildEvent event) { |
| Task task = event.getTask(); |
| if (task != null) { |
| Location location = task.getLocation(); |
| if (location != null) { |
| String path = location.toString().trim(); |
| if (path.length() == 0) { |
| return null; |
| } |
| if (path.startsWith("file:")) { //$NON-NLS-1$ |
| // remove "file:" |
| path= path.substring(5, path.length()); |
| } |
| // format is file:F:L: where F is file path, and L is line number |
| int index = path.lastIndexOf(':'); |
| if (index == path.length() - 1) { |
| // remove trailing ':' |
| path = path.substring(0, index); |
| index = path.lastIndexOf(':'); |
| } |
| // split file and line number |
| String fileName = path.substring(0, index); |
| IFile file = getFileForLocation(fileName); |
| if (file != null) { |
| try { |
| String lineNumber = path.substring(index + 1); |
| int line = Integer.parseInt(lineNumber); |
| return new FileLink(file, null, -1, -1, line); |
| } catch (NumberFormatException e) { |
| } |
| } |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Returns the associated Ant process, finding it if necessary, if not |
| * already found. |
| */ |
| private AntProcess getAntProcess(String processId) { |
| if (fProcess == null && processId != null) { |
| IProcess[] all = DebugPlugin.getDefault().getLaunchManager().getProcesses(); |
| for (int i = 0; i < all.length; i++) { |
| IProcess process = all[i]; |
| if (process instanceof AntProcess && processId.equals(process.getAttribute(AntProcess.ATTR_ANT_PROCESS_ID))) { |
| fProcess = (AntProcess)process; |
| break; |
| } |
| } |
| } |
| return fProcess; |
| } |
| |
| /** |
| * Set the start time. |
| * |
| * @see org.apache.tools.ant.BuildListener#buildStarted(org.apache.tools.ant.BuildEvent) |
| */ |
| public void buildStarted(BuildEvent event) { |
| fStartTime= System.currentTimeMillis(); |
| } |
| |
| /** |
| * @see org.apache.tools.ant.BuildListener#buildFinished(org.apache.tools. |
| * ant.BuildEvent) |
| */ |
| public void buildFinished(BuildEvent event) { |
| handleException(event); |
| fHandledException= null; |
| fBuildFileParent= null; |
| 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; |
| |
| StringBuffer result= new StringBuffer(AntSupportMessages.getString("AntProcessBuildLogger.Total_time")); //$NON-NLS-1$ |
| if (minutes > 0) { |
| result.append(minutes); |
| if (minutes > 1) { |
| result.append(AntSupportMessages.getString("AntProcessBuildLogger._minutes_2")); //$NON-NLS-1$ |
| } else { |
| result.append(AntSupportMessages.getString("AntProcessBuildLogger._minute_3")); //$NON-NLS-1$ |
| } |
| } |
| if (seconds > 0) { |
| if (minutes > 0) { |
| result.append(' '); |
| } |
| result.append(seconds); |
| |
| if (seconds > 1) { |
| result.append(AntSupportMessages.getString("AntProcessBuildLogger._seconds_4")); //$NON-NLS-1$ |
| } else { |
| result.append(AntSupportMessages.getString("AntProcessBuildLogger._second_5")); //$NON-NLS-1$ |
| } |
| } |
| if (seconds == 0 && minutes == 0) { |
| result.append(milliseconds); |
| result.append(AntSupportMessages.getString("AntProcessBuildLogger._milliseconds_6")); //$NON-NLS-1$ |
| } |
| return result.toString(); |
| } |
| |
| /** |
| * @see BuildListener#messageLogged(BuildEvent) |
| */ |
| public void messageLogged(BuildEvent event) { |
| logMessage(event.getMessage(), event, -1); |
| } |
| |
| protected void handleException(BuildEvent event) { |
| Throwable exception = event.getException(); |
| if (exception == null || exception == fHandledException |
| || exception instanceof OperationCanceledException |
| || exception instanceof AntSecurityException) { |
| return; |
| } |
| fHandledException= exception; |
| logMessage(MessageFormat.format(AntSupportMessages.getString("AntProcessBuildLogger.BUILD_FAILED__{0}_1"), new String[] { exception.toString()}), //$NON-NLS-1$ |
| event, Project.MSG_ERR); |
| } |
| |
| /** |
| * @see org.apache.tools.ant.BuildListener#targetStarted(org.apache.tools.ant.BuildEvent) |
| */ |
| public void targetStarted(BuildEvent event) { |
| if (Project.MSG_INFO > getMessageOutputLevel()) { |
| return; |
| } |
| StringBuffer msg= new StringBuffer(System.getProperty("line.separator")); //$NON-NLS-1$ |
| msg.append(event.getTarget().getName()); |
| msg.append(':'); |
| logMessage(msg.toString(), event, Project.MSG_INFO); |
| } |
| |
| /** |
| * Returns the workspace file associated with the given absolute path in the |
| * local file system, or <code>null</code> if none. |
| * |
| * @param absolutePath |
| * @return file or <code>null</code> |
| */ |
| private IFile getFileForLocation(String absolutePath) { |
| IPath filePath= new Path(absolutePath); |
| IFile file = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(filePath); |
| if (file == null) { |
| //relative path |
| File relativeFile= null; |
| try { |
| //this call is ok if fBuildFileParent is null |
| relativeFile= FileUtils.newFileUtils().resolveFile(fBuildFileParent, absolutePath); |
| filePath= new Path(relativeFile.getAbsolutePath()); |
| file = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(filePath); |
| if (file == null) { |
| return null; |
| } |
| } catch (BuildException be) { |
| return null; |
| } |
| } |
| |
| if (file.exists()) { |
| return file; |
| } |
| return null; |
| } |
| } |