Precompile jsp

Signed-off-by: Andrew DeMaria <lostonamountain@gmail.com>
This commit is contained in:
Andrew DeMaria
2019-07-27 16:25:59 +00:00
committed by jvoisin
parent ff08f6dd02
commit e7bd5da6fa
8 changed files with 196 additions and 2 deletions
@@ -139,7 +139,7 @@ public class GlobalSecurityConfig extends GlobalAuthenticationConfigurerAdapter
// See: https://docs.spring.io/spring-security/site/docs/3.0.x/reference/remember-me.html
String rememberMeKey = settingsService.getRememberMeKey();
boolean development = settingsService.isDevelopmentMode();
boolean development = SettingsService.isDevelopmentMode();
if (StringUtils.isBlank(rememberMeKey) && !development) {
// ...if it is empty, generate a random key on startup (default).
logger.debug("Generating a new ephemeral 'remember me' key in a secure way.");
@@ -791,7 +791,7 @@ public class SettingsService {
*
* @return true if we are in Development mode.
*/
public boolean isDevelopmentMode() {
public static boolean isDevelopmentMode() {
return System.getProperty("airsonic.development") != null;
}
@@ -0,0 +1,73 @@
package org.airsonic.player.spring;
import org.airsonic.player.service.SettingsService;
import org.airsonic.player.spring.webxmldomain.ServletDef;
import org.airsonic.player.spring.webxmldomain.ServletMappingDef;
import org.airsonic.player.spring.webxmldomain.WebApp;
import org.apache.commons.io.IOUtils;
import org.apache.cxf.jaxb.JAXBDataBinding;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.web.servlet.ServletContextInitializer;
import org.springframework.stereotype.Component;
import javax.servlet.ServletContext;
import javax.servlet.ServletRegistration;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import java.io.InputStream;
import java.io.SequenceInputStream;
import java.nio.charset.Charset;
@Component
public class RegisterPrecompiledJSPInitializer implements ServletContextInitializer {
private static final Logger logger = LoggerFactory.getLogger(RegisterPrecompiledJSPInitializer.class);
@Override
public void onStartup(ServletContext servletContext) {
if(SettingsService.isDevelopmentMode()) {
logger.debug("Not registering precompiled jsps");
} else {
logger.debug("Registering precompiled jsps");
registerPrecompiledJSPs(servletContext);
}
}
private static void registerPrecompiledJSPs(ServletContext servletContext) {
WebApp webApp = parseXmlFragment();
for (ServletDef def : webApp.getServletDefs()) {
logger.trace("Registering precompiled JSP: {} -> {}", def.getName(), def.getSclass());
ServletRegistration.Dynamic reg = servletContext.addServlet(def.getName(), def.getSclass());
// Need to set loadOnStartup somewhere between 0 and 128. 0 is highest priority. 99 should be fine
reg.setLoadOnStartup(99);
}
for (ServletMappingDef mapping : webApp.getServletMappingDefs()) {
logger.trace("Mapping servlet: {} -> {}", mapping.getName(), mapping.getUrlPattern());
servletContext.getServletRegistration(mapping.getName()).addMapping(mapping.getUrlPattern());
}
}
private static WebApp parseXmlFragment() {
InputStream precompiledJspWebXml = RegisterPrecompiledJSPInitializer.class.getResourceAsStream("/precompiled-jsp-web.xml");
InputStream webXmlIS = new SequenceInputStream(
new SequenceInputStream(
IOUtils.toInputStream("<web-app>", Charset.defaultCharset()),
precompiledJspWebXml),
IOUtils.toInputStream("</web-app>", Charset.defaultCharset()));
JAXBContext jaxbContext;
try {
jaxbContext = new JAXBDataBinding(WebApp.class).getContext();
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
WebApp webapp = (WebApp) unmarshaller.unmarshal(webXmlIS);
return webapp;
} catch (JAXBException e) {
throw new RuntimeException("Could not parse precompiled-jsp-web.xml", e);
}
}
}
@@ -0,0 +1,32 @@
package org.airsonic.player.spring.webxmldomain;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class ServletDef {
@XmlElement(name="servlet-name")
private String name;
@XmlElement(name="servlet-class")
private String sclass;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSclass() {
return sclass;
}
public void setSclass(String sclass) {
this.sclass = sclass;
}
}
@@ -0,0 +1,33 @@
package org.airsonic.player.spring.webxmldomain;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class ServletMappingDef {
@XmlElement(name="servlet-name")
private String name;
@XmlElement(name="url-pattern")
private String urlPattern;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUrlPattern() {
return urlPattern;
}
public void setUrlPattern(String urlPattern) {
this.urlPattern = urlPattern;
}
}
@@ -0,0 +1,34 @@
package org.airsonic.player.spring.webxmldomain;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import java.util.List;
@XmlRootElement(name="web-app")
@XmlAccessorType(XmlAccessType.FIELD)
public class WebApp {
@XmlElement(name="servlet")
private List<ServletDef> servletDefs;
@XmlElement(name="servlet-mapping")
private List<ServletMappingDef> servletMappingDefs;
public List<ServletDef> getServletDefs() {
return servletDefs;
}
public void setServletDefs(List<ServletDef> servletDefs) {
this.servletDefs = servletDefs;
}
public List<ServletMappingDef> getServletMappingDefs() {
return servletMappingDefs;
}
public void setServletMappingDefs(List<ServletMappingDef> servletMappingDefs) {
this.servletMappingDefs = servletMappingDefs;
}
}