View Javadoc

1   package com.atlassian.config.xml;
2   
3   import com.atlassian.config.AbstractConfigurationPersister;
4   import com.atlassian.config.ConfigurationException;
5   import com.atlassian.core.util.Dom4jUtil;
6   import org.dom4j.Document;
7   import org.dom4j.DocumentException;
8   import org.dom4j.DocumentHelper;
9   import org.dom4j.Element;
10  import org.dom4j.io.SAXReader;
11  import org.apache.log4j.Logger;
12  
13  import java.io.File;
14  import java.io.IOException;
15  import java.io.InputStream;
16  import java.net.MalformedURLException;
17  import java.util.List;
18  import java.util.Map;
19  
20  public abstract class AbstractDom4jXmlConfigurationPersister extends AbstractConfigurationPersister
21  {
22      public static final Logger log = Logger.getLogger(AbstractDom4jXmlConfigurationPersister.class);
23      private Document document;
24      protected boolean useCData = false;
25  
26      public AbstractDom4jXmlConfigurationPersister()
27      {
28          //Create the document root
29          clearDocument();
30  
31          //These define the mappings for the different objects stored in the config file
32          addConfigMapping(String.class, Dom4jXmlStringConfigElement.class);
33          addConfigMapping(Map.class, Dom4jXmlMapConfigElement.class);
34          addConfigMapping(Map.Entry.class, Dom4jXmlMapEntryConfigElement.class);
35          addConfigMapping(List.class, Dom4jXmlListConfigElement.class);
36      }
37  
38      public Document loadDocument(File xmlFile) throws DocumentException, MalformedURLException
39      {
40          SAXReader xmlReader = new SAXReader();
41          document = xmlReader.read(xmlFile);
42          return document;
43      }
44  
45      public Object load(InputStream istream) throws ConfigurationException
46      {
47          try
48          {
49              return loadDocument(istream);
50          }
51          catch (DocumentException e)
52          {
53              throw new ConfigurationException("Failed to load Xml doc: " + e.getMessage(), e);
54          }
55      }
56  
57      public Document loadDocument(InputStream istream) throws DocumentException
58      {
59          SAXReader xmlReader = new SAXReader();
60          document = xmlReader.read(istream);
61          return document;
62      }
63  
64      public void save(String configPath, String configFile) throws ConfigurationException
65      {
66          saveDocument(configPath, configFile);
67      }
68  
69      public void saveDocument(String configPath, String configFile) throws ConfigurationException
70      {
71          try
72          {
73              saveDocumentAtomically(getDocument(), configPath, configFile);
74          }
75          catch (IOException e)
76          {
77              throw new ConfigurationException("Couldn't save " + configFile + " to " + configPath + " directory.", e);
78          }
79      }
80  
81      private void saveDocumentAtomically(Document document, String configPath, String configFile) throws IOException
82      {
83          File tempFile = File.createTempFile(configFile, "tmp");
84          File saveFile = new File(configPath, configFile);
85  
86          try
87          {
88              Dom4jUtil.saveDocumentTo(document, tempFile.getParent(), tempFile.getName());
89  
90              // If the temp directory is on a different filesystem to the destination, the rename may fail on some
91              // operating systems.
92              if (!tempFile.renameTo(saveFile))
93              {
94                  log.warn("Unable to move " + tempFile.getCanonicalPath() + " to " + saveFile.getCanonicalPath() + ". Falling back to non-atomic overwrite.");
95                  Dom4jUtil.saveDocumentTo(document, configPath, configFile);
96              }
97          }
98          finally
99          {
100             tempFile.delete();
101         }
102     }
103 
104     public Document getDocument()
105     {
106         return document;
107     }
108 
109     public Object getRootContext()
110     {
111         return document.getRootElement();
112     }
113 
114     public Element getElement(String path)
115     {
116         return DocumentHelper.makeElement(document, path);
117     }
118 
119     public void clear()
120     {
121         clearDocument();
122     }
123 
124     private void clearDocument()
125     {
126         document = null;
127         document = DocumentHelper.createDocument();
128         document.addElement(getRootName());
129     }
130 
131     public abstract String getRootName();
132 
133     public boolean isUseCData()
134     {
135         return useCData;
136     }
137 
138     public void setUseCData(boolean useCData)
139     {
140         this.useCData = useCData;
141     }
142 }