Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: 30cc37b208aef1ded274ed1ed31a8959cd1312ef (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
/*******************************************************************************
 * Copyright (c) 2000, 2006 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
 *******************************************************************************/
package org.eclipse.team.internal.ui.actions;

import java.lang.reflect.InvocationTargetException;

import org.eclipse.core.resources.WorkspaceJob;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.IJobChangeListener;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.operation.IRunnableWithProgress;
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;
        }
        @Override
		public IStatus run(IProgressMonitor monitor) {
			return JobRunnableContext.this.run(runnable, monitor);
		}
		@Override
		public boolean belongsTo(Object family) {
		    return JobRunnableContext.this.belongsTo(this, family);
		}
        @Override
		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;
        }
        @Override
		public IStatus runInWorkspace(IProgressMonitor monitor) {
			return JobRunnableContext.this.run(runnable, monitor);
		}
		@Override
		public boolean belongsTo(Object family) {
		    return JobRunnableContext.this.belongsTo(this, family);
		}
        @Override
		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)
	 */
	@Override
	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());
	}

	/**
	 * 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 whether this job context is user initiated. Subclasses may override.
	 */
	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