James Moger
2015-11-22 ed552ba47c02779c270ffd62841d6d1048dade70
src/main/java/com/gitblit/FileSettings.java
@@ -18,10 +18,13 @@
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import com.gitblit.utils.FileUtils;
import com.gitblit.utils.StringUtils;
/**
 * Dynamically loads and reloads a properties file by keeping track of the last
@@ -77,9 +80,13 @@
      if (propertiesFile != null && propertiesFile.exists() && (forceReload || (propertiesFile.lastModified() > lastModified))) {
         FileInputStream is = null;
         try {
            logger.debug("loading {}", propertiesFile);
            Properties props = new Properties();
            is = new FileInputStream(propertiesFile);
            props.load(is);
            // ticket-110
            props = readIncludes(props);
            // load properties after we have successfully read file
            properties.clear();
@@ -103,12 +110,68 @@
      return properties;
   }
   /**
    * Recursively read "include" properties files.
    *
    * @param properties
    * @return
    * @throws IOException
    */
   private Properties readIncludes(Properties properties) throws IOException {
      Properties baseProperties = new Properties();
      String include = (String) properties.remove("include");
      if (!StringUtils.isEmpty(include)) {
         // allow for multiples
         List<String> names = StringUtils.getStringsFromValue(include, ",");
         for (String name : names) {
            if (StringUtils.isEmpty(name)) {
               continue;
            }
            // try co-located
            File file = new File(propertiesFile.getParentFile(), name.trim());
            if (!file.exists()) {
               // try absolute path
               file = new File(name.trim());
            }
            if (!file.exists()) {
               logger.warn("failed to locate {}", file);
               continue;
            }
            // load properties
            logger.debug("loading {}", file);
            try (FileInputStream iis = new FileInputStream(file)) {
               baseProperties.load(iis);
            }
            // read nested includes
            baseProperties = readIncludes(baseProperties);
         }
      }
      // includes are "default" properties, they must be set first and the
      // props which specified the "includes" must override
      Properties merged = new Properties();
      merged.putAll(baseProperties);
      merged.putAll(properties);
      return merged;
   }
   @Override
   public boolean saveSettings() {
      String content = FileUtils.readContent(propertiesFile, "\n");
      for (String key : removals) {
         String regex = "(?m)^(" + regExEscape(key) + "\\s*+=\\s*+)"
                + "(?:[^\r\n\\\\]++|\\\\(?:\r?\n|\r|.))*+$";
               + "(?:[^\r\n\\\\]++|\\\\(?:\r?\n|\r|.))*+$";
         content = content.replaceAll(regex, "");
      }
      removals.clear();
@@ -128,7 +191,7 @@
      String content = FileUtils.readContent(propertiesFile, "\n");
      for (Map.Entry<String, String> setting:settings.entrySet()) {
         String regex = "(?m)^(" + regExEscape(setting.getKey()) + "\\s*+=\\s*+)"
                + "(?:[^\r\n\\\\]++|\\\\(?:\r?\n|\r|.))*+$";
               + "(?:[^\r\n\\\\]++|\\\\(?:\r?\n|\r|.))*+$";
         String oldContent = content;
         content = content.replaceAll(regex, setting.getKey() + " = " + setting.getValue());
         if (content.equals(oldContent)) {