blob: 9bec550f11ff428bcd679f6e3a1d6d2f86523fd0 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2003, 2007 IBM Corporation 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:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.ui.internal.progress;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.core.commands.common.EventManager;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.ui.actions.ActionFactory;
import org.eclipse.ui.progress.IProgressConstants;
/**
* This singleton remembers all JobTreeElements that should be preserved (e.g.
* because their associated Jobs have the "keep" property set).
*/
public class FinishedJobs extends EventManager {
/*
* Interface for notify listeners.
*/
static interface KeptJobsListener {
/**
* A job to be kept has finished
*
* @param jte
*/
void finished(JobTreeElement jte);
/**
* A kept job has been removed.
*
* @param jte
*/
void removed(JobTreeElement jte);
}
private static FinishedJobs theInstance;
private IJobProgressManagerListener listener;
private HashSet keptjobinfos = new HashSet();
private HashMap finishedTime = new HashMap();
private static JobTreeElement[] EMPTY_INFOS;
public static synchronized FinishedJobs getInstance() {
if (theInstance == null) {
theInstance = new FinishedJobs();
EMPTY_INFOS = new JobTreeElement[0];
}
return theInstance;
}
private FinishedJobs() {
listener = new IJobProgressManagerListener() {
public void addJob(JobInfo info) {
checkForDuplicates(info);
}
public void addGroup(GroupInfo info) {
checkForDuplicates(info);
}
public void refreshJobInfo(JobInfo info) {
checkTasks(info);
}
public void refreshGroup(GroupInfo info) {
}
public void refreshAll() {
}
public void removeJob(JobInfo info) {
if (keep(info)) {
checkForDuplicates(info);
add(info);
}
}
public void removeGroup(GroupInfo group) {
}
public boolean showsDebug() {
return false;
}
};
ProgressManager.getInstance().addListener(listener);
}
/**
* Returns true if JobInfo indicates that it must be kept.
*/
static boolean keep(JobInfo info) {
Job job = info.getJob();
if (job != null) {
Object prop = job.getProperty(ProgressManagerUtil.KEEP_PROPERTY);
if (prop instanceof Boolean) {
if (((Boolean) prop).booleanValue()) {
return true;
}
}
prop = job.getProperty(ProgressManagerUtil.KEEPONE_PROPERTY);
if (prop instanceof Boolean) {
if (((Boolean) prop).booleanValue()) {
return true;
}
}
IStatus status = job.getResult();
if (status != null && status.getSeverity() == IStatus.ERROR) {
return true;
}
}
return false;
}
/**
* Register for notification.
*/
void addListener(KeptJobsListener l) {
addListenerObject(l);
}
/**
* Deregister for notification.
*/
void removeListener(KeptJobsListener l) {
removeListenerObject(l);
}
private void checkForDuplicates(GroupInfo info) {
Object[] objects = info.getChildren();
for (int i = 0; i < objects.length; i++) {
if (objects[i] instanceof JobInfo) {
checkForDuplicates((JobInfo) objects[i]);
}
}
}
private void checkForDuplicates(JobTreeElement info) {
JobTreeElement[] toBeRemoved = findJobsToRemove(info);
if (toBeRemoved != null) {
for (int i = 0; i < toBeRemoved.length; i++) {
remove(toBeRemoved[i]);
}
}
}
/**
* Add given Job to list of kept jobs.
*/
private void add(JobInfo info) {
boolean fire = false;
synchronized (keptjobinfos) {
if (!keptjobinfos.contains(info)) {
keptjobinfos.add(info);
long now = System.currentTimeMillis();
finishedTime.put(info, new Long(now));
Object parent = info.getParent();
if (!(parent == null || keptjobinfos.contains(parent))) {
keptjobinfos.add(parent);
finishedTime.put(parent, new Long(now));
}
fire = true;
}
}
if (fire) {
Object l[] = getListeners();
for (int i = 0; i < l.length; i++) {
KeptJobsListener jv = (KeptJobsListener) l[i];
jv.finished(info);
}
}
}
static void disposeAction(JobTreeElement jte) {
if (jte.isJobInfo()) {
JobInfo ji = (JobInfo) jte;
Job job = ji.getJob();
if (job != null) {
Object prop = job
.getProperty(IProgressConstants.ACTION_PROPERTY);
if (prop instanceof ActionFactory.IWorkbenchAction) {
((ActionFactory.IWorkbenchAction) prop).dispose();
}
}
}
}
private JobTreeElement[] findJobsToRemove(JobTreeElement info) {
if (info.isJobInfo()) {
Job myJob = ((JobInfo) info).getJob();
if (myJob != null) {
Object prop = myJob
.getProperty(ProgressManagerUtil.KEEPONE_PROPERTY);
if (prop instanceof Boolean && ((Boolean) prop).booleanValue()) {
ArrayList found = null;
JobTreeElement[] all;
synchronized (keptjobinfos) {
all = (JobTreeElement[]) keptjobinfos
.toArray(new JobTreeElement[keptjobinfos.size()]);
}
for (int i = 0; i < all.length; i++) {
JobTreeElement jte = all[i];
if (jte != info && jte.isJobInfo()) {
Job job = ((JobInfo) jte).getJob();
if (job != null && job != myJob
&& job.belongsTo(myJob)) {
if (found == null) {
found = new ArrayList();
}
found.add(jte);
}
}
}
if (found != null) {
return (JobTreeElement[]) found
.toArray(new JobTreeElement[found.size()]);
}
}
}
}
return null;
}
private void checkTasks(JobInfo info) {
if (keep(info)) {
TaskInfo tinfo = info.getTaskInfo();
if (tinfo != null) {
JobTreeElement[] toBeRemoved = null;
boolean fire = false;
JobTreeElement element = (JobTreeElement) tinfo.getParent();
synchronized (keptjobinfos) {
if (element == info && !keptjobinfos.contains(tinfo)) {
toBeRemoved = findJobsToRemove(element);
keptjobinfos.add(tinfo);
finishedTime.put(tinfo, new Long(System
.currentTimeMillis()));
}
}
if (toBeRemoved != null) {
for (int i = 0; i < toBeRemoved.length; i++) {
remove(toBeRemoved[i]);
}
}
if (fire) {
Object l[] = getListeners();
for (int i = 0; i < l.length; i++) {
KeptJobsListener jv = (KeptJobsListener) l[i];
jv.finished(info);
}
}
}
}
}
public void removeErrorJobs() {
JobTreeElement[] infos = getKeptElements();
for (int i = 0; i < infos.length; i++) {
if (infos[i].isJobInfo()) {
JobInfo info1 = (JobInfo) infos[i];
Job job = info1.getJob();
if (job != null) {
IStatus status = job.getResult();
if (status != null && status.getSeverity() == IStatus.ERROR) {
JobTreeElement topElement = (JobTreeElement) info1
.getParent();
if (topElement == null) {
topElement = info1;
}
FinishedJobs.getInstance().remove(topElement);
}
}
}
}
}
boolean remove(JobTreeElement jte) {
boolean fire = false;
boolean removed = false;
synchronized (keptjobinfos) {
if (keptjobinfos.remove(jte)) {
removed = true;
finishedTime.remove(jte);
disposeAction(jte);
// delete all elements that have jte as their direct or indirect
// parent
JobTreeElement jtes[] = (JobTreeElement[]) keptjobinfos
.toArray(new JobTreeElement[keptjobinfos.size()]);
for (int i = 0; i < jtes.length; i++) {
JobTreeElement parent = (JobTreeElement) jtes[i]
.getParent();
if (parent != null) {
if (parent == jte || parent.getParent() == jte) {
if (keptjobinfos.remove(jtes[i])) {
disposeAction(jtes[i]);
}
finishedTime.remove(jtes[i]);
}
}
}
fire = true;
}
}
if (fire) {
// notify listeners
Object l[] = getListeners();
for (int i = 0; i < l.length; i++) {
KeptJobsListener jv = (KeptJobsListener) l[i];
jv.removed(jte);
}
}
return removed;
}
/**
* Returns all kept elements.
*/
JobTreeElement[] getKeptElements() {
JobTreeElement[] all;
if (keptjobinfos.isEmpty()) {
return EMPTY_INFOS;
}
synchronized (keptjobinfos) {
all = (JobTreeElement[]) keptjobinfos
.toArray(new JobTreeElement[keptjobinfos.size()]);
}
return all;
}
/**
* Get the date that indicates the finish time.
*
* @param jte
* @return Date
*/
public Date getFinishDate(JobTreeElement jte) {
Object o = finishedTime.get(jte);
if (o instanceof Long) {
return new Date(((Long) o).longValue());
}
return null;
}
/**
* Return whether or not the kept infos have the element.
*
* @param element
* @return boolean
*/
public boolean isKept(JobTreeElement element) {
return keptjobinfos.contains(element);
}
/**
* Clear all kept jobs.
*/
public void clearAll() {
synchronized (keptjobinfos) {
JobTreeElement[] all = (JobTreeElement[]) keptjobinfos
.toArray(new JobTreeElement[keptjobinfos.size()]);
for (int i = 0; i < all.length; i++) {
disposeAction(all[i]);
}
keptjobinfos.clear();
finishedTime.clear();
}
// notify listeners
Object l[] = getListeners();
for (int i = 0; i < l.length; i++) {
KeptJobsListener jv = (KeptJobsListener) l[i];
jv.removed(null);
}
}
/**
* Return the set of kept jobs.
* @return Set
*/
Set getKeptAsSet() {
// TODO Auto-generated method stub
return keptjobinfos;
}
}