package at.gv.egiz.eaaf.utils.springboot.ajp; import java.io.File; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.Map; import org.apache.catalina.connector.Connector; import org.apache.commons.lang3.StringUtils; import org.apache.coyote.AbstractProtocol; import org.apache.coyote.ProtocolHandler; import org.apache.coyote.ajp.AbstractAjpProtocol; import org.apache.tomcat.util.net.NioChannel; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; import at.gv.egiz.eaaf.utils.springboot.ajp.logging.LoggingProperties; import at.gv.egiz.eaaf.utils.springboot.ajp.logging.MdcEnhancerFilter; import ch.qos.logback.access.tomcat.LogbackValve; import lombok.extern.slf4j.Slf4j; @Slf4j @Configuration @EnableConfigurationProperties(value = {LoggingProperties.class, TomcatProperties.class}) @PropertySource("classpath:tomcat.properties") @PropertySource(value = "classpath:tomcat-${spring.profiles.active}.properties", ignoreResourceNotFound = true) public class TomcatAjpConfiguration { private static final String PROTOCOL = "AJP/1.3"; @Autowired private LoggingProperties loggingProperties; @Autowired private TomcatProperties tomcatProperties; @Value("${tomcat.workingdir:./work}") String tomcatWorkDirectory; /** * Set MDC variables for embedded Tomcat access-logging. * * @param filter {@link MdcEnhancerFilter} that injects MDS variables * @return */ @Bean public FilterRegistrationBean enhacedMdcFilter(@Autowired MdcEnhancerFilter filter) { FilterRegistrationBean registration = new FilterRegistrationBean<>(filter); registration.setEnabled(loggingProperties.getMdc().isEnabled()); return registration; } /** * Adds AJP Connector to embedded Tomcat. * * @return */ @Bean public TomcatServletWebServerFactory servletContainer() { final TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory(); //set working directory final File workDirFile = new File(tomcatWorkDirectory); checkBasekDirectory(workDirFile); tomcat.setBaseDirectory(workDirFile); log.info("Set embedded Tomcat workingDirectory to: {}", workDirFile.getAbsolutePath()); //set logger configuration if (loggingProperties.getAccessLog().isEnabled()) { LogbackValve valve = new LogbackValve(); valve.setFilename(loggingProperties.getAccessLog().getFilename()); tomcat.addEngineValves(valve); } final TomcatProperties.Ajp ajp = tomcatProperties.getAjp(); if (ajp != null && ajp.isEnabled()) { final Connector ajpConnector = new Connector(PROTOCOL); ajpConnector.setPort(ajp.getPort()); ajpConnector.setSecure(ajp.isSecure()); ajpConnector.setAllowTrace(ajp.isAllowTrace()); ajpConnector.setScheme(ajp.getScheme()); setNetworkAddress(ajpConnector.getProtocolHandler(), ajp.getNetworkAddress()); if (ajp.getAdditionalAttributes() != null) { for (final Map.Entry entry : ajp.getAdditionalAttributes().entrySet()) { log.debug("Set Tomcat AJP property: {} with value: {}", entry.getKey(), entry.getValue()); ajpConnector.setAttribute(entry.getKey(), entry.getValue()); } } log.debug("AJP connector requires secret: {}", ((AbstractAjpProtocol) ajpConnector.getProtocolHandler()).getSecretRequired()); tomcat.addAdditionalTomcatConnectors(ajpConnector); } return tomcat; } private void setNetworkAddress(ProtocolHandler protocolHandler, String address) { log.trace("Set network address: {} to ProtocolHandler: {}", address, protocolHandler.getClass().getName()); if (StringUtils.isNotEmpty(address) && protocolHandler instanceof AbstractProtocol) { try { ((AbstractProtocol) protocolHandler).setAddress(InetAddress.getByName(address)); log.info("Bind connector: {} to address: {}", PROTOCOL, address); } catch (UnknownHostException e) { log.error("Can NOT set network address: {} to connector: {}", address, PROTOCOL); } } else { log.debug("Bind connector: {} to default address", PROTOCOL); } } private void checkBasekDirectory(File workDirFile) { if (!workDirFile.exists()) { log.debug("Embedded Tomcat workingDirectory: {} not exist. Create it ... ", workDirFile.getAbsolutePath()); if (workDirFile.mkdirs()) { log.info("Embedded Tomcat workingDirectory created"); } } if (!workDirFile.isDirectory()) { log.error("Path to embedded Tomcat workingDirectory: {} is NOT directory", workDirFile.getAbsolutePath()); } } }