1   package com.trendmicro.grid.acl.ds;
2   
3   import org.slf4j.Logger;
4   import org.slf4j.LoggerFactory;
5   
6   import javax.xml.bind.annotation.*;
7   import java.util.Arrays;
8   import java.util.Collections;
9   import java.util.List;
10  import java.util.Map;
11  
12  /**
13   * Is a helper class used to maintain the selection of an active repository.
14   *
15   * @author juergen_kellerer, 2010-05-05
16   * @version 1.0
17   */
18  @XmlType
19  @XmlAccessorType(XmlAccessType.FIELD)
20  public class RepositorySelector<R extends Repository> implements RepositorySelectorMBean {
21  
22  	private static final Logger log = LoggerFactory.getLogger(RepositorySelector.class);
23  
24  	private transient Map<String, R> repositories;
25  	private transient R selected;
26  	private transient long lastModified;
27  	transient boolean initialized, autoSelectedKey;
28  
29  	@XmlAttribute(required = true)
30  	private String repositoryClass;
31  
32  	@XmlElement(required = false)
33  	private String selectedKey;
34  	@XmlElement(name = "available", required = false)
35  	private String[] availableKeys;
36  
37  	public RepositorySelector() {
38  	}
39  
40  	public RepositorySelector(Map<String, R> repositories, Class<R> repositoryClass) {
41  		init(repositories, repositoryClass);
42  	}
43  
44  	public void initFrom(RepositorySelector<R> other) {
45  		try {
46  			lastModified = other.lastModified;
47  			if (!other.autoSelectedKey || !other.repositories.containsKey(selectedKey))
48  				selectedKey = other.getSelectedKey();
49  			init(other.repositories, other.getRepositoryClass());
50  		} finally {
51  			String selection = getSelectedKey();
52  			try {
53  				setSelectedKey(selection);
54  			} catch (IllegalArgumentException e) {
55  				log.warn("TMACL-00340:Failed to select the implementation '{}' for " +
56  						"repository type {}, using default of {} instead.",
57  						new Object[]{selection, repositoryClass, getSelectedKey()});
58  			}
59  		}
60  	}
61  
62  	public void init(Map<String, R> repositories, Class<R> repositoryClass) {
63  		init(repositories, repositoryClass.getName());
64  	}
65  
66  	private void init(Map<String, R> repositories, String repositoryClass) {
67  		if (repositories == null || repositories.isEmpty()) {
68  			log.warn("TMACL-00090:The repository type {} doesn't have any registered implementations.",
69  					repositoryClass);
70  		}
71  
72  		this.repositories = repositories;
73  		this.repositoryClass = repositoryClass;
74  		if (repositories != null)
75  			availableKeys = repositories.keySet().toArray(new String[repositories.size()]);
76  
77  		try {
78  			setSelectedKey(getSelectedKey());
79  		} catch (IllegalArgumentException e) {
80  			// ignore
81  		}
82  
83  		initialized = true;
84  	}
85  
86  	private void assertIsInitialized() {
87  		if (!initialized) {
88  			log.error("TMACL-00110:The selector for {} repositories was invoked " +
89  					"before it got initialized. The result will be 'null'.", repositoryClass);
90  			throw new IllegalStateException("Selector for repository " +
91  					repositoryClass + " is used before it was initialized.");
92  		}
93  	}
94  
95  	public long getLastModified() {
96  		return lastModified;
97  	}
98  
99  	public void setLastModified(long time) {
100 		lastModified = time;
101 	}
102 
103 	/**
104 	 * {@inheritDoc}
105 	 */
106 	public String getRepositoryClass() {
107 		return repositoryClass;
108 	}
109 
110 	public R getRepository(String key) {
111 		assertIsInitialized();
112 		return repositories == null ? null : repositories.get(key);
113 	}
114 
115 	/**
116 	 * Returns the currently selected repository.
117 	 *
118 	 * @return the currently selected repository.
119 	 */
120 	public R getRepository() {
121 		assertIsInitialized();
122 		return selected;
123 	}
124 
125 	public boolean hasSelection() {
126 		return selectedKey != null;
127 	}
128 
129 	public boolean isAutoSelectedKey() {
130 		return autoSelectedKey;
131 	}
132 
133 	/**
134 	 * {@inheritDoc}
135 	 */
136 	public String getSelectedKey() {
137 		if (!hasSelection() && repositories != null && !repositories.isEmpty()) {
138 			String key = repositories.keySet().iterator().next();
139 			log.info("TMACL-00120:No selection present for repository type {}, auto-selecting '{}'",
140 					repositoryClass, key);
141 			setSelectedKey(key);
142 			autoSelectedKey = true;
143 		}
144 		return selectedKey;
145 	}
146 
147 	/**
148 	 * {@inheritDoc}
149 	 */
150 	public void setSelectedKey(String selectedKey) {
151 		setSelectedKey(selectedKey, false);
152 	}
153 
154 	void setSelectedKey(String selectedKey, boolean autoSelectedKey) {
155 		if (repositories != null && selectedKey != null && !repositories.containsKey(selectedKey)) {
156 			throw new IllegalArgumentException("Cannot set the selection to '" + selectedKey +
157 					"' an implementation of that name does not exist.");
158 		}
159 
160 		if (!String.valueOf(this.selectedKey).equals(selectedKey)) {
161 			lastModified = System.currentTimeMillis();
162 			this.autoSelectedKey = autoSelectedKey;
163 		}
164 
165 		this.selectedKey = selectedKey;
166 		selected = repositories == null ? null : repositories.get(selectedKey);
167 	}
168 
169 	/**
170 	 * {@inheritDoc}
171 	 */
172 	public List<String> getAvailableKeys() {
173 		if (availableKeys == null)
174 			return Collections.emptyList();
175 		return Arrays.asList(availableKeys);
176 	}
177 }