General fixups

- Fixed tomcat deployment
- Removed web.xml
- Migrated to servlet api 3
- Added back in logging error resolver
- Fixed error jsp page not working
- Fixed login path when deployed to tomcat
- Cleanup custom liquibase precondition class
- Made the hsql index check more robust

Signed-off-by: Andrew DeMaria <lostonamountain@gmail.com>
master
Andrew DeMaria 8 years ago
parent 0f58ad43e1
commit 49dc5176d5
No known key found for this signature in database
GPG Key ID: 0A3F5E91F8364EDF
  1. 23
      libresonic-main/pom.xml
  2. 123
      libresonic-main/src/main/java/org/libresonic/player/boot/Application.java
  3. 54
      libresonic-main/src/main/java/org/libresonic/player/spring/DbmsVersionPrecondition.java
  4. 1
      libresonic-main/src/main/java/org/libresonic/player/spring/SpringLiquibase.java
  5. 3
      libresonic-main/src/main/resources/application.properties
  6. 2
      libresonic-main/src/main/resources/libresonic-servlet.xml
  7. 2
      libresonic-main/src/main/resources/liquibase/legacy/schema47.xml
  8. 2
      libresonic-main/src/main/resources/liquibase/legacy/schema53.xml
  9. 24
      libresonic-main/src/main/webapp/WEB-INF/jsp/error.jsp
  10. 2
      libresonic-main/src/main/webapp/WEB-INF/jsp/login.jsp
  11. 225
      libresonic-main/src/main/webapp/WEB-INF/web.xml
  12. 6
      pom.xml

@ -77,14 +77,15 @@
<!-- taglibs -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
<groupId>org.apache.taglibs</groupId>
<artifactId>taglibs-standard-impl</artifactId>
<version>1.2.5</version>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId>string</artifactId>
<version>1.1.0</version>
<scope>runtime</scope>
</dependency>
<!-- END taglibs -->
@ -223,6 +224,20 @@
<version>2.5.1</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>javax.mail</groupId>
<artifactId>javax.mail-api</artifactId>
@ -284,7 +299,6 @@
<artifactId>spring-web</artifactId>
</exclusion>
</exclusions>
<scope>runtime</scope>
</dependency>
<dependency>
@ -372,6 +386,7 @@
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>org.libresonic.player.boot.Application</mainClass>
<layout>WAR</layout>
</configuration>
<executions>
<execution>

@ -1,10 +1,18 @@
package org.libresonic.player.boot;
import javax.servlet.Filter;
import javax.servlet.ServletContextListener;
import net.sf.ehcache.constructs.web.ShutdownListener;
import org.directwebremoting.servlet.DwrServlet;
import org.libresonic.player.filter.BootstrapVerificationFilter;
import org.libresonic.player.filter.ParameterDecodingFilter;
import org.libresonic.player.filter.RESTFilter;
import org.libresonic.player.filter.RequestEncodingFilter;
import org.libresonic.player.filter.ResponseHeaderFilter;
import org.libresonic.player.spring.AdditionalPropertySourceConfigurer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
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;
@ -31,19 +39,124 @@ public class Application extends SpringBootServletInitializer {
return servlet;
}
@Bean
public ServletRegistrationBean cxfServletBean() {
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();
registration.setFilter(bootstrapVerificationFiler());
registration.addUrlPatterns("/*");
registration.setName("BootstrapVerificationFilter");
registration.setOrder(1);
return registration;
}
@Bean
public Filter bootstrapVerificationFiler() {
return new BootstrapVerificationFilter();
}
@Bean
public FilterRegistrationBean parameterDecodingFilterRegistration() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(parameterDecodingFilter());
registration.addUrlPatterns("/*");
registration.setName("ParameterDecodingFilter");
registration.setOrder(2);
return registration;
}
@Bean
public Filter parameterDecodingFilter() {
return new ParameterDecodingFilter();
}
@Bean
public FilterRegistrationBean restFilterRegistration() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(restFilter());
registration.addUrlPatterns("/rest/*");
registration.setName("RESTFilter");
registration.setOrder(3);
return registration;
}
@Bean
public Filter restFilter() {
return new RESTFilter();
}
@Bean
public FilterRegistrationBean requestEncodingFilterRegistration() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(requestEncodingFilter());
registration.addUrlPatterns("/*");
registration.addInitParameter("encoding", "UTF-8");
registration.setName("RequestEncodingFilter");
registration.setOrder(4);
return registration;
}
@Bean
public Filter requestEncodingFilter() {
return new RequestEncodingFilter();
}
@Bean
public FilterRegistrationBean cacheFilterRegistration() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(cacheFilter());
registration.addUrlPatterns("/icons/*", "/style/*");
registration.addInitParameter("Cache-Control", "max-age=36000");
registration.setName("CacheFilter");
registration.setOrder(5);
return registration;
}
@Bean
public Filter cacheFilter() {
return new ResponseHeaderFilter();
}
@Bean
public FilterRegistrationBean noCacheFilterRegistration() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(noCacheFilter());
registration.addUrlPatterns("/statusChart.view", "/userChart.view", "/playQueue.view", "/podcastChannels.view", "/podcastChannel.view", "/help.view", "/top.view", "/home.view");
registration.addInitParameter("Cache-Control", "no-cache, post-check=0, pre-check=0");
registration.addInitParameter("Pragma", "no-cache");
registration.addInitParameter("Expires", "Thu, 01 Dec 1994 16:00:00 GMT");
registration.setName("NoCacheFilter");
registration.setOrder(6);
return registration;
}
@Bean
public Filter noCacheFilter() {
return new ResponseHeaderFilter();
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
// Customize the application or call application.sources(...) to add sources
// Since our example is itself a @Configuration class (via @SpringBootApplication)
// we actually don't need to override this method.
return application;
return application.sources(Application.class);
}
public static void main(String[] args) {
SpringApplication springApplication = new SpringApplication(Application.class);
springApplication.addInitializers(new AdditionalPropertySourceConfigurer());
springApplication.run(args);
new Application().configure(new SpringApplicationBuilder(Application.class))
.web(true)
.initializers(new AdditionalPropertySourceConfigurer())
.run(args);
}
}

@ -1,62 +1,29 @@
package org.libresonic.player.spring;
import liquibase.changelog.ChangeSet;
import liquibase.changelog.DatabaseChangeLog;
import liquibase.database.Database;
import liquibase.exception.PreconditionErrorException;
import liquibase.exception.PreconditionFailedException;
import liquibase.exception.ValidationErrors;
import liquibase.exception.Warnings;
import liquibase.precondition.Precondition;
import liquibase.serializer.AbstractLiquibaseSerializable;
import liquibase.exception.CustomPreconditionErrorException;
import liquibase.exception.CustomPreconditionFailedException;
import liquibase.exception.DatabaseException;
import liquibase.precondition.CustomPrecondition;
public class DbmsVersionPrecondition extends AbstractLiquibaseSerializable implements Precondition {
public class DbmsVersionPrecondition implements CustomPrecondition {
private Integer major;
private Integer minor;
@Override
public String getName() {
return "dbmsVersion";
}
@Override
public Warnings warn(Database database) {
return new Warnings();
}
@Override
public ValidationErrors validate(Database database) {
return new ValidationErrors();
}
@Override
public void check(
Database database, DatabaseChangeLog changeLog, ChangeSet changeSet
) throws PreconditionFailedException, PreconditionErrorException {
public void check(Database database) throws CustomPreconditionFailedException, CustomPreconditionErrorException {
try {
int dbMajor = database.getDatabaseMajorVersion();
int dbMinor = database.getDatabaseMinorVersion();
if(major != null && !major.equals(dbMajor)) {
throw new PreconditionFailedException("DBMS Major Version Precondition failed: expected " + major + ", got " + dbMajor, changeLog, this);
throw new CustomPreconditionFailedException("DBMS Major Version Precondition failed: expected " + major + ", got " + dbMajor);
}
if(minor != null && !minor.equals(dbMinor)) {
throw new PreconditionFailedException("DBMS Minor Version Precondition failed: expected " + minor + ", got " + dbMinor, changeLog, this);
}
} catch (PreconditionFailedException e) {
throw e;
} catch (Exception e) {
throw new PreconditionErrorException(e, changeLog, this);
throw new CustomPreconditionFailedException("DBMS Minor Version Precondition failed: expected " + minor + ", got " + dbMinor);
}
} catch (DatabaseException e) {
throw new CustomPreconditionErrorException(e.getMessage());
}
@Override
public String getSerializedObjectName() {
return getName();
}
@Override
public String getSerializedObjectNamespace() {
return GENERIC_CHANGELOG_EXTENSION_NAMESPACE;
}
public Integer getMajor() {
@ -74,4 +41,5 @@ public class DbmsVersionPrecondition extends AbstractLiquibaseSerializable imple
public void setMinor(Integer minor) {
this.minor = minor;
}
}

@ -51,7 +51,6 @@ public class SpringLiquibase extends liquibase.integration.spring.SpringLiquibas
if (StringUtils.trimToNull(this.defaultSchema) != null) {
database.setDefaultSchemaName(this.defaultSchema);
}
liquibase.precondition.PreconditionFactory.getInstance().register(DbmsVersionPrecondition.class);
return database;
}

@ -0,0 +1,3 @@
spring.mvc.view.prefix: /WEB-INF/jsp/
spring.mvc.view.suffix: .jsp
server.error.includeStacktrace: ALWAYS

@ -47,4 +47,6 @@
<property name="suffix" value=".jsp"/>
</bean>
<bean class="org.libresonic.player.spring.LoggingExceptionResolver" />
</beans>

@ -238,7 +238,7 @@
</customPrecondition>
<sqlCheck expectedResult="0">
select count(*) from INFORMATION_SCHEMA.SYSTEM_INDEXINFO where
TABLE_NAME = 'album' and INDEX_NAME = 'idx_album_name';
lower(TABLE_NAME) = 'album' and lower(INDEX_NAME) = 'idx_album_name';
</sqlCheck>
</preConditions>
<createIndex tableName="album" indexName="idx_album_name">

@ -39,7 +39,7 @@
</customPrecondition>
<sqlCheck expectedResult="0">
select count(*) from INFORMATION_SCHEMA.SYSTEM_INDEXINFO where
TABLE_NAME = 'podcast_episode' and INDEX_NAME = 'idx_podcast_episode_url';
lower(TABLE_NAME) = 'podcast_episode' and lower(INDEX_NAME) = 'idx_podcast_episode_url';
</sqlCheck>
</preConditions>
<createIndex tableName="podcast_episode" indexName="idx_podcast_episode_url">

@ -1,5 +1,7 @@
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="iso-8859-1" isErrorPage="true" %>
<%@ page import="java.io.PrintWriter, java.io.StringWriter"%>
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="UTF-8" isErrorPage="true" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html><head>
<!--[if lt IE 7.]>
@ -22,8 +24,6 @@
</p>
<%
StringWriter sw = new StringWriter();
exception.printStackTrace(new PrintWriter(sw));
long totalMemory = Runtime.getRuntime().totalMemory();
long freeMemory = Runtime.getRuntime().freeMemory();
@ -32,9 +32,7 @@
<table class="ruleTable indent">
<tr><td class="ruleTableHeader">Exception</td>
<td class="ruleTableCell"><%=exception.getClass().getName()%></td></tr>
<tr><td class="ruleTableHeader">Message</td>
<td class="ruleTableCell"><%=exception.getMessage()%></td></tr>
<td class="ruleTableCell"><c:out value="${exception}" /></td></tr>
<tr><td class="ruleTableHeader">Java version</td>
<td class="ruleTableCell"><%=System.getProperty("java.vendor") + ' ' + System.getProperty("java.version")%></td></tr>
<tr><td class="ruleTableHeader">Operating system</td>
@ -43,8 +41,16 @@
<td class="ruleTableCell"><%=application.getServerInfo()%></td></tr>
<tr><td class="ruleTableHeader">Memory</td>
<td class="ruleTableCell">Used <%=usedMemory/1024L/1024L%> of <%=totalMemory/1024L/1024L%> MB</td></tr>
<tr><td class="ruleTableHeader" style="vertical-align:top;">Stack trace</td>
<td class="ruleTableCell" style="white-space:pre"><%=sw.getBuffer()%></td></tr>
<c:if test="${not empty trace}">
<tr>
<td class="ruleTableHeader" style="vertical-align:top;">Stack trace</td>
<td class="ruleTableCell" style="white-space:pre">
<pre>
${fn:escapeXml(trace)}
</pre>
</td>
</tr>
</c:if>
</table>
</body>

@ -12,7 +12,7 @@
</head>
<body class="mainframe bgcolor1" onload="document.getElementById('j_username').focus()">
<form action="/login" method="POST">
<form action="<c:url value="/login"/>" method="POST">
<sec:csrfInput />
<div class="bgcolor2 shadow" align="center" style="padding:20px 50px 20px 50px; margin-top:100px;margin-left:50px;margin-right:50px">

@ -1,225 +0,0 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app id="libresonic" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>Libresonic Music Streamer</display-name>
<!-- Location of application context. Used by ContextLoaderListener. -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/applicationContext-service.xml
/WEB-INF/applicationContext-security.xml
/WEB-INF/applicationContext-cache.xml
/WEB-INF/applicationContext-sonos.xml
</param-value>
</context-param>
<context-param>
<param-name>contextInitializerClasses</param-name>
<param-value>org.libresonic.player.spring.AdditionalPropertySourceConfigurer</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>net.sf.ehcache.constructs.web.ShutdownListener</listener-class>
</listener>
<servlet>
<servlet-name>libresonic</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<display-name>CFX Servlet</display-name>
<servlet-name>cxfservlet</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<display-name>DWR Servlet</display-name>
<servlet-name>dwr-invoker</servlet-name>
<servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class>
<init-param>
<param-name>crossDomainSessionSecurity</param-name>
<param-value>false</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>libresonic</servlet-name>
<url-pattern>*.view</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>libresonic</servlet-name>
<url-pattern>/podcast</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>libresonic</servlet-name>
<url-pattern>/wap</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>libresonic</servlet-name>
<url-pattern>/play.m3u</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>libresonic</servlet-name>
<url-pattern>/stream/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>libresonic</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>libresonic</servlet-name>
<url-pattern>/hls/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>libresonic</servlet-name>
<url-pattern>/share/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>dwr-invoker</servlet-name>
<url-pattern>/dwr/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>cxfservlet</servlet-name>
<url-pattern>/ws/*</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<error-page>
<exception-type>java.lang.Throwable</exception-type>
<location>/error.jsp</location>
</error-page>
<filter>
<filter-name>BootstrapVerificationFilter</filter-name>
<filter-class>org.libresonic.player.filter.BootstrapVerificationFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>BootstrapVerificationFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>ParameterDecodingFilter</filter-name>
<filter-class>org.libresonic.player.filter.ParameterDecodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>ParameterDecodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>RESTFilter</filter-name>
<filter-class>org.libresonic.player.filter.RESTFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>RESTFilter</filter-name>
<url-pattern>/rest/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>RequestEncodingFilter</filter-name>
<filter-class>org.libresonic.player.filter.RequestEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>RequestEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<description>Sets HTTP headers to enable browser caching.</description>
<filter-name>CacheFilter</filter-name>
<filter-class>org.libresonic.player.filter.ResponseHeaderFilter</filter-class>
<init-param>
<param-name>Cache-Control</param-name>
<param-value>max-age=36000</param-value>
</init-param>
</filter>
<filter>
<description>Sets HTTP headers to disable browser caching.</description>
<filter-name>NoCacheFilter</filter-name>
<filter-class>org.libresonic.player.filter.ResponseHeaderFilter</filter-class>
<init-param>
<param-name>Cache-Control</param-name>
<param-value>no-cache, post-check=0, pre-check=0</param-value>
</init-param>
<init-param>
<param-name>Pragma</param-name>
<param-value>no-cache</param-value>
</init-param>
<init-param>
<param-name>Expires</param-name>
<param-value>Thu, 01 Dec 1994 16:00:00 GMT</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CacheFilter</filter-name>
<url-pattern>/icons/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>CacheFilter</filter-name>
<url-pattern>/style/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>NoCacheFilter</filter-name>
<url-pattern>/statusChart.view</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>NoCacheFilter</filter-name>
<url-pattern>/userChart.view</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>NoCacheFilter</filter-name>
<url-pattern>/playQueue.view</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>NoCacheFilter</filter-name>
<url-pattern>/podcastChannels.view</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>NoCacheFilter</filter-name>
<url-pattern>/podcastChannel.view</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>NoCacheFilter</filter-name>
<url-pattern>/help.view</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>NoCacheFilter</filter-name>
<url-pattern>/top.view</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>NoCacheFilter</filter-name>
<url-pattern>/home.view</url-pattern>
</filter-mapping>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>

@ -142,6 +142,12 @@
<artifactId>maven-jaxb2-plugin</artifactId>
<version>0.13.1</version>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
</pluginManagement>

Loading…
Cancel
Save