001/* 002 * Licensed to DuraSpace under one or more contributor license agreements. 003 * See the NOTICE file distributed with this work for additional information 004 * regarding copyright ownership. 005 * 006 * DuraSpace licenses this file to you under the Apache License, 007 * Version 2.0 (the "License"); you may not use this file except in 008 * compliance with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.fcrepo.http.commons.test.util; 019 020import static org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory.createHttpServer; 021import static org.slf4j.LoggerFactory.getLogger; 022 023import java.net.URI; 024import java.util.Collection; 025 026import javax.annotation.PostConstruct; 027import javax.annotation.PreDestroy; 028import javax.xml.bind.JAXBContext; 029import javax.xml.bind.Unmarshaller; 030 031import com.google.common.base.Strings; 032import org.fcrepo.http.commons.webxml.WebAppConfig; 033import org.fcrepo.http.commons.webxml.bind.ContextParam; 034import org.fcrepo.http.commons.webxml.bind.Filter; 035import org.fcrepo.http.commons.webxml.bind.FilterMapping; 036import org.fcrepo.http.commons.webxml.bind.InitParam; 037import org.fcrepo.http.commons.webxml.bind.Listener; 038import org.fcrepo.http.commons.webxml.bind.Servlet; 039import org.fcrepo.http.commons.webxml.bind.ServletMapping; 040import org.glassfish.grizzly.http.server.HttpServer; 041import org.glassfish.grizzly.servlet.FilterRegistration; 042import org.glassfish.grizzly.servlet.ServletRegistration; 043import org.glassfish.grizzly.servlet.WebappContext; 044import org.slf4j.Logger; 045import org.springframework.beans.BeansException; 046import org.springframework.beans.factory.annotation.Value; 047import org.springframework.context.ApplicationContext; 048import org.springframework.context.ApplicationContextAware; 049import org.springframework.web.context.support.WebApplicationContextUtils; 050 051/** 052 * <p>ContainerWrapper class.</p> 053 * 054 * @author awoods 055 */ 056public class ContainerWrapper implements ApplicationContextAware { 057 058 private static final Logger logger = getLogger(ContainerWrapper.class); 059 060 private static final int DEFAULT_PORT = 8080; 061 062 @Value("${fcrepo.dynamic.test.port:" + DEFAULT_PORT + "}") 063 private String port; 064 065 private HttpServer server; 066 067 private WebappContext appContext; 068 069 private String configLocation; 070 071 public void setConfigLocation(final String configLocation) { 072 this.configLocation = configLocation.replaceFirst("^classpath:", "/"); 073 } 074 075 public void setPort(final int port) { 076 this.port = Integer.toString(port); 077 } 078 079 private int resolvePort() { 080 /* 081 This nonsense is necessary, rather than using @Value(${fcrepo.dynamic.test.port:8080}) because Intellij is 082 smart enough to attempt to set fcrepo.dynamic.test.port based on the pom but too dumb to run the 083 build-helper-maven-plugin plugin that actually determines its value. As a result, it's populated with an empty 084 value rather than null, and Spring will only default null property values. 085 */ 086 if (Strings.isNullOrEmpty(port)) { 087 return DEFAULT_PORT; 088 } 089 return Integer.parseInt(port); 090 } 091 092 @PostConstruct 093 public void start() throws Exception { 094 095 final JAXBContext context = JAXBContext.newInstance(WebAppConfig.class); 096 final Unmarshaller u = context.createUnmarshaller(); 097 final WebAppConfig o = 098 (WebAppConfig) u.unmarshal(getClass().getResource( 099 this.configLocation)); 100 101 final URI uri = URI.create("http://localhost:" + resolvePort()); 102 103 server = createHttpServer(uri); 104 105 // create a "root" web application 106 appContext = new WebappContext(o.displayName(), "/"); 107 108 for (final ContextParam p : o.contextParams()) { 109 appContext.addContextInitParameter(p.name(), p.value()); 110 } 111 112 for (final Listener l : o.listeners()) { 113 appContext.addListener(l.className()); 114 } 115 116 for (final Servlet s : o.servlets()) { 117 final ServletRegistration servlet = 118 appContext.addServlet(s.servletName(), s.servletClass()); 119 120 final Collection<ServletMapping> mappings = 121 o.servletMappings(s.servletName()); 122 for (final ServletMapping sm : mappings) { 123 servlet.addMapping(sm.urlPattern()); 124 } 125 for (final InitParam p : s.initParams()) { 126 servlet.setInitParameter(p.name(), p.value()); 127 } 128 } 129 130 for (final Filter f : o.filters()) { 131 final FilterRegistration filter = 132 appContext.addFilter(f.filterName(), f.filterClass()); 133 134 final Collection<FilterMapping> mappings = 135 o.filterMappings(f.filterName()); 136 for (final FilterMapping sm : mappings) { 137 final String urlPattern = sm.urlPattern(); 138 final String servletName = sm.servletName(); 139 if (urlPattern != null) { 140 filter.addMappingForUrlPatterns(null, urlPattern); 141 } else { 142 filter.addMappingForServletNames(null, servletName); 143 } 144 145 } 146 for (final InitParam p : f.initParams()) { 147 filter.setInitParameter(p.name(), p.value()); 148 } 149 } 150 151 appContext.deploy(server); 152 153 logger.debug("started grizzly webserver endpoint at " + 154 server.getHttpHandler().getName()); 155 } 156 157 @PreDestroy 158 public void stop() { 159 try { 160 appContext.undeploy(); 161 } catch (final Exception e) { 162 logger.warn(e.getMessage(), e); 163 } finally { 164 server.shutdownNow(); 165 } 166 } 167 168 public ApplicationContext getSpringAppContext() { 169 return WebApplicationContextUtils.findWebApplicationContext(appContext); 170 } 171 172 @Override 173 public void setApplicationContext(final ApplicationContext springAppContext) 174 throws BeansException { 175 } 176 177}