diff --git a/libresonic-main/pom.xml b/libresonic-main/pom.xml index 3f820085..499b9ffc 100644 --- a/libresonic-main/pom.xml +++ b/libresonic-main/pom.xml @@ -353,6 +353,19 @@ + + org.apache.commons + commons-configuration2 + 2.1 + + + commons-beanutils + commons-beanutils + 1.9.2 + + runtime + + diff --git a/libresonic-main/src/main/java/org/libresonic/player/service/ApacheCommonsConfigurationService.java b/libresonic-main/src/main/java/org/libresonic/player/service/ApacheCommonsConfigurationService.java new file mode 100644 index 00000000..dc8e0f6e --- /dev/null +++ b/libresonic-main/src/main/java/org/libresonic/player/service/ApacheCommonsConfigurationService.java @@ -0,0 +1,103 @@ +package org.libresonic.player.service; + +import com.google.common.collect.Lists; +import org.apache.commons.configuration2.Configuration; +import org.apache.commons.configuration2.FileBasedConfiguration; +import org.apache.commons.configuration2.ImmutableConfiguration; +import org.apache.commons.configuration2.MapConfiguration; +import org.apache.commons.configuration2.PropertiesConfiguration; +import org.apache.commons.configuration2.PropertiesConfigurationLayout; +import org.apache.commons.configuration2.builder.FileBasedConfigurationBuilder; +import org.apache.commons.configuration2.builder.fluent.Parameters; +import org.apache.commons.configuration2.ex.ConfigurationException; +import org.apache.commons.configuration2.sync.ReadWriteSynchronizer; +import org.apache.commons.io.FileUtils; +import org.libresonic.player.Logger; + +import java.io.File; +import java.io.IOException; +import java.util.HashMap; + +public class ApacheCommonsConfigurationService { + + private static final Logger LOG = Logger.getLogger(ApacheCommonsConfigurationService.class); + + private final FileBasedConfigurationBuilder builder; + + private final Configuration config; + + public static final String HEADER_COMMENT = "Libresonic preferences. NOTE: This file is automatically generated." + + " Do not modify while application is running"; + + public ApacheCommonsConfigurationService() { + File propertyFile = SettingsService.getPropertyFile(); + if(!propertyFile.exists()) { + try { + FileUtils.touch(propertyFile); + } catch (IOException e) { + throw new RuntimeException("Could not create new property file", e); + } + } + Parameters params = new Parameters(); + PropertiesConfigurationLayout layout = new PropertiesConfigurationLayout(); + // https://issues.apache.org/jira/browse/CONFIGURATION-644 +// layout.setHeaderComment(HEADER_COMMENT); + layout.setGlobalSeparator("="); + builder = new FileBasedConfigurationBuilder(PropertiesConfiguration.class).configure( + params.properties() + .setFile(propertyFile) + .setSynchronizer(new ReadWriteSynchronizer()) + .setLayout(layout)); + try { + config = builder.getConfiguration(); + } catch (ConfigurationException e) { + throw new RuntimeException("Could not load property file at " + propertyFile, e); + } + } + + public void save() { + try { + builder.save(); + } catch (ConfigurationException e) { + LOG.error("Unable to write to property file.", e); + } + } + + public Object getProperty(String key) { + return config.getProperty(key); + } + + public boolean containsKey(String key) { + return config.containsKey(key); + } + + public void clearProperty(String key) { + config.clearProperty(key); + } + + public String getString(String key, String defaultValue) { + return config.getString(key, defaultValue); + } + + public void setProperty(String key, Object value) { + config.setProperty(key, value); + } + + public long getLong(String key, long defaultValue) { + return config.getLong(key, defaultValue); + } + + public int getInteger(String key, int defaultValue) { + return config.getInteger(key, defaultValue); + } + + public boolean getBoolean(String key, boolean defaultValue) { + return config.getBoolean(key, defaultValue); + } + + public ImmutableConfiguration getImmutableSnapshot() { + MapConfiguration mapConfiguration = new MapConfiguration(new HashMap<>()); + mapConfiguration.copy(config); + return mapConfiguration; + } +} diff --git a/libresonic-main/src/main/java/org/libresonic/player/service/SettingsService.java b/libresonic-main/src/main/java/org/libresonic/player/service/SettingsService.java index 1f7185b7..25c8e534 100644 --- a/libresonic-main/src/main/java/org/libresonic/player/service/SettingsService.java +++ b/libresonic-main/src/main/java/org/libresonic/player/service/SettingsService.java @@ -19,29 +19,6 @@ */ package org.libresonic.player.service; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Date; -import java.util.Iterator; -import java.util.List; -import java.util.Locale; -import java.util.Properties; -import java.util.StringTokenizer; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; - -import org.apache.commons.io.IOUtils; import org.apache.commons.lang.StringUtils; import org.libresonic.player.Logger; @@ -61,6 +38,12 @@ import org.libresonic.player.util.FileUtil; import org.libresonic.player.util.StringUtil; import org.libresonic.player.util.Util; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.*; +import java.util.concurrent.*; + /** * Provides persistent storage of application settings and preferences. * @@ -219,13 +202,13 @@ public class SettingsService { private static final Logger LOG = Logger.getLogger(SettingsService.class); - private Properties properties = new Properties(); private List themes; private List locales; private InternetRadioDao internetRadioDao; private MusicFolderDao musicFolderDao; private UserDao userDao; private AvatarDao avatarDao; + private ApacheCommonsConfigurationService configurationService; private VersionService versionService; private String[] cachedCoverArtFileTypesArray; @@ -234,34 +217,33 @@ public class SettingsService { private List cachedMusicFolders; private final ConcurrentMap> cachedMusicFoldersPerUser = new ConcurrentHashMap>(); - private static File libresonicHome; - - private static final long LOCAL_IP_LOOKUP_DELAY_SECONDS = 60; private String localIpAddress; - public SettingsService() { - File propertyFile = getPropertyFile(); + private void removeObseleteProperties() { - if (propertyFile.exists()) { - FileInputStream in = null; - try { - in = new FileInputStream(propertyFile); - properties.load(in); - } catch (Exception x) { - LOG.error("Unable to read from property file.", x); - } finally { - IOUtils.closeQuietly(in); + OBSOLETE_KEYS.forEach( oKey -> { + if(configurationService.containsKey(oKey)) { + LOG.info("Removing obsolete property [" + oKey + ']'); + configurationService.clearProperty(oKey); } + }); - // Remove obsolete properties. - for (Iterator iterator = properties.keySet().iterator(); iterator.hasNext();) { - String key = (String) iterator.next(); - if (OBSOLETE_KEYS.contains(key)) { - LOG.info("Removing obsolete property [" + key + ']'); - iterator.remove(); - } - } + } + + public static synchronized File getLibresonicHome() { + + File home; + + String overrideHome = System.getProperty("libresonic.home"); + if (overrideHome != null) { + home = new File(overrideHome); + } else { + boolean isWindows = System.getProperty("os.name", "Windows").toLowerCase().startsWith("windows"); + home = isWindows ? LIBRESONIC_HOME_WINDOWS : LIBRESONIC_HOME_OTHER; } + ensureDirectoryPresent(home); + + return home; } @@ -284,92 +266,58 @@ public class SettingsService { save(true); } - public void save(boolean updateChangedDate) { - if (updateChangedDate) { - setProperty(KEY_SETTINGS_CHANGED, String.valueOf(System.currentTimeMillis())); - } - - OutputStream out = null; - try { - out = new FileOutputStream(getPropertyFile()); - properties.store(out, "Libresonic preferences. NOTE: This file is automatically generated."); - } catch (Exception x) { - LOG.error("Unable to write to property file.", x); - } finally { - IOUtils.closeQuietly(out); + public void save(boolean updateSettingsChanged) { + if(updateSettingsChanged) { + removeObseleteProperties(); + this.setLong(KEY_SETTINGS_CHANGED, System.currentTimeMillis()); } + configurationService.save(); } - private File getPropertyFile() { - return new File(getLibresonicHome(), "libresonic.properties"); - } - - /** - * Returns the Libresonic home directory. - * - * @return The Libresonic home directory, if it exists. - * @throws RuntimeException If directory doesn't exist. - */ - public static synchronized File getLibresonicHome() { - - if (libresonicHome != null) { - return libresonicHome; - } - - File home; - - String overrideHome = System.getProperty("libresonic.home"); - if (overrideHome != null) { - home = new File(overrideHome); - } else { - boolean isWindows = System.getProperty("os.name", "Windows").toLowerCase().startsWith("windows"); - home = isWindows ? LIBRESONIC_HOME_WINDOWS : LIBRESONIC_HOME_OTHER; - } - + private static void ensureDirectoryPresent(File home) { // Attempt to create home directory if it doesn't exist. if (!home.exists() || !home.isDirectory()) { boolean success = home.mkdirs(); - if (success) { - libresonicHome = home; - } else { + if (!success) { String message = "The directory " + home + " does not exist. Please create it and make it writable. " + "(You can override the directory location by specifying -Dlibresonic.home=... when " + "starting the servlet container.)"; - System.err.println("ERROR: " + message); + throw new RuntimeException(message); } - } else { - libresonicHome = home; } + } - return home; + public static File getPropertyFile() { + File propertyFile = getLibresonicHome(); + return new File(propertyFile, "libresonic.properties"); } private int getInt(String key, int defaultValue) { - return Integer.valueOf(properties.getProperty(key, String.valueOf(defaultValue))); + return configurationService.getInteger(key, defaultValue); } - private void setInt(String key, int value) { - setProperty(key, String.valueOf(value)); + private void setInt(String key, Integer value) { + setProperty(key, value); } private long getLong(String key, long defaultValue) { - return Long.valueOf(properties.getProperty(key, String.valueOf(defaultValue))); + return configurationService.getLong(key, defaultValue); } - private void setLong(String key, long value) { - setProperty(key, String.valueOf(value)); + private void setLong(String key, Long value) { + setProperty(key, value); } private boolean getBoolean(String key, boolean defaultValue) { - return Boolean.valueOf(properties.getProperty(key, String.valueOf(defaultValue))); + return configurationService.getBoolean(key, defaultValue); } - private void setBoolean(String key, boolean value) { - setProperty(key, String.valueOf(value)); + private void setBoolean(String key, Boolean value) { + setProperty(key, value); } private String getString(String key, String defaultValue) { - return properties.getProperty(key, defaultValue); + return getProperty(key, defaultValue); } private void setString(String key, String value) { @@ -377,7 +325,11 @@ public class SettingsService { } public String getIndexString() { - return properties.getProperty(KEY_INDEX_STRING, DEFAULT_INDEX_STRING); + return getProperty(KEY_INDEX_STRING, DEFAULT_INDEX_STRING); + } + + private String getProperty(String key, String defaultValue) { + return configurationService.getString(key, defaultValue); } public void setIndexString(String indexString) { @@ -385,7 +337,7 @@ public class SettingsService { } public String getIgnoredArticles() { - return properties.getProperty(KEY_IGNORED_ARTICLES, DEFAULT_IGNORED_ARTICLES); + return getProperty(KEY_IGNORED_ARTICLES, DEFAULT_IGNORED_ARTICLES); } public String[] getIgnoredArticlesAsArray() { @@ -397,7 +349,7 @@ public class SettingsService { } public String getShortcuts() { - return properties.getProperty(KEY_SHORTCUTS, DEFAULT_SHORTCUTS); + return getProperty(KEY_SHORTCUTS, DEFAULT_SHORTCUTS); } public String[] getShortcutsAsArray() { @@ -409,7 +361,7 @@ public class SettingsService { } public String getPlaylistFolder() { - return properties.getProperty(KEY_PLAYLIST_FOLDER, DEFAULT_PLAYLIST_FOLDER); + return getProperty(KEY_PLAYLIST_FOLDER, DEFAULT_PLAYLIST_FOLDER); } public void setPlaylistFolder(String playlistFolder) { @@ -417,7 +369,7 @@ public class SettingsService { } public String getMusicFileTypes() { - return properties.getProperty(KEY_MUSIC_FILE_TYPES, DEFAULT_MUSIC_FILE_TYPES); + return getProperty(KEY_MUSIC_FILE_TYPES, DEFAULT_MUSIC_FILE_TYPES); } public synchronized void setMusicFileTypes(String fileTypes) { @@ -433,7 +385,7 @@ public class SettingsService { } public String getVideoFileTypes() { - return properties.getProperty(KEY_VIDEO_FILE_TYPES, DEFAULT_VIDEO_FILE_TYPES); + return getProperty(KEY_VIDEO_FILE_TYPES, DEFAULT_VIDEO_FILE_TYPES); } public synchronized void setVideoFileTypes(String fileTypes) { @@ -449,7 +401,7 @@ public class SettingsService { } public String getCoverArtFileTypes() { - return properties.getProperty(KEY_COVER_ART_FILE_TYPES, DEFAULT_COVER_ART_FILE_TYPES); + return getProperty(KEY_COVER_ART_FILE_TYPES, DEFAULT_COVER_ART_FILE_TYPES); } public synchronized void setCoverArtFileTypes(String fileTypes) { @@ -469,7 +421,7 @@ public class SettingsService { } public String getWelcomeTitle() { - return StringUtils.trimToNull(properties.getProperty(KEY_WELCOME_TITLE, DEFAULT_WELCOME_TITLE)); + return StringUtils.trimToNull(getProperty(KEY_WELCOME_TITLE, DEFAULT_WELCOME_TITLE)); } public void setWelcomeTitle(String title) { @@ -477,7 +429,7 @@ public class SettingsService { } public String getWelcomeSubtitle() { - return StringUtils.trimToNull(properties.getProperty(KEY_WELCOME_SUBTITLE, DEFAULT_WELCOME_SUBTITLE)); + return StringUtils.trimToNull(getProperty(KEY_WELCOME_SUBTITLE, DEFAULT_WELCOME_SUBTITLE)); } public void setWelcomeSubtitle(String subtitle) { @@ -485,7 +437,7 @@ public class SettingsService { } public String getWelcomeMessage() { - return StringUtils.trimToNull(properties.getProperty(KEY_WELCOME_MESSAGE, DEFAULT_WELCOME_MESSAGE)); + return StringUtils.trimToNull(getProperty(KEY_WELCOME_MESSAGE, DEFAULT_WELCOME_MESSAGE)); } public void setWelcomeMessage(String message) { @@ -493,7 +445,7 @@ public class SettingsService { } public String getLoginMessage() { - return StringUtils.trimToNull(properties.getProperty(KEY_LOGIN_MESSAGE, DEFAULT_LOGIN_MESSAGE)); + return StringUtils.trimToNull(getProperty(KEY_LOGIN_MESSAGE, DEFAULT_LOGIN_MESSAGE)); } public void setLoginMessage(String message) { @@ -586,7 +538,7 @@ public class SettingsService { * Returns the Podcast download folder. */ public String getPodcastFolder() { - return properties.getProperty(KEY_PODCAST_FOLDER, DEFAULT_PODCAST_FOLDER); + return getProperty(KEY_PODCAST_FOLDER, DEFAULT_PODCAST_FOLDER); } /** @@ -600,7 +552,7 @@ public class SettingsService { * @return The download bitrate limit in Kbit/s. Zero if unlimited. */ public long getDownloadBitrateLimit() { - return Long.parseLong(properties.getProperty(KEY_DOWNLOAD_BITRATE_LIMIT, "" + DEFAULT_DOWNLOAD_BITRATE_LIMIT)); + return Long.parseLong(getProperty(KEY_DOWNLOAD_BITRATE_LIMIT, "" + DEFAULT_DOWNLOAD_BITRATE_LIMIT)); } /** @@ -625,7 +577,7 @@ public class SettingsService { } public String getDownsamplingCommand() { - return properties.getProperty(KEY_DOWNSAMPLING_COMMAND, DEFAULT_DOWNSAMPLING_COMMAND); + return getProperty(KEY_DOWNSAMPLING_COMMAND, DEFAULT_DOWNSAMPLING_COMMAND); } public void setDownsamplingCommand(String command) { @@ -633,7 +585,7 @@ public class SettingsService { } public String getHlsCommand() { - return properties.getProperty(KEY_HLS_COMMAND, DEFAULT_HLS_COMMAND); + return getProperty(KEY_HLS_COMMAND, DEFAULT_HLS_COMMAND); } public void setHlsCommand(String command) { @@ -641,10 +593,10 @@ public class SettingsService { } public String getJukeboxCommand() { - return properties.getProperty(KEY_JUKEBOX_COMMAND, DEFAULT_JUKEBOX_COMMAND); + return getProperty(KEY_JUKEBOX_COMMAND, DEFAULT_JUKEBOX_COMMAND); } public String getVideoImageCommand() { - return properties.getProperty(KEY_VIDEO_IMAGE_COMMAND, DEFAULT_VIDEO_IMAGE_COMMAND); + return getProperty(KEY_VIDEO_IMAGE_COMMAND, DEFAULT_VIDEO_IMAGE_COMMAND); } public boolean isRewriteUrlEnabled() { @@ -664,31 +616,31 @@ public class SettingsService { } public String getLdapUrl() { - return properties.getProperty(KEY_LDAP_URL, DEFAULT_LDAP_URL); + return getProperty(KEY_LDAP_URL, DEFAULT_LDAP_URL); } public void setLdapUrl(String ldapUrl) { - properties.setProperty(KEY_LDAP_URL, ldapUrl); + setProperty(KEY_LDAP_URL, ldapUrl); } public String getLdapSearchFilter() { - return properties.getProperty(KEY_LDAP_SEARCH_FILTER, DEFAULT_LDAP_SEARCH_FILTER); + return getProperty(KEY_LDAP_SEARCH_FILTER, DEFAULT_LDAP_SEARCH_FILTER); } public void setLdapSearchFilter(String ldapSearchFilter) { - properties.setProperty(KEY_LDAP_SEARCH_FILTER, ldapSearchFilter); + setProperty(KEY_LDAP_SEARCH_FILTER, ldapSearchFilter); } public String getLdapManagerDn() { - return properties.getProperty(KEY_LDAP_MANAGER_DN, DEFAULT_LDAP_MANAGER_DN); + return getProperty(KEY_LDAP_MANAGER_DN, DEFAULT_LDAP_MANAGER_DN); } public void setLdapManagerDn(String ldapManagerDn) { - properties.setProperty(KEY_LDAP_MANAGER_DN, ldapManagerDn); + setProperty(KEY_LDAP_MANAGER_DN, ldapManagerDn); } public String getLdapManagerPassword() { - String s = properties.getProperty(KEY_LDAP_MANAGER_PASSWORD, DEFAULT_LDAP_MANAGER_PASSWORD); + String s = getProperty(KEY_LDAP_MANAGER_PASSWORD, DEFAULT_LDAP_MANAGER_PASSWORD); try { return StringUtil.utf8HexDecode(s); } catch (Exception x) { @@ -703,7 +655,7 @@ public class SettingsService { } catch (Exception x) { LOG.warn("Failed to encode LDAP manager password.", x); } - properties.setProperty(KEY_LDAP_MANAGER_PASSWORD, ldapManagerPassword); + setProperty(KEY_LDAP_MANAGER_PASSWORD, ldapManagerPassword); } public boolean isLdapAutoShadowing() { @@ -762,43 +714,43 @@ public class SettingsService { } public String getUrlRedirectFrom() { - return properties.getProperty(KEY_URL_REDIRECT_FROM, DEFAULT_URL_REDIRECT_FROM); + return getProperty(KEY_URL_REDIRECT_FROM, DEFAULT_URL_REDIRECT_FROM); } public void setUrlRedirectFrom(String urlRedirectFrom) { - properties.setProperty(KEY_URL_REDIRECT_FROM, urlRedirectFrom); + setProperty(KEY_URL_REDIRECT_FROM, urlRedirectFrom); } public UrlRedirectType getUrlRedirectType() { - return UrlRedirectType.valueOf(properties.getProperty(KEY_URL_REDIRECT_TYPE, DEFAULT_URL_REDIRECT_TYPE.name())); + return UrlRedirectType.valueOf(getProperty(KEY_URL_REDIRECT_TYPE, DEFAULT_URL_REDIRECT_TYPE.name())); } public void setUrlRedirectType(UrlRedirectType urlRedirectType) { - properties.setProperty(KEY_URL_REDIRECT_TYPE, urlRedirectType.name()); + setProperty(KEY_URL_REDIRECT_TYPE, urlRedirectType.name()); } public String getUrlRedirectContextPath() { - return properties.getProperty(KEY_URL_REDIRECT_CONTEXT_PATH, DEFAULT_URL_REDIRECT_CONTEXT_PATH); + return getProperty(KEY_URL_REDIRECT_CONTEXT_PATH, DEFAULT_URL_REDIRECT_CONTEXT_PATH); } public void setUrlRedirectContextPath(String contextPath) { - properties.setProperty(KEY_URL_REDIRECT_CONTEXT_PATH, contextPath); + setProperty(KEY_URL_REDIRECT_CONTEXT_PATH, contextPath); } public String getUrlRedirectCustomUrl() { - return StringUtils.trimToNull(properties.getProperty(KEY_URL_REDIRECT_CUSTOM_URL, DEFAULT_URL_REDIRECT_CUSTOM_URL)); + return StringUtils.trimToNull(getProperty(KEY_URL_REDIRECT_CUSTOM_URL, DEFAULT_URL_REDIRECT_CUSTOM_URL)); } public void setUrlRedirectCustomUrl(String customUrl) { - properties.setProperty(KEY_URL_REDIRECT_CUSTOM_URL, customUrl); + setProperty(KEY_URL_REDIRECT_CUSTOM_URL, customUrl); } public String getServerId() { - return properties.getProperty(KEY_SERVER_ID, DEFAULT_SERVER_ID); + return getProperty(KEY_SERVER_ID, DEFAULT_SERVER_ID); } public void setServerId(String serverId) { - properties.setProperty(KEY_SERVER_ID, serverId); + setProperty(KEY_SERVER_ID, serverId); } public long getSettingsChanged() { @@ -806,13 +758,13 @@ public class SettingsService { } public Date getLastScanned() { - String lastScanned = properties.getProperty(KEY_LAST_SCANNED); + String lastScanned = getProperty(KEY_LAST_SCANNED, null); return lastScanned == null ? null : new Date(Long.parseLong(lastScanned)); } public void setLastScanned(Date date) { if (date == null) { - properties.remove(KEY_LAST_SCANNED); + setProperty(KEY_LAST_SCANNED, null); } else { setLong(KEY_LAST_SCANNED, date.getTime()); } @@ -848,9 +800,9 @@ public class SettingsService { * @return The locale. */ public Locale getLocale() { - String language = properties.getProperty(KEY_LOCALE_LANGUAGE, DEFAULT_LOCALE_LANGUAGE); - String country = properties.getProperty(KEY_LOCALE_COUNTRY, DEFAULT_LOCALE_COUNTRY); - String variant = properties.getProperty(KEY_LOCALE_VARIANT, DEFAULT_LOCALE_VARIANT); + String language = getProperty(KEY_LOCALE_LANGUAGE, DEFAULT_LOCALE_LANGUAGE); + String country = getProperty(KEY_LOCALE_COUNTRY, DEFAULT_LOCALE_COUNTRY); + String variant = getProperty(KEY_LOCALE_VARIANT, DEFAULT_LOCALE_VARIANT); return new Locale(language, country, variant); } @@ -872,7 +824,7 @@ public class SettingsService { * @return The theme ID. */ public String getThemeId() { - return properties.getProperty(KEY_THEME_ID, DEFAULT_THEME_ID); + return getProperty(KEY_THEME_ID, DEFAULT_THEME_ID); } /** @@ -1309,11 +1261,11 @@ public class SettingsService { getPort()); } - private void setProperty(String key, String value) { + private void setProperty(String key, Object value) { if (value == null) { - properties.remove(key); + configurationService.clearProperty(key); } else { - properties.setProperty(key, value); + configurationService.setProperty(key, value); } } @@ -1356,7 +1308,7 @@ public class SettingsService { } public String getSmtpServer() { - return properties.getProperty(KEY_SMTP_SERVER, DEFAULT_SMTP_SERVER); + return getProperty(KEY_SMTP_SERVER, DEFAULT_SMTP_SERVER); } public void setSmtpServer(String smtpServer) { @@ -1372,7 +1324,7 @@ public class SettingsService { } public String getSmtpEncryption() { - return properties.getProperty(KEY_SMTP_ENCRYPTION, DEFAULT_SMTP_ENCRYPTION); + return getProperty(KEY_SMTP_ENCRYPTION, DEFAULT_SMTP_ENCRYPTION); } public void setSmtpEncryption(String encryptionMethod) { @@ -1380,7 +1332,7 @@ public class SettingsService { } public String getSmtpUser() { - return properties.getProperty(KEY_SMTP_USER, DEFAULT_SMTP_USER); + return getProperty(KEY_SMTP_USER, DEFAULT_SMTP_USER); } public void setSmtpUser(String smtpUser) { @@ -1388,7 +1340,7 @@ public class SettingsService { } public String getSmtpPassword() { - String s = properties.getProperty(KEY_SMTP_PASSWORD, DEFAULT_SMTP_PASSWORD); + String s = getProperty(KEY_SMTP_PASSWORD, DEFAULT_SMTP_PASSWORD); try { return StringUtil.utf8HexDecode(s); } catch (Exception x) { @@ -1402,14 +1354,18 @@ public class SettingsService { } catch (Exception x) { LOG.warn("Failed to encode Smtp password.", x); } - properties.setProperty(KEY_SMTP_PASSWORD, smtpPassword); + setProperty(KEY_SMTP_PASSWORD, smtpPassword); } public String getSmtpFrom() { - return properties.getProperty(KEY_SMTP_FROM, DEFAULT_SMTP_FROM); + return getProperty(KEY_SMTP_FROM, DEFAULT_SMTP_FROM); } public void setSmtpFrom(String smtpFrom) { setString(KEY_SMTP_FROM, smtpFrom); } + + public void setConfigurationService(ApacheCommonsConfigurationService configurationService) { + this.configurationService = configurationService; + } } diff --git a/libresonic-main/src/main/java/org/libresonic/player/spring/AdditionalPropertySourceConfigurer.java b/libresonic-main/src/main/java/org/libresonic/player/spring/AdditionalPropertySourceConfigurer.java new file mode 100644 index 00000000..cb7ff9a6 --- /dev/null +++ b/libresonic-main/src/main/java/org/libresonic/player/spring/AdditionalPropertySourceConfigurer.java @@ -0,0 +1,20 @@ +package org.libresonic.player.spring; + +import org.apache.commons.configuration2.ImmutableConfiguration; +import org.libresonic.player.service.ApacheCommonsConfigurationService; +import org.springframework.context.ApplicationContextInitializer; +import org.springframework.core.env.PropertySource; +import org.springframework.web.context.ConfigurableWebApplicationContext; + +public class AdditionalPropertySourceConfigurer implements + ApplicationContextInitializer { + + public void initialize(ConfigurableWebApplicationContext ctx) { + + ApacheCommonsConfigurationService configurationService = new ApacheCommonsConfigurationService(); + ImmutableConfiguration snapshot = configurationService.getImmutableSnapshot(); + + PropertySource ps = new CommonsConfigurationPropertySource("libresonic-pre-init-configs", snapshot); + ctx.getEnvironment().getPropertySources().addLast(ps); + } +} diff --git a/libresonic-main/src/main/java/org/libresonic/player/spring/CommonsConfigurationPropertySource.java b/libresonic-main/src/main/java/org/libresonic/player/spring/CommonsConfigurationPropertySource.java new file mode 100644 index 00000000..3e9b02a0 --- /dev/null +++ b/libresonic-main/src/main/java/org/libresonic/player/spring/CommonsConfigurationPropertySource.java @@ -0,0 +1,19 @@ +package org.libresonic.player.spring; + +import org.apache.commons.configuration2.ImmutableConfiguration; +import org.springframework.core.env.PropertySource; + +public class CommonsConfigurationPropertySource extends PropertySource { + + private final ImmutableConfiguration configuration; + + public CommonsConfigurationPropertySource(String name, ImmutableConfiguration configuration) { + super(name); + this.configuration = configuration; + } + + @Override + public Object getProperty(String s) { + return configuration.getProperty(s); + } +} diff --git a/libresonic-main/src/main/resources/log4j.properties b/libresonic-main/src/main/resources/log4j.properties index 4908ba27..a8078146 100644 --- a/libresonic-main/src/main/resources/log4j.properties +++ b/libresonic-main/src/main/resources/log4j.properties @@ -7,3 +7,7 @@ log4j.appender.A1=org.apache.log4j.ConsoleAppender # A1 uses PatternLayout. log4j.appender.A1.layout=org.apache.log4j.PatternLayout log4j.appender.A1.layout.ConversionPattern=[%d{ISO8601}] %-5p %c - %m%n + +# TODO remove this once https://issues.apache.org/jira/browse/CONFIGURATION-627 is fixed +log4j.logger.org.apache.commons.beanutils.FluentPropertyBeanIntrospector=ERROR, A1 +log4j.additivity.org.apache.commons.beanutils.FluentPropertyBeanIntrospector=false diff --git a/libresonic-main/src/main/webapp/WEB-INF/applicationContext-service.xml b/libresonic-main/src/main/webapp/WEB-INF/applicationContext-service.xml index 45e6f641..7eb2a74d 100644 --- a/libresonic-main/src/main/webapp/WEB-INF/applicationContext-service.xml +++ b/libresonic-main/src/main/webapp/WEB-INF/applicationContext-service.xml @@ -86,12 +86,15 @@ + + + diff --git a/libresonic-main/src/main/webapp/WEB-INF/web.xml b/libresonic-main/src/main/webapp/WEB-INF/web.xml index 5bd36336..5f820afe 100644 --- a/libresonic-main/src/main/webapp/WEB-INF/web.xml +++ b/libresonic-main/src/main/webapp/WEB-INF/web.xml @@ -16,6 +16,11 @@ + + contextInitializerClasses + org.libresonic.player.spring.AdditionalPropertySourceConfigurer + + org.springframework.web.context.ContextLoaderListener