1   package com.atlassian.user.configuration.xml;
2   
3   import com.atlassian.user.util.ClassLoaderUtils;
4   import com.atlassian.user.util.FileUtils;
5   import com.atlassian.user.configuration.xml.XMLConfigurationParser;
6   import com.atlassian.user.configuration.*;
7   import org.apache.log4j.Logger;
8   
9   import java.io.*;
10  import java.util.List;
11  import java.util.Iterator;
12  
13  public class XMLConfiguration implements Configuration
14  {
15      private static final Logger log = Logger.getLogger(XMLConfiguration.class);
16  
17      /**
18       * the key of the system property containing the path to the atlassian user xml configuration file.
19       */
20      private static final String SYSTEM_ATLASSIAN_USER_CONFIGURATION = "atlassian.user.configuration";
21  
22      protected String fileName = "atlassian-user.xml";
23      protected XMLConfigurationParser xmlParser;
24      protected boolean initialized;
25      protected boolean initializing;
26      protected DelegationAccessor delegationAccessor;
27      protected List repositoryConfigs;
28      protected InputStream xmlIS;
29  
30      public static XMLConfiguration configureFromXMLString(String xmlString) throws ConfigurationException
31      {
32          ByteArrayInputStream in = new ByteArrayInputStream(xmlString.getBytes());
33          try
34          {
35              XMLConfiguration config = new XMLConfiguration(in);
36              config.init();
37              return config;
38          }
39          finally
40          {
41              FileUtils.shutdownStream(in);
42          }
43      }
44  
45      public XMLConfiguration() throws ConfigurationException
46      {
47          xmlParser = new XMLConfigurationParser();
48          delegationAccessor = new DefaultDelegationAccessor();
49      }
50  
51      public XMLConfiguration(String fileName) throws ConfigurationException
52      {
53          this.fileName = fileName;
54          xmlParser = new XMLConfigurationParser();
55          delegationAccessor = new DefaultDelegationAccessor();
56      }
57  
58      public XMLConfiguration(InputStream is) throws ConfigurationException
59      {
60          xmlIS = is;
61          xmlParser = new XMLConfigurationParser();
62          delegationAccessor = new DefaultDelegationAccessor();
63      }
64  
65      public DelegationAccessor getDelegationAccessor()
66      {
67          if (!initialized && !initializing)
68          {
69              try
70              {
71                  init();
72              }
73              catch (ConfigurationException e)
74              {
75                  throw new RuntimeException("Atlassian User failed to initialize: " + e.getMessage(), e);
76              }
77          }
78  
79          return delegationAccessor;
80      }
81  
82      public void init() throws ConfigurationException
83      {
84          if (!initialized && !initializing)
85          {
86              initializing = true;
87  
88              if (xmlIS == null)
89                  xmlIS = getXmlConfigurationFileAsInputStream();
90  
91              xmlParser.parse(xmlIS);
92  
93              try
94              {
95                  xmlIS.close();
96              }
97              catch (IOException e)
98              {
99                  throw new ConfigurationException("Could not close inputstream on [" + fileName + "]: "
100                         + e.getMessage(), e);
101             }
102 
103             repositoryConfigs = xmlParser.getRepositoryConfigurations();
104             for (Iterator configIter = repositoryConfigs.iterator(); configIter.hasNext(); )
105             {
106                 RepositoryConfiguration repositoryConfiguration = (RepositoryConfiguration) configIter.next();
107                 RepositoryAccessor accessor = configureRepository(repositoryConfiguration);
108                 delegationAccessor.addRepositoryAccessor(accessor);
109             }
110 
111             initialized = true;
112         }
113 
114         initializing = false;
115     }
116 
117     /**
118      * <p>Gets the {@link java.io.InputStream} of the xml configuration file to use.</p>
119      * <p>This methods strategy is:
120      * <ul>
121      * <li>Check for the {#SYSTEM_ATLASSIAN_USER_CONFIGURATION} system property, if it exists use configuration file denoted by the given path,</li>
122      * <li>Check for an "atlassian-user.xml" file in the classpath and use it if found</li>
123      * </ul>
124      * Whenever there is a problem with one specific configuration, it tries the next option, until there is no other option.
125      * </p>
126      *
127      * @return the {@link InputStream} to the configuration file, <code>null</code> if no suitable configuration file was found.
128      */
129     private InputStream getXmlConfigurationFileAsInputStream()
130     {
131         InputStream is = null;
132 
133         // check the system property first
134         String configurationFilePath = System.getProperty(SYSTEM_ATLASSIAN_USER_CONFIGURATION);
135         if (configurationFilePath != null)
136         {
137             final File configurationFile = new File(configurationFilePath);
138             if (configurationFile.exists())
139             {
140                 try
141                 {
142                     is = new BufferedInputStream(new FileInputStream(configurationFile));
143                     if (log.isInfoEnabled())
144                     {
145                         log.info("Using configuration file at: [" + configurationFile.getAbsolutePath() + "]");
146                     }
147                 }
148                 catch (IOException e)
149                 {
150                     is = null;
151                     log.warn("Couldn't load file at: [" + configurationFile.getAbsolutePath() + "], falling back on classpath resource.", e);
152                 }
153             }
154             else if (log.isDebugEnabled())
155             {
156                 log.debug("Couldn't find file at [" + configurationFile.getAbsolutePath() + "], falling back on classpath resource.");
157             }
158         }
159         else if (log.isDebugEnabled())
160         {
161             log.debug("System property " + SYSTEM_ATLASSIAN_USER_CONFIGURATION + " not specified, using classpath resource.");
162         }
163 
164         // if input stream is still null, look for resource in the classpath
165         if (is == null)
166         {
167             is = ClassLoaderUtils.getResourceAsStream(fileName, this.getClass());
168         }
169 
170         return is;
171     }
172 
173     protected RepositoryAccessor configureRepository(RepositoryConfiguration repositoryConfiguration) throws ConfigurationException
174     {
175         return repositoryConfiguration.configure();
176     }
177 
178     public boolean isInitialized()
179     {
180         return initialized;
181     }
182 }