View Javadoc

1   /**
2    * Copyright (C) 2008 Atlassian
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *    http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package com.atlassian.theplugin.commons.cfg;
17  
18  import com.atlassian.theplugin.commons.ServerType;
19  import com.atlassian.theplugin.commons.util.MiscUtil;
20  import static com.atlassian.theplugin.commons.util.MiscUtil.buildConcurrentHashMap;
21  
22  import java.util.*;
23  import java.util.concurrent.CopyOnWriteArraySet;
24  
25  public class CfgManagerImpl implements CfgManager {
26  	private final Map<ProjectId, ProjectConfiguration> projectConfigurations = buildConcurrentHashMap(INITIAL_CAPACITY);
27  	private Collection<ServerCfg> globalServers = MiscUtil.buildArrayList();
28  	private final Map<ProjectId, Collection<ConfigurationListener>> listeners = buildConcurrentHashMap(100);
29  	private final Map<ProjectId, Collection<ConfigurationCredentialsListener>> credentialListeners =
30  			buildConcurrentHashMap(100);
31  	private BambooCfg bambooCfg;
32  	private static final int INITIAL_CAPACITY = 4;
33  
34  	private static final ProjectListenerAction PROJECT_UNREGISTERED_LISTENER_ACTION = new ProjectListenerAction() {
35  		public void run(final ConfigurationListener projectListener, final ProjectId projectId,
36  				final CfgManagerImpl cfgManager) {
37  			projectListener.projectUnregistered();
38  		}
39  	};
40  	
41  	public CfgManagerImpl() {
42  		// TODO wseliga remove it later on and handle properly null values
43  		update(new GlobalConfiguration());
44  	}
45  
46  
47  	public ProjectConfiguration getProjectConfiguration(final ProjectId projectId) {
48  		verifyProjectId(projectId);
49  		return projectConfigurations.get(projectId);
50  	}
51  
52  	public Collection<ServerCfg> getAllServers(final ProjectId projectId) {
53          Collection<ServerCfg> tmp = new ArrayList<ServerCfg>(getProjectSpecificServers(projectId));
54          tmp.addAll(globalServers);
55          return tmp;
56      }
57  
58  	public Collection<CrucibleServerCfg> getAllCrucibleServers(ProjectId projectId) {
59  
60  		Collection<ServerCfg> tmp = getAllServers(projectId);
61  		Collection<CrucibleServerCfg> res = MiscUtil.buildArrayList();
62  		for (ServerCfg serverCfg : tmp) {
63  			if (serverCfg.getServerType() == ServerType.CRUCIBLE_SERVER && serverCfg instanceof CrucibleServerCfg) {
64  				res.add((CrucibleServerCfg) serverCfg);
65  			}
66  		}
67  		return res;
68  
69  	}
70  
71  	public Collection<ServerCfg> getProjectSpecificServers(final ProjectId projectId) {
72  		verifyProjectId(projectId);
73  		ProjectConfiguration res = projectConfigurations.get(projectId);
74          if (res == null) {
75              return Collections.emptyList();
76          }
77          return MiscUtil.buildArrayList(res.getServers());
78      }
79  
80  	public Collection<ServerCfg> getGlobalServers() {
81          return new ArrayList<ServerCfg>(globalServers);
82      }
83  
84  	public Collection<ServerCfg> getAllEnabledServers(final ProjectId projectId) {
85          Collection<ServerCfg> tmp = new ArrayList<ServerCfg>();
86          for (ServerCfg serverCfg : getAllServers(projectId)) {
87              if (serverCfg.isEnabled()) {
88                  tmp.add(serverCfg);
89              }
90          }
91          return tmp;
92      }
93  
94  
95  	public BambooCfg getGlobalBambooCfg() {
96  		return bambooCfg;
97      }
98  
99  	public void updateProjectConfiguration(final ProjectId projectId, final ProjectConfiguration projectConfiguration) {
100 		verifyProjectId(projectId);
101 		if (projectConfiguration == null) {
102 			throw new NullPointerException("Project configuration cannot be null");
103 		}
104 
105 //		notifyCredentialsListeners(projectId, projectConfiguration, getProjectConfiguration(projectId));
106 
107 		ProjectConfiguration oldConfiguration = null;
108 		if (getProjectConfiguration(projectId) != null) {
109 			oldConfiguration = new ProjectConfiguration(getProjectConfiguration(projectId));
110 		}
111 
112 		// internalize the list to be private and put it to array
113 		projectConfigurations.put(projectId, projectConfiguration);
114 
115 		notifyListeners(projectId, projectConfiguration, oldConfiguration);
116 //		notifyListeners(projectId, new UpdateConfigurationListenerAction(projectConfiguration));
117 
118 	}
119 
120 	private void notifyListeners(ProjectId projectId,
121 								 ProjectConfiguration newConfiguration,
122 								 ProjectConfiguration oldConfiguration) {
123 
124 		ProjectListenerAction[] actions = {
125 				new UpdateConfigurationListenerAction(newConfiguration),
126 				new ConfigurationTypeChangedAction(newConfiguration, oldConfiguration),
127 				new ServerChangedAction(newConfiguration, oldConfiguration),
128 				new ServerAddedAction(newConfiguration, oldConfiguration),
129 				new ServerRemovedAction(newConfiguration, oldConfiguration),
130 				new ServerEnabledDisabledAction(newConfiguration, oldConfiguration)
131 		};
132 
133 		for (ProjectListenerAction action : actions) {
134 			notifyListeners(projectId, action);
135 		}
136 	}
137 
138 	private void notifyListeners(final ProjectId projectId, ProjectListenerAction listenerAction) {
139 		Collection<ConfigurationListener> projectListeners = listeners.get(projectId);
140 		if (projectListeners != null) {
141 			for (ConfigurationListener projectListener : projectListeners) {
142 				listenerAction.run(projectListener, projectId, this);
143 				//projectListener.updateConfiguration(projectId, this);
144 			}
145 		}
146 	}
147 
148 	public void addProjectConfigurationListener(final ProjectId projectId, final ConfigurationListener configurationListener) {
149 		if (configurationListener == null) {
150 			throw new IllegalArgumentException(ProjectId.class.getSimpleName() + " cannot be null");
151 		}
152 		verifyProjectId(projectId);
153 
154 		Collection<ConfigurationListener> tmp = listeners.get(projectId);
155 		if (tmp == null) {
156 			tmp = new CopyOnWriteArraySet<ConfigurationListener>(); //MiscUtil.buildHashSet();
157 			listeners.put(projectId, tmp);
158 		}
159 		tmp.add(configurationListener);
160 	}
161 
162 	public boolean removeProjectConfigurationListener(final ProjectId projectId,
163 													  final ConfigurationListener configurationListener) {
164 		if (configurationListener == null) {
165 			throw new IllegalArgumentException(ProjectId.class.getSimpleName() + " cannot be null");
166 		}
167 		verifyProjectId(projectId);
168 		Collection<ConfigurationListener> tmp = listeners.get(projectId);
169 		return tmp.remove(configurationListener);
170 	}
171 
172 	public void updateGlobalConfiguration(final GlobalConfiguration globalConfiguration) {
173 		if (globalConfiguration == null) {
174 			throw new NullPointerException("Global configuration cannot be null");
175 		}
176 		// internalize the list to be private
177 		globalServers = MiscUtil.buildArrayList(globalConfiguration.getGlobalServers());
178 	}
179 
180 	public void addProjectSpecificServer(final ProjectId projectId, final ServerCfg serverCfg) {
181 		verifyProjectId(projectId);
182 		if (serverCfg == null) {
183 			throw new IllegalArgumentException(ServerCfg.class.getSimpleName() + " cannot be null");
184 		}
185 
186 		ProjectConfiguration projectCfg = getProjectConfiguration(projectId);
187 
188         if (projectCfg == null) {
189             projectCfg = new ProjectConfiguration();
190             projectConfigurations.put(projectId, projectCfg);
191         }
192 		if (!projectCfg.getServers().contains(serverCfg)) {
193 			projectCfg.getServers().add(serverCfg);
194 		}
195 
196 	}
197 
198 	public void addGlobalServer(final ServerCfg serverCfg) {
199         globalServers.add(serverCfg);
200     }
201 
202 	public ProjectConfiguration removeProject(final ProjectId projectId) {
203 		final ProjectConfiguration res = projectConfigurations.remove(projectId);
204 		if (res != null) {
205 			notifyListeners(projectId, PROJECT_UNREGISTERED_LISTENER_ACTION);
206 		}
207 		return res;
208 	}
209 
210 
211 	public ServerCfg removeGlobalServer(final ServerId serverId) {
212 		verifyServerId(serverId);
213 		return removeServer(serverId, globalServers);
214     }
215 
216 	private void verifyServerId(final ServerId serverId) {
217 		if (serverId == null) {
218 			throw new IllegalArgumentException(ServerId.class.getSimpleName() + " cannot be null");
219 		}
220 	}
221 
222 	public ServerCfg removeProjectSpecificServer(final ProjectId projectId, final ServerId serverId) {
223 		verifyProjectId(projectId);
224 		verifyServerId(serverId);
225 
226 		ProjectConfiguration projectCfg = getProjectConfiguration(projectId);
227 		if (projectCfg == null) {
228 			return null;
229 		}
230 
231 		return removeServer(serverId, projectCfg.getServers());
232 	}
233 
234 	private void verifyProjectId(final ProjectId projectId) {
235 		if (projectId == null) {
236 			throw new IllegalArgumentException(ProjectId.class.getSimpleName() + " cannot be null");
237 		}
238 	}
239 
240 	public boolean hasProject(ProjectId projectId) {
241 		return projectConfigurations.containsKey(projectId);
242 	}
243 
244 	public Collection<BambooServerCfg> getAllEnabledBambooServers(final ProjectId projectId) {
245 		Collection<ServerCfg> tmp = getAllEnabledServers(projectId);
246 		Collection<BambooServerCfg> res = MiscUtil.buildArrayList();
247 		for (ServerCfg serverCfg : tmp) {
248 			if (serverCfg instanceof BambooServerCfg) {
249 				BambooServerCfg bambooServerCfg = (BambooServerCfg) serverCfg;
250 				res.add(bambooServerCfg);
251 			}
252 		}
253 		return res;
254 	}
255 
256 	public ServerCfg getServer(final ProjectId projectId, final ServerId serverId) {
257 		final Collection<ServerCfg> tmp = getAllServers(projectId);
258 		for (ServerCfg serverCfg : tmp) {
259 			if (serverCfg.getServerId().equals(serverId)) {
260 				return serverCfg;
261 			}
262 		}
263 		return null;
264 	}
265 
266 	public Collection<CrucibleServerCfg> getAllEnabledCrucibleServers(final ProjectId projectId) {
267 		Collection<ServerCfg> tmp = getAllEnabledServers(projectId);
268 		Collection<CrucibleServerCfg> res = MiscUtil.buildArrayList();
269 		for (ServerCfg serverCfg : tmp) {
270 			if (serverCfg instanceof CrucibleServerCfg) {
271 				CrucibleServerCfg bambooServerCfg = (CrucibleServerCfg) serverCfg;
272 				res.add(bambooServerCfg);
273 			}
274 		}
275 		return res;
276 	}
277 
278 
279 	public Collection<JiraServerCfg> getAllEnabledJiraServers(final ProjectId projectId) {
280 		Collection<ServerCfg> tmp = getAllEnabledServers(projectId);
281 		Collection<JiraServerCfg> res = MiscUtil.buildArrayList();
282 		for (ServerCfg serverCfg : tmp) {
283 			if (serverCfg instanceof JiraServerCfg) {
284 				JiraServerCfg bambooServerCfg = (JiraServerCfg) serverCfg;
285 				res.add(bambooServerCfg);
286 			}
287 		}
288 		return res;
289 	}
290 
291 
292 	public Collection<ServerCfg> getAllEnabledServers(final ProjectId projectId, ServerType serverType) {
293 		Collection<ServerCfg> tmp = getAllEnabledServers(projectId);
294 		Collection<ServerCfg> res = MiscUtil.buildArrayList();
295 		for (ServerCfg serverCfg : tmp) {
296 			if (serverCfg.getServerType() == serverType) {
297 				res.add(serverCfg);
298 			}
299 		}
300 		return res;
301 	}
302 
303 	private ServerCfg removeServer(final ServerId serverId, final Collection<ServerCfg> servers) {
304         Iterator<ServerCfg> it = servers.iterator();
305         while (it.hasNext()) {
306             ServerCfg serverCfg = it.next();
307             if (serverCfg.getServerId().equals(serverId)) {
308                 it.remove();
309                 return serverCfg;
310             }
311         }
312         return null;
313     }
314 
315 
316 	public void update(GlobalConfiguration globalConfiguration) {
317 		bambooCfg = globalConfiguration.getBambooCfg();
318 	}
319 
320 	private interface ProjectListenerAction {
321 		void run(final ConfigurationListener projectListener, final ProjectId projectId, final CfgManagerImpl cfgManager);
322 	}
323 
324 
325 	public Collection<ServerCfg> getAllUniqueServers() {
326 		final Set<ServerCfg> res = new HashSet<ServerCfg>(globalServers);
327 		for (ProjectConfiguration projectCfg : projectConfigurations.values()) {
328 			res.addAll(projectCfg.getServers());
329 		}
330 		return res;
331 	}
332 
333 
334 	private static class UpdateConfigurationListenerAction implements ProjectListenerAction {
335 
336 		private final ProjectConfiguration projectConfiguration;
337 
338 		public UpdateConfigurationListenerAction(final ProjectConfiguration projectConfiguration) {
339 			this.projectConfiguration = projectConfiguration;
340 		}
341 
342 		public void run(final ConfigurationListener projectListener, final ProjectId projectId,
343 				final CfgManagerImpl cfgManager) {
344 			projectListener.configurationUpdated(projectConfiguration);
345 		}
346 	}
347 
348 	private class ServerChangedAction implements ProjectListenerAction {
349 		protected final ProjectConfiguration newConfiguration;
350 		protected ProjectConfiguration oldConfiguration;
351 
352 		public ServerChangedAction(ProjectConfiguration newConfiguration, ProjectConfiguration oldConfiguration) {
353 			this.newConfiguration = newConfiguration;
354 			this.oldConfiguration = oldConfiguration;
355 		}
356 
357 		public void run(ConfigurationListener projectListener, ProjectId projectId, CfgManagerImpl cfgManager) {
358 			if (oldConfiguration == null || newConfiguration == null) {
359 				return;
360 			}
361 
362 			for (ServerCfg oldServer : oldConfiguration.getServers()) {
363 				ServerCfg newServer = newConfiguration.getServerCfg(oldServer.getServerId());
364 
365 				// server general update
366 				if (newServer != null && !oldServer.equals(newServer)) {
367 					projectListener.serverDataChanged(oldServer.getServerId());
368 
369 					// server url or credentials updated
370 					if (checkCredentialsChanged(oldServer, newServer)
371 							|| checkUrlChanged(oldServer, newConfiguration.getServerCfg(oldServer.getServerId()))) {
372 						projectListener.serverConnectionDataChanged(oldServer.getServerId());
373 					}
374 
375 					// server name updated
376 					if (!oldServer.getName().equals(newServer.getName())) {
377 						projectListener.serverNameChanged(oldServer.getServerId());
378 					}
379 
380 				}
381 			}
382 		}
383 
384 		protected boolean checkCredentialsChanged(final ServerCfg oldServer, final ServerCfg newServer) {
385 			if (newServer == null) {
386 				return false;
387 			}
388 
389 			if (!oldServer.getUsername().equals(newServer.getUsername())
390 					|| !oldServer.getPassword().equals(newServer.getPassword())) {
391 				return true;
392 			}
393 
394 			return false;
395 		}
396 
397 		private boolean checkUrlChanged(final ServerCfg oldServer, final ServerCfg newServer) {
398 			if (newServer == null) {
399 				return false;
400 			}
401 			return !oldServer.getUrl().equals(newServer.getUrl());
402 		}
403 	}
404 
405 	private class ServerAddedAction implements ProjectListenerAction {
406 		private final ProjectConfiguration newConfiguration;
407 		private final ProjectConfiguration oldConfiguration;
408 
409 		public ServerAddedAction(ProjectConfiguration newConfiguration, ProjectConfiguration oldConfiguration) {
410 			this.newConfiguration = newConfiguration;
411 			this.oldConfiguration = oldConfiguration;
412 		}
413 
414 		public void run(ConfigurationListener projectListener, ProjectId projectId, CfgManagerImpl cfgManager) {
415 			if (oldConfiguration == null || newConfiguration == null) {
416 				return;
417 			}
418 
419 			for (ServerCfg newServer : newConfiguration.getServers()) {
420 				if (oldConfiguration.getServerCfg(newServer.getServerId()) == null) {
421 					projectListener.serverAdded(newServer);
422 				}
423 			}
424 		}
425 	}
426 
427 	private class ServerRemovedAction implements ProjectListenerAction {
428 		private final ProjectConfiguration newConfiguration;
429 		private final ProjectConfiguration oldConfiguration;
430 
431 		public ServerRemovedAction(ProjectConfiguration newConfiguration, ProjectConfiguration oldConfiguration) {
432 			this.newConfiguration = newConfiguration;
433 			this.oldConfiguration = oldConfiguration;
434 		}
435 
436 		public void run(ConfigurationListener projectListener, ProjectId projectId, CfgManagerImpl cfgManager) {
437 			if (oldConfiguration == null || newConfiguration == null) {
438 				return;
439 			}
440 
441 			for (ServerCfg oldServer : oldConfiguration.getServers()) {
442 				if (newConfiguration.getServerCfg(oldServer.getServerId()) == null) {
443 					projectListener.serverRemoved(oldServer);
444 				}
445 			}
446 		}
447 	}
448 
449 	private class ServerEnabledDisabledAction implements ProjectListenerAction {
450 
451 		private final ProjectConfiguration newConfiguration;
452 		private final ProjectConfiguration oldConfiguration;
453 
454 		public ServerEnabledDisabledAction(ProjectConfiguration newConfiguration, ProjectConfiguration oldConfiguration) {
455 			this.newConfiguration = newConfiguration;
456 			this.oldConfiguration = oldConfiguration;
457 		}
458 
459 		public void run(ConfigurationListener projectListener, ProjectId projectId, CfgManagerImpl cfgManager) {
460 			if (oldConfiguration == null || newConfiguration == null) {
461 				return;
462 			}
463 
464 			for (ServerCfg oldServer : oldConfiguration.getServers()) {
465 				ServerCfg newServer = newConfiguration.getServerCfg(oldServer.getServerId());
466 				if (newServer != null) {
467 					if (!oldServer.isEnabled() && newServer.isEnabled()) {
468 						projectListener.serverEnabled(oldServer.getServerId());
469 					} else if (oldServer.isEnabled() && !newServer.isEnabled()) {
470 						projectListener.serverDisabled(oldServer.getServerId());
471 					}
472 				}
473 			}
474 		}
475 
476 	}
477 
478 	private class ConfigurationTypeChangedAction implements ProjectListenerAction {
479 		private final ProjectConfiguration newConfiguration;
480 		private final ProjectConfiguration oldConfiguration;
481 
482 		public ConfigurationTypeChangedAction(
483 				ProjectConfiguration newConfiguration, ProjectConfiguration oldConfiguration) {
484 			this.newConfiguration = newConfiguration;
485 			this.oldConfiguration = oldConfiguration;
486 		}
487 
488 		public void run(ConfigurationListener projectListener, ProjectId projectId, CfgManagerImpl cfgManager) {
489 			if (oldConfiguration == null || newConfiguration == null) {
490 				return;
491 			}
492 
493 			// Collections.constainsAll is used in both directions below instead of Collection.equlas
494 			// as equals for Collection compares only references
495 			// and we cannot be sure if used implementation overrides equals correctly
496 			// and e.g. equals for List requires the same order of elements
497 
498 			// JIRA servers changed
499 			Collection<JiraServerCfg> newJiraServers = newConfiguration.getAllJIRAServers();
500 			Collection<JiraServerCfg> oldJiraServers = oldConfiguration.getAllJIRAServers();
501 			if (!newJiraServers.containsAll(oldJiraServers) || !oldJiraServers.containsAll(newJiraServers)) {
502 				projectListener.jiraServersChanged(newConfiguration);
503 			}
504 
505 			// Bamboo servers changed
506 			Collection<BambooServerCfg> newBambooServers = newConfiguration.getAllBambooServers();
507 			Collection<BambooServerCfg> oldBambooServers = oldConfiguration.getAllBambooServers();
508 			if (!newBambooServers.containsAll(oldBambooServers) || !oldBambooServers.containsAll(newBambooServers)) {
509 				projectListener.bambooServersChanged(newConfiguration);
510 			}
511 
512 			// Crucible servers changed
513 			Collection<CrucibleServerCfg> newCrucibleServers = newConfiguration.getAllCrucibleServers();
514 			Collection<CrucibleServerCfg> oldCrucibleServers = oldConfiguration.getAllCrucibleServers();
515 			if (!newCrucibleServers.containsAll(oldCrucibleServers) || !oldCrucibleServers.containsAll(newCrucibleServers)) {
516 				projectListener.crucibleServersChanged(newConfiguration);
517 			}
518 
519 			// Fisheye servers changed
520 			Collection<FishEyeServerCfg> newFisheyeServers = newConfiguration.getAllFisheyeServers();
521 			Collection<FishEyeServerCfg> oldFisheyeServers = oldConfiguration.getAllFisheyeServers();
522 			if (!newFisheyeServers.containsAll(oldFisheyeServers) || !oldFisheyeServers.containsAll(newFisheyeServers)) {
523 				projectListener.fisheyeServersChanged(newConfiguration);
524 			}
525 		}
526 	}
527 }