diff --git a/documentation/CONFIGURATION.md b/documentation/CONFIGURATION.md new file mode 100644 index 00000000..8eb2ebec --- /dev/null +++ b/documentation/CONFIGURATION.md @@ -0,0 +1,40 @@ +# Startup Configuration Guide + +Libresonic has some system-wide configuration. These configurations are stored in the +`libresonic.properties` file. There is one exception, which is the `libresonic.home` parameter which +is supplied as a Java System Property. + +## `libresonic.properties` +These parameters are simple key-value pairs stored in a list. It is recommended that these parameters +are changed through the web interface settings page. However, they can also be modified directly. Shutdown +your server first, modify, then start it for changes to take effect. + +## Java Parameters +The `libresonic.home` parameter is a Java System Property that is not modifiable through the web interface. +It must be configured via Java startup parameters. See below for steps to do this. + +#### `libresonic.home` +This parameter dictates the folder where Libresonic will store its logs, +settings, transcode binaries, index and database if using the default H2 +database. As such it is recommended to backup this folder. + +*default: `/var/libresonic` or `C:\\music`* + +#### Setting Java Parameters on Tomcat +As described in the [RUNNING.txt](http://tomcat.apache.org/tomcat-8.0-doc/RUNNING.txt) doc provided by tomcat, +you can create a file named `setenv.sh` or for windows `setenv.bat` in the Tomcat home `bin` folder to modify the +java args. + +Here is an example of a `setenv.sh` file (`setenv.bat` has slightly different syntax): +``` +export JAVA_OPTS="$JAVA_OPTS -Dlibresonic.home=/home/andrew/.cache/libresonic-test" +``` + +#### Setting Java Parameters for Standalone Package (SpringBoot) +When running the standalone package, add `-Dlibresonic.home=YOUR_PATH_HERE` to the `java` command line right before the +`-jar` argument. Here is an example for linux (windows users will want to use their OS specific path syntax i.e. +`C:\\your\path`) + +``` +java -Dlibresonic.home=/home/andrew/libresonichome -jar libresonic.war +``` diff --git a/documentation/DATABASE.md b/documentation/DATABASE.md index 5725b953..01884fe4 100644 --- a/documentation/DATABASE.md +++ b/documentation/DATABASE.md @@ -21,16 +21,19 @@ We will refer to container managed configuration as jndi and libresonic managed In your libresonic.properties file, you will need to add the following settings (this is just an example): ``` -database.config.type=embed -database.config.embed.driver=org.hsqldb.jdbcDriver -database.config.embed.url=jdbc:hsqldb:file:/tmp/libre/db/libresonic -database.config.embed.username=sa -database.config.embed.password= +DatabaseConfigType=embed +DatabaseConfigEmbedDriver=org.hsqldb.jdbcDriver +DatabaseConfigEmbedUrl=jdbc:hsqldb:file:/tmp/libre/db/libresonic +DatabaseConfigEmbedUsername=sa +DatabaseConfigEmbedPassword= ``` In addition, you will need to ensure that a jdbc driver suitable for your database is on the -[classpath](https://docs.oracle.com/javase/8/docs/technotes/tools/windows/classpath.html) +[classpath](https://docs.oracle.com/javase/8/docs/technotes/tools/windows/classpath.html). + +*Note adding to the classpath is currently pretty difficult for spring-boot. Tomcat is easy, just copy into tomcat home +/lib. TODO: provide prebuilt artifacts with tested databases built in?* ## JNDI *Before doing anything, make sure your database is properly backed up. Ensure your server is shutdown* @@ -38,8 +41,8 @@ database is on the In your libresonic.properties file, you will need to add the following settings (this is just an example): ``` -database.config.type=jndi -database.config.jndi.name=jdbc/libresonicDB +DatabaseConfigType=jndi +DatabaseConfigJNDIName=jdbc/libresonicDB ``` Then in your context.xml in your tomcat directory, add the jndi config: @@ -65,5 +68,10 @@ Finally, copy the jdbc driver from the database vendor website to the `lib` dire `stringtype=unspecified` on your jdbc url string is necessary. -You will also need to add `database.usertable.quote=\"` to your properties +You will also need to add `DatabaseUsertableQuote=\"` to your properties file. This is due to the fact that our `user` table is a keyword for postgres. + +## Troubleshooting + +In the event that you change these settings, restart your server and it fails to start, you can remedy this by reverting +to the LEGACY config by removing all `Database*` settings from your `libresonic.properties` file. diff --git a/libresonic-main/pom.xml b/libresonic-main/pom.xml index 0f574dd5..30e646ad 100644 --- a/libresonic-main/pom.xml +++ b/libresonic-main/pom.xml @@ -381,6 +381,12 @@ maven-artifact 3.3.9 + + + javax.validation + validation-api + 1.1.0.Final + diff --git a/libresonic-main/src/main/java/org/libresonic/player/command/DatabaseSettingsCommand.java b/libresonic-main/src/main/java/org/libresonic/player/command/DatabaseSettingsCommand.java new file mode 100644 index 00000000..769f0d8e --- /dev/null +++ b/libresonic-main/src/main/java/org/libresonic/player/command/DatabaseSettingsCommand.java @@ -0,0 +1,82 @@ +package org.libresonic.player.command; + +import org.libresonic.player.spring.DataSourceConfigType; + +import javax.validation.constraints.NotNull; + +public class DatabaseSettingsCommand { + + @NotNull + private DataSourceConfigType configType; + private String embedDriver; + private String embedPassword; + private String embedUrl; + private String embedUsername; + private String JNDIName; + private int mysqlVarcharMaxlength; + private String usertableQuote; + + public DataSourceConfigType getConfigType() { + return configType; + } + + public void setConfigType(DataSourceConfigType configType) { + this.configType = configType; + } + + public String getEmbedDriver() { + return embedDriver; + } + + public void setEmbedDriver(String embedDriver) { + this.embedDriver = embedDriver; + } + + public String getEmbedPassword() { + return embedPassword; + } + + public void setEmbedPassword(String embedPassword) { + this.embedPassword = embedPassword; + } + + public String getEmbedUrl() { + return embedUrl; + } + + public void setEmbedUrl(String embedUrl) { + this.embedUrl = embedUrl; + } + + public String getEmbedUsername() { + return embedUsername; + } + + public void setEmbedUsername(String embedUsername) { + this.embedUsername = embedUsername; + } + + public String getJNDIName() { + return JNDIName; + } + + public void setJNDIName(String JNDIName) { + this.JNDIName = JNDIName; + } + + public int getMysqlVarcharMaxlength() { + return mysqlVarcharMaxlength; + } + + public void setMysqlVarcharMaxlength(int mysqlVarcharMaxlength) { + this.mysqlVarcharMaxlength = mysqlVarcharMaxlength; + } + + public String getUsertableQuote() { + return usertableQuote; + } + + public void setUsertableQuote(String usertableQuote) { + this.usertableQuote = usertableQuote; + } +} diff --git a/libresonic-main/src/main/java/org/libresonic/player/controller/DatabaseSettingsController.java b/libresonic-main/src/main/java/org/libresonic/player/controller/DatabaseSettingsController.java new file mode 100644 index 00000000..438c677e --- /dev/null +++ b/libresonic-main/src/main/java/org/libresonic/player/controller/DatabaseSettingsController.java @@ -0,0 +1,106 @@ +/* + This file is part of Libresonic. + + Libresonic is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Libresonic is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Libresonic. If not, see . + + Copyright 2016 (C) Libresonic Authors + Based upon Subsonic, Copyright 2009 (C) Sindre Mehus + */ +package org.libresonic.player.controller; + +import org.libresonic.player.command.DatabaseSettingsCommand; +import org.libresonic.player.dao.AlbumDao; +import org.libresonic.player.dao.ArtistDao; +import org.libresonic.player.dao.MediaFileDao; +import org.libresonic.player.service.MediaScannerService; +import org.libresonic.player.service.SettingsService; +import org.libresonic.player.spring.DataSourceConfigType; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.validation.BindingResult; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.servlet.mvc.support.RedirectAttributes; + +@Controller +@RequestMapping("/databaseSettings") +public class DatabaseSettingsController { + + @Autowired + private SettingsService settingsService; + @Autowired + private MediaScannerService mediaScannerService; + @Autowired + private ArtistDao artistDao; + @Autowired + private AlbumDao albumDao; + @Autowired + private MediaFileDao mediaFileDao; + + @RequestMapping(method = RequestMethod.GET) + protected String displayForm() throws Exception { + return "databaseSettings"; + } + + @ModelAttribute + protected void formBackingObject(Model model) throws Exception { + DatabaseSettingsCommand command = new DatabaseSettingsCommand(); + command.setConfigType(settingsService.getDatabaseConfigType()); + command.setEmbedDriver(settingsService.getDatabaseConfigEmbedDriver()); + command.setEmbedPassword(settingsService.getDatabaseConfigEmbedPassword()); + command.setEmbedUrl(settingsService.getDatabaseConfigEmbedUrl()); + command.setEmbedUsername(settingsService.getDatabaseConfigEmbedUsername()); + command.setJNDIName(settingsService.getDatabaseConfigJNDIName()); + command.setMysqlVarcharMaxlength(settingsService.getDatabaseMysqlVarcharMaxlength()); + command.setUsertableQuote(settingsService.getDatabaseUsertableQuote()); + model.addAttribute("command", command); + } + + @RequestMapping(method = RequestMethod.POST) + protected String onSubmit(@ModelAttribute("command") @Validated DatabaseSettingsCommand command, + BindingResult bindingResult, + RedirectAttributes redirectAttributes) throws Exception { + if (!bindingResult.hasErrors()) { + settingsService.resetDatabaseToDefault(); + settingsService.setDatabaseConfigType(command.getConfigType()); + switch(command.getConfigType()) { + case EMBED: + settingsService.setDatabaseConfigEmbedDriver(command.getEmbedDriver()); + settingsService.setDatabaseConfigEmbedPassword(command.getEmbedPassword()); + settingsService.setDatabaseConfigEmbedUrl(command.getEmbedUrl()); + settingsService.setDatabaseConfigEmbedUsername(command.getEmbedUsername()); + break; + case JNDI: + settingsService.setDatabaseConfigJNDIName(command.getJNDIName()); + break; + case LEGACY: + default: + break; + } + if(command.getConfigType() != DataSourceConfigType.LEGACY) { + settingsService.setDatabaseMysqlVarcharMaxlength(command.getMysqlVarcharMaxlength()); + settingsService.setDatabaseUsertableQuote(command.getUsertableQuote()); + } + redirectAttributes.addFlashAttribute("settings_toast", true); + settingsService.save(); + return "redirect:databaseSettings.view"; + } else { + return "databaseSettings.view"; + } + } + +} \ No newline at end of file diff --git a/libresonic-main/src/main/java/org/libresonic/player/security/WebSecurityConfig.java b/libresonic-main/src/main/java/org/libresonic/player/security/WebSecurityConfig.java index a5283c0b..6a340fa9 100644 --- a/libresonic-main/src/main/java/org/libresonic/player/security/WebSecurityConfig.java +++ b/libresonic-main/src/main/java/org/libresonic/player/security/WebSecurityConfig.java @@ -79,7 +79,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { "/playerSettings.view", "/shareSettings.view","/passwordSettings.view") .hasRole("SETTINGS") .antMatchers("/generalSettings.view","/advancedSettings.view","/userSettings.view", - "/musicFolderSettings.view") + "/musicFolderSettings.view", "/databaseSettings.view") .hasRole("ADMIN") .antMatchers("/deletePlaylist.view","/savePlaylist.view") .hasRole("PLAYLIST") 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 16e09833..e30a6a6a 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 @@ -26,6 +26,7 @@ import org.libresonic.player.dao.InternetRadioDao; import org.libresonic.player.dao.MusicFolderDao; import org.libresonic.player.dao.UserDao; import org.libresonic.player.domain.*; +import org.libresonic.player.spring.DataSourceConfigType; import org.libresonic.player.util.FileUtil; import org.libresonic.player.util.StringUtil; import org.libresonic.player.util.Util; @@ -105,6 +106,16 @@ public class SettingsService { private static final String KEY_SMTP_PASSWORD = "SmtpPassword"; private static final String KEY_SMTP_FROM = "SmtpFrom"; + // Database Settings + private static final String KEY_DATABASE_CONFIG_TYPE = "DatabaseConfigType"; + private static final String KEY_DATABASE_CONFIG_EMBED_DRIVER = "DatabaseConfigEmbedDriver"; + private static final String KEY_DATABASE_CONFIG_EMBED_URL = "DatabaseConfigEmbedUrl"; + private static final String KEY_DATABASE_CONFIG_EMBED_USERNAME = "DatabaseConfigEmbedUsername"; + private static final String KEY_DATABASE_CONFIG_EMBED_PASSWORD = "DatabaseConfigEmbedPassword"; + private static final String KEY_DATABASE_CONFIG_JNDI_NAME = "DatabaseConfigJNDIName"; + private static final String KEY_DATABASE_MYSQL_VARCHAR_MAXLENGTH = "DatabaseMysqlMaxlength"; + private static final String KEY_DATABASE_USERTABLE_QUOTE = "DatabaseUsertableQuote"; + // Default values. private static final String DEFAULT_INDEX_STRING = "A B C D E F G H I J K L M N O P Q R S T U V W X-Z(XYZ)"; private static final String DEFAULT_IGNORED_ARTICLES = "The El La Los Las Le Les"; @@ -168,13 +179,26 @@ public class SettingsService { private static final String DEFAULT_SMTP_PASSWORD = null; private static final String DEFAULT_SMTP_FROM = "libresonic@libresonic.org"; + private static final DataSourceConfigType DEFAULT_DATABASE_CONFIG_TYPE = DataSourceConfigType.LEGACY; + private static final String DEFAULT_DATABASE_CONFIG_EMBED_DRIVER = null; + private static final String DEFAULT_DATABASE_CONFIG_EMBED_URL = null; + private static final String DEFAULT_DATABASE_CONFIG_EMBED_USERNAME = null; + private static final String DEFAULT_DATABASE_CONFIG_EMBED_PASSWORD = null; + private static final String DEFAULT_DATABASE_CONFIG_JNDI_NAME = null; + private static final Integer DEFAULT_DATABASE_MYSQL_VARCHAR_MAXLENGTH = 512; + private static final String DEFAULT_DATABASE_USERTABLE_QUOTE = null; + // Array of obsolete keys. Used to clean property file. private static final List OBSOLETE_KEYS = Arrays.asList("PortForwardingPublicPort", "PortForwardingLocalPort", "DownsamplingCommand", "DownsamplingCommand2", "DownsamplingCommand3", "AutoCoverBatch", "MusicMask", "VideoMask", "CoverArtMask, HlsCommand", "HlsCommand2", "JukeboxCommand", "CoverArtFileTypes", "UrlRedirectCustomHost", "CoverArtLimit", "StreamPort", "PortForwardingEnabled", "RewriteUrl", "UrlRedirectCustomUrl", "UrlRedirectContextPath", - "UrlRedirectFrom", "UrlRedirectionEnabled", "UrlRedirectType", "Port", "HttpsPort"); + "UrlRedirectFrom", "UrlRedirectionEnabled", "UrlRedirectType", "Port", "HttpsPort", + // Database settings renamed + "database.varchar.maxlength", "database.config.type", "database.config.embed.driver", + "database.config.embed.url", "database.config.embed.username", "database.config.embed.password", + "database.config.jndi.name", "database.usertable.quote"); private static final String LOCALES_FILE = "/org/libresonic/player/i18n/locales.txt"; private static final String THEMES_FILE = "/org/libresonic/player/theme/themes.txt"; @@ -1243,7 +1267,83 @@ public class SettingsService { setString(KEY_SMTP_FROM, smtpFrom); } + public DataSourceConfigType getDatabaseConfigType() { + String raw = getString(KEY_DATABASE_CONFIG_TYPE, DEFAULT_DATABASE_CONFIG_TYPE.name()); + return DataSourceConfigType.valueOf(StringUtils.upperCase(raw)); + } + + public void setDatabaseConfigType(DataSourceConfigType databaseConfigType) { + setString(KEY_DATABASE_CONFIG_TYPE, databaseConfigType.name()); + } + + public String getDatabaseConfigEmbedDriver() { + return getString(KEY_DATABASE_CONFIG_EMBED_DRIVER, DEFAULT_DATABASE_CONFIG_EMBED_DRIVER); + } + + public void setDatabaseConfigEmbedDriver(String embedDriver) { + setString(KEY_DATABASE_CONFIG_EMBED_DRIVER, embedDriver); + } + + public String getDatabaseConfigEmbedUrl() { + return getString(KEY_DATABASE_CONFIG_EMBED_URL, DEFAULT_DATABASE_CONFIG_EMBED_URL); + } + + public void setDatabaseConfigEmbedUrl(String url) { + setString(KEY_DATABASE_CONFIG_EMBED_URL, url); + } + + public String getDatabaseConfigEmbedUsername() { + return getString(KEY_DATABASE_CONFIG_EMBED_USERNAME, DEFAULT_DATABASE_CONFIG_EMBED_USERNAME); + } + + public void setDatabaseConfigEmbedUsername(String username) { + setString(KEY_DATABASE_CONFIG_EMBED_USERNAME, username); + } + + public String getDatabaseConfigEmbedPassword() { + return getString(KEY_DATABASE_CONFIG_EMBED_PASSWORD, DEFAULT_DATABASE_CONFIG_EMBED_PASSWORD); + } + + public void setDatabaseConfigEmbedPassword(String password) { + setString(KEY_DATABASE_CONFIG_EMBED_PASSWORD, password); + } + + public String getDatabaseConfigJNDIName() { + return getString(KEY_DATABASE_CONFIG_JNDI_NAME, DEFAULT_DATABASE_CONFIG_JNDI_NAME); + } + + public void setDatabaseConfigJNDIName(String jndiName) { + setString(KEY_DATABASE_CONFIG_JNDI_NAME, jndiName); + } + + public Integer getDatabaseMysqlVarcharMaxlength() { + return getInt(KEY_DATABASE_MYSQL_VARCHAR_MAXLENGTH, DEFAULT_DATABASE_MYSQL_VARCHAR_MAXLENGTH); + } + + public void setDatabaseMysqlVarcharMaxlength(int maxlength) { + setInt(KEY_DATABASE_MYSQL_VARCHAR_MAXLENGTH, maxlength); + } + + public String getDatabaseUsertableQuote() { + return getString(KEY_DATABASE_USERTABLE_QUOTE, DEFAULT_DATABASE_USERTABLE_QUOTE); + } + + public void setDatabaseUsertableQuote(String usertableQuote) { + setString(KEY_DATABASE_USERTABLE_QUOTE, usertableQuote); + } + public void setConfigurationService(ApacheCommonsConfigurationService configurationService) { this.configurationService = configurationService; } + + public void resetDatabaseToDefault() { + setDatabaseConfigEmbedDriver(DEFAULT_DATABASE_CONFIG_EMBED_DRIVER); + setDatabaseConfigEmbedPassword(DEFAULT_DATABASE_CONFIG_EMBED_PASSWORD); + setDatabaseConfigEmbedUrl(DEFAULT_DATABASE_CONFIG_EMBED_URL); + setDatabaseConfigEmbedUsername(DEFAULT_DATABASE_CONFIG_EMBED_USERNAME); + setDatabaseConfigJNDIName(DEFAULT_DATABASE_CONFIG_JNDI_NAME); + setDatabaseMysqlVarcharMaxlength(DEFAULT_DATABASE_MYSQL_VARCHAR_MAXLENGTH); + setDatabaseUsertableQuote(DEFAULT_DATABASE_USERTABLE_QUOTE); + setDatabaseConfigType(DEFAULT_DATABASE_CONFIG_TYPE); + } } diff --git a/libresonic-main/src/main/java/org/libresonic/player/spring/LibresonicPropertySourceConfigurer.java b/libresonic-main/src/main/java/org/libresonic/player/spring/LibresonicPropertySourceConfigurer.java index 1798dd0d..f7ab9722 100644 --- a/libresonic-main/src/main/java/org/libresonic/player/spring/LibresonicPropertySourceConfigurer.java +++ b/libresonic-main/src/main/java/org/libresonic/player/spring/LibresonicPropertySourceConfigurer.java @@ -13,7 +13,7 @@ import java.util.List; public class LibresonicPropertySourceConfigurer implements ApplicationContextInitializer { - public static final String DATASOURCE_CONFIG_TYPE = "database.config.type"; + public static final String DATASOURCE_CONFIG_TYPE = "DatabaseConfigType"; public void initialize(ConfigurableWebApplicationContext ctx) { diff --git a/libresonic-main/src/main/java/org/libresonic/player/util/Util.java b/libresonic-main/src/main/java/org/libresonic/player/util/Util.java index 9f69da6e..2f8ab6e5 100644 --- a/libresonic-main/src/main/java/org/libresonic/player/util/Util.java +++ b/libresonic-main/src/main/java/org/libresonic/player/util/Util.java @@ -20,14 +20,10 @@ package org.libresonic.player.util; import org.libresonic.player.Logger; -import org.libresonic.player.service.SettingsService; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletResponse; -import java.net.Inet4Address; -import java.net.InetAddress; -import java.net.NetworkInterface; import java.util.*; /** @@ -38,7 +34,6 @@ import java.util.*; public final class Util { private static final Logger LOG = Logger.getLogger(Util.class); - private static final Random RANDOM = new Random(System.currentTimeMillis()); /** * Disallow external instantiation. @@ -65,10 +60,6 @@ public final class Util { return System.getProperty("os.name", "Windows").toLowerCase().startsWith("windows"); } - public static boolean isWindowsInstall() { - return "true".equals(System.getProperty("libresonic.windowsInstall")); - } - /** * Similar to {@link ServletResponse#setContentLength(int)}, but this * method supports lengths bigger than 2GB. @@ -86,90 +77,6 @@ public final class Util { } } - /** - * Returns the local IP address. Honours the "libresonic.host" system property. - *

- * NOTE: For improved performance, use {@link SettingsService#getLocalIpAddress()} instead. - * - * @return The local IP, or the loopback address (127.0.0.1) if not found. - */ - public static String getLocalIpAddress() { - List ipAddresses = getLocalIpAddresses(); - String libresonicHost = System.getProperty("libresonic.host"); - if (libresonicHost != null && ipAddresses.contains(libresonicHost)) { - return libresonicHost; - } - return ipAddresses.get(0); - } - - private static List getLocalIpAddresses() { - List result = new ArrayList(); - - // Try the simple way first. - try { - InetAddress address = InetAddress.getLocalHost(); - if (!address.isLoopbackAddress()) { - result.add(address.getHostAddress()); - } - } catch (Throwable x) { - LOG.warn("Failed to resolve local IP address.", x); - } - - // Iterate through all network interfaces, looking for a suitable IP. - try { - Enumeration interfaces = NetworkInterface.getNetworkInterfaces(); - while (interfaces.hasMoreElements()) { - NetworkInterface iface = interfaces.nextElement(); - Enumeration addresses = iface.getInetAddresses(); - while (addresses.hasMoreElements()) { - InetAddress addr = addresses.nextElement(); - if (addr instanceof Inet4Address && !addr.isLoopbackAddress()) { - result.add(addr.getHostAddress()); - } - } - } - } catch (Throwable x) { - LOG.warn("Failed to resolve local IP address.", x); - } - - if (result.isEmpty()) { - result.add("127.0.0.1"); - } - - return result; - } - - public static int randomInt(int min, int max) { - if (min >= max) { - return 0; - } - return min + RANDOM.nextInt(max - min); - } - - public static Iterable toIterable(final Enumeration e) { - return new Iterable() { - public Iterator iterator() { - return toIterator(e); - } - }; - } - - public static Iterator toIterator(final Enumeration e) { - return new Iterator() { - public boolean hasNext() { - return e.hasMoreElements(); - } - - public T next() { - return (T) e.nextElement(); - } - - public void remove() { - throw new UnsupportedOperationException(); - } - }; - } - public static List subList(List list, long offset, long max) { return list.subList((int) offset, Math.min(list.size(), (int) (offset + max))); } diff --git a/libresonic-main/src/main/resources/applicationContext-db-embed.xml b/libresonic-main/src/main/resources/applicationContext-db-embed.xml index 4ba2e7ed..5a60fea8 100644 --- a/libresonic-main/src/main/resources/applicationContext-db-embed.xml +++ b/libresonic-main/src/main/resources/applicationContext-db-embed.xml @@ -6,9 +6,9 @@ - - - - + + + + \ No newline at end of file diff --git a/libresonic-main/src/main/resources/applicationContext-db-jndi.xml b/libresonic-main/src/main/resources/applicationContext-db-jndi.xml index 19e08839..8d1fb486 100644 --- a/libresonic-main/src/main/resources/applicationContext-db-jndi.xml +++ b/libresonic-main/src/main/resources/applicationContext-db-jndi.xml @@ -7,6 +7,6 @@ http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd" profile="jndi"> \ No newline at end of file diff --git a/libresonic-main/src/main/resources/applicationContext-db.xml b/libresonic-main/src/main/resources/applicationContext-db.xml index b49a44dd..8f87b2c2 100644 --- a/libresonic-main/src/main/resources/applicationContext-db.xml +++ b/libresonic-main/src/main/resources/applicationContext-db.xml @@ -23,7 +23,7 @@ - + @@ -33,7 +33,7 @@ - + diff --git a/libresonic-main/src/main/resources/liquibase/db-changelog.xml b/libresonic-main/src/main/resources/liquibase/db-changelog.xml index 512c96ba..2af15cef 100644 --- a/libresonic-main/src/main/resources/liquibase/db-changelog.xml +++ b/libresonic-main/src/main/resources/liquibase/db-changelog.xml @@ -5,7 +5,7 @@ - + diff --git a/libresonic-main/src/main/resources/org/libresonic/player/i18n/ResourceBundle_en.properties b/libresonic-main/src/main/resources/org/libresonic/player/i18n/ResourceBundle_en.properties index 5f905389..5f8bf8ff 100644 --- a/libresonic-main/src/main/resources/org/libresonic/player/i18n/ResourceBundle_en.properties +++ b/libresonic-main/src/main/resources/org/libresonic/player/i18n/ResourceBundle_en.properties @@ -340,6 +340,7 @@ settingsheader.user = Users settingsheader.search = Search/caching settingsheader.coverArt = Cover art settingsheader.password = Password +settingsheader.database = Database # generalSettings.jsp generalsettings.playlistfolder = Import playlists from @@ -599,6 +600,22 @@ usersettings.ldapdisabled = LDAP authentication is not enabled. See Advanced set usersettings.passwordnotsupportedforldap = Can't set or change password for LDAP-authenticated users. usersettings.ok = Password successfully changed for user {0}. +# databaseSettings.jsp +databasesettings.moreinfo = Additional information on database settings can be read at \ + DATABASE.md on the \ + Libresonic github page. +databasesettings.configtype = Database Connection Source +databasesettings.mysqlvarcharmaxlength = MySQL Varchar Maximum Length +databasesettings.usertablequote = User table Quote +databasesettings.jndiname = Data Source JNDI Lookup Name +databasesettings.jdbclibrary = Please ensure that you have your database driver on your \ + Java Classpath +databasesettings.embeddriver = JDBC Driver Java classname +databasesettings.embedurl = JDBC URL +databasesettings.embedusername = JDBC Username +databasesettings.embedpassword = JDBC Password +databasettings.restartRequired = Database settings require a restart to take affect. + # main.jsp main.up = Up main.playall = Play all @@ -732,6 +749,22 @@ helppopup.transcode.title = Max bitrate helppopup.transcode.text =

If you have constrained bandwidth, you may set an upper limit for the bitrate of the music streams. \ For instance, if your original mp3 files are encoded using 256 Kbps (kilobits per second), setting max bitrate \ to 128 will make {0} automatically resample the music from 256 to 128 Kbps.

+helppopup.databaseConfigType.title = Data Source Config Type +helppopup.databaseConfigType.text =

Legacy will default to an embed H2 database which is the backwards compatible \ + option. Embedded JDBC will connect to a JDBC database with the provided settings. JNDI will lookup \ + a DataSource connection already setup in your application container.

+helppopup.mysqlvarcharmaxlength.title = MySQL Varchar Max Length +helppopup.mysqlvarcharmaxlength.text =

MySQL has a maximum row length and as such needs varchar columns to be \ + bounded. This value entered here will be the maximum column size.

+helppopup.usertablequote.title = User Table Quote +helppopup.usertablequote.text =

The Libresonic users table is named user. This may be a keyword conflict in some \ + databases such as Postgres. So for postgres, you will want to use the double quote character (") here

+helppopup.jndiname.title = Data Source JNDI Lookup Name +helppopup.jndiname.text = A JNDI name to lookup a Data Source of type javax.sql.DataSource. This is something that is\ + created in your application container (i.e. tomcat). +helppopup.embeddriver.title = JDBC Driver Class +helppopup.embeddriver.text = JDBC Driver dependent class name that implments java.sql.Driver. I.E. for postgres one \ + would use org.postgresql.Driver. This class must be present on the classpath. helppopup.playlistfolder.title = Import playlist from helppopup.playlistfolder.text =

Libresonic will regularly import playlists stored in this folder.

helppopup.musicmask.title = Music files diff --git a/libresonic-main/src/main/webapp/WEB-INF/jsp/databaseSettings.jsp b/libresonic-main/src/main/webapp/WEB-INF/jsp/databaseSettings.jsp new file mode 100644 index 00000000..7e31135b --- /dev/null +++ b/libresonic-main/src/main/webapp/WEB-INF/jsp/databaseSettings.jsp @@ -0,0 +1,128 @@ +<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="iso-8859-1" %> +<%--@elvariable id="command" type="org.libresonic.player.command.DatabaseSettingsCommand"--%> + + + + <%@ include file="head.jsp" %> + <%@ include file="jquery.jsp" %> + + + + + + + + + + + + +

+ + + + + + +
+ + + + + + +
+ +
+ +
+ + + + + + + + + + + + + + + + +
+ + +
+ +
+ +
+ +
+ +
+ +
+ + + + + +
+ + +
+
+
+ + + + + + + + + +
+ + +
+ + +
+

+
+ +

+ +

+ " style="margin-right:0.3em"> + " onclick="location.href='nowPlaying.view'"> +

+ +
+ + + \ No newline at end of file diff --git a/libresonic-main/src/main/webapp/WEB-INF/jsp/generalDatabaseSettings.jsp b/libresonic-main/src/main/webapp/WEB-INF/jsp/generalDatabaseSettings.jsp new file mode 100644 index 00000000..e69de29b diff --git a/libresonic-main/src/main/webapp/WEB-INF/jsp/settingsHeader.jsp b/libresonic-main/src/main/webapp/WEB-INF/jsp/settingsHeader.jsp index 078806ab..1fe18ea9 100644 --- a/libresonic-main/src/main/webapp/WEB-INF/jsp/settingsHeader.jsp +++ b/libresonic-main/src/main/webapp/WEB-INF/jsp/settingsHeader.jsp @@ -9,7 +9,7 @@ - +

" alt=""/>