1 package com.atlassian.user.configuration.xml;
2
3 import org.dom4j.*;
4 import org.dom4j.io.SAXReader;
5 import org.apache.log4j.Logger;
6
7 import java.util.*;
8 import java.io.InputStream;
9 import java.io.IOException;
10
11 import com.atlassian.user.configuration.*;
12 import com.atlassian.user.repository.RepositoryIdentifier;
13 import com.atlassian.user.repository.DefaultRepositoryIdentifier;
14
15
16
17
18
19
20
21
22
23 public class XMLConfigurationParser
24 {
25 private final static Logger log = Logger.getLogger(XMLConfigurationParser.class);
26
27 private final XMLDefaultsParser defaultsParser;
28
29
30
31
32 private List<RepositoryIdentifier> repositoryIdentifiers = new ArrayList<RepositoryIdentifier>();
33
34 private Map<RepositoryIdentifier, RepositoryConfiguration> repositoryConfigurations = new HashMap<RepositoryIdentifier, RepositoryConfiguration>();
35
36
37 public XMLConfigurationParser() throws ConfigurationException
38 {
39 this(XMLDefaultsParser.DEFAULTS_FILE_NAME);
40 }
41
42 public XMLConfigurationParser(String defaultsFileName) throws ConfigurationException
43 {
44 try
45 {
46 defaultsParser = new XMLDefaultsParser(defaultsFileName);
47 }
48 catch (RuntimeException e)
49 {
50 throw e;
51 }
52 catch (Exception e)
53 {
54 throw new ConfigurationException("Unable to load atlassian-user configuration parser: " + e.getMessage(), e);
55 }
56 }
57
58 public void parse(InputStream docIS) throws ConfigurationException
59 {
60 try
61 {
62 if (docIS == null)
63 throw new ConfigurationException("Null inputstream: cannot locate atlassian-user.xml");
64
65 SAXReader reader = new SAXReader();
66 Document doc;
67 try
68 {
69 doc = reader.read(docIS);
70 }
71 catch (DocumentException e)
72 {
73 throw new ConfigurationException(e);
74 }
75
76 Node delegationNode = doc.selectSingleNode("//" + Configuration.DELEGATION);
77 Node repositoriesNode = doc.selectSingleNode("//" + Configuration.REPOSITORIES);
78
79 parseRepositories(repositoriesNode);
80
81 if (delegationNode != null)
82 parseDelegation(delegationNode);
83 }
84 catch (RuntimeException e)
85 {
86 throw e;
87 }
88 catch (Exception e)
89 {
90 throw new ConfigurationException("Unable to load atlassian-user configuration: " + e.getMessage(), e);
91 }
92 }
93
94 protected void parseRepositories(Node repositoriesNode) throws ConfigurationException, DocumentException, IOException
95 {
96 List repositoryElements = repositoriesNode.selectNodes("*");
97
98 if (repositoryElements.isEmpty())
99 throw new ConfigurationException("Nothing to init. There are no repositories specified.");
100
101 for (Object repositoryElement1 : repositoryElements)
102 {
103 Element repositoryElement = (Element) repositoryElement1;
104
105
106 String repositoryType = repositoryElement.getName();
107
108 Map<String, String> defaultComponentClassNames = defaultsParser.getDefaultClassesConfigForKey(repositoryType);
109 Map<String, String> defaultComponents = defaultsParser.getDefaultParameterConfigForKey(repositoryType);
110
111
112 RepositoryIdentifier identifier = parseRepositoryIdentifier(repositoryElement);
113 if (repositoryIdentifiers.contains(identifier))
114 {
115 throw new ConfigurationException("Repository keys must be unique. Please check that you have not " +
116 "used the key '" + identifier.getKey() + "' more than once in your atlassian-user.xml file.");
117 }
118
119 Map<String, String> componentClassNames = XMLConfigUtil.parseRepositoryElementForClassNames(repositoryElement);
120 Map<String, String> components = XMLConfigUtil.parseRepositoryElementForStringData(repositoryElement);
121
122
123
124
125
126 for (Object o : defaultComponentClassNames.keySet())
127 {
128 String componentClassName = (String) o;
129 if (!componentClassNames.containsKey(componentClassName))
130 {
131 componentClassNames.put(componentClassName, defaultComponentClassNames.get(componentClassName));
132 }
133 }
134
135 for (String componentName : defaultComponents.keySet())
136 {
137 if (!components.containsKey(componentName))
138 {
139 components.put(componentName, defaultComponents.get(componentName));
140 }
141 }
142
143 RepositoryProcessor processor = instantiateProcessor(componentClassNames);
144
145 RepositoryConfiguration configuration =
146 new DefaultRepositoryConfiguration(identifier, processor, components, componentClassNames);
147
148 if (isCachingEnabled(repositoryElement))
149 configuration.setCacheConfiguration(parseCacheConfiguration());
150
151 repositoryIdentifiers.add(identifier);
152 repositoryConfigurations.put(identifier, configuration);
153 }
154 }
155
156 private RepositoryIdentifier parseRepositoryIdentifier(Element repositoryElement)
157 {
158 String key = repositoryElement.attributeValue("key");
159 if (key == null) throw new RuntimeException("Cannot specify repository without a key");
160 String name = repositoryElement.attributeValue("name", "Unnamed repository");
161 return new DefaultRepositoryIdentifier(key, name);
162 }
163
164 private CacheConfiguration parseCacheConfiguration() throws DocumentException, IOException
165 {
166 Map classNames = defaultsParser.getDefaultClassesConfigForKey(Configuration.CACHE);
167 return new DefaultCacheConfiguration(classNames);
168 }
169
170 private boolean isCachingEnabled(Element repositoryElement)
171 {
172 String cache = repositoryElement.attributeValue(Configuration.CACHE);
173 return cache != null && cache.equalsIgnoreCase("true");
174 }
175
176
177
178
179 private void parseDelegation(Node delegationNode)
180 {
181 List<RepositoryIdentifier> delegationOrder = new LinkedList<RepositoryIdentifier>();
182
183 for (Object o : delegationNode.selectNodes(Configuration.KEY))
184 {
185 String delegationKey = ((Element) o).getText();
186 for (RepositoryIdentifier identifier : repositoryIdentifiers)
187 {
188 if (delegationKey.equals(identifier.getKey()))
189 {
190 delegationOrder.add(identifier);
191 break;
192 }
193 }
194 }
195 repositoryIdentifiers = delegationOrder;
196 }
197
198 private RepositoryProcessor instantiateProcessor(Map processorInfo)
199 {
200 String processorClassName = (String) processorInfo.get(Configuration.PROCESSOR);
201 RepositoryProcessor processor = null;
202
203 try
204 {
205 processor = (RepositoryProcessor) Class.forName(processorClassName).newInstance();
206 }
207 catch (Exception e)
208 {
209 log.error("Could not instantiate processor: " + e.getMessage());
210 }
211
212 return processor;
213 }
214
215
216
217
218 public List<RepositoryConfiguration> getRepositoryConfigurations()
219 {
220 List<RepositoryConfiguration> result = new LinkedList<RepositoryConfiguration>();
221
222 for (RepositoryIdentifier identifier : repositoryIdentifiers)
223 result.add(repositoryConfigurations.get(identifier));
224
225 return Collections.unmodifiableList(result);
226 }
227 }