/*****************************************************************
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
****************************************************************/
package org.apache.cayenne.configuration.web;
import org.apache.cayenne.configuration.CayenneRuntime;
import org.apache.cayenne.configuration.server.ServerModule;
import org.apache.cayenne.configuration.server.ServerRuntime;
import org.apache.cayenne.di.Module;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
/**
* A filter that creates a Cayenne server runtime, possibly including custom modules. By
* default runtime includes {@link ServerModule} and {@link WebModule}. Any custom modules
* are loaded after the two standard ones to allow custom service overrides. Filter
* initialization parameters:
* <ul>
* <li>configuration-location - (optional) a name of Cayenne configuration XML file that
* will be used to load Cayenne stack. If missing, the filter name will be used to derive
* the location. ".xml" extension will be appended to the filter name to get the location,
* so a filter named "cayenne-foo" will result in location "cayenne-foo.xml".
* <li>extra-modules - (optional) a comma or space-separated list of class names, with
* each class implementing {@link Module} interface. These are the custom modules loaded
* after the two standard ones that allow users to override any Cayenne runtime aspects,
* e.g. {@link RequestHandler}. Each custom module must have a no-arg constructor.
* </ul>
* <p>
* CayenneFilter is a great utility to quickly start a Cayenne application. More advanced
* apps most likely will not use it, relying on their own configuration mechanism (such as
* Guice, Spring, etc.)
*
* @since 3.1
*/
public class CayenneFilter implements Filter {
protected ServletContext servletContext;
public void init(FilterConfig config) throws ServletException {
checkAlreadyConfigured(config.getServletContext());
this.servletContext = config.getServletContext();
WebConfiguration configAdapter = new WebConfiguration(config);
String configurationLocation = configAdapter.getConfigurationLocation();
Collection<Module> modules = configAdapter.createModules(new WebModule());
modules.addAll(getAdditionalModules());
ServerRuntime runtime = ServerRuntime.builder()
.addConfig(configurationLocation)
.addModules(modules).build();
WebUtil.setCayenneRuntime(config.getServletContext(), runtime);
}
/**
* Subclasses may override this to specify additional modules that should be included when creating the CayenneRuntime
* (in addition to those specified in the web.xml file).
*
* @since 4.0
*/
protected Collection<Module> getAdditionalModules() {
return new ArrayList<>();
}
protected void checkAlreadyConfigured(ServletContext context) throws ServletException {
// sanity check
if (WebUtil.getCayenneRuntime(context) != null) {
throw new ServletException(
"CayenneRuntime is already configured in the servlet environment");
}
}
public void destroy() {
CayenneRuntime runtime = WebUtil.getCayenneRuntime(servletContext);
if (runtime != null) {
runtime.shutdown();
}
}
public void doFilter(
ServletRequest request,
ServletResponse response,
FilterChain chain) throws IOException, ServletException {
CayenneRuntime runtime = WebUtil.getCayenneRuntime(servletContext);
RequestHandler handler = runtime.getInjector().getInstance(RequestHandler.class);
handler.requestStart(request, response);
try {
chain.doFilter(request, response);
}
finally {
handler.requestEnd(request, response);
}
}
}