/*
* Copyright (C) 2014 Civilian Framework.
*
* Licensed under the Civilian License (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.civilian-framework.org/license.txt
*
* 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.civilian.context.servlet;
import java.io.IOException;
import java.util.Iterator;
import javax.servlet.MultipartConfigElement;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletRegistration;
import org.civilian.Application;
import org.civilian.Context;
import org.civilian.application.UploadConfig;
import org.civilian.content.ContentTypeLookup;
import org.civilian.internal.Logs;
import org.civilian.resource.Path;
import org.civilian.util.ClassUtil;
import org.civilian.util.Iterators;
import org.civilian.util.ResourceLoader;
import org.civilian.util.Settings;
import org.civilian.util.StringUtil;
/**
* A Context implementation which wraps a javax.servlet.ServletContext.
*/
class ServletContextAdapter extends Context
{
/**
* The parameter name in web.xml to overwrite the name of
* the Civilian config file.
*/
public static final String CONFIG_PARAM = "civilian-config";
/**
* Returns the ServletContextAdapter instance associated with the ServletContext.
*/
public static ServletContextAdapter getInstance(ServletContext context)
{
return (ServletContextAdapter)context.getAttribute(ServletContextAdapter.class.getName());
}
//----------------------
// init
//----------------------
/**
* Creates a ServletContextAdapter.
*/
public ServletContextAdapter(ServletContext servletContext)
{
servletContext_ = servletContext;
servletContext_.setAttribute(getClass().getName(), this);
path_ = new Path(servletContext_.getContextPath());
resourceLoader_ = ResourceLoader.builder.forSerlvetContext(servletContext);
contentTypeLookup_ = ContentTypeLookup.forServletContext(servletContext);
try
{
// a servlet context param may override the name of the config file
Settings settings = readSettings();
init(getClass().getClassLoader(), settings);
}
catch (Exception e)
{
Logs.CONTEXT.error("could not initialize", e);
close();
}
}
private Settings readSettings() throws IOException
{
// a servlet context param may override the name of the config file
String paramName = servletContext_.getInitParameter(CONFIG_PARAM);
String configName = paramName != null ? paramName : DEFAULT_CONFIG_FILE;
return readSettings(configName);
}
/**
* Creates and returns the AppServlet of an application.
*/
@Override protected Object connect(Application app, boolean supportAsync)
{
AppServlet servlet = new AppServlet(app);
ServletRegistration.Dynamic registration = servletContext_.addServlet("civilian.AppServlet-" + app.getId(), servlet);
registration.addMapping(app.getRelativePath().add("/*").toString());
registration.setAsyncSupported(supportAsync);
UploadConfig uc = app.getUploadConfig();
if (uc.isEnabled())
{
registration.setMultipartConfig(new MultipartConfigElement(
uc.getTempDirectory(),
uc.getMaxFileSize(),
uc.getMaxRequestSize(),
uc.getFileSizeThreshold())
);
}
return servlet;
}
/**
* The servlet api does not allow to remove the servlet.
* but we stop serving requests.
*/
@Override protected void disconnect(Application app)
{
AppServlet servlet = app.getConnector(AppServlet.class);
if (servlet != null)
servlet.close();
}
//----------------------
// close
//----------------------
/**
* Called by the servlet context listener when the servlet context is getting destroyed.
*/
void contextDestroyed(ServletContextEvent event)
{
close();
servletContext_ = null;
}
//-----------------------------------------------------------------
// implementation of Context API using the ServletContext
//-----------------------------------------------------------------
/**
* Forwards to the ServletContext.
*/
@Override public String getServerVersion()
{
return servletContext_.getMajorVersion() + "." + servletContext_.getMinorVersion();
}
/**
* Returns ServletContext#getServerInfo()
*/
@Override public String getServerInfo()
{
return servletContext_.getServerInfo();
}
/**
* Returns the path of the servlet context.
*/
@Override public Path getPath()
{
return path_;
}
/**
* Returns a ResourceLoader based on ServletContext#getResource().
*/
@Override public ResourceLoader getResourceLoader()
{
return resourceLoader_;
}
/**
* Returns a ContentTypeLookup to translate file names into content types.
*/
@Override public ContentTypeLookup getContentTypeLookup()
{
return contentTypeLookup_;
}
/**
* Logs to ServletContext#log
*/
@Override public void log(String msg, Throwable error)
{
if ((msg != null) || (error != null))
{
if (msg == null)
msg = "error";
if (error == null)
servletContext_.log(msg);
else
servletContext_.log(msg, error);
}
}
/**
* Returns ServletContext#getAttribute(String)
*/
@Override public Object getAttribute(String name)
{
return servletContext_.getAttribute(name);
}
/**
* Returns an iterator of the attribute names stored in the context.
*/
@Override public Iterator<String> getAttributeNames()
{
return Iterators.asIterator(servletContext_.getAttributeNames());
}
/**
* Calls ServletContext#getAttribute(String)
*/
@Override public void setAttribute(String name, Object object)
{
servletContext_.setAttribute(name, object);
}
/**
* Returns the servlet context if you pass ServletContext.class
*/
@Override public <T> T unwrap(Class<T> implClass)
{
return ClassUtil.unwrap(servletContext_, implClass);
}
/**
* Returns if the given path contains WEB-INF or META-INF.
*/
@Override public boolean isProhibitedPath(String path)
{
return ServletUtil.isProhibitedPath(path);
}
/**
* Calls ServletContext#getRealPath(String).
*/
@Override public String getRealPath(String path)
{
return servletContext_.getRealPath(path);
}
/**
* Prefixes the path to start with "/WEB-INF/".
*/
@Override public String getConfigPath(String path)
{
path = StringUtil.haveLeft(path, "/");
if (!path.startsWith("/WEB-INF/"))
path = "/WEB-INF" + path;
return path;
}
private Path path_;
private ServletContext servletContext_;
private ResourceLoader resourceLoader_;
private ContentTypeLookup contentTypeLookup_;
}