Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: b67c8bc0b95cc5800191c8047f4fe876f8c66104 (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
/*******************************************************************************
 * Copyright (c) 2006, 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.team.core.subscribers;

import java.util.*;

import org.eclipse.core.resources.*;
import org.eclipse.core.resources.mapping.*;
import org.eclipse.core.runtime.*;
import org.eclipse.team.core.mapping.*;
import org.eclipse.team.core.mapping.provider.SynchronizationScopeManager;

/**
 * A {@link ISynchronizationScopeManager} that uses a {@link Subscriber} to provide
 * a {@link RemoteResourceMappingContext} and to notify participants when the
 * remote state of resources change.
 * @since 3.2
 */
public class SubscriberScopeManager extends SynchronizationScopeManager implements ISubscriberChangeListener {

	private final Subscriber subscriber;
	private Map participants = new HashMap();

	/**
	 * Create a manager for the given subscriber and input.
	 * @param name a human readable name for the scope
	 * @param inputMappings the input mappings
	 * @param subscriber the subscriber
	 * @param consultModels whether models should be consulted when calculating the scope
	 */
	public SubscriberScopeManager(String name, ResourceMapping[] inputMappings, Subscriber subscriber, boolean consultModels) {
		this(name, inputMappings, subscriber, SubscriberResourceMappingContext.createContext(subscriber), consultModels);
	}

	/**
	 * Create a manager for the given subscriber and input.
	 * @param name a human readable name for the scope
	 * @param inputMappings the input mappings
	 * @param subscriber the subscriber
	 * @param context a remote resource mapping context for the subscriber
	 * @param consultModels whether models should be consulted when calculating the scope
	 */
	public SubscriberScopeManager(String name, ResourceMapping[] inputMappings, Subscriber subscriber, RemoteResourceMappingContext context, boolean consultModels) {
		super(name, inputMappings, context, consultModels);
		this.subscriber = subscriber;
	}

	/**
	 * Return the subscriber for this manager.
	 * @return the subscriber for this manager
	 */
	protected Subscriber getSubscriber() {
		return subscriber;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.team.core.mapping.IResourceMappingScopeManager#dispose()
	 */
	public void dispose() {
		for (Iterator iter = participants.values().iterator(); iter.hasNext();) {
			ISynchronizationScopeParticipant p = (ISynchronizationScopeParticipant) iter.next();
			p.dispose();
		}
		super.dispose();
	}

	/* (non-Javadoc)
	 * @see org.eclipse.team.core.mapping.provider.ResourceMappingScopeManager#initialize(org.eclipse.core.runtime.IProgressMonitor)
	 */
	public void initialize(IProgressMonitor monitor) throws CoreException {
		ResourcesPlugin.getWorkspace().run(new IWorkspaceRunnable() {
			public void run(IProgressMonitor monitor) throws CoreException {
				SubscriberScopeManager.super.initialize(monitor);
				hookupParticipants();
				getSubscriber().addListener(SubscriberScopeManager.this);
			}
		}, getSchedulingRule(), IResource.NONE, monitor);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.team.core.mapping.provider.ResourceMappingScopeManager#refresh(org.eclipse.core.resources.mapping.ResourceMapping[], org.eclipse.core.runtime.IProgressMonitor)
	 */
	public ResourceTraversal[] refresh(final ResourceMapping[] mappings, IProgressMonitor monitor) throws CoreException {
		final List result = new ArrayList(1);
		ResourcesPlugin.getWorkspace().run(new IWorkspaceRunnable() {
			public void run(IProgressMonitor monitor) throws CoreException {
				result.add(SubscriberScopeManager.super.refresh(mappings, monitor));
				hookupParticipants();
			}
		}, getSchedulingRule(), IResource.NONE, monitor);
		if (result.isEmpty())
			return new ResourceTraversal[0];
		return (ResourceTraversal[])result.get(0);
	}

	/*
	 * Hook up the participants for the participating models.
	 * This is done to ensure that future local and remote changes to
	 * resources will update the resources contained in the scope
	 * appropriately
	 */
	/* private */ void hookupParticipants() {
		ModelProvider[] providers = getScope().getModelProviders();
		for (int i = 0; i < providers.length; i++) {
			ModelProvider provider = providers[i];
			if (!participants.containsKey(provider)) {
				ISynchronizationScopeParticipant p = createParticipant(provider);
				if (p != null) {
					participants.put(provider, p);
				}
			}
		}
	}

	/*
	 * Obtain a participant through the factory which is obtained using IAdaptable
	 */
	private ISynchronizationScopeParticipant createParticipant(ModelProvider provider) {
		Object factoryObject = provider.getAdapter(ISynchronizationScopeParticipantFactory.class);
		if (factoryObject instanceof ISynchronizationScopeParticipantFactory) {
			ISynchronizationScopeParticipantFactory factory = (ISynchronizationScopeParticipantFactory) factoryObject;
			return factory.createParticipant(provider, this.getScope());
		}
		return null;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.team.core.subscribers.ISubscriberChangeListener#subscriberResourceChanged(org.eclipse.team.core.subscribers.ISubscriberChangeEvent[])
	 */
	public void subscriberResourceChanged(ISubscriberChangeEvent[] deltas) {
		List changedResources = new ArrayList();
		List changedProjects = new ArrayList();
		for (int i = 0; i < deltas.length; i++) {
			ISubscriberChangeEvent event = deltas[i];
			if ((event.getFlags() & (ISubscriberChangeEvent.ROOT_ADDED | ISubscriberChangeEvent.ROOT_REMOVED)) != 0) {
				changedProjects.add(event.getResource().getProject());
			}
			if ((event.getFlags() & ISubscriberChangeEvent.SYNC_CHANGED) != 0) {
				changedResources.add(event.getResource());
			}
		}
		fireChange((IResource[]) changedResources.toArray(new IResource[changedResources.size()]), (IProject[]) changedProjects.toArray(new IProject[changedProjects.size()]));
	}

	private void fireChange(final IResource[] resources, final IProject[] projects) {
		final Set result = new HashSet();
		ISynchronizationScopeParticipant[] handlers = (ISynchronizationScopeParticipant[]) participants.values().toArray(new ISynchronizationScopeParticipant[participants.size()]);
		for (int i = 0; i < handlers.length; i++) {
			final ISynchronizationScopeParticipant participant = handlers[i];
			SafeRunner.run(new ISafeRunnable() {
				public void run() throws Exception {
					ResourceMapping[] mappings = participant.handleContextChange(SubscriberScopeManager.this.getScope(), resources, projects);
					for (int j = 0; j < mappings.length; j++) {
						ResourceMapping mapping = mappings[j];
						result.add(mapping);
					}
				}
				public void handleException(Throwable exception) {
					// Handled by platform
				}
			});
		}
		if (!result.isEmpty()) {
			refresh((ResourceMapping[]) result.toArray(new ResourceMapping[result.size()]));
		}
	}

}

Back to the top