KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > team > internal > ccvs > core > util > KnownRepositories


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.team.internal.ccvs.core.util;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.HashMap JavaDoc;
15 import java.util.List JavaDoc;
16 import java.util.Map JavaDoc;
17
18 import org.eclipse.core.resources.IProject;
19 import org.eclipse.core.resources.ResourcesPlugin;
20 import org.eclipse.core.runtime.*;
21 import org.eclipse.core.runtime.preferences.IEclipsePreferences;
22 import org.eclipse.core.runtime.preferences.IEclipsePreferences.INodeChangeListener;
23 import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener;
24 import org.eclipse.core.runtime.preferences.IEclipsePreferences.NodeChangeEvent;
25 import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent;
26 import org.eclipse.team.core.RepositoryProvider;
27 import org.eclipse.team.internal.ccvs.core.*;
28 import org.eclipse.team.internal.ccvs.core.connection.CVSRepositoryLocation;
29 import org.eclipse.team.internal.ccvs.core.resources.CVSWorkspaceRoot;
30 import org.eclipse.team.internal.ccvs.core.syncinfo.FolderSyncInfo;
31 import org.osgi.service.prefs.BackingStoreException;
32
33 /**
34  * This class keeps track of the CVS repository locations that are known to
35  * the CVS plugin.
36  */

37 public class KnownRepositories implements INodeChangeListener, IPreferenceChangeListener {
38
39     private List JavaDoc repositoryListeners = new ArrayList JavaDoc();
40     private Map JavaDoc repositories;
41
42     private static KnownRepositories instance;
43     
44     public static synchronized KnownRepositories getInstance() {
45         if (instance == null) {
46             instance = new KnownRepositories();
47         }
48         return instance;
49     }
50     
51     /*
52      * Private class used to safely notify listeners of resouce sync info changes.
53      * Subclass override the notify(IResourceStateChangeListener) method to
54      * fire specific events inside an ISafeRunnable.
55      */

56     private abstract class Notification implements ISafeRunnable {
57         private ICVSListener listener;
58         public void handleException(Throwable JavaDoc exception) {
59             // don't log the exception....it is already being logged in Platform#run
60
}
61         public void run(ICVSListener listener) {
62             this.listener = listener;
63             Platform.run(this);
64         }
65         public void run() throws Exception JavaDoc {
66             notify(listener);
67         }
68         /**
69          * Subsclasses overide this method to send an event safely to a lsistener
70          * @param listener
71          */

72         protected abstract void notify(ICVSListener listener);
73     }
74     
75     /**
76      * Register to receive notification of repository creation and disposal
77      */

78     public void addRepositoryListener(ICVSListener listener) {
79         synchronized(repositoryListeners) {
80             repositoryListeners.add(listener);
81         }
82     }
83     
84     /**
85      * De-register a listener
86      */

87     public void removeRepositoryListener(ICVSListener listener) {
88         synchronized(repositoryListeners) {
89             repositoryListeners.remove(listener);
90         }
91     }
92
93     /**
94      * Add the repository to the receiver's list of known repositories. Doing this will enable
95      * password caching across platform invocations.
96      */

97     public ICVSRepositoryLocation addRepository(final ICVSRepositoryLocation repository, boolean broadcast) {
98         CVSRepositoryLocation existingLocation;
99         synchronized (this) {
100             // Check the cache for an equivalent instance and if there is one, just update the cache
101
existingLocation = internalGetRepository(repository.getLocation(false));
102             if (existingLocation == null) {
103                 // Store the location
104
store((CVSRepositoryLocation)repository);
105                 existingLocation = (CVSRepositoryLocation)repository;
106             }
107         }
108         // Notify no matter what since it may not have been broadcast before
109
if (broadcast) {
110             final CVSRepositoryLocation location = existingLocation;
111             ((CVSRepositoryLocation)repository).updateCache();
112             fireNotification(new Notification() {
113                 public void notify(ICVSListener listener) {
114                     listener.repositoryAdded(location);
115                 }
116             });
117         }
118         return existingLocation;
119     }
120     
121     /**
122      * Dispose of the repository location
123      *
124      * Removes any cached information about the repository such as a remembered password.
125      */

126     public void disposeRepository(final ICVSRepositoryLocation repository) {
127         Object JavaDoc removed;
128         synchronized (this) {
129             ((CVSRepositoryLocation)repository).dispose();
130             removed = getRepositoriesMap().remove(repository.getLocation(false));
131         }
132         if (removed != null) {
133             fireNotification(new Notification() {
134                 public void notify(ICVSListener listener) {
135                     listener.repositoryRemoved(repository);
136                 }
137             });
138         }
139     }
140
141     /**
142      * Answer whether the provided repository location is known by the provider or not.
143      * The location string corresponds to the String returned by ICVSRepositoryLocation#getLocation()
144      */

145     public synchronized boolean isKnownRepository(String JavaDoc location) {
146         return internalGetRepository(location) != null;
147     }
148
149     /**
150      * Return a list of the know repository locations
151      */

152     public synchronized ICVSRepositoryLocation[] getRepositories() {
153         return (ICVSRepositoryLocation[])getRepositoriesMap().values().toArray(new ICVSRepositoryLocation[getRepositoriesMap().size()]);
154     }
155     
156     /**
157      * Get the repository instance which matches the given String. The format of the String is
158      * the same as that returned by ICVSRepositoryLocation#getLocation().
159      * The format is:
160      *
161      * connection:user[:password]@host[#port]:root
162      *
163      * where [] indicates optional and the identier meanings are:
164      *
165      * connection The connection method to be used
166      * user The username for the connection
167      * password The password used for the connection (optional)
168      * host The host where the repository resides
169      * port The port to connect to (optional)
170      * root The server directory where the repository is located
171      *
172      * If the repository is already registered, the cahced instance is returned.
173      * Otherwise, a new uncached instance is returned.
174      *
175      * WARNING: Providing the password as part of the String will result in the password being part
176      * of the location permanently. This means that it cannot be modified by the authenticator.
177      */

178     public synchronized ICVSRepositoryLocation getRepository(String JavaDoc location) throws CVSException {
179         ICVSRepositoryLocation repository = internalGetRepository(location);
180         if (repository == null) {
181             repository = CVSRepositoryLocation.fromString(location);
182         }
183         return repository;
184     }
185     
186     private CVSRepositoryLocation internalGetRepository(String JavaDoc location) {
187         return (CVSRepositoryLocation)getRepositoriesMap().get(location);
188     }
189     
190     /*
191      * Cache the location and store it in the preferences for persistance
192      */

193     private void store(CVSRepositoryLocation location) {
194         // Cache the location instance for later retrieval
195
getRepositoriesMap().put(location.getLocation(), location);
196         location.storePreferences();
197     }
198     
199     private Map JavaDoc getRepositoriesMap() {
200         if (repositories == null) {
201             // Load the repositories from the preferences
202
repositories = new HashMap JavaDoc();
203             IEclipsePreferences prefs = (IEclipsePreferences) CVSRepositoryLocation.getParentPreferences();
204             prefs.addNodeChangeListener(this);
205             try {
206                 String JavaDoc[] keys = prefs.childrenNames();
207                 for (int i = 0; i < keys.length; i++) {
208                     String JavaDoc key = keys[i];
209                     try {
210                         IEclipsePreferences node = (IEclipsePreferences) prefs.node(key);
211                         node.addPreferenceChangeListener(this);
212                         String JavaDoc location = node.get(CVSRepositoryLocation.PREF_LOCATION, null);
213                         if (location != null) {
214                             repositories.put(location, CVSRepositoryLocation.fromString(location));
215                         } else {
216                             node.removeNode();
217                             prefs.flush();
218                         }
219                     } catch (CVSException e) {
220                         // Log and continue
221
CVSProviderPlugin.log(e);
222                     }
223                 }
224                 if (repositories.isEmpty()) {
225                     getRepositoriesFromProjects();
226                 }
227             } catch (BackingStoreException e) {
228                 // Log and continue (although all repos will be missing)
229
CVSProviderPlugin.log(IStatus.ERROR, CVSMessages.KnownRepositories_0, e);
230             } catch (CVSException e) {
231                 CVSProviderPlugin.log(e);
232             }
233         }
234         return repositories;
235     }
236     
237     private void getRepositoriesFromProjects() throws CVSException {
238         // If the file did not exist, then prime the list of repositories with
239
// the providers with which the projects in the workspace are shared.
240
IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
241         for (int i = 0; i < projects.length; i++) {
242             RepositoryProvider provider = RepositoryProvider.getProvider(projects[i], CVSProviderPlugin.getTypeId());
243             if (provider!=null) {
244                 ICVSFolder folder = (ICVSFolder)CVSWorkspaceRoot.getCVSResourceFor(projects[i]);
245                 FolderSyncInfo info = folder.getFolderSyncInfo();
246                 if (info != null) {
247                     addRepository(getRepository(info.getRoot()), false);
248                 }
249             }
250         }
251     }
252     
253     private ICVSListener[] getListeners() {
254         synchronized(repositoryListeners) {
255             return (ICVSListener[]) repositoryListeners.toArray(new ICVSListener[repositoryListeners.size()]);
256         }
257     }
258     
259     private void fireNotification(Notification notification) {
260         // Get a snapshot of the listeners so the list doesn't change while we're firing
261
ICVSListener[] listeners = getListeners();
262         // Notify each listener in a safe manner (i.e. so their exceptions don't kill us)
263
for (int i = 0; i < listeners.length; i++) {
264             ICVSListener listener = listeners[i];
265             notification.run(listener);
266         }
267     }
268
269     public void added(NodeChangeEvent event) {
270         ((IEclipsePreferences)event.getChild()).addPreferenceChangeListener(this);
271     }
272
273     public void removed(NodeChangeEvent event) {
274         // Cannot remove the listener once the node is removed
275
//((IEclipsePreferences)event.getChild()).removePreferenceChangeListener(this);
276
}
277
278     public void preferenceChange(PreferenceChangeEvent event) {
279         if (CVSRepositoryLocation.PREF_LOCATION.equals(event.getKey())) {
280             String JavaDoc location = (String JavaDoc)event.getNewValue();
281             if (location == null) {
282                 ((IEclipsePreferences)event.getNode()).removePreferenceChangeListener(this);
283             } else {
284                 try {
285                     addRepository(CVSRepositoryLocation.fromString(location), true);
286                 } catch (CVSException e) {
287                     CVSProviderPlugin.log(e);
288                 }
289             }
290         }
291     }
292 }
293
Popular Tags