-
Notifications
You must be signed in to change notification settings - Fork 55
/
ResourceChangePublisher.java
272 lines (241 loc) · 9.92 KB
/
ResourceChangePublisher.java
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
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
/*******************************************************************************
* Copyright (c) 2016 Red Hat Inc..
* 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:
* Red Hat Incorporated - initial API and implementation
*******************************************************************************/
package org.jboss.tools.openshift.internal.core.server.resources;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.resources.IResourceRuleFactory;
import org.eclipse.core.resources.IncrementalProjectBuilder;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.jobs.MultiRule;
import org.eclipse.osgi.util.NLS;
import org.eclipse.wst.server.core.IServer;
import org.eclipse.wst.server.core.ServerCore;
import org.eclipse.wst.server.core.ServerUtil;
import org.eclipse.wst.server.core.internal.Messages;
import org.eclipse.wst.server.core.internal.Server;
import org.jboss.tools.openshift.core.server.OpenShiftServer;
import org.jboss.tools.openshift.core.server.OpenShiftServerBehaviour;
import org.jboss.tools.openshift.core.server.OpenShiftServerUtils;
import org.jboss.tools.openshift.internal.core.OpenShiftCoreActivator;
import org.jboss.tools.openshift.internal.core.Trace;
/**
* A server adapter publisher that listens to changes in the local (magic)
* project and publishes the server adapter upon those.
*
* @author Xaveir Coulon
* @author Rob Stryker
*/
public class ResourceChangePublisher implements IResourceChangeListener {
@Override
public void resourceChanged(IResourceChangeEvent event) {
final IResourceDelta delta = event.getDelta();
if (delta == null)
return;
// ignore clean builds
if (event.getBuildKind() == IncrementalProjectBuilder.CLEAN_BUILD)
return;
// search for changes to any project using a visitor
try {
delta.accept(new IResourceDeltaVisitor() {
@Override
public boolean visit(IResourceDelta visitorDelta) {
IResource resource = visitorDelta.getResource();
// only respond to project changes
if (resource != null && resource instanceof IProject) {
publishHandleProjectChange(visitorDelta, event);
return false;
}
return true;
}
});
} catch (Exception e) {
Trace.error("Error responding to resource change", e);
}
}
private List<IResource> getDeltaResourceChanges(IResourceDelta delta) {
final List<IResource> changed = new ArrayList<>();
IResourceDeltaVisitor visitor = new IResourceDeltaVisitor() {
@Override
public boolean visit(IResourceDelta delta2) throws CoreException {
// has this deltaResource been changed?
if (delta2.getKind() == IResourceDelta.NO_CHANGE) {
return false;
} else if (delta2.getResource() instanceof IFolder && (delta2.getKind() == IResourceDelta.ADDED
|| delta2.getKind() == IResourceDelta.REMOVED)) {
// only take folders additions and removals into account.
changed.add(delta2.getResource());
} else if (delta2.getResource() instanceof IFile) {
if (delta2.getKind() == IResourceDelta.CHANGED
&& (delta2.getFlags() & IResourceDelta.MARKERS) != 0
&& (delta2.getFlags() & IResourceDelta.CONTENT) == 0
&& (delta2.getFlags() & IResourceDelta.REPLACED) == 0
&& (delta2.getFlags() & IResourceDelta.SYNC) == 0) {
// this resource is effectively a no change
return false;
}
// Still here means delta has changes
changed.add(delta2.getResource());
}
return true;
}
};
try {
delta.accept(visitor);
} catch(CoreException ce) {
OpenShiftCoreActivator.logError("Could not determine the changed OpenShift resources.", ce);
}
return changed;
}
protected void publishHandleProjectChange(IResourceDelta delta, IResourceChangeEvent event) {
IProject project = (IProject) delta.getResource();
if (project == null)
return;
List<IResource> changes = getDeltaResourceChanges(delta);
if (!changes.isEmpty()) {
OpenShiftServer[] servers2 = getPublishRequiredServers(delta);
int size2 = servers2.length;
for (int j = 0; j < size2; j++) {
handleSpecialProjectChange(servers2[j], delta, changes, event);
}
}
}
private OpenShiftServer[] getPublishRequiredServers(IResourceDelta delta){
// The list of servers that will require publish
final List<OpenShiftServer> servers2 = new ArrayList<>();
// wrksServers = Workspaces Servers
final IServer[] wrksServers = ServerCore.getServers();
for( int i = 0; i < wrksServers.length; i++ ) {
OpenShiftServer os = (OpenShiftServer)wrksServers[i].loadAdapter(OpenShiftServer.class, new NullProgressMonitor());
if( os != null ) {
IProject magic = OpenShiftServerUtils.getDeployProject(wrksServers[i]);
if( magic != null ) {
// Safe because we've already eliminated non-project deltas
IProject p = (IProject)delta.getResource();
if( magic.equals(p)) {
servers2.add(os);
}
}
}
}
return servers2.toArray(new OpenShiftServer[servers2.size()]);
}
protected void handleSpecialProjectChange(OpenShiftServer server, IResourceDelta delta, List<IResource> changes, IResourceChangeEvent event) {
// check for duplicate jobs already waiting and don't create a new one
Job[] jobs = Job.getJobManager().find(ServerUtil.SERVER_JOB_FAMILY);
if (jobs != null) {
int size = jobs.length;
for (int i = 0; i < size; i++) {
if (jobs[i] instanceof MagicProjectChangeJob) {
MagicProjectChangeJob rcj = (MagicProjectChangeJob) jobs[i];
if (rcj.getServer().equals(server.getServer()) && rcj.getState() == Job.WAITING)
return;
}
}
}
MagicProjectChangeJob job = new MagicProjectChangeJob(server, delta, changes, event);
job.setSystem(true);
job.setPriority(Job.BUILD);
job.schedule();
}
/**
* Give the server an indication that its magic project has been changed somehow
*/
public class MagicProjectChangeJob extends Job {
private IResourceDelta delta;
private OpenShiftServer openshiftServer;
private IResourceChangeEvent event;
private List<IResource> changes;
public MagicProjectChangeJob(OpenShiftServer openshiftServer, IResourceDelta delta, List<IResource> change, IResourceChangeEvent event) {
super(NLS.bind(Messages.jobUpdateServer, openshiftServer.getServer().getName()));
this.openshiftServer = openshiftServer;
this.delta = delta;
this.changes = change;
this.event = event;
setRule(createResourcesRule(openshiftServer, delta));
}
private ISchedulingRule createResourcesRule(OpenShiftServer openshiftServer, IResourceDelta delta) {
ISchedulingRule[] rules = new ISchedulingRule[2];
IResourceRuleFactory ruleFactory = ResourcesPlugin.getWorkspace().getRuleFactory();
rules[0] = ruleFactory.createRule(delta.getResource());
rules[1] = openshiftServer.getServer();
return MultiRule.combine(rules);
}
@Override
public boolean belongsTo(Object family) {
return ServerUtil.SERVER_JOB_FAMILY.equals(family);
}
public IServer getServer() {
return openshiftServer.getServer();
}
@Override
protected IStatus run(IProgressMonitor monitor) {
IServer server = openshiftServer.getServer();
OpenShiftServerBehaviour behaviourDelegate = (OpenShiftServerBehaviour)
server.loadAdapter(OpenShiftServerBehaviour.class, new NullProgressMonitor());
int oldState = server.getServerPublishState();
int newState = ((oldState == IServer.PUBLISH_STATE_FULL || oldState == IServer.PUBLISH_STATE_UNKNOWN)
? IServer.PUBLISH_STATE_FULL : IServer.PUBLISH_STATE_INCREMENTAL);
((Server)server).setServerPublishState(newState);
if (server.getServerState() != IServer.STATE_STOPPED && behaviourDelegate != null)
behaviourDelegate.handleResourceChange();
if (server.getServerState() == IServer.STATE_STARTED)
autoPublish(event);
return Status.OK_STATUS;
}
private void autoPublish(IResourceChangeEvent event) {
boolean buildOccurred = event != null && didBuildOccur(event);
boolean projectClosedOrDeleted = event != null && isProjectCloseOrDeleteEvent(event);
int auto = ((Server)openshiftServer.getServer()).getAutoPublishSetting();
if (auto == Server.AUTO_PUBLISH_DISABLE)
return;
if( (auto == Server.AUTO_PUBLISH_BUILD)
&& !buildOccurred
&& !projectClosedOrDeleted)
return;
int time = ((Server)openshiftServer.getServer()).getAutoPublishTime();
if (time >= 0) {
openshiftServer.getServer().publish(IServer.PUBLISH_INCREMENTAL,
new NullProgressMonitor());
}
}
private boolean isProjectCloseOrDeleteEvent(IResourceChangeEvent event) {
int kind = event.getType();
if( (kind & IResourceChangeEvent.PRE_CLOSE) > 0
|| (kind & IResourceChangeEvent.PRE_DELETE) > 0)
return true;
return false;
}
private boolean didBuildOccur(IResourceChangeEvent event) {
int kind = event.getBuildKind();
final boolean eventOccurred =
kind == IncrementalProjectBuilder.INCREMENTAL_BUILD
|| kind == IncrementalProjectBuilder.FULL_BUILD
|| (kind == IncrementalProjectBuilder.AUTO_BUILD
&& ResourcesPlugin.getWorkspace().isAutoBuilding());
return eventOccurred;
}
}
}