diff --git a/airsonic-main/pom.xml b/airsonic-main/pom.xml index f919a492..3766313b 100755 --- a/airsonic-main/pom.xml +++ b/airsonic-main/pom.xml @@ -149,7 +149,6 @@ org.apache.commons commons-dbcp2 2.5.0 - runtime @@ -568,6 +567,11 @@ 2.1.2 runtime + + org.hamcrest + hamcrest-core + test + diff --git a/airsonic-main/src/main/java/org/airsonic/player/Application.java b/airsonic-main/src/main/java/org/airsonic/player/Application.java index 5ffd130e..498c067a 100644 --- a/airsonic-main/src/main/java/org/airsonic/player/Application.java +++ b/airsonic-main/src/main/java/org/airsonic/player/Application.java @@ -1,6 +1,5 @@ package org.airsonic.player; -import net.sf.ehcache.constructs.web.ShutdownListener; import org.airsonic.player.filter.*; import org.directwebremoting.servlet.DwrServlet; import org.slf4j.Logger; @@ -19,12 +18,9 @@ import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.boot.web.support.SpringBootServletInitializer; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.ImportResource; import org.springframework.util.ReflectionUtils; import javax.servlet.Filter; -import javax.servlet.ServletContextListener; import java.lang.reflect.Method; @@ -35,11 +31,6 @@ import java.lang.reflect.Method; DataSourceTransactionManagerAutoConfiguration.class, MultipartAutoConfiguration.class, // TODO: update to use spring boot builtin multipart support LiquibaseAutoConfiguration.class}) -@Configuration -@ImportResource({"classpath:/applicationContext-service.xml", - "classpath:/applicationContext-cache.xml", - "classpath:/applicationContext-sonos.xml", - "classpath:/servlet.xml"}) public class Application extends SpringBootServletInitializer implements EmbeddedServletContainerCustomizer { private static final Logger LOG = LoggerFactory.getLogger(Application.class); @@ -61,11 +52,6 @@ public class Application extends SpringBootServletInitializer implements Embedde return new ServletRegistrationBean(new org.apache.cxf.transport.servlet.CXFServlet(), "/ws/*"); } - @Bean - public ServletContextListener ehCacheShutdownListener() { - return new ShutdownListener(); - } - @Bean public FilterRegistrationBean bootstrapVerificationFilterRegistration() { FilterRegistrationBean registration = new FilterRegistrationBean(); diff --git a/airsonic-main/src/main/java/org/airsonic/player/controller/ReloadFrame.java b/airsonic-main/src/main/java/org/airsonic/player/controller/ReloadFrame.java index 65a78567..429ac00c 100644 --- a/airsonic-main/src/main/java/org/airsonic/player/controller/ReloadFrame.java +++ b/airsonic-main/src/main/java/org/airsonic/player/controller/ReloadFrame.java @@ -20,7 +20,6 @@ package org.airsonic.player.controller; /** - * Used in servlet.xml to specify frame reloading. * * @author Sindre Mehus */ diff --git a/airsonic-main/src/main/java/org/airsonic/player/service/metadata/DefaultMetaDataParser.java b/airsonic-main/src/main/java/org/airsonic/player/service/metadata/DefaultMetaDataParser.java index cafe3fe3..53ae1289 100644 --- a/airsonic-main/src/main/java/org/airsonic/player/service/metadata/DefaultMetaDataParser.java +++ b/airsonic-main/src/main/java/org/airsonic/player/service/metadata/DefaultMetaDataParser.java @@ -22,6 +22,7 @@ package org.airsonic.player.service.metadata; import org.airsonic.player.domain.MediaFile; import org.airsonic.player.service.SettingsService; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.annotation.Order; import org.springframework.stereotype.Service; import java.io.File; @@ -32,6 +33,7 @@ import java.io.File; * @author Sindre Mehus */ @Service +@Order(200) public class DefaultMetaDataParser extends MetaDataParser { @Autowired diff --git a/airsonic-main/src/main/java/org/airsonic/player/service/metadata/FFmpegParser.java b/airsonic-main/src/main/java/org/airsonic/player/service/metadata/FFmpegParser.java index 99cc7cea..83d60e92 100644 --- a/airsonic-main/src/main/java/org/airsonic/player/service/metadata/FFmpegParser.java +++ b/airsonic-main/src/main/java/org/airsonic/player/service/metadata/FFmpegParser.java @@ -28,6 +28,7 @@ import org.apache.commons.io.FilenameUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.annotation.Order; import org.springframework.stereotype.Service; import java.io.File; @@ -43,6 +44,7 @@ import java.util.List; * @author Sindre Mehus */ @Service("ffmpegParser") +@Order(100) public class FFmpegParser extends MetaDataParser { private static final Logger LOG = LoggerFactory.getLogger(FFmpegParser.class); diff --git a/airsonic-main/src/main/java/org/airsonic/player/service/metadata/JaudiotaggerParser.java b/airsonic-main/src/main/java/org/airsonic/player/service/metadata/JaudiotaggerParser.java index 300bfb60..8b0e9956 100644 --- a/airsonic-main/src/main/java/org/airsonic/player/service/metadata/JaudiotaggerParser.java +++ b/airsonic-main/src/main/java/org/airsonic/player/service/metadata/JaudiotaggerParser.java @@ -36,6 +36,7 @@ import org.jaudiotagger.tag.reference.GenreTypes; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.annotation.Order; import org.springframework.stereotype.Service; import org.springframework.util.ObjectUtils; @@ -53,6 +54,7 @@ import java.util.regex.Pattern; * @author Sindre Mehus */ @Service +@Order(0) public class JaudiotaggerParser extends MetaDataParser { private static final Logger LOG = LoggerFactory.getLogger(JaudiotaggerParser.class); diff --git a/airsonic-main/src/main/java/org/airsonic/player/service/metadata/MetaDataParserFactory.java b/airsonic-main/src/main/java/org/airsonic/player/service/metadata/MetaDataParserFactory.java index cb26ef8b..bce48539 100644 --- a/airsonic-main/src/main/java/org/airsonic/player/service/metadata/MetaDataParserFactory.java +++ b/airsonic-main/src/main/java/org/airsonic/player/service/metadata/MetaDataParserFactory.java @@ -19,6 +19,9 @@ */ package org.airsonic.player.service.metadata; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + import java.io.File; import java.util.List; @@ -27,11 +30,13 @@ import java.util.List; * * @author Sindre Mehus */ +@Component public class MetaDataParserFactory { private List parsers; - public void setParsers(List parsers) { + @Autowired + public MetaDataParserFactory(List parsers) { this.parsers = parsers; } diff --git a/airsonic-main/src/main/java/org/airsonic/player/service/sonos/SonosFaultInterceptor.java b/airsonic-main/src/main/java/org/airsonic/player/service/sonos/SonosFaultInterceptor.java index 89dcf8bf..a15d0570 100644 --- a/airsonic-main/src/main/java/org/airsonic/player/service/sonos/SonosFaultInterceptor.java +++ b/airsonic-main/src/main/java/org/airsonic/player/service/sonos/SonosFaultInterceptor.java @@ -26,6 +26,7 @@ import org.apache.cxf.interceptor.Fault; import org.apache.cxf.phase.Phase; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -37,6 +38,7 @@ import javax.xml.namespace.QName; * @author Sindre Mehus * @version $Id$ */ +@Component public class SonosFaultInterceptor extends AbstractSoapInterceptor { private static final Logger LOG = LoggerFactory.getLogger(SonosFaultInterceptor.class); diff --git a/airsonic-main/src/main/java/org/airsonic/player/spring/DatabaseConfiguration.java b/airsonic-main/src/main/java/org/airsonic/player/spring/DatabaseConfiguration.java new file mode 100644 index 00000000..6aa1d455 --- /dev/null +++ b/airsonic-main/src/main/java/org/airsonic/player/spring/DatabaseConfiguration.java @@ -0,0 +1,105 @@ +package org.airsonic.player.spring; + +import org.airsonic.player.dao.DaoHelper; +import org.airsonic.player.dao.GenericDaoHelper; +import org.airsonic.player.dao.LegacyHsqlDaoHelper; +import org.airsonic.player.service.SettingsService; +import org.airsonic.player.util.Util; +import org.apache.commons.dbcp2.BasicDataSource; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; +import org.springframework.jdbc.datasource.DataSourceTransactionManager; +import org.springframework.jdbc.datasource.DriverManagerDataSource; +import org.springframework.jdbc.datasource.lookup.JndiDataSourceLookup; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +import javax.sql.DataSource; + +import java.io.File; +import java.util.HashMap; +import java.util.Map; + +@Configuration +@EnableTransactionManagement +public class DatabaseConfiguration { + + @Bean + public DataSourceTransactionManager transactionManager(DataSource dataSource) { + return new DataSourceTransactionManager(dataSource); + } + + @Bean + @Profile("legacy") + public DaoHelper legacyDaoHelper(DataSource dataSource) { + return new LegacyHsqlDaoHelper(dataSource); + } + + @Bean + @ConditionalOnMissingBean + public DaoHelper daoHelper(DataSource dataSource) { + return new GenericDaoHelper(dataSource); + } + + @Bean + @Profile("legacy") + public DataSource legacyDataSource() { + DriverManagerDataSource dataSource = new DriverManagerDataSource(); + dataSource.setDriverClassName("org.hsqldb.jdbcDriver"); + dataSource.setUrl(SettingsService.getDefaultJDBCUrl()); + dataSource.setUsername("sa"); + dataSource.setPassword(""); + return dataSource; + } + + @Bean + @Profile("embed") + public DataSource embedDataSource(@Value("${DatabaseConfigEmbedDriver}") String driver, + @Value("${DatabaseConfigEmbedUrl}") String url, + @Value("${DatabaseConfigEmbedUsername}") String username, + @Value("${DatabaseConfigEmbedPassword}") String password) { + BasicDataSource basicDataSource = new BasicDataSource(); + basicDataSource.setDriverClassName(driver); + basicDataSource.setUrl(url); + basicDataSource.setUsername(username); + basicDataSource.setPassword(password); + return basicDataSource; + } + + @Bean + @Profile("jndi") + public DataSource jndiDataSource(@Value("${DatabaseConfigJNDIName}") String jndiName) { + JndiDataSourceLookup jndiLookup = new JndiDataSourceLookup(); + return jndiLookup.getDataSource(jndiName); + } + + @Bean + public File rollbackFile() { + return new File(SettingsService.getAirsonicHome(), "rollback.sql"); + } + + @Bean + public String userTableQuote(@Value("${DatabaseUsertableQuote:}") String value) { + return value; + } + + @Bean + public SpringLiquibase liquibase(DataSource dataSource, + @Value("${DatabaseMysqlMaxlength:512}") + String mysqlVarcharLimit, + String userTableQuote) { + SpringLiquibase springLiquibase = new SpringLiquibase(); + springLiquibase.setDataSource(dataSource); + springLiquibase.setChangeLog("classpath:liquibase/db-changelog.xml"); + springLiquibase.setRollbackFile(rollbackFile()); + Map parameters = new HashMap<>(); + parameters.put("defaultMusicFolder", Util.getDefaultMusicFolder()); + parameters.put("mysqlVarcharLimit", mysqlVarcharLimit); + parameters.put("userTableQuote", userTableQuote); + springLiquibase.setChangeLogParameters(parameters); + return springLiquibase; + } + +} diff --git a/airsonic-main/src/main/java/org/airsonic/player/spring/EhcacheConfiguration.java b/airsonic-main/src/main/java/org/airsonic/player/spring/EhcacheConfiguration.java new file mode 100644 index 00000000..50a0aedc --- /dev/null +++ b/airsonic-main/src/main/java/org/airsonic/player/spring/EhcacheConfiguration.java @@ -0,0 +1,33 @@ +package org.airsonic.player.spring; + +import net.sf.ehcache.Ehcache; +import net.sf.ehcache.constructs.web.ShutdownListener; +import org.airsonic.player.cache.CacheFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import javax.servlet.ServletContextListener; + +@Configuration +public class EhcacheConfiguration { + + @Bean + public ServletContextListener ehCacheShutdownListener() { + return new ShutdownListener(); + } + + @Bean + public Ehcache userCache(CacheFactory cacheFactory) { + return cacheFactory.getCache("userCache"); + } + + @Bean + public Ehcache mediaFileMemoryCache(CacheFactory cacheFactory) { + return cacheFactory.getCache("mediaFileMemoryCache"); + } + + @Bean + public CacheFactory cacheFactory() { + return new CacheFactory(); + } +} diff --git a/airsonic-main/src/main/java/org/airsonic/player/spring/LoggingExceptionResolver.java b/airsonic-main/src/main/java/org/airsonic/player/spring/LoggingExceptionResolver.java index 691b12ea..fe411eb5 100644 --- a/airsonic-main/src/main/java/org/airsonic/player/spring/LoggingExceptionResolver.java +++ b/airsonic-main/src/main/java/org/airsonic/player/spring/LoggingExceptionResolver.java @@ -4,12 +4,14 @@ import org.airsonic.player.util.Util; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.core.Ordered; +import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerExceptionResolver; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +@Component public class LoggingExceptionResolver implements HandlerExceptionResolver, Ordered { private static final Logger LOG = LoggerFactory.getLogger(LoggingExceptionResolver.class); diff --git a/airsonic-main/src/main/java/org/airsonic/player/spring/ServletConfiguration.java b/airsonic-main/src/main/java/org/airsonic/player/spring/ServletConfiguration.java new file mode 100644 index 00000000..6259a5b0 --- /dev/null +++ b/airsonic-main/src/main/java/org/airsonic/player/spring/ServletConfiguration.java @@ -0,0 +1,34 @@ +package org.airsonic.player.spring; + +import org.airsonic.player.controller.PodcastController; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.ViewResolver; +import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping; +import org.springframework.web.servlet.view.InternalResourceViewResolver; +import org.springframework.web.servlet.view.JstlView; + +import java.util.Properties; + +@Configuration +public class ServletConfiguration { + + @Bean + public SimpleUrlHandlerMapping podcastUrlMapping(PodcastController podcastController) { + SimpleUrlHandlerMapping handlerMapping = new SimpleUrlHandlerMapping(); + handlerMapping.setAlwaysUseFullPath(true); + Properties properties = new Properties(); + properties.put("/podcast/**", podcastController); + handlerMapping.setMappings(properties); + return handlerMapping; + } + + @Bean + public ViewResolver viewResolver() { + InternalResourceViewResolver resolver = new InternalResourceViewResolver(); + resolver.setViewClass(JstlView.class); + resolver.setPrefix("/WEB-INF/jsp/"); + resolver.setSuffix(".jsp"); + return resolver; + } +} diff --git a/airsonic-main/src/main/java/org/airsonic/player/spring/SonosConfiguration.java b/airsonic-main/src/main/java/org/airsonic/player/spring/SonosConfiguration.java new file mode 100644 index 00000000..d5afc39d --- /dev/null +++ b/airsonic-main/src/main/java/org/airsonic/player/spring/SonosConfiguration.java @@ -0,0 +1,26 @@ +package org.airsonic.player.spring; + +import org.airsonic.player.service.SonosService; +import org.airsonic.player.service.sonos.SonosFaultInterceptor; +import org.apache.cxf.jaxws.EndpointImpl; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.ImportResource; + +import javax.xml.ws.Endpoint; + +import java.util.Collections; + +@Configuration +@ImportResource({"classpath:META-INF/cxf/cxf.xml", "classpath:META-INF/cxf/cxf-servlet.xml"}) +public class SonosConfiguration { + + @Bean + public Endpoint sonosEndpoint(SonosService sonosService, SonosFaultInterceptor sonosFaultInterceptor) { + EndpointImpl endpoint = new EndpointImpl(sonosService); + endpoint.publish("/Sonos"); + endpoint.setOutFaultInterceptors(Collections.singletonList(sonosFaultInterceptor)); + return endpoint; + } + +} diff --git a/airsonic-main/src/main/java/org/airsonic/player/theme/CustomThemeResolver.java b/airsonic-main/src/main/java/org/airsonic/player/theme/CustomThemeResolver.java index 6f2e0bd5..cce487c1 100644 --- a/airsonic-main/src/main/java/org/airsonic/player/theme/CustomThemeResolver.java +++ b/airsonic-main/src/main/java/org/airsonic/player/theme/CustomThemeResolver.java @@ -23,6 +23,8 @@ import org.airsonic.player.domain.Theme; import org.airsonic.player.domain.UserSettings; import org.airsonic.player.service.SecurityService; import org.airsonic.player.service.SettingsService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; import org.springframework.web.servlet.ThemeResolver; import javax.servlet.http.HttpServletRequest; @@ -36,6 +38,7 @@ import java.util.Set; * * @author Sindre Mehus */ +@Component("themeResolver") public class CustomThemeResolver implements ThemeResolver { private SecurityService securityService; @@ -113,10 +116,12 @@ public class CustomThemeResolver implements ThemeResolver { throw new UnsupportedOperationException("Cannot change theme - use a different theme resolution strategy"); } + @Autowired public void setSecurityService(SecurityService securityService) { this.securityService = securityService; } + @Autowired public void setSettingsService(SettingsService settingsService) { this.settingsService = settingsService; } diff --git a/airsonic-main/src/main/java/org/airsonic/player/theme/CustomThemeSource.java b/airsonic-main/src/main/java/org/airsonic/player/theme/CustomThemeSource.java index 864e7d64..510944d5 100644 --- a/airsonic-main/src/main/java/org/airsonic/player/theme/CustomThemeSource.java +++ b/airsonic-main/src/main/java/org/airsonic/player/theme/CustomThemeSource.java @@ -21,9 +21,13 @@ package org.airsonic.player.theme; import org.airsonic.player.domain.Theme; import org.airsonic.player.service.SettingsService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.context.MessageSource; import org.springframework.context.support.ResourceBundleMessageSource; +import org.springframework.stereotype.Component; import org.springframework.ui.context.support.ResourceBundleThemeSource; +import org.springframework.ui.context.support.UiApplicationContextUtils; /** * Theme source implementation which uses two resource bundles: the @@ -31,6 +35,7 @@ import org.springframework.ui.context.support.ResourceBundleThemeSource; * * @author Sindre Mehus */ +@Component(UiApplicationContextUtils.THEME_SOURCE_BEAN_NAME) public class CustomThemeSource extends ResourceBundleThemeSource { private SettingsService settingsService; @@ -51,12 +56,15 @@ public class CustomThemeSource extends ResourceBundleThemeSource { return messageSource; } + @Autowired + @Value("org.airsonic.player.theme.") @Override public void setBasenamePrefix(String basenamePrefix) { this.basenamePrefix = basenamePrefix; super.setBasenamePrefix(basenamePrefix); } + @Autowired public void setSettingsService(SettingsService settingsService) { this.settingsService = settingsService; } diff --git a/airsonic-main/src/main/resources/application.properties b/airsonic-main/src/main/resources/application.properties index a536e667..2363702e 100644 --- a/airsonic-main/src/main/resources/application.properties +++ b/airsonic-main/src/main/resources/application.properties @@ -1,6 +1,7 @@ -spring.mvc.view.prefix: /WEB-INF/jsp/ -spring.mvc.view.suffix: .jsp -server.error.includeStacktrace: ALWAYS +spring.mvc.view.prefix=/WEB-INF/jsp/ +spring.mvc.view.suffix=.jsp +spring.messages.basename=org.airsonic.player.i18n.ResourceBundle +server.error.includeStacktrace=ALWAYS logging.level.root=WARN logging.level.org.airsonic=INFO logging.level.liquibase=INFO diff --git a/airsonic-main/src/main/resources/applicationContext-cache.xml b/airsonic-main/src/main/resources/applicationContext-cache.xml deleted file mode 100644 index ae0ee30c..00000000 --- a/airsonic-main/src/main/resources/applicationContext-cache.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/airsonic-main/src/main/resources/applicationContext-db-embed.xml b/airsonic-main/src/main/resources/applicationContext-db-embed.xml deleted file mode 100644 index 2668caa6..00000000 --- a/airsonic-main/src/main/resources/applicationContext-db-embed.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - diff --git a/airsonic-main/src/main/resources/applicationContext-db-jndi.xml b/airsonic-main/src/main/resources/applicationContext-db-jndi.xml deleted file mode 100644 index 8d1fb486..00000000 --- a/airsonic-main/src/main/resources/applicationContext-db-jndi.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - \ No newline at end of file diff --git a/airsonic-main/src/main/resources/applicationContext-db-legacy.xml b/airsonic-main/src/main/resources/applicationContext-db-legacy.xml deleted file mode 100644 index b933f284..00000000 --- a/airsonic-main/src/main/resources/applicationContext-db-legacy.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/airsonic-main/src/main/resources/applicationContext-db.xml b/airsonic-main/src/main/resources/applicationContext-db.xml deleted file mode 100644 index de2db1ae..00000000 --- a/airsonic-main/src/main/resources/applicationContext-db.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/airsonic-main/src/main/resources/applicationContext-service.xml b/airsonic-main/src/main/resources/applicationContext-service.xml deleted file mode 100644 index 482a32f8..00000000 --- a/airsonic-main/src/main/resources/applicationContext-service.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/airsonic-main/src/main/resources/applicationContext-sonos.xml b/airsonic-main/src/main/resources/applicationContext-sonos.xml deleted file mode 100644 index ccf35125..00000000 --- a/airsonic-main/src/main/resources/applicationContext-sonos.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/airsonic-main/src/main/resources/servlet.xml b/airsonic-main/src/main/resources/servlet.xml deleted file mode 100644 index a38c152d..00000000 --- a/airsonic-main/src/main/resources/servlet.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - - - - podcastController - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/airsonic-main/src/test/java/org/airsonic/player/TestCaseUtils.java b/airsonic-main/src/test/java/org/airsonic/player/TestCaseUtils.java index 70aa0d4f..2de4f9fc 100644 --- a/airsonic-main/src/test/java/org/airsonic/player/TestCaseUtils.java +++ b/airsonic-main/src/test/java/org/airsonic/player/TestCaseUtils.java @@ -6,8 +6,6 @@ import org.airsonic.player.service.MediaScannerService; import org.apache.commons.io.FileUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.context.ApplicationContext; -import org.springframework.context.support.ClassPathXmlApplicationContext; import java.io.File; import java.io.IOException; @@ -91,17 +89,6 @@ public class TestCaseUtils { return daoHelper.getJdbcTemplate().queryForObject("select count(1) from " + tableName,Integer.class); } - public static ApplicationContext loadSpringApplicationContext(String baseResources) { - String applicationContextService = baseResources + "applicationContext-service.xml"; - String applicationContextCache = baseResources + "applicationContext-cache.xml"; - - String[] configLocations = new String[]{ - TestCaseUtils.class.getClass().getResource(applicationContextCache).toString(), - TestCaseUtils.class.getClass().getResource(applicationContextService).toString() - }; - return new ClassPathXmlApplicationContext(configLocations); - } - /** * Scans the music library * @param mediaScannerService */ diff --git a/airsonic-main/src/test/java/org/airsonic/player/dao/DaoTestCaseBean2.java b/airsonic-main/src/test/java/org/airsonic/player/dao/DaoTestCaseBean2.java index 1afafd32..c31bb4da 100644 --- a/airsonic-main/src/test/java/org/airsonic/player/dao/DaoTestCaseBean2.java +++ b/airsonic-main/src/test/java/org/airsonic/player/dao/DaoTestCaseBean2.java @@ -6,16 +6,12 @@ import org.junit.Rule; import org.junit.runner.Description; import org.junit.runners.model.Statement; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.rules.SpringClassRule; import org.springframework.test.context.junit4.rules.SpringMethodRule; -@ContextConfiguration(locations = { - "/applicationContext-service.xml", - "/applicationContext-cache.xml", - "/applicationContext-testdb.xml", - "/applicationContext-mockSonos.xml"}) +@SpringBootTest public class DaoTestCaseBean2 { @ClassRule public static final SpringClassRule classRule = new SpringClassRule() { diff --git a/airsonic-main/src/test/java/org/airsonic/player/service/LegacyDatabaseStartupTestCase.java b/airsonic-main/src/test/java/org/airsonic/player/service/LegacyDatabaseStartupTestCase.java index b4141104..4eb713eb 100644 --- a/airsonic-main/src/test/java/org/airsonic/player/service/LegacyDatabaseStartupTestCase.java +++ b/airsonic-main/src/test/java/org/airsonic/player/service/LegacyDatabaseStartupTestCase.java @@ -8,17 +8,13 @@ import org.junit.Rule; import org.junit.Test; import org.junit.runner.Description; import org.junit.runners.model.Statement; -import org.springframework.test.context.ContextConfiguration; +import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.rules.SpringClassRule; import org.springframework.test.context.junit4.rules.SpringMethodRule; import java.io.File; -@ContextConfiguration(locations = { - "/applicationContext-service.xml", - "/applicationContext-cache.xml", - "/applicationContext-testdb.xml", - "/applicationContext-mockSonos.xml"}) +@SpringBootTest public class LegacyDatabaseStartupTestCase { @ClassRule diff --git a/airsonic-main/src/test/java/org/airsonic/player/service/MediaScannerServiceTestCase.java b/airsonic-main/src/test/java/org/airsonic/player/service/MediaScannerServiceTestCase.java index 87415a2e..68e37b88 100644 --- a/airsonic-main/src/test/java/org/airsonic/player/service/MediaScannerServiceTestCase.java +++ b/airsonic-main/src/test/java/org/airsonic/player/service/MediaScannerServiceTestCase.java @@ -20,15 +20,14 @@ import org.junit.rules.TemporaryFolder; import org.junit.runner.Description; import org.junit.runners.model.Statement; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.core.io.Resource; -import org.springframework.core.io.ResourceLoader; +import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.rules.SpringClassRule; import org.springframework.test.context.junit4.rules.SpringMethodRule; import java.io.File; import java.io.FileOutputStream; +import java.io.InputStream; import java.util.ArrayList; import java.util.Date; import java.util.List; @@ -50,11 +49,7 @@ import static org.junit.Assert.assertNotNull; * At runtime, the subsonic_home dir is set to target/test-classes/org/airsonic/player/service/mediaScannerServiceTestCase. * An empty database is created on the fly. */ -@ContextConfiguration(locations = { - "/applicationContext-service.xml", - "/applicationContext-cache.xml", - "/applicationContext-testdb.xml", - "/applicationContext-mockSonos.xml"}) +@SpringBootTest @DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) public class MediaScannerServiceTestCase { @@ -101,9 +96,6 @@ public class MediaScannerServiceTestCase { @Rule public TemporaryFolder temporaryFolder = new TemporaryFolder(); - @Autowired - ResourceLoader resourceLoader; - /** * Tests the MediaScannerService by scanning the test media library into an empty database. @@ -161,12 +153,15 @@ public class MediaScannerServiceTestCase { @Test public void testSpecialCharactersInFilename() throws Exception { - Resource resource = resourceLoader.getResource("MEDIAS/piano.mp3"); + InputStream resource = MediaScannerServiceTestCase.class + .getClassLoader() + .getResourceAsStream("MEDIAS/piano.mp3"); + assert resource != null; String directoryName = "Muff1nman\u2019s \uFF0FMusic"; String fileName = "Muff1nman\u2019s\uFF0FPiano.mp3"; File artistDir = temporaryFolder.newFolder(directoryName); File musicFile = artistDir.toPath().resolve(fileName).toFile(); - IOUtils.copy(resource.getInputStream(), new FileOutputStream(musicFile)); + IOUtils.copy(resource, new FileOutputStream(musicFile)); MusicFolder musicFolder = new MusicFolder(1, temporaryFolder.getRoot(), "Music", true, new Date()); musicFolderDao.createMusicFolder(musicFolder); diff --git a/airsonic-main/src/test/java/org/airsonic/player/service/metadata/MetaDataFactoryTestCase.java b/airsonic-main/src/test/java/org/airsonic/player/service/metadata/MetaDataFactoryTestCase.java new file mode 100644 index 00000000..4e5c25b3 --- /dev/null +++ b/airsonic-main/src/test/java/org/airsonic/player/service/metadata/MetaDataFactoryTestCase.java @@ -0,0 +1,75 @@ +package org.airsonic.player.service.metadata; + +import org.airsonic.player.service.SettingsService; +import org.airsonic.player.util.HomeRule; +import org.junit.*; +import org.junit.rules.TemporaryFolder; +import org.junit.runner.Description; +import org.junit.runners.model.Statement; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.junit4.rules.SpringClassRule; +import org.springframework.test.context.junit4.rules.SpringMethodRule; + +import java.io.File; +import java.io.IOException; + +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.junit.Assert.assertThat; + +@SpringBootTest +@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) +public class MetaDataFactoryTestCase { + + @ClassRule + public static final SpringClassRule classRule = new SpringClassRule() { + HomeRule homeRule = new HomeRule(); + + @Override + public Statement apply(Statement base, Description description) { + Statement spring = super.apply(base, description); + return homeRule.apply(spring, description); + } + }; + + @ClassRule + public static TemporaryFolder temporaryFolder = new TemporaryFolder(); + + private static File someMp3; + private static File someFlv; + private static File someJunk; + + @BeforeClass + public static void createTestFiles() throws IOException { + someMp3 = temporaryFolder.newFile("some.mp3"); + someFlv = temporaryFolder.newFile("some.flv"); + someJunk = temporaryFolder.newFile("some.junk"); + } + + @Rule + public final SpringMethodRule springMethodRule = new SpringMethodRule(); + + @Autowired + MetaDataParserFactory metaDataParserFactory; + + @Autowired + SettingsService settingsService; + + @Test + public void testorder() { + MetaDataParser parser; + + settingsService.setVideoFileTypes("mp3 flv"); + + parser = metaDataParserFactory.getParser(someMp3); + assertThat(parser, instanceOf(JaudiotaggerParser.class)); + + parser = metaDataParserFactory.getParser(someFlv); + assertThat(parser, instanceOf(FFmpegParser.class)); + + parser = metaDataParserFactory.getParser(someJunk); + assertThat(parser, instanceOf(DefaultMetaDataParser.class)); + } + +} diff --git a/airsonic-main/src/test/java/org/airsonic/player/service/search/AbstractAirsonicHomeTest.java b/airsonic-main/src/test/java/org/airsonic/player/service/search/AbstractAirsonicHomeTest.java index 67952ccc..02e36e17 100644 --- a/airsonic-main/src/test/java/org/airsonic/player/service/search/AbstractAirsonicHomeTest.java +++ b/airsonic-main/src/test/java/org/airsonic/player/service/search/AbstractAirsonicHomeTest.java @@ -13,9 +13,8 @@ import org.junit.rules.TemporaryFolder; import org.junit.runner.Description; import org.junit.runners.model.Statement; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; +import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.rules.SpringClassRule; import org.springframework.test.context.junit4.rules.SpringMethodRule; @@ -23,12 +22,8 @@ import java.util.Map; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Function; -@ContextConfiguration(locations = { - "/applicationContext-service.xml", - "/applicationContext-cache.xml", - "/applicationContext-testdb.xml"}) +@SpringBootTest @DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS) -@Component /* * Abstract class for scanning MusicFolder. */ diff --git a/airsonic-main/src/test/java/org/airsonic/player/service/search/QueryFactoryTestCase.java b/airsonic-main/src/test/java/org/airsonic/player/service/search/QueryFactoryTestCase.java index 02936b65..dda0d023 100644 --- a/airsonic-main/src/test/java/org/airsonic/player/service/search/QueryFactoryTestCase.java +++ b/airsonic-main/src/test/java/org/airsonic/player/service/search/QueryFactoryTestCase.java @@ -13,8 +13,8 @@ import org.junit.Test; import org.junit.runner.Description; import org.junit.runners.model.Statement; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.rules.SpringClassRule; import org.springframework.test.context.junit4.rules.SpringMethodRule; @@ -30,12 +30,8 @@ import static org.junit.Assert.assertEquals; * These cases have the purpose of observing the current situation * and observing the impact of upgrading Lucene. */ -@ContextConfiguration( - locations = { - "/applicationContext-service.xml", - "/applicationContext-cache.xml", - "/applicationContext-testdb.xml", - "/applicationContext-mockSonos.xml" }) + +@SpringBootTest @DirtiesContext( classMode = DirtiesContext.ClassMode.AFTER_CLASS) public class QueryFactoryTestCase { diff --git a/airsonic-main/src/test/resources/applicationContext-mockSonos.xml b/airsonic-main/src/test/resources/applicationContext-mockSonos.xml deleted file mode 100644 index 49bd9202..00000000 --- a/airsonic-main/src/test/resources/applicationContext-mockSonos.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - diff --git a/airsonic-main/src/test/resources/applicationContext-testdb.xml b/airsonic-main/src/test/resources/applicationContext-testdb.xml deleted file mode 100644 index dda560c6..00000000 --- a/airsonic-main/src/test/resources/applicationContext-testdb.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - -