1   package com.atlassian.user.configuration.xml;
2   
3   import org.dom4j.Node;
4   import org.dom4j.DocumentException;
5   import org.dom4j.Document;
6   import org.dom4j.Element;
7   import org.dom4j.io.SAXReader;
8   import org.apache.commons.lang.StringUtils;
9   import org.apache.log4j.Logger;
10  
11  import java.util.*;
12  import java.io.IOException;
13  import java.io.FileNotFoundException;
14  import java.net.URL;
15  
16  import com.atlassian.user.util.ClassLoaderUtils;
17  import com.atlassian.user.configuration.Configuration;
18  
19  /**
20   * Loads the default configuration for the available atlassian-user repositories. These defaults define
21   * fall-through values for any configuration option not specified in the proper atlassian-user config.
22   *
23   * <p>The parser will search the classpath roots for all files matching the defaults config file
24   * name (<code>atlassian-user-defaults.xml</code>), and load the default configuration values from them.
25   * If defaults are configured for the same repository type in multiple defaults files, the behaviour is
26   * undefined.
27   *
28   * <p>For an example of the file format of the defaults file, just look at the <code>atlassian-user-defaults.xml</code>
29   * included in atlassian-user.
30   */
31  public class XMLDefaultsParser
32  {
33      private static final Logger log = Logger.getLogger(XMLDefaultsParser.class);
34  
35      public static final String DEFAULTS_FILE_NAME = "atlassian-user-defaults.xml";
36  
37      private final List<Node> defaultsBaseNodes = new ArrayList<Node>();
38  
39      public XMLDefaultsParser() throws IOException, DocumentException
40      {
41          this(DEFAULTS_FILE_NAME);
42      }
43  
44      public XMLDefaultsParser(String defaultsFileName) throws IOException, DocumentException
45      {
46          this(new String[] { defaultsFileName });
47      }
48  
49      private void initialiseDefaultsNodesForFile(String defaultsFileName)
50              throws IOException, DocumentException
51      {
52          Enumeration defaultsFileUrls = ClassLoaderUtils.getResources(defaultsFileName, this.getClass());
53  
54          while (defaultsFileUrls.hasMoreElements())
55          {
56              URL url = (URL) defaultsFileUrls.nextElement();
57              Node defaultsNode = findBaseNodeInFile(url);
58              if (defaultsNode != null)
59                  defaultsBaseNodes.add(defaultsNode);
60              else
61                  log.error("Unable to find valid atlassian-user defaults data in file: " + url);
62          }
63      }
64  
65      public XMLDefaultsParser(String[] defaultsFileNames) throws DocumentException, IOException
66      {
67          for (String defaultsFileName : defaultsFileNames)
68              initialiseDefaultsNodesForFile(defaultsFileName);
69  
70          if (defaultsBaseNodes.isEmpty())
71              throw new FileNotFoundException("No valid user defaults files found in classpath with name: " + StringUtils.join(defaultsFileNames, ", "));
72      }
73  
74      public Map<String, String> getDefaultClassesConfigForKey(String key) throws DocumentException, IOException
75      {
76          Map<String, String> defaults = new HashMap<String, String>();
77  
78          for (Node node : defaultsBaseNodes)
79          {
80              Node defaultsNode = node.selectSingleNode(key);
81  
82              if (defaultsNode != null)
83                  defaults.putAll(XMLConfigUtil.parseRepositoryElementForClassNames((Element) defaultsNode));
84          }
85  
86          return defaults;
87      }
88  
89      private Node findBaseNodeInFile(URL url) throws DocumentException
90      {
91          SAXReader reader = new SAXReader();
92          Document doc = reader.read(url);
93  
94          return doc.selectSingleNode("//" + Configuration.DEFAULT);
95      }
96  
97      public Map<String, String> getDefaultParameterConfigForKey(String key)
98      {
99          Map<String, String> defaults = new HashMap<String, String>();
100 
101         for (Node node : defaultsBaseNodes)
102         {
103             Node defaultsNode = node.selectSingleNode(key);
104 
105             if (defaultsNode != null)
106             {
107                 defaults.putAll(XMLConfigUtil.parseRepositoryElementForStringData((Element) defaultsNode));
108                 break;
109             }
110         }
111 
112         return defaults;
113     }
114 }