/*******************************************************************************
* Copyright (c) 2014 Mentor Graphics and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Mentor Graphics - initial API and implementation
*******************************************************************************/
package com.codesourcery.internal.installer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.ProgressMonitorWrapper;
import org.eclipse.osgi.util.NLS;
import com.codesourcery.installer.Installer;
/**
* Delegating progress monitor used during installation
* to filter p2 progress messages.
*/
public class ProvisioningProgressMonitor extends ProgressMonitorWrapper {
/** IU name macro */
private static String MACRO_IU_NAME = "$IU_NAME";
/** Log message prefix */
private static final String LOG_PREFIX = "P2: ";
/** Delegated progress monitor */
private IProgressMonitor delegateProgressMonitor;
/** Current progress message */
private String currentMessage = "";
/** Progress regular expression find patterns */
private Pattern[] findPatterns;
/** Progress replace patterns */
private String[] replacePatterns;
/** Start time */
private long startTime;
/** Total work amount */
private double totalWork;
/** Worked amount */
private double worked;
/** Task name */
private String taskName;
/** <code>true</code> to append time estimate to task name */
private boolean showRemainingTime = false;
/**
* Constructor
*
* @param delegateProgressMonitor Progress monitor for delegation
*/
public ProvisioningProgressMonitor(IProgressMonitor delegateProgressMonitor) {
super(delegateProgressMonitor);
this.delegateProgressMonitor = delegateProgressMonitor;
}
/**
* Sets the progress monitor filter.
*
* @param find Regular expressions for find patterns.
* @param replace Corresponding regular expressions for replace patterns.
*/
public void setFilter(String[] find, String[] replace) {
try {
if (find != null) {
findPatterns = new Pattern[find.length];
for (int index = 0; index < findPatterns.length; index ++) {
findPatterns[index] = Pattern.compile(find[index]);
}
}
replacePatterns = replace;
}
catch (Exception e) {
findPatterns = null;
replacePatterns = null;
Installer.log(e);
}
}
/**
* Set whether a remaining time estimate should be appended to the task name.
*
* @param showTimeEstimate <code>true</code> to show remaining time estimate
*/
public void setShowRemainingTime(boolean showTimeEstimate) {
this.showRemainingTime = showTimeEstimate;
}
/**
* @return <code>true</code> if remaining time estimate will be appended to the task name
*/
public boolean getShowRemainingTime() {
return showRemainingTime;
}
/**
* Called to filter progress messages before
* sending them to the delegated progress monitor.
*
* @param name Name
* @return Filtered name
*/
protected String filterName(String name) {
// No replacement
if (findPatterns == null) {
return name;
}
// Pattern replacements
else {
// Loop through find patterns
for (int index = 0; index < findPatterns.length; index ++) {
Matcher match = findPatterns[index].matcher(name);
// Match found
if ((match != null) && match.find()) {
String replacePattern = replacePatterns[index];
// Replace pattern contains IU name macro
int i1 = replacePattern.indexOf(MACRO_IU_NAME + "(");
if (i1 > 0) {
String iuName = null;
try {
int i2 = replacePattern.indexOf(')', i1);
if (i2 > 0) {
String groupPart = replacePattern.substring(i1 + MACRO_IU_NAME.length() + 1, i2);
if (groupPart.startsWith("$")) {
groupPart = groupPart.substring(1);
int group = Integer.parseInt(groupPart);
if (group != -1) {
String iuId = match.group(group);
if (iuId != null) {
iuName = RepositoryManager.getDefault().queryIuName(iuId);
if (iuName != null) {
replacePattern = replacePattern.substring(0, i1) + iuName + replacePattern.substring(i2 + 1);
}
}
}
}
}
}
catch (Exception e) {
Installer.log(e);
}
if (iuName == null) {
replacePattern = null;
}
}
if (replacePattern != null) {
String progress = match.replaceFirst(replacePattern);
if (!currentMessage.equals(progress)) {
currentMessage = progress;
}
}
break;
}
}
return currentMessage;
}
}
/**
* Returns the delegated progress monitor.
*
* @return Progress monitor
*/
protected IProgressMonitor getProgressMonitor() {
return delegateProgressMonitor;
}
@Override
public void beginTask(String name, int totalWork) {
super.beginTask(filterName(name), totalWork);
this.taskName = name;
this.totalWork = totalWork;
this.startTime = System.currentTimeMillis();
Log.getDefault().log(name);
}
@Override
public void setTaskName(String name) {
super.setTaskName(filterName(name));
this.taskName = name;
Log.getDefault().log(LOG_PREFIX + name);
}
@Override
public void subTask(String name) {
super.subTask(filterName(name));
Log.getDefault().log(LOG_PREFIX + name);
}
/**
* Appends a time segment to the buffer.
*
* @param buffer Buffer
* @param time Time amount
* @param notation Time notation (hours, minutes, seconds, etc.)
*/
private void appendTimeSegment(StringBuilder buffer, long time, String notation) {
if (time > 0) {
if (buffer.length() != 0) {
buffer.append(", ");
}
buffer.append(Long.toString(time));
buffer.append(' ');
buffer.append(notation);
}
}
@Override
public void internalWorked(double work) {
super.internalWorked(work);
// Append remaining time
if (getShowRemainingTime()) {
try {
worked += work;
if (worked > totalWork) {
worked = totalWork;
}
long currentTime = System.currentTimeMillis();
long remainingTime = (long)((currentTime - startTime) / worked * (totalWork - worked));
long estimatedSeconds = (remainingTime / 1000) % 60;
long estimatedMinutes = (remainingTime / (1000 *60)) % 60;
long estimatedHours = (remainingTime / (1000 * 60 * 60)) % 24;
// Don't show if more than a day
if (estimatedHours < 24) {
StringBuilder buffer = new StringBuilder();
appendTimeSegment(buffer, estimatedHours, InstallMessages.Hours);
appendTimeSegment(buffer, estimatedMinutes, InstallMessages.Minutes);
// Only show seconds if no more hours or minutes remaining
if ((estimatedHours == 0) && (estimatedMinutes == 0)) {
appendTimeSegment(buffer, estimatedSeconds, InstallMessages.Seconds);
}
if (buffer.length() > 0) {
String formattedTaskName = NLS.bind(InstallMessages.RemainingTime1, taskName, buffer.toString());
super.setTaskName(formattedTaskName);
}
else {
super.setTaskName(taskName);
}
}
}
catch (Exception e) {
Installer.log(e);
}
}
}
}