Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: fe8085b7a84e290f0f98bfd22186e78832719ff8 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
/*******************************************************************************
 * Copyright (c) 2000, 2004 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.team.internal.ui.actions;

import java.lang.reflect.InvocationTargetException;

import org.eclipse.core.resources.WorkspaceJob;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.jobs.*;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.team.core.TeamException;
import org.eclipse.team.internal.ui.Utils;
import org.eclipse.ui.IWorkbenchSite;

/**
 * This runnable context executes it's operation in the context of a background job.
 */
public class JobRunnableContext implements ITeamRunnableContext {

	private IJobChangeListener listener;
	private IWorkbenchSite site;
	private String jobName;
	private ISchedulingRule schedulingRule;
	private boolean postponeBuild;
	
	/*
	 * Interface that provides access to the runnable of the job so
	 * that subclasses can do belongsTo family checking.
	 */
	public interface IContextJob {
	    IRunnableWithProgress getRunnable();
	}
	
	/*
	 * Class that provides a basic job (i.e. no resource specific interactions)
	 */
	private class BasicJob extends Job implements IContextJob {
        private final IRunnableWithProgress runnable;
        public BasicJob(String name, IRunnableWithProgress runnable) {
            super(name);
            this.runnable = runnable;
        }
        public IStatus run(IProgressMonitor monitor) {
			return JobRunnableContext.this.run(runnable, monitor);
		}
		public boolean belongsTo(Object family) {
		    return JobRunnableContext.this.belongsTo(this, family);
		}
        public IRunnableWithProgress getRunnable() {
            return runnable;
        }
	}
	
	/*
	 * Class that provides a resource job (i.e. resource specific interactions)
	 */
	private class ResourceJob extends WorkspaceJob implements IContextJob {
        private final IRunnableWithProgress runnable;
        public ResourceJob(String name, IRunnableWithProgress runnable) {
            super(name);
            this.runnable = runnable;
        }
        public IStatus runInWorkspace(IProgressMonitor monitor) {
			return JobRunnableContext.this.run(runnable, monitor);
		}
		public boolean belongsTo(Object family) {
		    return JobRunnableContext.this.belongsTo(this, family);
		}
        public IRunnableWithProgress getRunnable() {
            return runnable;
        }
	}
	public JobRunnableContext(String jobName, IJobChangeListener listener, IWorkbenchSite site) {
		this.jobName = jobName;
		this.listener = listener;
		this.site = site;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.team.internal.ccvs.ui.operations.ITeamRunnableContext#run(java.lang.String, boolean, org.eclipse.jface.operation.IRunnableWithProgress)
	 */
	public void run(IRunnableWithProgress runnable) {
		Job job;
		if (schedulingRule == null && !postponeBuild) {
			job = new BasicJob(jobName, runnable);
		} else {
			job = new ResourceJob(jobName, runnable);
		}
		if (listener != null) {
			job.addJobChangeListener(listener);
		}
		configureJob(job);
		Utils.schedule(job, site);
	}
	
	/**
	 * Configure the job. By default, the job is configured to be a user
	 * job meaning that it will make use of the progress service.
	 * Subclasses can tailor how the job appears in the progress service.
	 * @param job the job that will provide the execution context
	 */
	protected void configureJob(Job job) {
		if (schedulingRule != null) {
			job.setRule(schedulingRule);
		}
	    job.setUser(isUser());
	}

	/* (non-Javadoc)
	 * @see org.eclipse.team.internal.ccvs.ui.operations.ITeamRunnableContext#getShell()
	 */
	public Shell getShell() {
		final Shell[] newShell = new Shell[] { null };
		Display.getDefault().syncExec(
			new Runnable() {
				public void run() {
					newShell[0] = Utils.getShell(site);
				}
			});
		return newShell[0];
	}
	
	/**
	 * Returns whether the auto-build will be postponed while this
	 * context is executing a runnable.
	 * @return whether the auto-build will be postponed while this
	 * context is executing a runnable.
	 */
	public boolean isPostponeBuild() {
		return postponeBuild;
	}
	
	/**
	 * Set whether the auto-build will be postponed while this
	 * context is executing a runnable.
	 * @param postponeBuild whether to postpone the auto-build.
	 */
	public void setPostponeBuild(boolean postponeBuild) {
		this.postponeBuild = postponeBuild;
	}
	
	/**
	 * Return the scheduling rule that will be obtained before the context
	 * executes a runnable or <code>null</code> if no scheduling rule is to be onbtained.
	 * @return the schedulingRule to be obtained or <code>null</code>.
	 */
	public ISchedulingRule getSchedulingRule() {
		return schedulingRule;
	}
	
	/**
	 * Return whether this job context is user initiated. Subclasses may override.
	 * @param boolean <code>true</code> if the job is a result of a user initiated actions
	 * and <code>false</code> otherwise.
	 */
	protected boolean isUser() {
		return true;
	}
	
	/**
	 * Set the scheduling rule that will be obtained before the context
	 * executes a runnable or <code>null</code> if no scheduling rule is to be onbtained.
	 * @param schedulingRule The schedulingRule to be obtained or <code>null</code>.
	 */
	public void setSchedulingRule(ISchedulingRule schedulingRule) {
		this.schedulingRule = schedulingRule;
	}
	
	/* private */ IStatus run(IRunnableWithProgress runnable, IProgressMonitor monitor) {
		try {
			runnable.run(monitor);
		} catch (InvocationTargetException e) {
			return TeamException.asTeamException(e).getStatus();
		} catch (InterruptedException e) {
			return Status.CANCEL_STATUS;
		}
		return getCompletionStatus();
	}
    
	/**
	 * Return the completions status for the job.
	 * By default, <code>Status.OK_STATUS</code>
	 * is returned.
     * @return the completions status for the job
     */
    protected IStatus getCompletionStatus() {
        return Status.OK_STATUS;
    }

    /**
	 * Return whether the job for this context is in the given family.
	 * By default, <code>false</code> is returned. Subclasses may override.
     * @param family the job family being queried
     */
    protected boolean belongsTo(IContextJob job, Object family) {
        return false;
    }

}

Back to the top