New Configuration structure. This structure will be modified in jetty-8 to accommodate servlet spec3. This checkin moves jetty-7 closer to that final structure. Configuration now consists of 3 phases: preConfigure(), configure() and postConfigure(). All Configurations can now be chained together rather than having to override/replace existing Configurations.
git-svn-id: svn+ssh://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/trunk@230 7e9141cc-0065-0410-87d8-b60c137991c4
This commit is contained in:
parent
c236945c53
commit
688fbac7aa
|
@ -141,7 +141,7 @@ public class AnnotationProcessor
|
|||
{
|
||||
for (Class clazz:_finder.getClassesForAnnotation(RunAs.class))
|
||||
{
|
||||
if (!javax.servlet.Servlet.class.isAssignableFrom(clazz) && !(_pojoInstances.containsKey(clazz)))
|
||||
if (!javax.servlet.Servlet.class.isAssignableFrom(clazz))
|
||||
{
|
||||
Log.debug("Ignoring runAs notation on on-servlet class "+clazz.getName());
|
||||
continue;
|
||||
|
@ -611,8 +611,7 @@ public class AnnotationProcessor
|
|||
javax.servlet.ServletRequestListener.class.isAssignableFrom(c) ||
|
||||
javax.servlet.ServletRequestAttributeListener.class.isAssignableFrom(c) ||
|
||||
javax.servlet.http.HttpSessionListener.class.isAssignableFrom(c) ||
|
||||
javax.servlet.http.HttpSessionAttributeListener.class.isAssignableFrom(c) ||
|
||||
(_pojoInstances.get(c) != null))
|
||||
javax.servlet.http.HttpSessionAttributeListener.class.isAssignableFrom(c))
|
||||
|
||||
isServlet=true;
|
||||
|
||||
|
@ -620,26 +619,7 @@ public class AnnotationProcessor
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get an already-created instance of a pojo, or create one
|
||||
* otherwise.
|
||||
* @param clazz
|
||||
* @return
|
||||
* @throws InstantiationException
|
||||
* @throws IllegalAccessException
|
||||
*/
|
||||
private Object getPojoInstanceFor (Class clazz)
|
||||
throws InstantiationException, IllegalAccessException
|
||||
{
|
||||
Object instance = _pojoInstances.get(clazz);
|
||||
if (instance == null)
|
||||
{
|
||||
instance = clazz.newInstance();
|
||||
_pojoInstances.put(clazz, instance);
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
|
||||
private static boolean isEnvEntryType (Class type)
|
||||
{
|
||||
boolean result = false;
|
||||
|
|
|
@ -14,13 +14,17 @@
|
|||
package org.eclipse.jetty.annotations;
|
||||
|
||||
import java.util.EventListener;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jetty.plus.servlet.ServletHandler;
|
||||
import org.eclipse.jetty.security.SecurityHandler;
|
||||
import org.eclipse.jetty.servlet.FilterHolder;
|
||||
import org.eclipse.jetty.servlet.FilterMapping;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.eclipse.jetty.servlet.ServletMapping;
|
||||
import org.eclipse.jetty.util.LazyList;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
|
||||
/**
|
||||
* Configuration
|
||||
|
@ -42,7 +46,7 @@ public class Configuration extends org.eclipse.jetty.plus.webapp.Configuration
|
|||
/**
|
||||
* @see org.eclipse.jetty.plus.webapp.AbstractConfiguration#parseAnnotations()
|
||||
*/
|
||||
public void parseAnnotations() throws Exception
|
||||
public void parseAnnotations(final WebAppContext context) throws Exception
|
||||
{
|
||||
/*
|
||||
* TODO Need to also take account of hidden classes on system classpath that should never
|
||||
|
@ -67,20 +71,20 @@ public class Configuration extends org.eclipse.jetty.plus.webapp.Configuration
|
|||
|
||||
//if no pattern for the container path is defined, then by default scan NOTHING
|
||||
Log.debug("Scanning system jars");
|
||||
finder.find(getWebAppContext().getClassLoader().getParent(), true, getWebAppContext().getInitParameter(__container_pattern), false,
|
||||
finder.find(context.getClassLoader().getParent(), true, context.getInitParameter(__container_pattern), false,
|
||||
new ClassNameResolver ()
|
||||
{
|
||||
public boolean isExcluded (String name)
|
||||
{
|
||||
if (getWebAppContext().isSystemClass(name)) return false;
|
||||
if (getWebAppContext().isServerClass(name)) return true;
|
||||
if (context.isSystemClass(name)) return false;
|
||||
if (context.isServerClass(name)) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean shouldOverride (String name)
|
||||
{
|
||||
//looking at system classpath
|
||||
if (getWebAppContext().isParentLoaderPriority())
|
||||
if (context.isParentLoaderPriority())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
@ -88,58 +92,67 @@ public class Configuration extends org.eclipse.jetty.plus.webapp.Configuration
|
|||
|
||||
Log.debug("Scanning WEB-INF/lib jars");
|
||||
//if no pattern for web-inf/lib is defined, then by default scan everything in it
|
||||
finder.find (getWebAppContext().getClassLoader(), false, getWebAppContext().getInitParameter(__web_inf_pattern), true,
|
||||
finder.find (context.getClassLoader(), false, context.getInitParameter(__web_inf_pattern), true,
|
||||
new ClassNameResolver()
|
||||
{
|
||||
public boolean isExcluded (String name)
|
||||
{
|
||||
if (getWebAppContext().isSystemClass(name)) return true;
|
||||
if (getWebAppContext().isServerClass(name)) return false;
|
||||
if (context.isSystemClass(name)) return true;
|
||||
if (context.isServerClass(name)) return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean shouldOverride (String name)
|
||||
{
|
||||
//looking at webapp classpath, found already-parsed class of same name - did it come from system or duplicate in webapp?
|
||||
if (getWebAppContext().isParentLoaderPriority())
|
||||
if (context.isParentLoaderPriority())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
Log.debug("Scanning classes in WEB-INF/classes");
|
||||
finder.find(_context.getWebInf().addPath("classes/"),
|
||||
finder.find(context.getWebInf().addPath("classes/"),
|
||||
new ClassNameResolver()
|
||||
{
|
||||
public boolean isExcluded (String name)
|
||||
{
|
||||
if (getWebAppContext().isSystemClass(name)) return true;
|
||||
if (getWebAppContext().isServerClass(name)) return false;
|
||||
if (context.isSystemClass(name)) return true;
|
||||
if (context.isServerClass(name)) return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean shouldOverride (String name)
|
||||
{
|
||||
//looking at webapp classpath, found already-parsed class of same name - did it come from system or duplicate in webapp?
|
||||
if (getWebAppContext().isParentLoaderPriority())
|
||||
if (context.isParentLoaderPriority())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
AnnotationProcessor processor = new AnnotationProcessor(getWebAppContext(), finder, _runAsCollection, _injections, _callbacks,
|
||||
LazyList.getList(_servlets), LazyList.getList(_filters), LazyList.getList(_listeners),
|
||||
LazyList.getList(_servletMappings), LazyList.getList(_filterMappings));
|
||||
ServletHandler servletHandler = (ServletHandler)context.getServletHandler();
|
||||
List filters = LazyList.array2List(servletHandler.getFilters());
|
||||
List filterMappings = LazyList.array2List(servletHandler.getFilterMappings());
|
||||
List servlets = LazyList.array2List(servletHandler.getServlets());
|
||||
List servletMappings = LazyList.array2List(servletHandler.getServletMappings());
|
||||
List listeners = LazyList.array2List(context.getEventListeners());
|
||||
|
||||
AnnotationProcessor processor = new AnnotationProcessor(context, finder, _runAsCollection, _injections, _callbacks,
|
||||
servlets, filters,listeners,
|
||||
servletMappings, filterMappings);
|
||||
processor.process();
|
||||
_servlets = processor.getServlets();
|
||||
_filters = processor.getFilters();
|
||||
_servletMappings = processor.getServletMappings();
|
||||
_filterMappings = processor.getFilterMappings();
|
||||
_listeners = processor.getListeners();
|
||||
_servletHandler.setFilters((FilterHolder[])LazyList.toArray(_filters,FilterHolder.class));
|
||||
_servletHandler.setFilterMappings((FilterMapping[])LazyList.toArray(_filterMappings,FilterMapping.class));
|
||||
_servletHandler.setServlets((ServletHolder[])LazyList.toArray(_servlets,ServletHolder.class));
|
||||
_servletHandler.setServletMappings((ServletMapping[])LazyList.toArray(_servletMappings,ServletMapping.class));
|
||||
getWebAppContext().setEventListeners((EventListener[])LazyList.toArray(_listeners,EventListener.class));
|
||||
|
||||
servlets = processor.getServlets();
|
||||
filters = processor.getFilters();
|
||||
servletMappings = processor.getServletMappings();
|
||||
filterMappings = processor.getFilterMappings();
|
||||
listeners = processor.getListeners();
|
||||
|
||||
servletHandler.setFilters((FilterHolder[])LazyList.toArray(filters,FilterHolder.class));
|
||||
servletHandler.setFilterMappings((FilterMapping[])LazyList.toArray(filterMappings,FilterMapping.class));
|
||||
servletHandler.setServlets((ServletHolder[])LazyList.toArray(servlets,ServletHolder.class));
|
||||
servletHandler.setServletMappings((ServletMapping[])LazyList.toArray(servletMappings,ServletMapping.class));
|
||||
context.setEventListeners((EventListener[])LazyList.toArray(listeners,EventListener.class));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,6 +42,9 @@
|
|||
<!-- =========================================================== -->
|
||||
<Array id="plusConfig" type="java.lang.String">
|
||||
<Item>org.eclipse.jetty.webapp.WebInfConfiguration</Item>
|
||||
<Item>org.eclipse.jetty.webapp.WebXmlConfiguration</Item>
|
||||
<Item>org.eclipse.jetty.webapp.MetaInfConfiguration</Item>
|
||||
<Item>org.eclipse.jetty.webapp.FragmentConfiguration</Item>
|
||||
<Item>org.eclipse.jetty.plus.webapp.EnvConfiguration</Item>
|
||||
<Item>org.eclipse.jetty.plus.webapp.Configuration</Item>
|
||||
<Item>org.eclipse.jetty.webapp.JettyWebXmlConfiguration</Item>
|
||||
|
|
|
@ -201,6 +201,7 @@ public abstract class NamingEntry
|
|||
objectName.addAll(0, prefix);
|
||||
objectNameString = objectName.toString();
|
||||
NamingUtil.bind(ic, objectNameString, objectToBind);
|
||||
System.err.println("Bound: "+objectName.toString()+" to "+objectToBind);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -239,7 +239,7 @@ public class NamingEntryUtil
|
|||
if (scope==null)
|
||||
return "";
|
||||
|
||||
String str = scope.toString();
|
||||
String str = scope.getClass().getName()+"@"+scope.hashCode();
|
||||
str=str.replace('/', '_').replace(' ', '_');
|
||||
return str;
|
||||
}
|
||||
|
|
|
@ -31,8 +31,10 @@ import org.eclipse.jetty.security.SecurityHandler;
|
|||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.eclipse.jetty.util.TypeUtil;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.webapp.Configuration;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
import org.eclipse.jetty.webapp.WebXmlConfiguration;
|
||||
import org.eclipse.jetty.webapp.WebXmlProcessor;
|
||||
import org.eclipse.jetty.xml.XmlParser;
|
||||
|
||||
|
||||
|
@ -42,22 +44,348 @@ import org.eclipse.jetty.xml.XmlParser;
|
|||
*
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractConfiguration extends WebXmlConfiguration
|
||||
public abstract class AbstractConfiguration implements Configuration
|
||||
{
|
||||
protected LifeCycleCallbackCollection _callbacks = new LifeCycleCallbackCollection();
|
||||
protected InjectionCollection _injections = new InjectionCollection();
|
||||
protected RunAsCollection _runAsCollection = new RunAsCollection();
|
||||
protected SecurityHandler _securityHandler;
|
||||
|
||||
public abstract void bindEnvEntry (String name, Object value) throws Exception;
|
||||
public abstract void bindEnvEntry (WebAppContext context, String name, Object value) throws Exception;
|
||||
|
||||
public abstract void bindResourceRef (String name, Class type) throws Exception;
|
||||
public abstract void bindResourceRef (WebAppContext context, String name, Class type) throws Exception;
|
||||
|
||||
public abstract void bindResourceEnvRef (String name, Class type) throws Exception;
|
||||
public abstract void bindResourceEnvRef (WebAppContext context, String name, Class type) throws Exception;
|
||||
|
||||
public abstract void bindUserTransaction () throws Exception;
|
||||
public abstract void bindUserTransaction (WebAppContext context) throws Exception;
|
||||
|
||||
public abstract void bindMessageDestinationRef (WebAppContext context, String name, Class type) throws Exception;
|
||||
|
||||
protected abstract void parseAnnotations (WebAppContext context) throws Exception;
|
||||
|
||||
|
||||
public class PlusWebXmlProcessor
|
||||
{
|
||||
WebAppContext _context;
|
||||
|
||||
public PlusWebXmlProcessor (WebAppContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
|
||||
public void process (XmlParser.Node root)
|
||||
throws Exception
|
||||
{
|
||||
if (root == null)
|
||||
return;
|
||||
|
||||
|
||||
Iterator iter = root.iterator();
|
||||
XmlParser.Node node = null;
|
||||
while (iter.hasNext())
|
||||
{
|
||||
try
|
||||
{
|
||||
Object o = iter.next();
|
||||
if (!(o instanceof XmlParser.Node)) continue;
|
||||
node = (XmlParser.Node) o;
|
||||
String name = node.getTag();
|
||||
initWebXmlElement(name, node);
|
||||
}
|
||||
catch (ClassNotFoundException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.warn("Configuration problem at " + node, e);
|
||||
throw new UnavailableException("Configuration problem");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void initWebXmlElement(String element,XmlParser.Node node) throws Exception
|
||||
{
|
||||
if ("env-entry".equals(element))
|
||||
{
|
||||
initEnvEntry (node);
|
||||
}
|
||||
else if ("resource-ref".equals(element))
|
||||
{
|
||||
//resource-ref entries are ONLY for connection factories
|
||||
//the resource-ref says how the app will reference the jndi lookup relative
|
||||
//to java:comp/env, but it is up to the deployer to map this reference to
|
||||
//a real resource in the environment. At the moment, we insist that the
|
||||
//jetty.xml file name of the resource has to be exactly the same as the
|
||||
//name in web.xml deployment descriptor, but it shouldn't have to be
|
||||
initResourceRef(node);
|
||||
}
|
||||
else if ("resource-env-ref".equals(element))
|
||||
{
|
||||
//resource-env-ref elements are a non-connection factory type of resource
|
||||
//the app looks them up relative to java:comp/env
|
||||
//again, need a way for deployer to link up app naming to real naming.
|
||||
//Again, we insist now that the name of the resource in jetty.xml is
|
||||
//the same as web.xml
|
||||
initResourceEnvRef(node);
|
||||
}
|
||||
else if ("message-destination-ref".equals(element))
|
||||
{
|
||||
initMessageDestinationRef(node);
|
||||
}
|
||||
else if ("post-construct".equals(element))
|
||||
{
|
||||
//post-construct is the name of a class and method to call after all
|
||||
//resources have been setup but before the class is put into use
|
||||
initPostConstruct(node);
|
||||
}
|
||||
else if ("pre-destroy".equals(element))
|
||||
{
|
||||
//pre-destroy is the name of a class and method to call just as
|
||||
//the instance is being destroyed
|
||||
initPreDestroy(node);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* JavaEE 5.4.1.3
|
||||
*
|
||||
*
|
||||
* @param node
|
||||
* @throws Exception
|
||||
*/
|
||||
protected void initEnvEntry (XmlParser.Node node)
|
||||
throws Exception
|
||||
{
|
||||
String name=node.getString("env-entry-name",false,true);
|
||||
String type = node.getString("env-entry-type",false,true);
|
||||
String valueStr = node.getString("env-entry-value",false,true);
|
||||
|
||||
//if there's no value there's no point in making a jndi entry
|
||||
//nor processing injection entries
|
||||
if (valueStr==null || valueStr.equals(""))
|
||||
{
|
||||
Log.warn("No value for env-entry-name "+name);
|
||||
return;
|
||||
}
|
||||
|
||||
//the javaee_5.xsd says that the env-entry-type is optional
|
||||
//if there is an <injection> element, because you can get
|
||||
//type from the element, but what to do if there is more
|
||||
//than one <injection> element, do you just pick the type
|
||||
//of the first one?
|
||||
|
||||
//check for <injection> elements
|
||||
initInjection (node, name, TypeUtil.fromName(type));
|
||||
|
||||
//bind the entry into jndi
|
||||
Object value = TypeUtil.valueOf(type,valueStr);
|
||||
bindEnvEntry(_context, name, value);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Common Annotations Spec section 2.3:
|
||||
* resource-ref is for:
|
||||
* - javax.sql.DataSource
|
||||
* - javax.jms.ConnectionFactory
|
||||
* - javax.jms.QueueConnectionFactory
|
||||
* - javax.jms.TopicConnectionFactory
|
||||
* - javax.mail.Session
|
||||
* - java.net.URL
|
||||
* - javax.resource.cci.ConnectionFactory
|
||||
* - org.omg.CORBA_2_3.ORB
|
||||
* - any other connection factory defined by a resource adapter
|
||||
* @param node
|
||||
* @throws Exception
|
||||
*/
|
||||
protected void initResourceRef (XmlParser.Node node)
|
||||
throws Exception
|
||||
{
|
||||
String jndiName = node.getString("res-ref-name",false,true);
|
||||
String type = node.getString("res-type", false, true);
|
||||
String auth = node.getString("res-auth", false, true);
|
||||
String shared = node.getString("res-sharing-scope", false, true);
|
||||
|
||||
//check for <injection> elements
|
||||
Class typeClass = TypeUtil.fromName(type);
|
||||
if (typeClass==null)
|
||||
typeClass = _context.loadClass(type);
|
||||
initInjection (node, jndiName, typeClass);
|
||||
|
||||
bindResourceRef(_context, jndiName, typeClass);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Common Annotations Spec section 2.3:
|
||||
* resource-env-ref is for:
|
||||
* - javax.transaction.UserTransaction
|
||||
* - javax.resource.cci.InteractionSpec
|
||||
* - anything else that is not a connection factory
|
||||
* @param node
|
||||
* @throws Exception
|
||||
*/
|
||||
protected void initResourceEnvRef (XmlParser.Node node)
|
||||
throws Exception
|
||||
{
|
||||
String jndiName = node.getString("resource-env-ref-name",false,true);
|
||||
String type = node.getString("resource-env-ref-type", false, true);
|
||||
|
||||
//check for <injection> elements
|
||||
|
||||
//JavaEE Spec sec 5.7.1.3 says the resource-env-ref-type
|
||||
//is mandatory, but the schema says it is optional!
|
||||
Class typeClass = TypeUtil.fromName(type);
|
||||
if (typeClass==null)
|
||||
typeClass = _context.loadClass(type);
|
||||
initInjection (node, jndiName, typeClass);
|
||||
|
||||
bindResourceEnvRef(_context, jndiName, typeClass);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Common Annotations Spec section 2.3:
|
||||
* message-destination-ref is for:
|
||||
* - javax.jms.Queue
|
||||
* - javax.jms.Topic
|
||||
* @param node
|
||||
* @throws Exception
|
||||
*/
|
||||
protected void initMessageDestinationRef (XmlParser.Node node)
|
||||
throws Exception
|
||||
{
|
||||
String jndiName = node.getString("message-destination-ref-name",false,true);
|
||||
String type = node.getString("message-destination-type",false,true);
|
||||
String usage = node.getString("message-destination-usage",false,true);
|
||||
|
||||
Class typeClass = TypeUtil.fromName(type);
|
||||
if (typeClass==null)
|
||||
typeClass = _context.loadClass(type);
|
||||
initInjection(node, jndiName, typeClass);
|
||||
|
||||
bindMessageDestinationRef(_context, jndiName, typeClass);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Process <post-construct>
|
||||
* @param node
|
||||
*/
|
||||
protected void initPostConstruct(XmlParser.Node node)
|
||||
{
|
||||
String className = node.getString("lifecycle-callback-class", false, true);
|
||||
String methodName = node.getString("lifecycle-callback-method", false, true);
|
||||
|
||||
if (className==null || className.equals(""))
|
||||
{
|
||||
Log.warn("No lifecycle-callback-class specified");
|
||||
return;
|
||||
}
|
||||
if (methodName==null || methodName.equals(""))
|
||||
{
|
||||
Log.warn("No lifecycle-callback-method specified for class "+className);
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Class clazz = _context.loadClass(className);
|
||||
LifeCycleCallback callback = new PostConstructCallback();
|
||||
callback.setTarget(clazz, methodName);
|
||||
_callbacks.add(callback);
|
||||
}
|
||||
catch (ClassNotFoundException e)
|
||||
{
|
||||
Log.warn("Couldn't load post-construct target class "+className);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Process <pre-destroy>
|
||||
* @param node
|
||||
*/
|
||||
protected void initPreDestroy(XmlParser.Node node)
|
||||
{
|
||||
String className = node.getString("lifecycle-callback-class", false, true);
|
||||
String methodName = node.getString("lifecycle-callback-method", false, true);
|
||||
if (className==null || className.equals(""))
|
||||
{
|
||||
Log.warn("No lifecycle-callback-class specified for pre-destroy");
|
||||
return;
|
||||
}
|
||||
if (methodName==null || methodName.equals(""))
|
||||
{
|
||||
Log.warn("No lifecycle-callback-method specified for pre-destroy class "+className);
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Class clazz = _context.loadClass(className);
|
||||
LifeCycleCallback callback = new PreDestroyCallback();
|
||||
callback.setTarget(clazz, methodName);
|
||||
_callbacks.add(callback);
|
||||
}
|
||||
catch (ClassNotFoundException e)
|
||||
{
|
||||
Log.warn("Couldn't load pre-destory target class "+className);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Iterate over the <injection-target> entries for a node
|
||||
*
|
||||
* @param node
|
||||
* @param jndiName
|
||||
* @param valueClass
|
||||
* @return the type of the injectable
|
||||
*/
|
||||
protected void initInjection (XmlParser.Node node, String jndiName, Class valueClass)
|
||||
{
|
||||
Iterator itor = node.iterator("injection-target");
|
||||
|
||||
while(itor.hasNext())
|
||||
{
|
||||
XmlParser.Node injectionNode = (XmlParser.Node)itor.next();
|
||||
String targetClassName = injectionNode.getString("injection-target-class", false, true);
|
||||
String targetName = injectionNode.getString("injection-target-name", false, true);
|
||||
if ((targetClassName==null) || targetClassName.equals(""))
|
||||
{
|
||||
Log.warn("No classname found in injection-target");
|
||||
continue;
|
||||
}
|
||||
if ((targetName==null) || targetName.equals(""))
|
||||
{
|
||||
Log.warn("No field or method name in injection-target");
|
||||
continue;
|
||||
}
|
||||
|
||||
// comments in the javaee_5.xsd file specify that the targetName is looked
|
||||
// for first as a java bean property, then if that fails, as a field
|
||||
try
|
||||
{
|
||||
Class clazz = _context.loadClass(targetClassName);
|
||||
Injection injection = new Injection();
|
||||
injection.setTargetClass(clazz);
|
||||
injection.setJndiName(jndiName);
|
||||
injection.setTarget(clazz, targetName, valueClass);
|
||||
_injections.add(injection);
|
||||
}
|
||||
catch (ClassNotFoundException e)
|
||||
{
|
||||
Log.warn("Couldn't load injection target class "+targetClassName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void bindMessageDestinationRef (String name, Class type) throws Exception;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -68,388 +396,82 @@ public abstract class AbstractConfiguration extends WebXmlConfiguration
|
|||
super();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void setWebAppContext (WebAppContext context)
|
||||
public void preConfigure (WebAppContext context)
|
||||
throws Exception
|
||||
{
|
||||
super.setWebAppContext(context);
|
||||
|
||||
//set up our special ServletHandler to remember injections and lifecycle callbacks
|
||||
//set up our special ServletHandler to remember injections and lifecycle callbacks
|
||||
ServletHandler servletHandler = new ServletHandler();
|
||||
_securityHandler = getWebAppContext().getSecurityHandler();
|
||||
org.eclipse.jetty.servlet.ServletHandler existingHandler = getWebAppContext().getServletHandler();
|
||||
_securityHandler = context.getSecurityHandler();
|
||||
org.eclipse.jetty.servlet.ServletHandler existingHandler = context.getServletHandler();
|
||||
servletHandler.setFilterMappings(existingHandler.getFilterMappings());
|
||||
servletHandler.setFilters(existingHandler.getFilters());
|
||||
servletHandler.setServlets(existingHandler.getServlets());
|
||||
servletHandler.setServletMappings(existingHandler.getServletMappings());
|
||||
getWebAppContext().setServletHandler(servletHandler);
|
||||
_securityHandler.setHandler(servletHandler);
|
||||
}
|
||||
|
||||
public void configureDefaults ()
|
||||
throws Exception
|
||||
{
|
||||
super.configureDefaults();
|
||||
context.setServletHandler(servletHandler);
|
||||
_securityHandler.setHandler(servletHandler);
|
||||
}
|
||||
|
||||
public void configureWebApp ()
|
||||
public void configure (WebAppContext context)
|
||||
throws Exception
|
||||
{
|
||||
super.configureWebApp();
|
||||
bindUserTransaction();
|
||||
bindUserTransaction(context);
|
||||
|
||||
WebXmlProcessor webXmlProcessor = (WebXmlProcessor)context.getAttribute(WebXmlProcessor.__web_processor);
|
||||
if (webXmlProcessor == null)
|
||||
throw new IllegalStateException ("No processor for web xml");
|
||||
|
||||
//parse classes for annotations, if necessary
|
||||
if (!webXmlProcessor.isMetaDataComplete())
|
||||
{
|
||||
if (Log.isDebugEnabled()) Log.debug("Processing annotations");
|
||||
parseAnnotations(context);
|
||||
}
|
||||
//TODO: When webdefaults.xml, web.xml, fragments and web-override.xml are merged into an effective web.xml this
|
||||
//will change
|
||||
PlusWebXmlProcessor plusProcessor = new PlusWebXmlProcessor(context);
|
||||
plusProcessor.process(webXmlProcessor.getWebDefault());
|
||||
plusProcessor.process(webXmlProcessor.getWebXml());
|
||||
|
||||
//TODO: can web-fragment contain resource-ref and injection-targets?
|
||||
for (XmlParser.Node frag: webXmlProcessor.getFragments())
|
||||
plusProcessor.process(frag);
|
||||
|
||||
plusProcessor.process(webXmlProcessor.getOverrideWeb());
|
||||
|
||||
|
||||
//configure injections and callbacks to be called by the FilterHolder and ServletHolder
|
||||
//when they lazily instantiate the Filter/Servlet.
|
||||
((ServletHandler)context.getServletHandler()).setInjections(_injections);
|
||||
((ServletHandler)context.getServletHandler()).setCallbacks(_callbacks);
|
||||
|
||||
//do any injects on the listeners that were created and then
|
||||
//also callback any postConstruct lifecycle methods
|
||||
injectAndCallPostConstructCallbacks(context);
|
||||
}
|
||||
|
||||
public void deconfigureWebApp()
|
||||
public void deconfigure (WebAppContext context)
|
||||
throws Exception
|
||||
{
|
||||
//call any preDestroy methods on the listeners
|
||||
callPreDestroyCallbacks();
|
||||
|
||||
super.deconfigureWebApp();
|
||||
callPreDestroyCallbacks(context);
|
||||
}
|
||||
|
||||
public void configure(String webXml)
|
||||
throws Exception
|
||||
{
|
||||
//parse web.xml
|
||||
super.configure(webXml);
|
||||
|
||||
//parse classes for annotations, if necessary
|
||||
if (!_metaDataComplete)
|
||||
{
|
||||
if (Log.isDebugEnabled()) Log.debug("Processing annotations");
|
||||
parseAnnotations();
|
||||
}
|
||||
//do any injects on the listeners that were created and then
|
||||
//also callback any postConstruct lifecycle methods
|
||||
injectAndCallPostConstructCallbacks();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
protected void initialize(XmlParser.Node config)
|
||||
throws ClassNotFoundException,UnavailableException
|
||||
{
|
||||
super.initialize(config);
|
||||
|
||||
//configure injections and callbacks to be called by the FilterHolder and ServletHolder
|
||||
//when they lazily instantiate the Filter/Servlet.
|
||||
((ServletHandler)getWebAppContext().getServletHandler()).setInjections(_injections);
|
||||
((ServletHandler)getWebAppContext().getServletHandler()).setCallbacks(_callbacks);
|
||||
}
|
||||
|
||||
|
||||
protected void initWebXmlElement(String element,XmlParser.Node node) throws Exception
|
||||
{
|
||||
if ("env-entry".equals(element))
|
||||
{
|
||||
initEnvEntry (node);
|
||||
}
|
||||
else if ("resource-ref".equals(element))
|
||||
{
|
||||
//resource-ref entries are ONLY for connection factories
|
||||
//the resource-ref says how the app will reference the jndi lookup relative
|
||||
//to java:comp/env, but it is up to the deployer to map this reference to
|
||||
//a real resource in the environment. At the moment, we insist that the
|
||||
//jetty.xml file name of the resource has to be exactly the same as the
|
||||
//name in web.xml deployment descriptor, but it shouldn't have to be
|
||||
initResourceRef(node);
|
||||
}
|
||||
else if ("resource-env-ref".equals(element))
|
||||
{
|
||||
//resource-env-ref elements are a non-connection factory type of resource
|
||||
//the app looks them up relative to java:comp/env
|
||||
//again, need a way for deployer to link up app naming to real naming.
|
||||
//Again, we insist now that the name of the resource in jetty.xml is
|
||||
//the same as web.xml
|
||||
initResourceEnvRef(node);
|
||||
}
|
||||
else if ("message-destination-ref".equals(element))
|
||||
{
|
||||
initMessageDestinationRef(node);
|
||||
}
|
||||
else if ("post-construct".equals(element))
|
||||
{
|
||||
//post-construct is the name of a class and method to call after all
|
||||
//resources have been setup but before the class is put into use
|
||||
initPostConstruct(node);
|
||||
}
|
||||
else if ("pre-destroy".equals(element))
|
||||
{
|
||||
//pre-destroy is the name of a class and method to call just as
|
||||
//the instance is being destroyed
|
||||
initPreDestroy(node);
|
||||
}
|
||||
else
|
||||
{
|
||||
super.initWebXmlElement(element, node);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* JavaEE 5.4.1.3
|
||||
*
|
||||
*
|
||||
* @param node
|
||||
* @throws Exception
|
||||
*/
|
||||
protected void initEnvEntry (XmlParser.Node node)
|
||||
throws Exception
|
||||
{
|
||||
String name=node.getString("env-entry-name",false,true);
|
||||
String type = node.getString("env-entry-type",false,true);
|
||||
String valueStr = node.getString("env-entry-value",false,true);
|
||||
|
||||
//if there's no value there's no point in making a jndi entry
|
||||
//nor processing injection entries
|
||||
if (valueStr==null || valueStr.equals(""))
|
||||
{
|
||||
Log.warn("No value for env-entry-name "+name);
|
||||
return;
|
||||
}
|
||||
|
||||
//the javaee_5.xsd says that the env-entry-type is optional
|
||||
//if there is an <injection> element, because you can get
|
||||
//type from the element, but what to do if there is more
|
||||
//than one <injection> element, do you just pick the type
|
||||
//of the first one?
|
||||
|
||||
//check for <injection> elements
|
||||
initInjection (node, name, TypeUtil.fromName(type));
|
||||
|
||||
//bind the entry into jndi
|
||||
Object value = TypeUtil.valueOf(type,valueStr);
|
||||
bindEnvEntry(name, value);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Common Annotations Spec section 2.3:
|
||||
* resource-ref is for:
|
||||
* - javax.sql.DataSource
|
||||
* - javax.jms.ConnectionFactory
|
||||
* - javax.jms.QueueConnectionFactory
|
||||
* - javax.jms.TopicConnectionFactory
|
||||
* - javax.mail.Session
|
||||
* - java.net.URL
|
||||
* - javax.resource.cci.ConnectionFactory
|
||||
* - org.omg.CORBA_2_3.ORB
|
||||
* - any other connection factory defined by a resource adapter
|
||||
* @param node
|
||||
* @throws Exception
|
||||
*/
|
||||
protected void initResourceRef (XmlParser.Node node)
|
||||
throws Exception
|
||||
{
|
||||
String jndiName = node.getString("res-ref-name",false,true);
|
||||
String type = node.getString("res-type", false, true);
|
||||
String auth = node.getString("res-auth", false, true);
|
||||
String shared = node.getString("res-sharing-scope", false, true);
|
||||
|
||||
//check for <injection> elements
|
||||
Class typeClass = TypeUtil.fromName(type);
|
||||
if (typeClass==null)
|
||||
typeClass = getWebAppContext().loadClass(type);
|
||||
initInjection (node, jndiName, typeClass);
|
||||
|
||||
bindResourceRef(jndiName, typeClass);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Common Annotations Spec section 2.3:
|
||||
* resource-env-ref is for:
|
||||
* - javax.transaction.UserTransaction
|
||||
* - javax.resource.cci.InteractionSpec
|
||||
* - anything else that is not a connection factory
|
||||
* @param node
|
||||
* @throws Exception
|
||||
*/
|
||||
protected void initResourceEnvRef (XmlParser.Node node)
|
||||
throws Exception
|
||||
{
|
||||
String jndiName = node.getString("resource-env-ref-name",false,true);
|
||||
String type = node.getString("resource-env-ref-type", false, true);
|
||||
|
||||
//check for <injection> elements
|
||||
|
||||
//JavaEE Spec sec 5.7.1.3 says the resource-env-ref-type
|
||||
//is mandatory, but the schema says it is optional!
|
||||
Class typeClass = TypeUtil.fromName(type);
|
||||
if (typeClass==null)
|
||||
typeClass = getWebAppContext().loadClass(type);
|
||||
initInjection (node, jndiName, typeClass);
|
||||
|
||||
bindResourceEnvRef(jndiName, typeClass);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Common Annotations Spec section 2.3:
|
||||
* message-destination-ref is for:
|
||||
* - javax.jms.Queue
|
||||
* - javax.jms.Topic
|
||||
* @param node
|
||||
* @throws Exception
|
||||
*/
|
||||
protected void initMessageDestinationRef (XmlParser.Node node)
|
||||
throws Exception
|
||||
{
|
||||
String jndiName = node.getString("message-destination-ref-name",false,true);
|
||||
String type = node.getString("message-destination-type",false,true);
|
||||
String usage = node.getString("message-destination-usage",false,true);
|
||||
|
||||
Class typeClass = TypeUtil.fromName(type);
|
||||
if (typeClass==null)
|
||||
typeClass = getWebAppContext().loadClass(type);
|
||||
initInjection(node, jndiName, typeClass);
|
||||
|
||||
bindMessageDestinationRef(jndiName, typeClass);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Process <post-construct>
|
||||
* @param node
|
||||
*/
|
||||
protected void initPostConstruct(XmlParser.Node node)
|
||||
{
|
||||
String className = node.getString("lifecycle-callback-class", false, true);
|
||||
String methodName = node.getString("lifecycle-callback-method", false, true);
|
||||
|
||||
if (className==null || className.equals(""))
|
||||
{
|
||||
Log.warn("No lifecycle-callback-class specified");
|
||||
return;
|
||||
}
|
||||
if (methodName==null || methodName.equals(""))
|
||||
{
|
||||
Log.warn("No lifecycle-callback-method specified for class "+className);
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Class clazz = getWebAppContext().loadClass(className);
|
||||
LifeCycleCallback callback = new PostConstructCallback();
|
||||
callback.setTarget(clazz, methodName);
|
||||
_callbacks.add(callback);
|
||||
}
|
||||
catch (ClassNotFoundException e)
|
||||
{
|
||||
Log.warn("Couldn't load post-construct target class "+className);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Process <pre-destroy>
|
||||
* @param node
|
||||
*/
|
||||
protected void initPreDestroy(XmlParser.Node node)
|
||||
{
|
||||
String className = node.getString("lifecycle-callback-class", false, true);
|
||||
String methodName = node.getString("lifecycle-callback-method", false, true);
|
||||
if (className==null || className.equals(""))
|
||||
{
|
||||
Log.warn("No lifecycle-callback-class specified for pre-destroy");
|
||||
return;
|
||||
}
|
||||
if (methodName==null || methodName.equals(""))
|
||||
{
|
||||
Log.warn("No lifecycle-callback-method specified for pre-destroy class "+className);
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Class clazz = getWebAppContext().loadClass(className);
|
||||
LifeCycleCallback callback = new PreDestroyCallback();
|
||||
callback.setTarget(clazz, methodName);
|
||||
_callbacks.add(callback);
|
||||
}
|
||||
catch (ClassNotFoundException e)
|
||||
{
|
||||
Log.warn("Couldn't load pre-destory target class "+className);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Iterate over the <injection-target> entries for a node
|
||||
*
|
||||
* @param node
|
||||
* @param jndiName
|
||||
* @param valueClass
|
||||
* @return the type of the injectable
|
||||
*/
|
||||
protected void initInjection (XmlParser.Node node, String jndiName, Class valueClass)
|
||||
{
|
||||
Iterator itor = node.iterator("injection-target");
|
||||
|
||||
while(itor.hasNext())
|
||||
{
|
||||
XmlParser.Node injectionNode = (XmlParser.Node)itor.next();
|
||||
String targetClassName = injectionNode.getString("injection-target-class", false, true);
|
||||
String targetName = injectionNode.getString("injection-target-name", false, true);
|
||||
if ((targetClassName==null) || targetClassName.equals(""))
|
||||
{
|
||||
Log.warn("No classname found in injection-target");
|
||||
continue;
|
||||
}
|
||||
if ((targetName==null) || targetName.equals(""))
|
||||
{
|
||||
Log.warn("No field or method name in injection-target");
|
||||
continue;
|
||||
}
|
||||
|
||||
// comments in the javaee_5.xsd file specify that the targetName is looked
|
||||
// for first as a java bean property, then if that fails, as a field
|
||||
try
|
||||
{
|
||||
Class clazz = getWebAppContext().loadClass(targetClassName);
|
||||
Injection injection = new Injection();
|
||||
injection.setTargetClass(clazz);
|
||||
injection.setJndiName(jndiName);
|
||||
injection.setTarget(clazz, targetName, valueClass);
|
||||
_injections.add(injection);
|
||||
}
|
||||
catch (ClassNotFoundException e)
|
||||
{
|
||||
Log.warn("Couldn't load injection target class "+targetClassName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parse all classes that are mentioned in web.xml (servlets, filters, listeners)
|
||||
* for annotations.
|
||||
*
|
||||
*
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
protected abstract void parseAnnotations () throws Exception;
|
||||
|
||||
|
||||
|
||||
protected void injectAndCallPostConstructCallbacks()
|
||||
protected void injectAndCallPostConstructCallbacks(WebAppContext context)
|
||||
throws Exception
|
||||
{
|
||||
//look thru the servlets to apply any runAs annotations
|
||||
//NOTE: that any run-as in web.xml will already have been applied
|
||||
ServletHolder[] holders = getWebAppContext().getServletHandler().getServlets();
|
||||
ServletHolder[] holders = context.getServletHandler().getServlets();
|
||||
for (int i=0;holders!=null && i<holders.length;i++)
|
||||
{
|
||||
_runAsCollection.setRunAs(holders[i], _securityHandler);
|
||||
}
|
||||
|
||||
EventListener[] listeners = getWebAppContext().getEventListeners();
|
||||
EventListener[] listeners = context.getEventListeners();
|
||||
for (int i=0;listeners!=null && i<listeners.length;i++)
|
||||
{
|
||||
_injections.inject(listeners[i]);
|
||||
|
@ -458,10 +480,10 @@ public abstract class AbstractConfiguration extends WebXmlConfiguration
|
|||
}
|
||||
|
||||
|
||||
protected void callPreDestroyCallbacks ()
|
||||
protected void callPreDestroyCallbacks (WebAppContext context)
|
||||
throws Exception
|
||||
{
|
||||
EventListener[] listeners = getWebAppContext().getEventListeners();
|
||||
EventListener[] listeners = context.getEventListeners();
|
||||
for (int i=0; listeners!=null && i<listeners.length;i++)
|
||||
{
|
||||
_callbacks.callPreDestroyCallback(listeners[i]);
|
||||
|
|
|
@ -26,6 +26,7 @@ import org.eclipse.jetty.plus.jndi.NamingEntry;
|
|||
import org.eclipse.jetty.plus.jndi.NamingEntryUtil;
|
||||
import org.eclipse.jetty.plus.jndi.Transaction;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -50,7 +51,7 @@ public class Configuration extends AbstractConfiguration
|
|||
* @param value
|
||||
* @throws Exception
|
||||
*/
|
||||
public void bindEnvEntry(String name, Object value) throws Exception
|
||||
public void bindEnvEntry(WebAppContext context, String name, Object value) throws Exception
|
||||
{
|
||||
InitialContext ic = null;
|
||||
boolean bound = false;
|
||||
|
@ -90,10 +91,10 @@ public class Configuration extends AbstractConfiguration
|
|||
* @param name
|
||||
* @throws Exception
|
||||
*/
|
||||
public void bindResourceRef(String name, Class typeClass)
|
||||
public void bindResourceRef(WebAppContext context, String name, Class typeClass)
|
||||
throws Exception
|
||||
{
|
||||
bindEntry(name, typeClass);
|
||||
bindEntry(context, name, typeClass);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -101,20 +102,20 @@ public class Configuration extends AbstractConfiguration
|
|||
* @param name
|
||||
* @throws Exception
|
||||
*/
|
||||
public void bindResourceEnvRef(String name, Class typeClass)
|
||||
public void bindResourceEnvRef(WebAppContext context, String name, Class typeClass)
|
||||
throws Exception
|
||||
{
|
||||
bindEntry(name, typeClass);
|
||||
bindEntry(context, name, typeClass);
|
||||
}
|
||||
|
||||
|
||||
public void bindMessageDestinationRef(String name, Class typeClass)
|
||||
public void bindMessageDestinationRef(WebAppContext context, String name, Class typeClass)
|
||||
throws Exception
|
||||
{
|
||||
bindEntry(name, typeClass);
|
||||
bindEntry(context, name, typeClass);
|
||||
}
|
||||
|
||||
public void bindUserTransaction ()
|
||||
public void bindUserTransaction (WebAppContext context)
|
||||
throws Exception
|
||||
{
|
||||
try
|
||||
|
@ -127,38 +128,38 @@ public class Configuration extends AbstractConfiguration
|
|||
}
|
||||
}
|
||||
|
||||
public void configureClassLoader ()
|
||||
public void preConfigure (WebAppContext context)
|
||||
throws Exception
|
||||
{
|
||||
super.configureClassLoader();
|
||||
super.preConfigure(context);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void configure (WebAppContext context)
|
||||
throws Exception
|
||||
{
|
||||
super.configure (context);
|
||||
}
|
||||
|
||||
public void configureDefaults ()
|
||||
public void postConfigure (WebAppContext context)
|
||||
throws Exception
|
||||
{
|
||||
super.configureDefaults();
|
||||
}
|
||||
|
||||
|
||||
public void configureWebApp ()
|
||||
throws Exception
|
||||
{
|
||||
super.configureWebApp();
|
||||
//lock this webapp's java:comp namespace as per J2EE spec
|
||||
//lock this webapp's java:comp namespace as per J2EE spec
|
||||
ClassLoader oldLoader = Thread.currentThread().getContextClassLoader();
|
||||
Thread.currentThread().setContextClassLoader(getWebAppContext().getClassLoader());
|
||||
Thread.currentThread().setContextClassLoader(context.getClassLoader());
|
||||
lockCompEnv();
|
||||
Thread.currentThread().setContextClassLoader(oldLoader);
|
||||
}
|
||||
|
||||
public void deconfigureWebApp() throws Exception
|
||||
public void deconfigure (WebAppContext context) throws Exception
|
||||
{
|
||||
ClassLoader oldLoader = Thread.currentThread().getContextClassLoader();
|
||||
Thread.currentThread().setContextClassLoader(getWebAppContext().getClassLoader());
|
||||
Thread.currentThread().setContextClassLoader(context.getClassLoader());
|
||||
unlockCompEnv();
|
||||
_key = null;
|
||||
Thread.currentThread().setContextClassLoader(oldLoader);
|
||||
super.deconfigureWebApp();
|
||||
super.deconfigure (context);
|
||||
}
|
||||
|
||||
protected void lockCompEnv ()
|
||||
|
@ -185,7 +186,7 @@ public class Configuration extends AbstractConfiguration
|
|||
/**
|
||||
* @see org.eclipse.jetty.plus.webapp.AbstractConfiguration#parseAnnotations()
|
||||
*/
|
||||
public void parseAnnotations() throws Exception
|
||||
public void parseAnnotations(WebAppContext context) throws Exception
|
||||
{
|
||||
//see org.eclipse.jetty.annotations.Configuration instead
|
||||
}
|
||||
|
@ -205,7 +206,7 @@ public class Configuration extends AbstractConfiguration
|
|||
* @param typeClass
|
||||
* @throws Exception
|
||||
*/
|
||||
private void bindEntry (String name, Class typeClass)
|
||||
private void bindEntry (WebAppContext context, String name, Class typeClass)
|
||||
throws Exception
|
||||
{
|
||||
String nameInEnvironment = name;
|
||||
|
@ -213,7 +214,7 @@ public class Configuration extends AbstractConfiguration
|
|||
|
||||
//check if the name in web.xml has been mapped to something else
|
||||
//check a context-specific naming environment first
|
||||
Object scope = getWebAppContext();
|
||||
Object scope = context;
|
||||
NamingEntry ne = NamingEntryUtil.lookupNamingEntry(scope, name);
|
||||
|
||||
if (ne!=null && (ne instanceof Link))
|
||||
|
@ -221,33 +222,38 @@ public class Configuration extends AbstractConfiguration
|
|||
//if we found a mapping, get out name it is mapped to in the environment
|
||||
nameInEnvironment = (String)((Link)ne).getObjectToBind();
|
||||
Link l = (Link)ne;
|
||||
System.err.println("Link, with nameInEnvironment="+nameInEnvironment);
|
||||
}
|
||||
|
||||
//try finding that mapped name in the webapp's environment first
|
||||
scope = getWebAppContext();
|
||||
System.err.println("Trying to find "+nameInEnvironment+" in webapp scope");
|
||||
scope = context;
|
||||
bound = NamingEntryUtil.bindToENC(scope, name, nameInEnvironment);
|
||||
|
||||
if (bound)
|
||||
return;
|
||||
|
||||
|
||||
System.err.println("Trying to find "+nameInEnvironment+" in server scope");
|
||||
//try the server's environment
|
||||
scope = getWebAppContext().getServer();
|
||||
scope = context.getServer();
|
||||
bound = NamingEntryUtil.bindToENC(scope, name, nameInEnvironment);
|
||||
if (bound)
|
||||
return;
|
||||
|
||||
System.err.println("Trying to find "+nameInEnvironment+" in jvm scope");
|
||||
//try the jvm environment
|
||||
bound = NamingEntryUtil.bindToENC(null, name, nameInEnvironment);
|
||||
if (bound)
|
||||
return;
|
||||
|
||||
|
||||
System.err.println("Didn't find "+nameInEnvironment+" anywhere - looking for "+typeClass.getName()+"/default in server or jvm scope");
|
||||
//There is no matching resource so try a default name.
|
||||
//The default name syntax is: the [res-type]/default
|
||||
//eg javax.sql.DataSource/default
|
||||
nameInEnvironment = typeClass.getName()+"/default";
|
||||
//First try the server scope
|
||||
NamingEntry defaultNE = NamingEntryUtil.lookupNamingEntry(getWebAppContext().getServer(), nameInEnvironment);
|
||||
NamingEntry defaultNE = NamingEntryUtil.lookupNamingEntry(context.getServer(), nameInEnvironment);
|
||||
if (defaultNE==null)
|
||||
defaultNE = NamingEntryUtil.lookupNamingEntry(null, nameInEnvironment);
|
||||
|
||||
|
|
|
@ -40,67 +40,37 @@ import org.eclipse.jetty.xml.XmlConfiguration;
|
|||
*/
|
||||
public class EnvConfiguration implements Configuration
|
||||
{
|
||||
private WebAppContext webAppContext;
|
||||
|
||||
private Context compCtx;
|
||||
private Context envCtx;
|
||||
private URL jettyEnvXmlUrl;
|
||||
|
||||
protected void createEnvContext ()
|
||||
throws NamingException
|
||||
{
|
||||
Context context = new InitialContext();
|
||||
compCtx = (Context)context.lookup ("java:comp");
|
||||
envCtx = compCtx.createSubcontext("env");
|
||||
if (Log.isDebugEnabled())
|
||||
Log.debug("Created java:comp/env for webapp "+getWebAppContext().getContextPath());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.webapp.Configuration#setWebAppContext(org.eclipse.jetty.webapp.WebAppContext)
|
||||
* @param context
|
||||
*/
|
||||
public void setWebAppContext(WebAppContext context)
|
||||
{
|
||||
this.webAppContext = context;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void setJettyEnvXml (URL url)
|
||||
{
|
||||
this.jettyEnvXmlUrl = url;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.webapp.Configuration#getWebAppContext()
|
||||
*/
|
||||
public WebAppContext getWebAppContext()
|
||||
{
|
||||
return webAppContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.webapp.Configuration#configureClassLoader()
|
||||
* @throws Exception
|
||||
*/
|
||||
public void configureClassLoader() throws Exception
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.webapp.Configuration#configureDefaults()
|
||||
* @throws Exception
|
||||
*/
|
||||
public void configureDefaults() throws Exception
|
||||
public void preConfigure (WebAppContext context) throws Exception
|
||||
{
|
||||
//create a java:comp/env
|
||||
createEnvContext();
|
||||
if (Log.isDebugEnabled())
|
||||
Log.debug("Created java:comp/env for webapp "+context.getContextPath());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.webapp.Configuration#configureWebApp()
|
||||
* @throws Exception
|
||||
*/
|
||||
public void configureWebApp() throws Exception
|
||||
public void configure (WebAppContext context) throws Exception
|
||||
{
|
||||
//check to see if an explicit file has been set, if not,
|
||||
//look in WEB-INF/jetty-env.xml
|
||||
|
@ -109,7 +79,7 @@ public class EnvConfiguration implements Configuration
|
|||
|
||||
//look for a file called WEB-INF/jetty-env.xml
|
||||
//and process it if it exists
|
||||
org.eclipse.jetty.util.resource.Resource web_inf = getWebAppContext().getWebInf();
|
||||
org.eclipse.jetty.util.resource.Resource web_inf = context.getWebInf();
|
||||
if(web_inf!=null && web_inf.isDirectory())
|
||||
{
|
||||
org.eclipse.jetty.util.resource.Resource jettyEnv = web_inf.addPath("jetty-env.xml");
|
||||
|
@ -119,38 +89,48 @@ public class EnvConfiguration implements Configuration
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
//apply the jetty-env.xml file
|
||||
if (jettyEnvXmlUrl != null)
|
||||
{
|
||||
System.err.println("Applying "+jettyEnvXmlUrl);
|
||||
XmlConfiguration configuration = new XmlConfiguration(jettyEnvXmlUrl);
|
||||
configuration.configure(getWebAppContext());
|
||||
configuration.configure(context);
|
||||
}
|
||||
|
||||
//add java:comp/env entries for any EnvEntries that have been defined so far
|
||||
bindEnvEntries();
|
||||
bindEnvEntries(context);
|
||||
}
|
||||
|
||||
public void postConfigure(WebAppContext context) throws Exception
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove all jndi setup
|
||||
* @see org.eclipse.jetty.webapp.Configuration#deconfigureWebApp()
|
||||
* @throws Exception
|
||||
*/
|
||||
public void deconfigureWebApp() throws Exception
|
||||
public void deconfigure (WebAppContext context) throws Exception
|
||||
{
|
||||
//get rid of any bindings for comp/env for webapp
|
||||
ClassLoader oldLoader = Thread.currentThread().getContextClassLoader();
|
||||
Thread.currentThread().setContextClassLoader(webAppContext.getClassLoader());
|
||||
Thread.currentThread().setContextClassLoader(context.getClassLoader());
|
||||
compCtx.destroySubcontext("env");
|
||||
|
||||
//unbind any NamingEntries that were configured in this webapp's name space
|
||||
try
|
||||
{
|
||||
Context scopeContext = NamingEntryUtil.getContextForScope(getWebAppContext());
|
||||
Context scopeContext = NamingEntryUtil.getContextForScope(context);
|
||||
scopeContext.destroySubcontext(NamingEntry.__contextName);
|
||||
}
|
||||
catch (NameNotFoundException e)
|
||||
{
|
||||
Log.ignore(e);
|
||||
Log.debug("No naming entries configured in environment for webapp "+getWebAppContext());
|
||||
Log.debug("No naming entries configured in environment for webapp "+context);
|
||||
}
|
||||
Thread.currentThread().setContextClassLoader(oldLoader);
|
||||
}
|
||||
|
@ -162,7 +142,7 @@ public class EnvConfiguration implements Configuration
|
|||
* We first bind EnvEntries declared in Server scope, then WebAppContext scope.
|
||||
* @throws NamingException
|
||||
*/
|
||||
public void bindEnvEntries ()
|
||||
public void bindEnvEntries (WebAppContext context)
|
||||
throws NamingException
|
||||
{
|
||||
Log.debug("Binding env entries from the jvm scope");
|
||||
|
@ -179,7 +159,7 @@ public class EnvConfiguration implements Configuration
|
|||
|
||||
Log.debug("Binding env entries from the server scope");
|
||||
|
||||
scope = getWebAppContext().getServer();
|
||||
scope = context.getServer();
|
||||
list = NamingEntryUtil.lookupNamingEntries(scope, EnvEntry.class);
|
||||
itor = list.iterator();
|
||||
while (itor.hasNext())
|
||||
|
@ -191,7 +171,7 @@ public class EnvConfiguration implements Configuration
|
|||
}
|
||||
|
||||
Log.debug("Binding env entries from the context scope");
|
||||
scope = getWebAppContext();
|
||||
scope = context;
|
||||
list = NamingEntryUtil.lookupNamingEntries(scope, EnvEntry.class);
|
||||
itor = list.iterator();
|
||||
while (itor.hasNext())
|
||||
|
@ -202,4 +182,12 @@ public class EnvConfiguration implements Configuration
|
|||
NamingUtil.bind(envCtx, namingEntryName.toString(), ee);//also save the EnvEntry in the context so we can check it later
|
||||
}
|
||||
}
|
||||
|
||||
protected void createEnvContext ()
|
||||
throws NamingException
|
||||
{
|
||||
Context context = new InitialContext();
|
||||
compCtx = (Context)context.lookup ("java:comp");
|
||||
envCtx = compCtx.createSubcontext("env");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,11 +67,11 @@ public class TestConfiguration extends TestCase
|
|||
assertNotNull(NamingEntryUtil.lookupNamingEntry(wac, "zzz/e"));
|
||||
|
||||
Configuration config = new Configuration();
|
||||
config.setWebAppContext(wac);
|
||||
|
||||
EnvConfiguration envConfig = new EnvConfiguration();
|
||||
envConfig.setWebAppContext(wac);
|
||||
envConfig.configureDefaults();
|
||||
envConfig.bindEnvEntries();
|
||||
|
||||
envConfig.preConfigure(wac);
|
||||
envConfig.bindEnvEntries(wac);
|
||||
|
||||
String val = (String)ic.lookup("java:comp/env/xxx/a");
|
||||
assertEquals("900", val); //webapp naming overrides server
|
||||
|
@ -95,20 +95,20 @@ public class TestConfiguration extends TestCase
|
|||
ne = (NamingEntry)ic.lookup("java:comp/env/"+NamingEntry.__contextName+"/zzz/e");
|
||||
assertNotNull(ne);
|
||||
|
||||
config.bindEnvEntry("foo", "99");
|
||||
config.bindEnvEntry(wac, "foo", "99");
|
||||
assertEquals("99",ic.lookup( "java:comp/env/foo"));
|
||||
|
||||
config.bindEnvEntry("xxx/a", "7");
|
||||
config.bindEnvEntry(wac, "xxx/a", "7");
|
||||
assertEquals("900", ic.lookup("java:comp/env/xxx/a")); //webapp overrides web.xml
|
||||
config.bindEnvEntry("yyy/b", "7");
|
||||
config.bindEnvEntry(wac, "yyy/b", "7");
|
||||
assertEquals("910", ic.lookup("java:comp/env/yyy/b"));//webapp overrides web.xml
|
||||
config.bindEnvEntry("zzz/c", "7");
|
||||
config.bindEnvEntry(wac,"zzz/c", "7");
|
||||
assertEquals("7", ic.lookup("java:comp/env/zzz/c"));//webapp does NOT override web.xml
|
||||
config.bindEnvEntry("zzz/d", "7");
|
||||
config.bindEnvEntry(wac,"zzz/d", "7");
|
||||
assertEquals("7", ic.lookup("java:comp/env/zzz/d"));//server does NOT override web.xml
|
||||
config.bindEnvEntry("zzz/e", "7");
|
||||
config.bindEnvEntry(wac,"zzz/e", "7");
|
||||
assertEquals("7", ic.lookup("java:comp/env/zzz/e"));//webapp does NOT override web.xml
|
||||
config.bindEnvEntry("zzz/f", "7");
|
||||
config.bindEnvEntry(wac,"zzz/f", "7");
|
||||
assertEquals("500", ic.lookup("java:comp/env/zzz/f"));//server overrides web.xml
|
||||
|
||||
((Context)ic.lookup("java:comp")).destroySubcontext("env");
|
||||
|
|
|
@ -17,61 +17,39 @@ package org.eclipse.jetty.webapp;
|
|||
/* ------------------------------------------------------------------------------- */
|
||||
/** Base Class for WebApplicationContext Configuration.
|
||||
* This class can be extended to customize or extend the configuration
|
||||
* of the WebApplicationContext. If WebApplicationContext.setConfiguration is not
|
||||
* called, then an XMLConfiguration instance is created.
|
||||
*
|
||||
*
|
||||
* of the WebApplicationContext.
|
||||
*/
|
||||
public interface Configuration
|
||||
{
|
||||
|
||||
/* ------------------------------------------------------------------------------- */
|
||||
/** Set up a context on which to perform the configuration.
|
||||
* @param context
|
||||
*/
|
||||
public void setWebAppContext (WebAppContext context);
|
||||
|
||||
/* ------------------------------------------------------------------------------- */
|
||||
/** Get the context on which the configuration is performed.
|
||||
*/
|
||||
public WebAppContext getWebAppContext();
|
||||
|
||||
/* ------------------------------------------------------------------------------- */
|
||||
/** Configure ClassPath.
|
||||
* This method is called to configure the context ClassLoader. It is called just
|
||||
* after a new WebAppClassLoader is constructed and before it has been used.
|
||||
* Class paths may be added, options changed or the loader totally replaced.
|
||||
/** Set up for configuration.
|
||||
* @throws Exception
|
||||
*/
|
||||
public void configureClassLoader()
|
||||
throws Exception;
|
||||
|
||||
/* ------------------------------------------------------------------------------- */
|
||||
/** Configure Defaults.
|
||||
* This method is called to intialize the context to the containers default configuration.
|
||||
* Typically this would mean application of the webdefault.xml file.
|
||||
* @throws Exception
|
||||
*/
|
||||
public void configureDefaults()
|
||||
throws Exception;
|
||||
public void preConfigure (WebAppContext context) throws Exception;
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------- */
|
||||
/** Configure WebApp.
|
||||
* This method is called to apply the standard and vendor deployment descriptors.
|
||||
* Typically this is web.xml and jetty-web.xml.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public void configureWebApp()
|
||||
throws Exception;
|
||||
|
||||
public void configure (WebAppContext context) throws Exception;
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------- */
|
||||
/** Clear down after configuration.
|
||||
* @throws Exception
|
||||
*/
|
||||
public void postConfigure (WebAppContext context) throws Exception;
|
||||
|
||||
/* ------------------------------------------------------------------------------- */
|
||||
/** DeConfigure WebApp.
|
||||
* This method is called to undo all configuration done to this webapphandler. This is
|
||||
* This method is called to undo all configuration done. This is
|
||||
* called to allow the context to work correctly over a stop/start cycle
|
||||
* @throws Exception
|
||||
*/
|
||||
public void deconfigureWebApp()
|
||||
throws Exception;
|
||||
public void deconfigure (WebAppContext context) throws Exception;
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,125 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) 2009 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
|
||||
package org.eclipse.jetty.webapp;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.resource.Resource;
|
||||
|
||||
/**
|
||||
* FragmentConfiguration
|
||||
*
|
||||
* Process web-fragments in jars
|
||||
*/
|
||||
public class FragmentConfiguration implements Configuration
|
||||
{
|
||||
public void preConfigure(WebAppContext context) throws Exception
|
||||
{
|
||||
WebXmlProcessor processor = (WebXmlProcessor)context.getAttribute(WebXmlProcessor.__web_processor);
|
||||
if (processor == null)
|
||||
{
|
||||
processor = new WebXmlProcessor (context);
|
||||
context.setAttribute(WebXmlProcessor.__web_processor, processor);
|
||||
}
|
||||
|
||||
//parse web-fragment.xmls
|
||||
parseWebFragments(context, processor);
|
||||
|
||||
//TODO for jetty-8/servletspec 3 we will need to merge the parsed web fragments into the
|
||||
//effective pom in this preConfigure step
|
||||
}
|
||||
|
||||
public void configure(WebAppContext context) throws Exception
|
||||
{
|
||||
//TODO for jetty-8/servletspec3 the fragments will not be separately processed here, but
|
||||
//will be done by webXmlConfiguration when it processes the effective merged web.xml
|
||||
WebXmlProcessor processor = (WebXmlProcessor)context.getAttribute(WebXmlProcessor.__web_processor);
|
||||
if (processor == null)
|
||||
{
|
||||
processor = new WebXmlProcessor (context);
|
||||
context.setAttribute(WebXmlProcessor.__web_processor, processor);
|
||||
}
|
||||
processor.processFragments();
|
||||
}
|
||||
|
||||
public void deconfigure(WebAppContext context) throws Exception
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
public void postConfigure(WebAppContext context) throws Exception
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------- */
|
||||
/**
|
||||
* Look for any web.xml fragments in META-INF of jars in WEB-INF/lib
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public void parseWebFragments (final WebAppContext context, final WebXmlProcessor processor) throws Exception
|
||||
{
|
||||
// Check to see if a specific search pattern has been set.
|
||||
String tmp = (String) context.getInitParameter("org.eclipse.jetty.webapp.WebXmlFragmentPattern");
|
||||
Pattern webFragPattern = (tmp == null ? null : Pattern.compile(tmp));
|
||||
|
||||
List<URL> urls = (List<URL>)context.getAttribute(MetaInfConfiguration.__webFragJars);
|
||||
|
||||
JarScanner fragScanner = new JarScanner()
|
||||
{
|
||||
public void processEntry(URL jarUrl, JarEntry entry)
|
||||
{
|
||||
try
|
||||
{
|
||||
String name = entry.getName();
|
||||
if (name.toLowerCase().equals("meta-inf/web-fragment.xml"))
|
||||
{
|
||||
Resource webXmlFrag = context.newResource("jar:" + jarUrl + "!/" + name);
|
||||
Log.debug("web.xml fragment found {}", webXmlFrag);
|
||||
// Process web.xml
|
||||
// web-fragment
|
||||
// servlet
|
||||
// servlet-mapping
|
||||
// filter
|
||||
// filter-mapping
|
||||
// listener
|
||||
processor.parseFragment(webXmlFrag.getURL());
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.warn("Problem processing jar entry " + entry, e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//process only the jars that have web fragments in them, according to the pattern provided
|
||||
if (urls != null)
|
||||
fragScanner.scan(webFragPattern, urls.toArray(new URL[urls.size()]), true);
|
||||
else
|
||||
{
|
||||
if (Log.isDebugEnabled()) Log.debug("No jars with web-fragments");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -43,6 +43,60 @@ public abstract class JarScanner
|
|||
|
||||
public abstract void processEntry (URL jarUrl, JarEntry entry);
|
||||
|
||||
/**
|
||||
* Find jar names from the provided list matching a pattern.
|
||||
*
|
||||
* If the pattern is null and isNullInclusive is true, then
|
||||
* all jar names will match.
|
||||
*
|
||||
* A pattern is a set of acceptable jar names. Each acceptable
|
||||
* jar name is a regex. Each regex can be separated by either a
|
||||
* "," or a "|". If you use a "|" this or's together the jar
|
||||
* name patterns. This means that ordering of the matches is
|
||||
* unimportant to you. If instead, you want to match particular
|
||||
* jar names, and you want to match them in order, you should
|
||||
* separate the regexs with "," instead.
|
||||
*
|
||||
* Eg "aaa-.*\\.jar|bbb-.*\\.jar"
|
||||
* Will iterate over the jar names and match
|
||||
* in any order.
|
||||
*
|
||||
* Eg "aaa-*\\.jar,bbb-.*\\.jar"
|
||||
* Will iterate over the jar names, matching
|
||||
* all those starting with "aaa-" first, then "bbb-".
|
||||
*
|
||||
* @param pattern
|
||||
* @param loader
|
||||
* @param isNullInclusive if true, an empty pattern means all names match, if false, none match
|
||||
* @throws Exception
|
||||
*/
|
||||
public void scan (Pattern pattern, URL[] urls, boolean isNullInclusive)
|
||||
throws Exception
|
||||
{
|
||||
if (urls!=null)
|
||||
{
|
||||
String[] patterns = (pattern==null?null:pattern.pattern().split(","));
|
||||
|
||||
List<Pattern> subPatterns = new ArrayList<Pattern>();
|
||||
for (int i=0; patterns!=null && i<patterns.length;i++)
|
||||
subPatterns.add(Pattern.compile(patterns[i]));
|
||||
if (subPatterns.isEmpty())
|
||||
subPatterns.add(pattern);
|
||||
|
||||
if (subPatterns.isEmpty())
|
||||
{
|
||||
processJars(null, urls, isNullInclusive);
|
||||
}
|
||||
else
|
||||
{
|
||||
//for each subpattern, iterate over all the urls, processing those that match
|
||||
for (Pattern p : subPatterns)
|
||||
{
|
||||
processJars(p, urls, isNullInclusive);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find jar names from the classloader matching a pattern.
|
||||
|
|
|
@ -29,46 +29,22 @@ import org.eclipse.jetty.xml.XmlConfiguration;
|
|||
*/
|
||||
public class JettyWebXmlConfiguration implements Configuration
|
||||
{
|
||||
private WebAppContext _context;
|
||||
public void preConfigure(WebAppContext context) throws Exception
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see Configuration#setWebAppContext
|
||||
*/
|
||||
public void setWebAppContext (WebAppContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public WebAppContext getWebAppContext ()
|
||||
{
|
||||
return _context;
|
||||
}
|
||||
|
||||
/** configureClassPath
|
||||
* Not used.
|
||||
* @see Configuration#configureClassLoader
|
||||
*/
|
||||
public void configureClassLoader () throws Exception
|
||||
{
|
||||
}
|
||||
|
||||
/** configureDefaults
|
||||
* Not used.
|
||||
* @see Configuration#configureDefaults
|
||||
*/
|
||||
public void configureDefaults () throws Exception
|
||||
{
|
||||
}
|
||||
|
||||
/** configureWebApp
|
||||
/**
|
||||
* Configure
|
||||
* Apply web-jetty.xml configuration
|
||||
* @see Configuration#configureWebApp()
|
||||
* @see Configuration#configure(WebAppContext)
|
||||
*/
|
||||
public void configureWebApp () throws Exception
|
||||
public void configure (WebAppContext context) throws Exception
|
||||
{
|
||||
//cannot configure if the _context is already started
|
||||
if (_context.isStarted())
|
||||
if (context.isStarted())
|
||||
{
|
||||
if (Log.isDebugEnabled()){Log.debug("Cannot configure webapp after it is started");}
|
||||
return;
|
||||
|
@ -77,7 +53,7 @@ public class JettyWebXmlConfiguration implements Configuration
|
|||
if(Log.isDebugEnabled())
|
||||
Log.debug("Configuring web-jetty.xml");
|
||||
|
||||
Resource web_inf=getWebAppContext().getWebInf();
|
||||
Resource web_inf = context.getWebInf();
|
||||
// handle any WEB-INF descriptors
|
||||
if(web_inf!=null&&web_inf.isDirectory())
|
||||
{
|
||||
|
@ -91,31 +67,35 @@ public class JettyWebXmlConfiguration implements Configuration
|
|||
if(jetty.exists())
|
||||
{
|
||||
// No server classes while configuring
|
||||
String[] old_server_classes = _context.getServerClasses();
|
||||
String[] old_server_classes = context.getServerClasses();
|
||||
try
|
||||
{
|
||||
_context.setServerClasses(null);
|
||||
context.setServerClasses(null);
|
||||
if(Log.isDebugEnabled())
|
||||
Log.debug("Configure: "+jetty);
|
||||
XmlConfiguration jetty_config=new XmlConfiguration(jetty.getURL());
|
||||
jetty_config.configure(getWebAppContext());
|
||||
jetty_config.configure(context);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (_context.getServerClasses()==null)
|
||||
_context.setServerClasses(old_server_classes);
|
||||
if (context.getServerClasses()==null)
|
||||
context.setServerClasses(old_server_classes);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** deconfigureWebApp
|
||||
* @see Configuration#deconfigureWebApp()
|
||||
*/
|
||||
public void deconfigureWebApp () throws Exception
|
||||
public void postConfigure(WebAppContext context) throws Exception
|
||||
{
|
||||
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void deconfigure(WebAppContext context) throws Exception
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,140 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) 2009 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
package org.eclipse.jetty.webapp;
|
||||
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.jar.JarEntry;
|
||||
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.resource.Resource;
|
||||
|
||||
/**
|
||||
* MetaInfConfiguration
|
||||
*
|
||||
* Scan META-INF of all jars in WEB-INF/lib to find:
|
||||
* <ul>
|
||||
* <li>tlds
|
||||
* <li>web-fragment.xml
|
||||
* <li>resources
|
||||
* </ul>
|
||||
*/
|
||||
public class MetaInfConfiguration implements Configuration
|
||||
{
|
||||
|
||||
public static final String __tldJars = "org.eclipse.jetty.tlds";
|
||||
public static final String __webFragJars = "org.eclipse.jetty.webFragments";
|
||||
public static final String __metaResourceJars = "org.eclipse.jetty.metaResources";
|
||||
|
||||
|
||||
|
||||
public void preConfigure(final WebAppContext context) throws Exception
|
||||
{
|
||||
|
||||
//Find all jars in WEB-INF
|
||||
Resource web_inf = context.getWebInf();
|
||||
Resource web_inf_lib = web_inf.addPath("/lib");
|
||||
List<URL> urls = new ArrayList<URL>();
|
||||
|
||||
if (web_inf_lib.exists() && web_inf_lib.isDirectory())
|
||||
{
|
||||
String[] files=web_inf_lib.list();
|
||||
for (int f=0;files!=null && f<files.length;f++)
|
||||
{
|
||||
try
|
||||
{
|
||||
Resource file = web_inf_lib.addPath(files[f]);
|
||||
String fnlc = file.getName().toLowerCase();
|
||||
int dot = fnlc.lastIndexOf('.');
|
||||
String extension = (dot < 0 ? null : fnlc.substring(dot));
|
||||
if (extension != null && (extension.equals(".jar") || extension.equals(".zip")))
|
||||
{
|
||||
urls.add(file.getURL());
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.warn(Log.EXCEPTION,ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final List<URL> tldJars = new ArrayList<URL>();
|
||||
final List<URL> webFragJars = new ArrayList<URL>();
|
||||
final List<URL> metaResourceJars = new ArrayList<URL>();
|
||||
|
||||
JarScanner fragScanner = new JarScanner()
|
||||
{
|
||||
public void processEntry(URL jarUrl, JarEntry entry)
|
||||
{
|
||||
try
|
||||
{
|
||||
String name = entry.getName().toLowerCase();
|
||||
if (name.startsWith("meta-inf"))
|
||||
{
|
||||
if (name.equals("meta-inf/web-fragment.xml"))
|
||||
{
|
||||
addJar(jarUrl, webFragJars);
|
||||
}
|
||||
else if (name.endsWith(".tld"))
|
||||
{
|
||||
addJar(jarUrl, tldJars);
|
||||
}
|
||||
else if (name.equals("meta-inf/resources"))
|
||||
{
|
||||
addJar(jarUrl, metaResourceJars);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.warn("Problem processing jar entry " + entry, e);
|
||||
}
|
||||
}
|
||||
};
|
||||
fragScanner.scan(null, urls.toArray(new URL[urls.size()]), true);
|
||||
|
||||
context.setAttribute(__tldJars, tldJars);
|
||||
context.setAttribute(__webFragJars, webFragJars);
|
||||
context.setAttribute(__metaResourceJars, metaResourceJars);
|
||||
}
|
||||
|
||||
|
||||
public void configure(WebAppContext context) throws Exception
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
public void deconfigure(WebAppContext context) throws Exception
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
public void postConfigure(WebAppContext context) throws Exception
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
public void addJar (URL jarUrl, List<URL> list)
|
||||
{
|
||||
if (!list.contains(jarUrl))
|
||||
list.add(jarUrl);
|
||||
}
|
||||
|
||||
}
|
|
@ -14,9 +14,11 @@
|
|||
package org.eclipse.jetty.webapp;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.EventListener;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.regex.Pattern;
|
||||
|
@ -50,14 +52,24 @@ public class TagLibConfiguration implements Configuration
|
|||
{
|
||||
public static final String __web_inf_pattern = "org.eclipse.jetty.webapp.WebInfIncludeTLDJarPattern";
|
||||
public static final String __container_pattern = "org.eclipse.jetty.server.webapp.ContainerIncludeTLDJarPattern";
|
||||
WebAppContext _context;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public class TagLibJarScanner extends JarScanner
|
||||
/**
|
||||
* TagLibJarScanner
|
||||
*
|
||||
* Scan jars for META-INF/*.tlds
|
||||
*/
|
||||
public class TagLibJarScanner extends JarScanner
|
||||
{
|
||||
Set _tlds;
|
||||
WebAppContext _context;
|
||||
|
||||
public TagLibJarScanner (WebAppContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public void setTldSet (Set tlds)
|
||||
{
|
||||
|
@ -88,52 +100,164 @@ public class TagLibConfiguration implements Configuration
|
|||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void setWebAppContext(WebAppContext context)
|
||||
{
|
||||
_context=context;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public WebAppContext getWebAppContext()
|
||||
{
|
||||
return _context;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void configureClassLoader() throws Exception
|
||||
{
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/*
|
||||
* @see org.eclipse.jetty.servlet.WebAppContext.Configuration#configureDefaults()
|
||||
*/
|
||||
public void configureDefaults() throws Exception
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/*
|
||||
* @see org.eclipse.jetty.servlet.WebAppContext.Configuration#configureWebApp()
|
||||
*/
|
||||
public void configureWebApp() throws Exception
|
||||
{
|
||||
|
||||
Set tlds = new HashSet();
|
||||
public class TldProcessor
|
||||
{
|
||||
public static final String __taglib_processor = "org.eclipse.jetty.tagLibProcessor";
|
||||
XmlParser _parser;
|
||||
WebAppContext _context;
|
||||
List<XmlParser.Node> _roots = new ArrayList<XmlParser.Node>();
|
||||
|
||||
|
||||
// Find tld's from web.xml
|
||||
// When the XMLConfigurator (or other configurator) parsed the web.xml,
|
||||
// It should have created aliases for all TLDs. So search resources aliases
|
||||
// for aliases ending in tld
|
||||
if (_context.getResourceAliases()!=null &&
|
||||
_context.getBaseResource()!=null &&
|
||||
_context.getBaseResource().exists())
|
||||
public TldProcessor (WebAppContext context)
|
||||
throws Exception
|
||||
{
|
||||
Iterator iter=_context.getResourceAliases().values().iterator();
|
||||
_context = context;
|
||||
createParser();
|
||||
}
|
||||
|
||||
private void createParser ()
|
||||
throws Exception
|
||||
{
|
||||
// Create a TLD parser
|
||||
_parser = new XmlParser(false);
|
||||
|
||||
URL taglib11=null;
|
||||
URL taglib12=null;
|
||||
URL taglib20=null;
|
||||
URL taglib21=null;
|
||||
|
||||
try
|
||||
{
|
||||
Class jsp_page = Loader.loadClass(WebXmlConfiguration.class,"javax.servlet.jsp.JspPage");
|
||||
taglib11=jsp_page.getResource("javax/servlet/jsp/resources/web-jsptaglibrary_1_1.dtd");
|
||||
taglib12=jsp_page.getResource("javax/servlet/jsp/resources/web-jsptaglibrary_1_2.dtd");
|
||||
taglib20=jsp_page.getResource("javax/servlet/jsp/resources/web-jsptaglibrary_2_0.xsd");
|
||||
taglib21=jsp_page.getResource("javax/servlet/jsp/resources/web-jsptaglibrary_2_1.xsd");
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
Log.ignore(e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if(taglib11==null)
|
||||
taglib11=Loader.getResource(Servlet.class,"javax/servlet/jsp/resources/web-jsptaglibrary_1_1.dtd",true);
|
||||
if(taglib12==null)
|
||||
taglib12=Loader.getResource(Servlet.class,"javax/servlet/jsp/resources/web-jsptaglibrary_1_2.dtd",true);
|
||||
if(taglib20==null)
|
||||
taglib20=Loader.getResource(Servlet.class,"javax/servlet/jsp/resources/web-jsptaglibrary_2_0.xsd",true);
|
||||
if(taglib21==null)
|
||||
taglib21=Loader.getResource(Servlet.class,"javax/servlet/jsp/resources/web-jsptaglibrary_2_1.xsd",true);
|
||||
}
|
||||
|
||||
|
||||
if(taglib11!=null)
|
||||
{
|
||||
_parser.redirectEntity("web-jsptaglib_1_1.dtd",taglib11);
|
||||
_parser.redirectEntity("web-jsptaglibrary_1_1.dtd",taglib11);
|
||||
}
|
||||
if(taglib12!=null)
|
||||
{
|
||||
_parser.redirectEntity("web-jsptaglib_1_2.dtd",taglib12);
|
||||
_parser.redirectEntity("web-jsptaglibrary_1_2.dtd",taglib12);
|
||||
}
|
||||
if(taglib20!=null)
|
||||
{
|
||||
_parser.redirectEntity("web-jsptaglib_2_0.xsd",taglib20);
|
||||
_parser.redirectEntity("web-jsptaglibrary_2_0.xsd",taglib20);
|
||||
}
|
||||
if(taglib21!=null)
|
||||
{
|
||||
_parser.redirectEntity("web-jsptaglib_2_1.xsd",taglib21);
|
||||
_parser.redirectEntity("web-jsptaglibrary_2_1.xsd",taglib21);
|
||||
}
|
||||
|
||||
_parser.setXpath("/taglib/listener/listener-class");
|
||||
}
|
||||
|
||||
|
||||
public XmlParser.Node parse (Resource tld)
|
||||
throws Exception
|
||||
{
|
||||
XmlParser.Node root;
|
||||
try
|
||||
{
|
||||
//xerces on apple appears to sometimes close the zip file instead
|
||||
//of the inputstream, so try opening the input stream, but if
|
||||
//that doesn't work, fallback to opening a new url
|
||||
root = _parser.parse(tld.getInputStream());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
root = _parser.parse(tld.getURL().toString());
|
||||
}
|
||||
|
||||
if (root==null)
|
||||
{
|
||||
Log.warn("No TLD root in {}",tld);
|
||||
}
|
||||
else
|
||||
_roots.add(root);
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
public void processRoots ()
|
||||
{
|
||||
for (XmlParser.Node root: _roots)
|
||||
process(root);
|
||||
}
|
||||
|
||||
public void process (XmlParser.Node root)
|
||||
{
|
||||
for (int i=0;i<root.size();i++)
|
||||
{
|
||||
Object o=root.get(i);
|
||||
if (o instanceof XmlParser.Node)
|
||||
{
|
||||
XmlParser.Node node = (XmlParser.Node)o;
|
||||
if ("listener".equals(node.getTag()))
|
||||
{
|
||||
String className=node.getString("listener-class",false,true);
|
||||
if (Log.isDebugEnabled()) Log.debug("listener="+className);
|
||||
|
||||
try
|
||||
{
|
||||
Class listenerClass = _context.loadClass(className);
|
||||
EventListener l = (EventListener)listenerClass.newInstance();
|
||||
_context.addEventListener(l);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
Log.warn("Could not instantiate listener "+className+": "+e);
|
||||
Log.debug(e);
|
||||
}
|
||||
catch(Error e)
|
||||
{
|
||||
Log.warn("Could not instantiate listener "+className+": "+e);
|
||||
Log.debug(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void preConfigure(WebAppContext context) throws Exception
|
||||
{
|
||||
Set tlds = new HashSet();
|
||||
|
||||
// Find tld's from web.xml
|
||||
// When web.xml was processed, it should have created aliases for all TLDs. So search resources aliases
|
||||
// for aliases ending in tld
|
||||
if (context.getResourceAliases()!=null &&
|
||||
context.getBaseResource()!=null &&
|
||||
context.getBaseResource().exists())
|
||||
{
|
||||
Iterator iter=context.getResourceAliases().values().iterator();
|
||||
while(iter.hasNext())
|
||||
{
|
||||
String location = (String)iter.next();
|
||||
|
@ -141,14 +265,14 @@ public class TagLibConfiguration implements Configuration
|
|||
{
|
||||
if (!location.startsWith("/"))
|
||||
location="/WEB-INF/"+location;
|
||||
Resource l=_context.getBaseResource().addPath(location);
|
||||
Resource l=context.getBaseResource().addPath(location);
|
||||
tlds.add(l);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Look for any tlds in WEB-INF directly.
|
||||
Resource web_inf = _context.getWebInf();
|
||||
Resource web_inf = context.getWebInf();
|
||||
if (web_inf!=null)
|
||||
{
|
||||
String[] contents = web_inf.list();
|
||||
|
@ -156,13 +280,14 @@ public class TagLibConfiguration implements Configuration
|
|||
{
|
||||
if (contents[i]!=null && contents[i].toLowerCase().endsWith(".tld"))
|
||||
{
|
||||
Resource l=_context.getWebInf().addPath(contents[i]);
|
||||
Resource l=context.getWebInf().addPath(contents[i]);
|
||||
tlds.add(l);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Look for tlds in any jars
|
||||
//Use an opt-in style:
|
||||
//
|
||||
|
@ -181,81 +306,33 @@ public class TagLibConfiguration implements Configuration
|
|||
// else
|
||||
// examine only files matching pattern
|
||||
//
|
||||
String tmp = _context.getInitParameter(__web_inf_pattern);
|
||||
String tmp = context.getInitParameter(__web_inf_pattern);
|
||||
Pattern webInfPattern = (tmp==null?null:Pattern.compile(tmp));
|
||||
tmp = _context.getInitParameter(__container_pattern);
|
||||
tmp = context.getInitParameter(__container_pattern);
|
||||
Pattern containerPattern = (tmp==null?null:Pattern.compile(tmp));
|
||||
|
||||
TagLibJarScanner tldScanner = new TagLibJarScanner();
|
||||
List<URL> tldJars = (List<URL>)context.getAttribute(MetaInfConfiguration.__tldJars);
|
||||
|
||||
TagLibJarScanner tldScanner = new TagLibJarScanner(context);
|
||||
try
|
||||
{
|
||||
tldScanner.setTldSet(tlds);
|
||||
tldScanner.scan(webInfPattern, Thread.currentThread().getContextClassLoader(), true, false);
|
||||
//scan the jars we know have META-INF/tld files
|
||||
if (tldJars != null)
|
||||
tldScanner.scan(webInfPattern, tldJars.toArray(new URL[tldJars.size()]), true);
|
||||
|
||||
//scan the parent loader for tld files
|
||||
tldScanner.scan(containerPattern, Thread.currentThread().getContextClassLoader().getParent(), false, true);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.warn(e);
|
||||
}
|
||||
|
||||
|
||||
// Create a TLD parser
|
||||
XmlParser parser = new XmlParser(false);
|
||||
|
||||
URL taglib11=null;
|
||||
URL taglib12=null;
|
||||
URL taglib20=null;
|
||||
URL taglib21=null;
|
||||
|
||||
try
|
||||
{
|
||||
Class jsp_page = Loader.loadClass(WebXmlConfiguration.class,"javax.servlet.jsp.JspPage");
|
||||
taglib11=jsp_page.getResource("javax/servlet/jsp/resources/web-jsptaglibrary_1_1.dtd");
|
||||
taglib12=jsp_page.getResource("javax/servlet/jsp/resources/web-jsptaglibrary_1_2.dtd");
|
||||
taglib20=jsp_page.getResource("javax/servlet/jsp/resources/web-jsptaglibrary_2_0.xsd");
|
||||
taglib21=jsp_page.getResource("javax/servlet/jsp/resources/web-jsptaglibrary_2_1.xsd");
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
Log.ignore(e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if(taglib11==null)
|
||||
taglib11=Loader.getResource(Servlet.class,"javax/servlet/jsp/resources/web-jsptaglibrary_1_1.dtd",true);
|
||||
if(taglib12==null)
|
||||
taglib12=Loader.getResource(Servlet.class,"javax/servlet/jsp/resources/web-jsptaglibrary_1_2.dtd",true);
|
||||
if(taglib20==null)
|
||||
taglib20=Loader.getResource(Servlet.class,"javax/servlet/jsp/resources/web-jsptaglibrary_2_0.xsd",true);
|
||||
if(taglib21==null)
|
||||
taglib21=Loader.getResource(Servlet.class,"javax/servlet/jsp/resources/web-jsptaglibrary_2_1.xsd",true);
|
||||
}
|
||||
|
||||
|
||||
if(taglib11!=null)
|
||||
{
|
||||
parser.redirectEntity("web-jsptaglib_1_1.dtd",taglib11);
|
||||
parser.redirectEntity("web-jsptaglibrary_1_1.dtd",taglib11);
|
||||
}
|
||||
if(taglib12!=null)
|
||||
{
|
||||
parser.redirectEntity("web-jsptaglib_1_2.dtd",taglib12);
|
||||
parser.redirectEntity("web-jsptaglibrary_1_2.dtd",taglib12);
|
||||
}
|
||||
if(taglib20!=null)
|
||||
{
|
||||
parser.redirectEntity("web-jsptaglib_2_0.xsd",taglib20);
|
||||
parser.redirectEntity("web-jsptaglibrary_2_0.xsd",taglib20);
|
||||
}
|
||||
if(taglib21!=null)
|
||||
{
|
||||
parser.redirectEntity("web-jsptaglib_2_1.xsd",taglib21);
|
||||
parser.redirectEntity("web-jsptaglibrary_2_1.xsd",taglib21);
|
||||
}
|
||||
|
||||
parser.setXpath("/taglib/listener/listener-class");
|
||||
|
||||
// Parse all the discovered TLDs
|
||||
|
||||
// Create a processor for the tlds and save it
|
||||
TldProcessor processor = new TldProcessor (context);
|
||||
context.setAttribute(TldProcessor.__taglib_processor, processor);
|
||||
// Parse the tlds into memory
|
||||
Iterator iter = tlds.iterator();
|
||||
while (iter.hasNext())
|
||||
{
|
||||
|
@ -263,57 +340,7 @@ public class TagLibConfiguration implements Configuration
|
|||
{
|
||||
Resource tld = (Resource)iter.next();
|
||||
if (Log.isDebugEnabled()) Log.debug("TLD="+tld);
|
||||
|
||||
XmlParser.Node root;
|
||||
|
||||
try
|
||||
{
|
||||
//xerces on apple appears to sometimes close the zip file instead
|
||||
//of the inputstream, so try opening the input stream, but if
|
||||
//that doesn't work, fallback to opening a new url
|
||||
root = parser.parse(tld.getInputStream());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
root = parser.parse(tld.getURL().toString());
|
||||
}
|
||||
|
||||
if (root==null)
|
||||
{
|
||||
Log.warn("No TLD root in {}",tld);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int i=0;i<root.size();i++)
|
||||
{
|
||||
Object o=root.get(i);
|
||||
if (o instanceof XmlParser.Node)
|
||||
{
|
||||
XmlParser.Node node = (XmlParser.Node)o;
|
||||
if ("listener".equals(node.getTag()))
|
||||
{
|
||||
String className=node.getString("listener-class",false,true);
|
||||
if (Log.isDebugEnabled()) Log.debug("listener="+className);
|
||||
|
||||
try
|
||||
{
|
||||
Class listenerClass=getWebAppContext().loadClass(className);
|
||||
EventListener l=(EventListener)listenerClass.newInstance();
|
||||
_context.addEventListener(l);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
Log.warn("Could not instantiate listener "+className+": "+e);
|
||||
Log.debug(e);
|
||||
}
|
||||
catch(Error e)
|
||||
{
|
||||
Log.warn("Could not instantiate listener "+className+": "+e);
|
||||
Log.debug(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
processor.parse(tld);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
|
@ -321,11 +348,31 @@ public class TagLibConfiguration implements Configuration
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void configure (WebAppContext context) throws Exception
|
||||
{
|
||||
TldProcessor processor = (TldProcessor)context.getAttribute(TldProcessor.__taglib_processor);
|
||||
if (processor == null)
|
||||
{
|
||||
Log.warn("No TldProcessor configured, skipping tld processing");
|
||||
return;
|
||||
}
|
||||
|
||||
public void deconfigureWebApp() throws Exception
|
||||
{
|
||||
//Create listeners from the parsed tld trees
|
||||
processor.processRoots();
|
||||
}
|
||||
|
||||
public void postConfigure(WebAppContext context) throws Exception
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
public void deconfigure(WebAppContext context) throws Exception
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -73,6 +73,8 @@ public class WebAppContext extends ServletContextHandler
|
|||
{
|
||||
"org.eclipse.jetty.webapp.WebInfConfiguration",
|
||||
"org.eclipse.jetty.webapp.WebXmlConfiguration",
|
||||
"org.eclipse.jetty.webapp.MetaInfConfiguration",
|
||||
"org.eclipse.jetty.webapp.FragmentConfiguration",
|
||||
"org.eclipse.jetty.webapp.JettyWebXmlConfiguration",
|
||||
"org.eclipse.jetty.webapp.TagLibConfiguration"
|
||||
} ;
|
||||
|
@ -107,7 +109,6 @@ public class WebAppContext extends ServletContextHandler
|
|||
"org.slf4j." // hide slf4j
|
||||
};
|
||||
private File _tmpDir;
|
||||
private boolean _isExistingTmpDir;
|
||||
private String _war;
|
||||
private String _extraClasspath;
|
||||
private Throwable _unavailableException;
|
||||
|
@ -296,9 +297,7 @@ public class WebAppContext extends ServletContextHandler
|
|||
// Setup configurations
|
||||
loadConfigurations();
|
||||
|
||||
for (int i=0;i<_configurations.length;i++)
|
||||
_configurations[i].setWebAppContext(this);
|
||||
|
||||
|
||||
// Configure classloader
|
||||
_ownClassLoader=false;
|
||||
if (getClassLoader()==null)
|
||||
|
@ -319,19 +318,17 @@ public class WebAppContext extends ServletContextHandler
|
|||
loader=loader.getParent();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Prepare for configuration
|
||||
for (int i=0;i<_configurations.length;i++)
|
||||
_configurations[i].configureClassLoader();
|
||||
|
||||
getTempDirectory();
|
||||
if (_tmpDir!=null && !_isExistingTmpDir && !isTempWorkDirectory())
|
||||
{
|
||||
File sentinel = new File(_tmpDir, ".active");
|
||||
if(!sentinel.exists())
|
||||
sentinel.mkdir();
|
||||
}
|
||||
|
||||
_configurations[i].preConfigure(this);
|
||||
|
||||
super.doStart();
|
||||
|
||||
// Clean up after configuration
|
||||
for (int i=0;i<_configurations.length;i++)
|
||||
_configurations[i].postConfigure(this);
|
||||
|
||||
|
||||
if (isLogUrlOnStart())
|
||||
dumpUrl();
|
||||
|
@ -373,9 +370,9 @@ public class WebAppContext extends ServletContextHandler
|
|||
|
||||
try
|
||||
{
|
||||
// Configure classloader
|
||||
for (int i=_configurations.length;i-->0;)
|
||||
_configurations[i].deconfigureWebApp();
|
||||
_configurations[i].deconfigure(this);
|
||||
|
||||
_configurations=null;
|
||||
|
||||
// restore security handler
|
||||
|
@ -384,13 +381,6 @@ public class WebAppContext extends ServletContextHandler
|
|||
_sessionHandler.setHandler(_securityHandler);
|
||||
_securityHandler.setHandler(_servletHandler);
|
||||
}
|
||||
|
||||
// delete temp directory if we had to create it or if it isn't called work
|
||||
if (_tmpDir!=null && !_isExistingTmpDir && !isTempWorkDirectory()) //_tmpDir!=null && !"work".equals(_tmpDir.getName()))
|
||||
{
|
||||
IO.delete(_tmpDir);
|
||||
_tmpDir=null;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@ -540,186 +530,7 @@ public class WebAppContext extends ServletContextHandler
|
|||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Get a temporary directory in which to unpack the war etc etc.
|
||||
* The algorithm for determining this is to check these alternatives
|
||||
* in the order shown:
|
||||
*
|
||||
* <p>A. Try to use an explicit directory specifically for this webapp:</p>
|
||||
* <ol>
|
||||
* <li>
|
||||
* Iff an explicit directory is set for this webapp, use it. Do NOT set
|
||||
* delete on exit.
|
||||
* </li>
|
||||
* <li>
|
||||
* Iff javax.servlet.context.tempdir context attribute is set for
|
||||
* this webapp && exists && writeable, then use it. Do NOT set delete on exit.
|
||||
* </li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>B. Create a directory based on global settings. The new directory
|
||||
* will be called "Jetty_"+host+"_"+port+"__"+context+"_"+virtualhost
|
||||
* Work out where to create this directory:
|
||||
* <ol>
|
||||
* <li>
|
||||
* Iff $(jetty.home)/work exists create the directory there. Do NOT
|
||||
* set delete on exit. Do NOT delete contents if dir already exists.
|
||||
* </li>
|
||||
* <li>
|
||||
* Iff WEB-INF/work exists create the directory there. Do NOT set
|
||||
* delete on exit. Do NOT delete contents if dir already exists.
|
||||
* </li>
|
||||
* <li>
|
||||
* Else create dir in $(java.io.tmpdir). Set delete on exit. Delete
|
||||
* contents if dir already exists.
|
||||
* </li>
|
||||
* </ol>
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public File getTempDirectory()
|
||||
{
|
||||
if (_tmpDir!=null && _tmpDir.isDirectory() && _tmpDir.canWrite())
|
||||
return _tmpDir;
|
||||
|
||||
// Initialize temporary directory
|
||||
//
|
||||
// I'm afraid that this is very much black magic.
|
||||
// but if you can think of better....
|
||||
Object t = getAttribute(TEMPDIR);
|
||||
|
||||
if (t!=null && (t instanceof File))
|
||||
{
|
||||
_tmpDir=(File)t;
|
||||
if (_tmpDir.isDirectory() && _tmpDir.canWrite())
|
||||
return _tmpDir;
|
||||
}
|
||||
|
||||
if (t!=null && (t instanceof String))
|
||||
{
|
||||
try
|
||||
{
|
||||
_tmpDir=new File((String)t);
|
||||
|
||||
if (_tmpDir.isDirectory() && _tmpDir.canWrite())
|
||||
{
|
||||
if(Log.isDebugEnabled())Log.debug("Converted to File "+_tmpDir+" for "+this);
|
||||
setAttribute(TEMPDIR,_tmpDir);
|
||||
return _tmpDir;
|
||||
}
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
Log.warn(Log.EXCEPTION,e);
|
||||
}
|
||||
}
|
||||
|
||||
// No tempdir so look for a work directory to use as tempDir base
|
||||
File work=null;
|
||||
try
|
||||
{
|
||||
File w=new File(System.getProperty("jetty.home"),"work");
|
||||
if (w.exists() && w.canWrite() && w.isDirectory())
|
||||
work=w;
|
||||
else if (getBaseResource()!=null)
|
||||
{
|
||||
Resource web_inf = getWebInf();
|
||||
if (web_inf !=null && web_inf.exists())
|
||||
{
|
||||
w=new File(web_inf.getFile(),"work");
|
||||
if (w.exists() && w.canWrite() && w.isDirectory())
|
||||
work=w;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
Log.ignore(e);
|
||||
}
|
||||
|
||||
// No tempdir set so make one!
|
||||
try
|
||||
{
|
||||
|
||||
String temp = getCanonicalNameForWebAppTmpDir();
|
||||
|
||||
if (work!=null)
|
||||
_tmpDir=new File(work,temp);
|
||||
else
|
||||
{
|
||||
_tmpDir=new File(System.getProperty("java.io.tmpdir"),temp);
|
||||
|
||||
if (_tmpDir.exists())
|
||||
{
|
||||
if(Log.isDebugEnabled())Log.debug("Delete existing temp dir "+_tmpDir+" for "+this);
|
||||
if (!IO.delete(_tmpDir))
|
||||
{
|
||||
if(Log.isDebugEnabled())Log.debug("Failed to delete temp dir "+_tmpDir);
|
||||
}
|
||||
|
||||
if (_tmpDir.exists())
|
||||
{
|
||||
String old=_tmpDir.toString();
|
||||
_tmpDir=File.createTempFile(temp+"_","");
|
||||
if (_tmpDir.exists())
|
||||
_tmpDir.delete();
|
||||
Log.warn("Can't reuse "+old+", using "+_tmpDir);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!_tmpDir.exists())
|
||||
_tmpDir.mkdir();
|
||||
|
||||
//if not in a dir called "work" then we want to delete it on jvm exit
|
||||
if (!isTempWorkDirectory())
|
||||
_tmpDir.deleteOnExit();
|
||||
if(Log.isDebugEnabled())Log.debug("Created temp dir "+_tmpDir+" for "+this);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
_tmpDir=null;
|
||||
Log.ignore(e);
|
||||
}
|
||||
|
||||
if (_tmpDir==null)
|
||||
{
|
||||
try{
|
||||
// that didn't work, so try something simpler (ish)
|
||||
_tmpDir=File.createTempFile("JettyContext","");
|
||||
if (_tmpDir.exists())
|
||||
_tmpDir.delete();
|
||||
_tmpDir.mkdir();
|
||||
_tmpDir.deleteOnExit();
|
||||
if(Log.isDebugEnabled())Log.debug("Created temp dir "+_tmpDir+" for "+this);
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
Log.warn("tmpdir",e); System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
setAttribute(TEMPDIR,_tmpDir);
|
||||
return _tmpDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the _tmpDir itself is called "work", or if the _tmpDir
|
||||
* is in a directory called "work".
|
||||
* @return
|
||||
*/
|
||||
public boolean isTempWorkDirectory ()
|
||||
{
|
||||
if (_tmpDir == null)
|
||||
return false;
|
||||
if (_tmpDir.getName().equalsIgnoreCase("work"))
|
||||
return true;
|
||||
File t = _tmpDir.getParentFile();
|
||||
if (t == null)
|
||||
return false;
|
||||
return (t.getName().equalsIgnoreCase("work"));
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
|
@ -735,7 +546,8 @@ public class WebAppContext extends ServletContextHandler
|
|||
/* ------------------------------------------------------------ */
|
||||
public Resource getWebInf() throws IOException
|
||||
{
|
||||
resolveWebApp();
|
||||
if (super.getBaseResource() == null)
|
||||
return null;
|
||||
|
||||
// Iw there a WEB-INF directory?
|
||||
Resource web_inf= super.getBaseResource().addPath("WEB-INF/");
|
||||
|
@ -813,104 +625,8 @@ public class WebAppContext extends ServletContextHandler
|
|||
return super.toString()+(_war==null?"":(","+_war));
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Resolve Web App directory
|
||||
* If the BaseResource has not been set, use the war resource to
|
||||
* derive a webapp resource (expanding WAR if required).
|
||||
*/
|
||||
protected void resolveWebApp() throws IOException
|
||||
{
|
||||
Resource web_app = super.getBaseResource();
|
||||
if (web_app == null)
|
||||
{
|
||||
if (_war==null || _war.length()==0)
|
||||
_war=getResourceBase();
|
||||
|
||||
// Set dir or WAR
|
||||
web_app= newResource(_war);
|
||||
|
||||
// Accept aliases for WAR files
|
||||
if (web_app.getAlias() != null)
|
||||
{
|
||||
Log.debug(web_app + " anti-aliased to " + web_app.getAlias());
|
||||
web_app= newResource(web_app.getAlias());
|
||||
}
|
||||
|
||||
if (Log.isDebugEnabled())
|
||||
Log.debug("Try webapp=" + web_app + ", exists=" + web_app.exists() + ", directory=" + web_app.isDirectory());
|
||||
|
||||
// Is the WAR usable directly?
|
||||
if (web_app.exists() && !web_app.isDirectory() && !web_app.toString().startsWith("jar:"))
|
||||
{
|
||||
// No - then lets see if it can be turned into a jar URL.
|
||||
Resource jarWebApp= newResource("jar:" + web_app + "!/");
|
||||
if (jarWebApp.exists() && jarWebApp.isDirectory())
|
||||
{
|
||||
web_app= jarWebApp;
|
||||
}
|
||||
}
|
||||
|
||||
// If we should extract or the URL is still not usable
|
||||
if (web_app.exists() && (
|
||||
(_copyDir && web_app.getFile()!= null && web_app.getFile().isDirectory())
|
||||
||
|
||||
(_extractWAR && web_app.getFile()!= null && !web_app.getFile().isDirectory())
|
||||
||
|
||||
(_extractWAR && web_app.getFile() == null)
|
||||
||
|
||||
!web_app.isDirectory()
|
||||
))
|
||||
{
|
||||
// Then extract it if necessary.
|
||||
File extractedWebAppDir= new File(getTempDirectory(), "webapp");
|
||||
|
||||
if (web_app.getFile()!=null && web_app.getFile().isDirectory())
|
||||
{
|
||||
// Copy directory
|
||||
Log.info("Copy " + web_app.getFile() + " to " + extractedWebAppDir);
|
||||
IO.copyDir(web_app.getFile(),extractedWebAppDir);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!extractedWebAppDir.exists())
|
||||
{
|
||||
//it hasn't been extracted before so extract it
|
||||
extractedWebAppDir.mkdir();
|
||||
Log.info("Extract " + _war + " to " + extractedWebAppDir);
|
||||
JarResource.extract(web_app, extractedWebAppDir, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
//only extract if the war file is newer
|
||||
if (web_app.lastModified() > extractedWebAppDir.lastModified())
|
||||
{
|
||||
extractedWebAppDir.delete();
|
||||
extractedWebAppDir.mkdir();
|
||||
Log.info("Extract " + _war + " to " + extractedWebAppDir);
|
||||
JarResource.extract(web_app, extractedWebAppDir, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
web_app= Resource.newResource(extractedWebAppDir.getCanonicalPath());
|
||||
|
||||
}
|
||||
|
||||
// Now do we have something usable?
|
||||
if (!web_app.exists() || !web_app.isDirectory())
|
||||
{
|
||||
Log.warn("Web application not found " + _war);
|
||||
throw new java.io.FileNotFoundException(_war);
|
||||
}
|
||||
|
||||
if (Log.isDebugEnabled())
|
||||
Log.debug("webapp=" + web_app);
|
||||
|
||||
// ResourcePath
|
||||
super.setBaseResource(web_app);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
|
@ -1112,8 +828,6 @@ public class WebAppContext extends ServletContextHandler
|
|||
dir.mkdir();
|
||||
dir.deleteOnExit();
|
||||
}
|
||||
else if (dir != null)
|
||||
_isExistingTmpDir = true;
|
||||
|
||||
if (dir!=null && ( !dir.exists() || !dir.isDirectory() || !dir.canWrite()))
|
||||
throw new IllegalArgumentException("Bad temp directory: "+dir);
|
||||
|
@ -1122,6 +836,11 @@ public class WebAppContext extends ServletContextHandler
|
|||
setAttribute(TEMPDIR,_tmpDir);
|
||||
}
|
||||
|
||||
public File getTempDirectory ()
|
||||
{
|
||||
return _tmpDir;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @param war The war to set as a file name or URL
|
||||
|
@ -1175,120 +894,14 @@ public class WebAppContext extends ServletContextHandler
|
|||
protected void startContext()
|
||||
throws Exception
|
||||
{
|
||||
// Configure defaults
|
||||
for (int i=0;i<_configurations.length;i++)
|
||||
_configurations[i].configureDefaults();
|
||||
|
||||
// Is there a WEB-INF work directory
|
||||
Resource web_inf=getWebInf();
|
||||
if (web_inf!=null)
|
||||
{
|
||||
Resource work= web_inf.addPath("work");
|
||||
if (work.exists()
|
||||
&& work.isDirectory()
|
||||
&& work.getFile() != null
|
||||
&& work.getFile().canWrite()
|
||||
&& getAttribute(TEMPDIR) == null)
|
||||
setAttribute(TEMPDIR, work.getFile());
|
||||
}
|
||||
|
||||
|
||||
// Configure webapp
|
||||
for (int i=0;i<_configurations.length;i++)
|
||||
_configurations[i].configureWebApp();
|
||||
_configurations[i].configure(this);
|
||||
|
||||
|
||||
super.startContext();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a canonical name for a webapp tmp directory.
|
||||
* The form of the name is:
|
||||
* "Jetty_"+host+"_"+port+"__"+resourceBase+"_"+context+"_"+virtualhost+base36 hashcode of whole string
|
||||
*
|
||||
* host and port uniquely identify the server
|
||||
* context and virtual host uniquely identify the webapp
|
||||
* @return
|
||||
*/
|
||||
private String getCanonicalNameForWebAppTmpDir ()
|
||||
{
|
||||
StringBuffer canonicalName = new StringBuffer();
|
||||
canonicalName.append("Jetty");
|
||||
|
||||
//get the host and the port from the first connector
|
||||
Connector[] connectors = getServer().getConnectors();
|
||||
|
||||
|
||||
//Get the host
|
||||
canonicalName.append("_");
|
||||
String host = (connectors==null||connectors[0]==null?"":connectors[0].getHost());
|
||||
if (host == null)
|
||||
host = "0.0.0.0";
|
||||
canonicalName.append(host.replace('.', '_'));
|
||||
|
||||
//Get the port
|
||||
canonicalName.append("_");
|
||||
//try getting the real port being listened on
|
||||
int port = (connectors==null||connectors[0]==null?0:connectors[0].getLocalPort());
|
||||
//if not available (eg no connectors or connector not started),
|
||||
//try getting one that was configured.
|
||||
if (port < 0)
|
||||
port = connectors[0].getPort();
|
||||
canonicalName.append(port);
|
||||
|
||||
|
||||
//Resource base
|
||||
canonicalName.append("_");
|
||||
try
|
||||
{
|
||||
Resource resource = super.getBaseResource();
|
||||
if (resource == null)
|
||||
{
|
||||
if (_war==null || _war.length()==0)
|
||||
resource=newResource(getResourceBase());
|
||||
|
||||
// Set dir or WAR
|
||||
resource= newResource(_war);
|
||||
}
|
||||
|
||||
String tmp = URIUtil.decodePath(resource.getURL().getPath());
|
||||
if (tmp.endsWith("/"))
|
||||
tmp = tmp.substring(0, tmp.length()-1);
|
||||
if (tmp.endsWith("!"))
|
||||
tmp = tmp.substring(0, tmp.length() -1);
|
||||
//get just the last part which is the filename
|
||||
int i = tmp.lastIndexOf("/");
|
||||
canonicalName.append(tmp.substring(i+1, tmp.length()));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.warn("Can't generate resourceBase as part of webapp tmp dir name", e);
|
||||
}
|
||||
|
||||
//Context name
|
||||
canonicalName.append("_");
|
||||
String contextPath = getContextPath();
|
||||
contextPath=contextPath.replace('/','_');
|
||||
contextPath=contextPath.replace('\\','_');
|
||||
canonicalName.append(contextPath);
|
||||
|
||||
//Virtual host (if there is one)
|
||||
canonicalName.append("_");
|
||||
String[] vhosts = getVirtualHosts();
|
||||
canonicalName.append((vhosts==null||vhosts[0]==null?"":vhosts[0]));
|
||||
|
||||
//base36 hash of the whole string for uniqueness
|
||||
String hash = Integer.toString(canonicalName.toString().hashCode(),36);
|
||||
canonicalName.append("_");
|
||||
canonicalName.append(hash);
|
||||
|
||||
// sanitize
|
||||
for (int i=0;i<canonicalName.length();i++)
|
||||
{
|
||||
char c=canonicalName.charAt(i);
|
||||
if (!Character.isJavaIdentifierPart(c))
|
||||
canonicalName.setCharAt(i,'.');
|
||||
}
|
||||
|
||||
return canonicalName.toString();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,94 +1,484 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) 2003-2009 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
package org.eclipse.jetty.webapp;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.eclipse.jetty.server.Connector;
|
||||
import org.eclipse.jetty.util.IO;
|
||||
import org.eclipse.jetty.util.URIUtil;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.resource.JarResource;
|
||||
import org.eclipse.jetty.util.resource.Resource;
|
||||
/* ------------------------------------------------------------------------------- */
|
||||
/**
|
||||
* Configure class path from a WEB-INF directory found within a contexts resource base.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
public class WebInfConfiguration implements Configuration
|
||||
{
|
||||
protected WebAppContext _context;
|
||||
|
||||
public WebInfConfiguration()
|
||||
public static final String TEMPDIR_CREATED = "org.eclipse.jetty.tmpdirCreated";
|
||||
|
||||
public void preConfigure(WebAppContext context) throws Exception
|
||||
{
|
||||
}
|
||||
//Make a temp directory for the webapp if one is not already set
|
||||
resolveTempDirectory(context);
|
||||
|
||||
//Extract webapp if necessary
|
||||
unpack (context);
|
||||
|
||||
/* ------------------------------------------------------------------------------- */
|
||||
public void setWebAppContext (WebAppContext context)
|
||||
File work = findWorkDirectory(context);
|
||||
if (work != null)
|
||||
makeTempDirectory(work, context, false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void postConfigure(WebAppContext context) throws Exception
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
/* ------------------------------------------------------------------------------- */
|
||||
public WebAppContext getWebAppContext()
|
||||
{
|
||||
return _context;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------- */
|
||||
/** Configure ClassPath.
|
||||
* This method is called before the context ClassLoader is created.
|
||||
* Paths and libraries should be added to the context using the setClassPath,
|
||||
* addClassPath and addClassPaths methods. The default implementation looks
|
||||
* for WEB-INF/classes, WEB-INF/lib/*.zip and WEB-INF/lib/*.jar
|
||||
* @throws Exception
|
||||
*/
|
||||
public void configureClassLoader()
|
||||
throws Exception
|
||||
public void configure(WebAppContext context) throws Exception
|
||||
{
|
||||
//cannot configure if the context is already started
|
||||
if (_context.isStarted())
|
||||
if (context.isStarted())
|
||||
{
|
||||
if (Log.isDebugEnabled()){Log.debug("Cannot configure webapp after it is started");}
|
||||
if (Log.isDebugEnabled()){Log.debug("Cannot configure webapp "+context+" after it is started");}
|
||||
return;
|
||||
}
|
||||
|
||||
Resource web_inf=_context.getWebInf();
|
||||
Resource web_inf = context.getWebInf();
|
||||
|
||||
// Add WEB-INF classes and lib classpaths
|
||||
if (web_inf != null && web_inf.isDirectory() && _context.getClassLoader() instanceof WebAppClassLoader)
|
||||
if (web_inf != null && web_inf.isDirectory() && context.getClassLoader() instanceof WebAppClassLoader)
|
||||
{
|
||||
// Look for classes directory
|
||||
Resource classes= web_inf.addPath("classes/");
|
||||
if (classes.exists())
|
||||
((WebAppClassLoader)_context.getClassLoader()).addClassPath(classes.toString());
|
||||
((WebAppClassLoader)context.getClassLoader()).addClassPath(classes.toString());
|
||||
|
||||
// Look for jars
|
||||
Resource lib= web_inf.addPath("lib/");
|
||||
if (lib.exists() || lib.isDirectory())
|
||||
((WebAppClassLoader)_context.getClassLoader()).addJars(lib);
|
||||
((WebAppClassLoader)context.getClassLoader()).addJars(lib);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void deconfigure(WebAppContext context) throws Exception
|
||||
{
|
||||
// delete temp directory if we had to create it or if it isn't called work
|
||||
Boolean containerCreated = (Boolean)context.getAttribute(TEMPDIR_CREATED);
|
||||
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------- */
|
||||
public void configureDefaults() throws Exception
|
||||
{
|
||||
if (context.getTempDirectory()!=null && (containerCreated != null && containerCreated.booleanValue()) && !isTempWorkDirectory(context.getTempDirectory()))
|
||||
{
|
||||
IO.delete(context.getTempDirectory());
|
||||
setTempDirectory(null, context);
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------- */
|
||||
public void configureWebApp() throws Exception
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Get a temporary directory in which to unpack the war etc etc.
|
||||
* The algorithm for determining this is to check these alternatives
|
||||
* in the order shown:
|
||||
*
|
||||
* <p>A. Try to use an explicit directory specifically for this webapp:</p>
|
||||
* <ol>
|
||||
* <li>
|
||||
* Iff an explicit directory is set for this webapp, use it. Do NOT set
|
||||
* delete on exit.
|
||||
* </li>
|
||||
* <li>
|
||||
* Iff javax.servlet.context.tempdir context attribute is set for
|
||||
* this webapp && exists && writeable, then use it. Do NOT set delete on exit.
|
||||
* </li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>B. Create a directory based on global settings. The new directory
|
||||
* will be called "Jetty_"+host+"_"+port+"__"+context+"_"+virtualhost
|
||||
* Work out where to create this directory:
|
||||
* <ol>
|
||||
* <li>
|
||||
* Iff $(jetty.home)/work exists create the directory there. Do NOT
|
||||
* set delete on exit. Do NOT delete contents if dir already exists.
|
||||
* </li>
|
||||
* <li>
|
||||
* Iff WEB-INF/work exists create the directory there. Do NOT set
|
||||
* delete on exit. Do NOT delete contents if dir already exists.
|
||||
* </li>
|
||||
* <li>
|
||||
* Else create dir in $(java.io.tmpdir). Set delete on exit. Delete
|
||||
* contents if dir already exists.
|
||||
* </li>
|
||||
* </ol>
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public void resolveTempDirectory (WebAppContext context)
|
||||
{
|
||||
//If a tmp directory is already set, we're done
|
||||
File tmpDir = context.getTempDirectory();
|
||||
if (tmpDir!=null && tmpDir.isDirectory() && tmpDir.canWrite())
|
||||
return; //Already have a suitable tmp dir configured
|
||||
|
||||
|
||||
//None configured, try and come up with one
|
||||
//First ... see if one is configured in a context attribute
|
||||
//either as a File or name of a file
|
||||
Object t = context.getAttribute(WebAppContext.TEMPDIR);
|
||||
if (t != null)
|
||||
{
|
||||
//Is it a File?
|
||||
if (t instanceof File)
|
||||
{
|
||||
tmpDir=(File)t;
|
||||
if (tmpDir.isDirectory() && tmpDir.canWrite())
|
||||
{
|
||||
context.setTempDirectory(tmpDir);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// The context attribute specified a name not a File
|
||||
if (t instanceof String)
|
||||
{
|
||||
try
|
||||
{
|
||||
tmpDir=new File((String)t);
|
||||
|
||||
if (tmpDir.isDirectory() && tmpDir.canWrite())
|
||||
{
|
||||
context.setAttribute(context.TEMPDIR,tmpDir);
|
||||
context.setTempDirectory(tmpDir);
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
Log.warn(Log.EXCEPTION,e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Second ... make a tmp directory, in a work directory if one exists
|
||||
String temp = getCanonicalNameForWebAppTmpDir(context);
|
||||
|
||||
try
|
||||
{
|
||||
//Put the tmp dir in the work directory if we had one
|
||||
File work = new File(System.getProperty("jetty.home"),"work");
|
||||
if (!work.exists() || !work.canWrite() || !work.isDirectory())
|
||||
work = null;
|
||||
|
||||
if (work!=null)
|
||||
makeTempDirectory(work, context, false); //make a tmp dir inside work, don't delete if it exists
|
||||
else
|
||||
makeTempDirectory(new File(System.getProperty("java.io.tmpdir")), context, true); //make a tmpdir, delete if it already exists
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
tmpDir=null;
|
||||
Log.ignore(e);
|
||||
}
|
||||
|
||||
//Third ... Something went wrong trying to make the tmp directory, just make
|
||||
//a jvm managed tmp directory
|
||||
if (context.getTempDirectory() == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Last resort
|
||||
tmpDir=File.createTempFile("JettyContext","");
|
||||
if (tmpDir.exists())
|
||||
tmpDir.delete();
|
||||
tmpDir.mkdir();
|
||||
tmpDir.deleteOnExit();
|
||||
setTempDirectory(tmpDir, context);
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
Log.warn("tmpdir",e); System.exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void makeTempDirectory (File parent, WebAppContext context, boolean deleteExisting)
|
||||
throws IOException
|
||||
{
|
||||
if (parent != null && parent.exists() && parent.canWrite() && parent.isDirectory())
|
||||
{
|
||||
String temp = getCanonicalNameForWebAppTmpDir(context);
|
||||
File tmpDir = new File(parent,temp);
|
||||
|
||||
if (deleteExisting && tmpDir.exists())
|
||||
{
|
||||
if (!IO.delete(tmpDir))
|
||||
{
|
||||
if(Log.isDebugEnabled())Log.debug("Failed to delete temp dir "+tmpDir);
|
||||
}
|
||||
|
||||
//If we can't delete the existing tmp dir, create a new one
|
||||
if (tmpDir.exists())
|
||||
{
|
||||
String old=tmpDir.toString();
|
||||
tmpDir=File.createTempFile(temp+"_","");
|
||||
if (tmpDir.exists())
|
||||
tmpDir.delete();
|
||||
Log.warn("Can't reuse "+old+", using "+tmpDir);
|
||||
}
|
||||
}
|
||||
|
||||
if (!tmpDir.exists())
|
||||
tmpDir.mkdir();
|
||||
|
||||
//If the parent is not a work directory
|
||||
if (!isTempWorkDirectory(tmpDir))
|
||||
{
|
||||
tmpDir.deleteOnExit();
|
||||
//TODO why is this here?
|
||||
File sentinel = new File(tmpDir, ".active");
|
||||
if(!sentinel.exists())
|
||||
sentinel.mkdir();
|
||||
}
|
||||
setTempDirectory(tmpDir, context);
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------- */
|
||||
public void deconfigureWebApp() throws Exception
|
||||
|
||||
public void setTempDirectory (File tmpDir, WebAppContext context)
|
||||
{
|
||||
context.setAttribute(TEMPDIR_CREATED, Boolean.TRUE);
|
||||
context.setAttribute(context.TEMPDIR,tmpDir);
|
||||
context.setTempDirectory(tmpDir);
|
||||
if(Log.isDebugEnabled())Log.debug("Set temp dir "+tmpDir);
|
||||
}
|
||||
|
||||
|
||||
public void unpack (WebAppContext context) throws IOException
|
||||
{
|
||||
Resource web_app = context.getBaseResource();
|
||||
if (web_app == null)
|
||||
{
|
||||
String war = context.getWar();
|
||||
if (war==null || war.length()==0)
|
||||
war=context.getResourceBase();
|
||||
|
||||
// Set dir or WAR
|
||||
web_app = context.newResource(war);
|
||||
|
||||
// Accept aliases for WAR files
|
||||
if (web_app.getAlias() != null)
|
||||
{
|
||||
Log.debug(web_app + " anti-aliased to " + web_app.getAlias());
|
||||
web_app = context.newResource(web_app.getAlias());
|
||||
}
|
||||
|
||||
if (Log.isDebugEnabled())
|
||||
Log.debug("Try webapp=" + web_app + ", exists=" + web_app.exists() + ", directory=" + web_app.isDirectory());
|
||||
|
||||
// Is the WAR usable directly?
|
||||
if (web_app.exists() && !web_app.isDirectory() && !web_app.toString().startsWith("jar:"))
|
||||
{
|
||||
// No - then lets see if it can be turned into a jar URL.
|
||||
Resource jarWebApp = context.newResource("jar:" + web_app + "!/");
|
||||
if (jarWebApp.exists() && jarWebApp.isDirectory())
|
||||
{
|
||||
web_app= jarWebApp;
|
||||
}
|
||||
}
|
||||
|
||||
// If we should extract or the URL is still not usable
|
||||
if (web_app.exists() &&
|
||||
(
|
||||
(context.isCopyWebDir() && web_app.getFile()!= null && web_app.getFile().isDirectory())
|
||||
||
|
||||
(context.isExtractWAR() && web_app.getFile()!= null && !web_app.getFile().isDirectory())
|
||||
||
|
||||
(context.isExtractWAR() && web_app.getFile() == null)
|
||||
||
|
||||
!web_app.isDirectory()
|
||||
))
|
||||
{
|
||||
// Then extract it if necessary to the temporary location
|
||||
File extractedWebAppDir= new File(context.getTempDirectory(), "webapp");
|
||||
|
||||
if (web_app.getFile()!=null && web_app.getFile().isDirectory())
|
||||
{
|
||||
// Copy directory
|
||||
Log.info("Copy " + web_app.getFile() + " to " + extractedWebAppDir);
|
||||
IO.copyDir(web_app.getFile(),extractedWebAppDir);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!extractedWebAppDir.exists())
|
||||
{
|
||||
//it hasn't been extracted before so extract it
|
||||
extractedWebAppDir.mkdir();
|
||||
Log.info("Extract " + war + " to " + extractedWebAppDir);
|
||||
JarResource.extract(web_app, extractedWebAppDir, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
//only extract if the war file is newer
|
||||
if (web_app.lastModified() > extractedWebAppDir.lastModified())
|
||||
{
|
||||
extractedWebAppDir.delete();
|
||||
extractedWebAppDir.mkdir();
|
||||
Log.info("Extract " + war + " to " + extractedWebAppDir);
|
||||
JarResource.extract(web_app, extractedWebAppDir, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
web_app = Resource.newResource(extractedWebAppDir.getCanonicalPath());
|
||||
}
|
||||
|
||||
// Now do we have something usable?
|
||||
if (!web_app.exists() || !web_app.isDirectory())
|
||||
{
|
||||
Log.warn("Web application not found " + war);
|
||||
throw new java.io.FileNotFoundException(war);
|
||||
}
|
||||
|
||||
|
||||
context.setBaseResource(web_app);
|
||||
System.err.println("SetBaseResource in WebInfConfiguration, toString="+context.toString());
|
||||
|
||||
|
||||
if (Log.isDebugEnabled())
|
||||
Log.debug("webapp=" + web_app);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public File findWorkDirectory (WebAppContext context) throws IOException
|
||||
{
|
||||
if (context.getBaseResource() != null)
|
||||
{
|
||||
Resource web_inf = context.getWebInf();
|
||||
if (web_inf !=null && web_inf.exists())
|
||||
{
|
||||
return new File(web_inf.getFile(),"work");
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Check if the tmpDir itself is called "work", or if the tmpDir
|
||||
* is in a directory called "work".
|
||||
* @return
|
||||
*/
|
||||
public boolean isTempWorkDirectory (File tmpDir)
|
||||
{
|
||||
if (tmpDir == null)
|
||||
return false;
|
||||
if (tmpDir.getName().equalsIgnoreCase("work"))
|
||||
return true;
|
||||
File t = tmpDir.getParentFile();
|
||||
if (t == null)
|
||||
return false;
|
||||
return (t.getName().equalsIgnoreCase("work"));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a canonical name for a webapp tmp directory.
|
||||
* The form of the name is:
|
||||
* "Jetty_"+host+"_"+port+"__"+resourceBase+"_"+context+"_"+virtualhost+base36 hashcode of whole string
|
||||
*
|
||||
* host and port uniquely identify the server
|
||||
* context and virtual host uniquely identify the webapp
|
||||
* @return
|
||||
*/
|
||||
public String getCanonicalNameForWebAppTmpDir (WebAppContext context)
|
||||
{
|
||||
StringBuffer canonicalName = new StringBuffer();
|
||||
canonicalName.append("Jetty");
|
||||
|
||||
//get the host and the port from the first connector
|
||||
Connector[] connectors = context.getServer().getConnectors();
|
||||
|
||||
|
||||
//Get the host
|
||||
canonicalName.append("_");
|
||||
String host = (connectors==null||connectors[0]==null?"":connectors[0].getHost());
|
||||
if (host == null)
|
||||
host = "0.0.0.0";
|
||||
canonicalName.append(host.replace('.', '_'));
|
||||
|
||||
//Get the port
|
||||
canonicalName.append("_");
|
||||
//try getting the real port being listened on
|
||||
int port = (connectors==null||connectors[0]==null?0:connectors[0].getLocalPort());
|
||||
//if not available (eg no connectors or connector not started),
|
||||
//try getting one that was configured.
|
||||
if (port < 0)
|
||||
port = connectors[0].getPort();
|
||||
canonicalName.append(port);
|
||||
|
||||
|
||||
//Resource base
|
||||
canonicalName.append("_");
|
||||
try
|
||||
{
|
||||
Resource resource = context.getBaseResource();
|
||||
if (resource == null)
|
||||
{
|
||||
if (context.getWar()==null || context.getWar().length()==0)
|
||||
resource=context.newResource(context.getResourceBase());
|
||||
|
||||
// Set dir or WAR
|
||||
resource = context.newResource(context.getWar());
|
||||
}
|
||||
|
||||
String tmp = URIUtil.decodePath(resource.getURL().getPath());
|
||||
if (tmp.endsWith("/"))
|
||||
tmp = tmp.substring(0, tmp.length()-1);
|
||||
if (tmp.endsWith("!"))
|
||||
tmp = tmp.substring(0, tmp.length() -1);
|
||||
//get just the last part which is the filename
|
||||
int i = tmp.lastIndexOf("/");
|
||||
canonicalName.append(tmp.substring(i+1, tmp.length()));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.warn("Can't generate resourceBase as part of webapp tmp dir name", e);
|
||||
}
|
||||
|
||||
//Context name
|
||||
canonicalName.append("_");
|
||||
String contextPath = context.getContextPath();
|
||||
contextPath=contextPath.replace('/','_');
|
||||
contextPath=contextPath.replace('\\','_');
|
||||
canonicalName.append(contextPath);
|
||||
|
||||
//Virtual host (if there is one)
|
||||
canonicalName.append("_");
|
||||
String[] vhosts = context.getVirtualHosts();
|
||||
canonicalName.append((vhosts==null||vhosts[0]==null?"":vhosts[0]));
|
||||
|
||||
//base36 hash of the whole string for uniqueness
|
||||
String hash = Integer.toString(canonicalName.toString().hashCode(),36);
|
||||
canonicalName.append("_");
|
||||
canonicalName.append(hash);
|
||||
|
||||
// sanitize
|
||||
for (int i=0;i<canonicalName.length();i++)
|
||||
{
|
||||
char c=canonicalName.charAt(i);
|
||||
if (!Character.isJavaIdentifierPart(c))
|
||||
canonicalName.setCharAt(i,'.');
|
||||
}
|
||||
|
||||
return canonicalName.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,954 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) 2009 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
package org.eclipse.jetty.webapp;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.EventListener;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.Servlet;
|
||||
import javax.servlet.UnavailableException;
|
||||
|
||||
import org.eclipse.jetty.http.security.Constraint;
|
||||
import org.eclipse.jetty.security.ConstraintAware;
|
||||
import org.eclipse.jetty.security.ConstraintMapping;
|
||||
import org.eclipse.jetty.security.SecurityHandler;
|
||||
import org.eclipse.jetty.security.authentication.FormAuthenticator;
|
||||
import org.eclipse.jetty.servlet.ErrorPageErrorHandler;
|
||||
import org.eclipse.jetty.servlet.FilterHolder;
|
||||
import org.eclipse.jetty.servlet.FilterMapping;
|
||||
import org.eclipse.jetty.servlet.ServletHandler;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.eclipse.jetty.servlet.ServletMapping;
|
||||
import org.eclipse.jetty.util.LazyList;
|
||||
import org.eclipse.jetty.util.Loader;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.resource.Resource;
|
||||
import org.eclipse.jetty.xml.XmlParser;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* WebXmlProcessor
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class WebXmlProcessor
|
||||
{
|
||||
public static final String __web_processor = "org.eclipse.jetty.webProcessor";
|
||||
|
||||
protected WebAppContext _context;
|
||||
protected XmlParser _xmlParser;
|
||||
protected XmlParser.Node _webDefaultsRoot;
|
||||
protected XmlParser.Node _webXmlRoot;
|
||||
protected List<XmlParser.Node> _webFragmentRoots = new ArrayList<XmlParser.Node>();
|
||||
protected XmlParser.Node _webOverrideRoot;
|
||||
protected int _version;
|
||||
protected boolean _metaDataComplete = false;
|
||||
|
||||
protected ServletHandler _servletHandler;
|
||||
protected SecurityHandler _securityHandler;
|
||||
protected Object _filters;
|
||||
protected Object _filterMappings;
|
||||
protected Object _servlets;
|
||||
protected Object _servletMappings;
|
||||
protected Object _listeners;
|
||||
protected Object _welcomeFiles;
|
||||
protected Set<String> _roles = new HashSet<String>();
|
||||
protected Object _constraintMappings;
|
||||
protected Map _errorPages;
|
||||
protected boolean _hasJSP;
|
||||
protected String _jspServletName;
|
||||
protected String _jspServletClass;
|
||||
protected boolean _defaultWelcomeFileList;
|
||||
|
||||
|
||||
|
||||
|
||||
public static XmlParser webXmlParser() throws ClassNotFoundException
|
||||
{
|
||||
XmlParser xmlParser=new XmlParser();
|
||||
//set up cache of DTDs and schemas locally
|
||||
URL dtd22=Loader.getResource(Servlet.class,"javax/servlet/resources/web-app_2_2.dtd",true);
|
||||
URL dtd23=Loader.getResource(Servlet.class,"javax/servlet/resources/web-app_2_3.dtd",true);
|
||||
URL j2ee14xsd=Loader.getResource(Servlet.class,"javax/servlet/resources/j2ee_1_4.xsd",true);
|
||||
URL webapp24xsd=Loader.getResource(Servlet.class,"javax/servlet/resources/web-app_2_4.xsd",true);
|
||||
URL webapp25xsd=Loader.getResource(Servlet.class,"javax/servlet/resources/web-app_2_5.xsd",true);
|
||||
URL webapp30xsd=Loader.getResource(Servlet.class,"javax/servlet/resources/web-app_3_0.xsd",true);
|
||||
URL webcommon30xsd=Loader.getResource(Servlet.class,"javax/servlet/resources/web-common_3_0.xsd",true);
|
||||
URL webfragment30xsd=Loader.getResource(Servlet.class,"javax/servlet/resources/web-fragment_3_0.xsd",true);
|
||||
URL schemadtd=Loader.getResource(Servlet.class,"javax/servlet/resources/XMLSchema.dtd",true);
|
||||
URL xmlxsd=Loader.getResource(Servlet.class,"javax/servlet/resources/xml.xsd",true);
|
||||
URL webservice11xsd=Loader.getResource(Servlet.class,"javax/servlet/resources/j2ee_web_services_client_1_1.xsd",true);
|
||||
URL webservice12xsd=Loader.getResource(Servlet.class,"javax/servlet/resources/javaee_web_services_client_1_2.xsd",true);
|
||||
URL datatypesdtd=Loader.getResource(Servlet.class,"javax/servlet/resources/datatypes.dtd",true);
|
||||
|
||||
URL jsp20xsd = null;
|
||||
URL jsp21xsd = null;
|
||||
|
||||
try
|
||||
{
|
||||
Class jsp_page = Loader.loadClass(WebXmlConfiguration.class, "javax.servlet.jsp.JspPage");
|
||||
jsp20xsd = jsp_page.getResource("/javax/servlet/resources/jsp_2_0.xsd");
|
||||
jsp21xsd = jsp_page.getResource("/javax/servlet/resources/jsp_2_1.xsd");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.ignore(e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (jsp20xsd == null) jsp20xsd = Loader.getResource(Servlet.class, "javax/servlet/resources/jsp_2_0.xsd", true);
|
||||
if (jsp21xsd == null) jsp21xsd = Loader.getResource(Servlet.class, "javax/servlet/resources/jsp_2_1.xsd", true);
|
||||
}
|
||||
|
||||
redirect(xmlParser,"web-app_2_2.dtd",dtd22);
|
||||
redirect(xmlParser,"-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN",dtd22);
|
||||
redirect(xmlParser,"web.dtd",dtd23);
|
||||
redirect(xmlParser,"web-app_2_3.dtd",dtd23);
|
||||
redirect(xmlParser,"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN",dtd23);
|
||||
redirect(xmlParser,"XMLSchema.dtd",schemadtd);
|
||||
redirect(xmlParser,"http://www.w3.org/2001/XMLSchema.dtd",schemadtd);
|
||||
redirect(xmlParser,"-//W3C//DTD XMLSCHEMA 200102//EN",schemadtd);
|
||||
redirect(xmlParser,"jsp_2_0.xsd",jsp20xsd);
|
||||
redirect(xmlParser,"http://java.sun.com/xml/ns/j2ee/jsp_2_0.xsd",jsp20xsd);
|
||||
redirect(xmlParser,"jsp_2_1.xsd",jsp21xsd);
|
||||
redirect(xmlParser,"http://java.sun.com/xml/ns/javaee/jsp_2_1.xsd",jsp21xsd);
|
||||
redirect(xmlParser,"j2ee_1_4.xsd",j2ee14xsd);
|
||||
redirect(xmlParser,"http://java.sun.com/xml/ns/j2ee/j2ee_1_4.xsd",j2ee14xsd);
|
||||
redirect(xmlParser,"web-app_2_4.xsd",webapp24xsd);
|
||||
redirect(xmlParser,"http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd",webapp24xsd);
|
||||
redirect(xmlParser,"web-app_2_5.xsd",webapp25xsd);
|
||||
redirect(xmlParser,"http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd",webapp25xsd);
|
||||
redirect(xmlParser,"web-app_3_0.xsd",webapp30xsd);
|
||||
redirect(xmlParser,"http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd",webapp30xsd);
|
||||
redirect(xmlParser,"web-common_3_0.xsd",webcommon30xsd);
|
||||
redirect(xmlParser,"http://java.sun.com/xml/ns/javaee/web-common_3_0.xsd",webcommon30xsd);
|
||||
redirect(xmlParser,"web-fragment_3_0.xsd",webfragment30xsd);
|
||||
redirect(xmlParser,"http://java.sun.com/xml/ns/javaee/web-fragment_3_0.xsd",webfragment30xsd);
|
||||
redirect(xmlParser,"xml.xsd",xmlxsd);
|
||||
redirect(xmlParser,"http://www.w3.org/2001/xml.xsd",xmlxsd);
|
||||
redirect(xmlParser,"datatypes.dtd",datatypesdtd);
|
||||
redirect(xmlParser,"http://www.w3.org/2001/datatypes.dtd",datatypesdtd);
|
||||
redirect(xmlParser,"j2ee_web_services_client_1_1.xsd",webservice11xsd);
|
||||
redirect(xmlParser,"http://www.ibm.com/webservices/xsd/j2ee_web_services_client_1_1.xsd",webservice11xsd);
|
||||
redirect(xmlParser,"javaee_web_services_client_1_2.xsd",webservice12xsd);
|
||||
redirect(xmlParser,"http://www.ibm.com/webservices/xsd/javaee_web_services_client_1_2.xsd",webservice12xsd);
|
||||
|
||||
return xmlParser;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------- */
|
||||
protected static void redirect(XmlParser parser, String resource, URL source)
|
||||
{
|
||||
if (source != null) parser.redirectEntity(resource, source);
|
||||
}
|
||||
|
||||
|
||||
public WebXmlProcessor (WebAppContext context) throws ClassNotFoundException
|
||||
{
|
||||
_context = context;
|
||||
_xmlParser = webXmlParser();
|
||||
}
|
||||
|
||||
|
||||
public int getVersion ()
|
||||
{
|
||||
return _version;
|
||||
}
|
||||
|
||||
public boolean isMetaDataComplete ()
|
||||
{
|
||||
return _metaDataComplete;
|
||||
}
|
||||
|
||||
public void processForVersion (XmlParser.Node config)
|
||||
{
|
||||
String version = config.getAttribute("version", "DTD");
|
||||
if ("2.5".equals(version))
|
||||
_version = 25;
|
||||
else if ("2.4".equals(version))
|
||||
_version = 24;
|
||||
else if ("3.0".equals(version))
|
||||
_version = 30;
|
||||
else if ("DTD".equals(version))
|
||||
{
|
||||
_version = 23;
|
||||
String dtd = _xmlParser.getDTD();
|
||||
if (dtd != null && dtd.indexOf("web-app_2_2") >= 0) _version = 22;
|
||||
}
|
||||
|
||||
if (_version < 25)
|
||||
_metaDataComplete = true; // does not apply before 2.5
|
||||
else
|
||||
_metaDataComplete = Boolean.valueOf((String) config.getAttribute("metadata-complete", "false")).booleanValue();
|
||||
|
||||
Log.debug("Calculated metadatacomplete = " + _metaDataComplete + " with version=" + version);
|
||||
|
||||
_context.setAttribute("metadata-complete", String.valueOf(_metaDataComplete));
|
||||
}
|
||||
|
||||
public XmlParser.Node parseDefaults (URL webDefaults)
|
||||
throws Exception
|
||||
{
|
||||
_webDefaultsRoot = _xmlParser.parse(webDefaults.toString());
|
||||
return _webDefaultsRoot;
|
||||
|
||||
}
|
||||
|
||||
public XmlParser.Node parseWebXml (URL webXml)
|
||||
throws Exception
|
||||
{
|
||||
_webXmlRoot = _xmlParser.parse(webXml.toString());
|
||||
processForVersion(_webXmlRoot);
|
||||
return _webXmlRoot;
|
||||
}
|
||||
|
||||
public XmlParser.Node parseFragment (URL fragment)
|
||||
throws Exception
|
||||
{
|
||||
if (isMetaDataComplete())
|
||||
return null; //do not process anything else if main web.xml file is complete
|
||||
|
||||
//Metadata-complete is not set, or there is no web.xml
|
||||
XmlParser.Node root = _xmlParser.parse(fragment.toString());
|
||||
_webFragmentRoots.add(root);
|
||||
return root;
|
||||
}
|
||||
|
||||
public XmlParser.Node parseOverride (URL override)
|
||||
throws Exception
|
||||
{
|
||||
_xmlParser.setValidating(false);
|
||||
_webOverrideRoot = _xmlParser.parse(override.toString());
|
||||
return _webOverrideRoot;
|
||||
}
|
||||
|
||||
|
||||
public void processDefaults ()
|
||||
throws Exception
|
||||
{
|
||||
process (_webDefaultsRoot);
|
||||
_defaultWelcomeFileList = _context.getWelcomeFiles() != null;
|
||||
}
|
||||
|
||||
public void processWebXml ()
|
||||
throws Exception
|
||||
{
|
||||
process (_webXmlRoot);
|
||||
}
|
||||
|
||||
public void processFragments ()
|
||||
throws Exception
|
||||
{
|
||||
for (XmlParser.Node frag : _webFragmentRoots)
|
||||
{
|
||||
process (frag);
|
||||
}
|
||||
}
|
||||
|
||||
public void processOverride ()
|
||||
throws Exception
|
||||
{
|
||||
process(_webOverrideRoot);
|
||||
}
|
||||
|
||||
public XmlParser.Node getWebXml ()
|
||||
{
|
||||
return _webXmlRoot;
|
||||
}
|
||||
|
||||
public XmlParser.Node getOverrideWeb ()
|
||||
{
|
||||
return _webOverrideRoot;
|
||||
}
|
||||
|
||||
public XmlParser.Node getWebDefault ()
|
||||
{
|
||||
return _webDefaultsRoot;
|
||||
}
|
||||
|
||||
public List<XmlParser.Node> getFragments ()
|
||||
{
|
||||
return _webFragmentRoots;
|
||||
}
|
||||
|
||||
|
||||
public void process (XmlParser.Node config)
|
||||
throws Exception
|
||||
{
|
||||
//Get the current objects from the context
|
||||
_servletHandler = _context.getServletHandler();
|
||||
_securityHandler = (SecurityHandler)_context.getSecurityHandler();
|
||||
_filters = LazyList.array2List(_servletHandler.getFilters());
|
||||
_filterMappings = LazyList.array2List(_servletHandler.getFilterMappings());
|
||||
_servlets = LazyList.array2List(_servletHandler.getServlets());
|
||||
_servletMappings = LazyList.array2List(_servletHandler.getServletMappings());
|
||||
_listeners = LazyList.array2List(_context.getEventListeners());
|
||||
_welcomeFiles = LazyList.array2List(_context.getWelcomeFiles());
|
||||
if (_securityHandler instanceof ConstraintAware)
|
||||
{
|
||||
_constraintMappings = LazyList.array2List(((ConstraintAware) _securityHandler).getConstraintMappings());
|
||||
|
||||
if (((ConstraintAware) _securityHandler).getRoles() != null)
|
||||
{
|
||||
_roles.addAll(((ConstraintAware) _securityHandler).getRoles());
|
||||
}
|
||||
}
|
||||
_errorPages = _context.getErrorHandler() instanceof ErrorPageErrorHandler ? ((ErrorPageErrorHandler)_context.getErrorHandler()).getErrorPages() : null;
|
||||
|
||||
Iterator iter = config.iterator();
|
||||
XmlParser.Node node = null;
|
||||
while (iter.hasNext())
|
||||
{
|
||||
try
|
||||
{
|
||||
Object o = iter.next();
|
||||
if (!(o instanceof XmlParser.Node)) continue;
|
||||
node = (XmlParser.Node) o;
|
||||
String name = node.getTag();
|
||||
initWebXmlElement(name, node);
|
||||
}
|
||||
catch (ClassNotFoundException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.warn("Configuration problem at " + node, e);
|
||||
throw new UnavailableException("Configuration problem");
|
||||
}
|
||||
}
|
||||
|
||||
//Set the context with the results of the processing
|
||||
_servletHandler.setFilters((FilterHolder[]) LazyList.toArray(_filters, FilterHolder.class));
|
||||
_servletHandler.setFilterMappings((FilterMapping[]) LazyList.toArray(_filterMappings, FilterMapping.class));
|
||||
_servletHandler.setServlets((ServletHolder[]) LazyList.toArray(_servlets, ServletHolder.class));
|
||||
_servletHandler.setServletMappings((ServletMapping[]) LazyList.toArray(_servletMappings, ServletMapping.class));
|
||||
_context.setEventListeners((EventListener[]) LazyList.toArray(_listeners, EventListener.class));
|
||||
_context.setWelcomeFiles((String[]) LazyList.toArray(_welcomeFiles, String.class));
|
||||
// TODO jaspi check this
|
||||
if (_securityHandler instanceof ConstraintAware)
|
||||
{
|
||||
((ConstraintAware) _securityHandler).setConstraintMappings((ConstraintMapping[]) LazyList.toArray(_constraintMappings,
|
||||
ConstraintMapping.class),
|
||||
_roles);
|
||||
}
|
||||
|
||||
if (_errorPages != null && _context.getErrorHandler() instanceof ErrorPageErrorHandler)
|
||||
((ErrorPageErrorHandler)_context.getErrorHandler()).setErrorPages(_errorPages);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Handle web.xml element. This method is called for each top level element
|
||||
* within the web.xml file. It may be specialized by derived WebAppHandlers
|
||||
* to provide additional configuration and handling.
|
||||
*
|
||||
* @param element The element name
|
||||
* @param node The node containing the element.
|
||||
*/
|
||||
protected void initWebXmlElement(String element, XmlParser.Node node) throws Exception
|
||||
{
|
||||
if ("display-name".equals(element))
|
||||
initDisplayName(node);
|
||||
else if ("description".equals(element))
|
||||
{
|
||||
}
|
||||
else if ("context-param".equals(element))
|
||||
initContextParam(node);
|
||||
else if ("servlet".equals(element))
|
||||
initServlet(node);
|
||||
else if ("servlet-mapping".equals(element))
|
||||
initServletMapping(node);
|
||||
else if ("session-config".equals(element))
|
||||
initSessionConfig(node);
|
||||
else if ("mime-mapping".equals(element))
|
||||
initMimeConfig(node);
|
||||
else if ("welcome-file-list".equals(element))
|
||||
initWelcomeFileList(node);
|
||||
else if ("locale-encoding-mapping-list".equals(element))
|
||||
initLocaleEncodingList(node);
|
||||
else if ("error-page".equals(element))
|
||||
initErrorPage(node);
|
||||
else if ("taglib".equals(element))
|
||||
initTagLib(node);
|
||||
else if ("jsp-config".equals(element))
|
||||
initJspConfig(node);
|
||||
else if ("resource-ref".equals(element))
|
||||
{
|
||||
if (Log.isDebugEnabled()) Log.debug("No implementation: " + node);
|
||||
}
|
||||
else if ("security-constraint".equals(element))
|
||||
initSecurityConstraint(node);
|
||||
else if ("login-config".equals(element))
|
||||
initLoginConfig(node);
|
||||
else if ("security-role".equals(element))
|
||||
initSecurityRole(node);
|
||||
else if ("filter".equals(element))
|
||||
initFilter(node);
|
||||
else if ("filter-mapping".equals(element))
|
||||
initFilterMapping(node);
|
||||
else if ("listener".equals(element))
|
||||
initListener(node);
|
||||
else if ("distributable".equals(element))
|
||||
initDistributable(node);
|
||||
else if ("web-fragment".equals(element))
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Log.isDebugEnabled())
|
||||
{
|
||||
Log.debug("Element {} not handled in {}", element, this);
|
||||
Log.debug(node.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
protected void initDisplayName(XmlParser.Node node)
|
||||
{
|
||||
_context.setDisplayName(node.toString(false, true));
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
protected void initContextParam(XmlParser.Node node)
|
||||
{
|
||||
String name = node.getString("param-name", false, true);
|
||||
String value = node.getString("param-value", false, true);
|
||||
if (Log.isDebugEnabled()) Log.debug("ContextParam: " + name + "=" + value);
|
||||
_context.getInitParams().put(name, value);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
protected void initFilter(XmlParser.Node node)
|
||||
{
|
||||
String name = node.getString("filter-name", false, true);
|
||||
FilterHolder holder = _servletHandler.getFilter(name);
|
||||
if (holder == null)
|
||||
{
|
||||
holder = _servletHandler.newFilterHolder();
|
||||
holder.setName(name);
|
||||
_filters = LazyList.add(_filters, holder);
|
||||
}
|
||||
|
||||
String filter_class = node.getString("filter-class", false, true);
|
||||
if (filter_class != null) holder.setClassName(filter_class);
|
||||
|
||||
Iterator iter = node.iterator("init-param");
|
||||
while (iter.hasNext())
|
||||
{
|
||||
XmlParser.Node paramNode = (XmlParser.Node) iter.next();
|
||||
String pname = paramNode.getString("param-name", false, true);
|
||||
String pvalue = paramNode.getString("param-value", false, true);
|
||||
holder.setInitParameter(pname, pvalue);
|
||||
}
|
||||
|
||||
String async=node.getString("async-support",false,true);
|
||||
if (async!=null)
|
||||
holder.setAsyncSupported(Boolean.valueOf(async));
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
protected void initFilterMapping(XmlParser.Node node)
|
||||
{
|
||||
String filter_name = node.getString("filter-name", false, true);
|
||||
|
||||
FilterMapping mapping = new FilterMapping();
|
||||
|
||||
mapping.setFilterName(filter_name);
|
||||
|
||||
ArrayList paths = new ArrayList();
|
||||
Iterator iter = node.iterator("url-pattern");
|
||||
while (iter.hasNext())
|
||||
{
|
||||
String p = ((XmlParser.Node) iter.next()).toString(false, true);
|
||||
p = normalizePattern(p);
|
||||
paths.add(p);
|
||||
}
|
||||
mapping.setPathSpecs((String[]) paths.toArray(new String[paths.size()]));
|
||||
|
||||
ArrayList names = new ArrayList();
|
||||
iter = node.iterator("servlet-name");
|
||||
while (iter.hasNext())
|
||||
{
|
||||
String n = ((XmlParser.Node) iter.next()).toString(false, true);
|
||||
names.add(n);
|
||||
}
|
||||
mapping.setServletNames((String[]) names.toArray(new String[names.size()]));
|
||||
|
||||
int dispatcher=FilterMapping.DEFAULT;
|
||||
iter=node.iterator("dispatcher");
|
||||
while(iter.hasNext())
|
||||
{
|
||||
String d=((XmlParser.Node)iter.next()).toString(false,true);
|
||||
dispatcher|=FilterMapping.dispatch(d);
|
||||
}
|
||||
mapping.setDispatches(dispatcher);
|
||||
|
||||
_filterMappings = LazyList.add(_filterMappings, mapping);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
protected String normalizePattern(String p)
|
||||
{
|
||||
if (p != null && p.length() > 0 && !p.startsWith("/") && !p.startsWith("*")) return "/" + p;
|
||||
return p;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
protected void initServlet(XmlParser.Node node)
|
||||
{
|
||||
String id = node.getAttribute("id");
|
||||
|
||||
// initialize holder
|
||||
String servlet_name = node.getString("servlet-name", false, true);
|
||||
ServletHolder holder = _servletHandler.getServlet(servlet_name);
|
||||
if (holder == null)
|
||||
{
|
||||
holder = _servletHandler.newServletHolder();
|
||||
holder.setName(servlet_name);
|
||||
_servlets = LazyList.add(_servlets, holder);
|
||||
}
|
||||
|
||||
// init params
|
||||
Iterator iParamsIter = node.iterator("init-param");
|
||||
while (iParamsIter.hasNext())
|
||||
{
|
||||
XmlParser.Node paramNode = (XmlParser.Node) iParamsIter.next();
|
||||
String pname = paramNode.getString("param-name", false, true);
|
||||
String pvalue = paramNode.getString("param-value", false, true);
|
||||
holder.setInitParameter(pname, pvalue);
|
||||
}
|
||||
|
||||
String servlet_class = node.getString("servlet-class", false, true);
|
||||
|
||||
// Handle JSP
|
||||
if (id != null && id.equals("jsp"))
|
||||
{
|
||||
_jspServletName = servlet_name;
|
||||
_jspServletClass = servlet_class;
|
||||
try
|
||||
{
|
||||
Loader.loadClass(this.getClass(), servlet_class);
|
||||
_hasJSP = true;
|
||||
}
|
||||
catch (ClassNotFoundException e)
|
||||
{
|
||||
Log.info("NO JSP Support for {}, did not find {}", _context.getContextPath(), servlet_class);
|
||||
_hasJSP = false;
|
||||
_jspServletClass = servlet_class = "org.eclipse.jetty.servlet.NoJspServlet";
|
||||
}
|
||||
if (holder.getInitParameter("scratchdir") == null)
|
||||
{
|
||||
File tmp = _context.getTempDirectory();
|
||||
File scratch = new File(tmp, "jsp");
|
||||
if (!scratch.exists()) scratch.mkdir();
|
||||
holder.setInitParameter("scratchdir", scratch.getAbsolutePath());
|
||||
|
||||
if ("?".equals(holder.getInitParameter("classpath")))
|
||||
{
|
||||
String classpath = _context.getClassPath();
|
||||
Log.debug("classpath=" + classpath);
|
||||
if (classpath != null) holder.setInitParameter("classpath", classpath);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (servlet_class != null) holder.setClassName(servlet_class);
|
||||
|
||||
// Handler JSP file
|
||||
String jsp_file = node.getString("jsp-file", false, true);
|
||||
if (jsp_file != null)
|
||||
{
|
||||
holder.setForcedPath(jsp_file);
|
||||
holder.setClassName(_jspServletClass);
|
||||
}
|
||||
|
||||
// handle startup
|
||||
XmlParser.Node startup = node.get("load-on-startup");
|
||||
if (startup != null)
|
||||
{
|
||||
String s = startup.toString(false, true).toLowerCase();
|
||||
if (s.startsWith("t"))
|
||||
{
|
||||
Log.warn("Deprecated boolean load-on-startup. Please use integer");
|
||||
holder.setInitOrder(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
int order = 0;
|
||||
try
|
||||
{
|
||||
if (s != null && s.trim().length() > 0) order = Integer.parseInt(s);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.warn("Cannot parse load-on-startup " + s + ". Please use integer");
|
||||
Log.ignore(e);
|
||||
}
|
||||
holder.setInitOrder(order);
|
||||
}
|
||||
}
|
||||
|
||||
Iterator sRefsIter = node.iterator("security-role-ref");
|
||||
while (sRefsIter.hasNext())
|
||||
{
|
||||
XmlParser.Node securityRef = (XmlParser.Node) sRefsIter.next();
|
||||
String roleName = securityRef.getString("role-name", false, true);
|
||||
String roleLink = securityRef.getString("role-link", false, true);
|
||||
if (roleName != null && roleName.length() > 0 && roleLink != null && roleLink.length() > 0)
|
||||
{
|
||||
if (Log.isDebugEnabled()) Log.debug("link role " + roleName + " to " + roleLink + " for " + this);
|
||||
holder.setUserRoleLink(roleName, roleLink);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.warn("Ignored invalid security-role-ref element: " + "servlet-name=" + holder.getName() + ", " + securityRef);
|
||||
}
|
||||
}
|
||||
|
||||
XmlParser.Node run_as = node.get("run-as");
|
||||
if (run_as != null)
|
||||
{
|
||||
String roleName = run_as.getString("role-name", false, true);
|
||||
if (roleName != null)
|
||||
holder.setRunAsRole(roleName);
|
||||
}
|
||||
|
||||
String async=node.getString("async-support",false,true);
|
||||
if (async!=null)
|
||||
holder.setAsyncSupported(Boolean.valueOf(async));
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
protected void initServletMapping(XmlParser.Node node)
|
||||
{
|
||||
String servlet_name = node.getString("servlet-name", false, true);
|
||||
ServletMapping mapping = new ServletMapping();
|
||||
mapping.setServletName(servlet_name);
|
||||
|
||||
ArrayList paths = new ArrayList();
|
||||
Iterator iter = node.iterator("url-pattern");
|
||||
while (iter.hasNext())
|
||||
{
|
||||
String p = ((XmlParser.Node) iter.next()).toString(false, true);
|
||||
p = normalizePattern(p);
|
||||
paths.add(p);
|
||||
}
|
||||
mapping.setPathSpecs((String[]) paths.toArray(new String[paths.size()]));
|
||||
|
||||
_servletMappings = LazyList.add(_servletMappings, mapping);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
protected void initListener(XmlParser.Node node)
|
||||
{
|
||||
String className = node.getString("listener-class", false, true);
|
||||
Object listener = null;
|
||||
try
|
||||
{
|
||||
Class listenerClass = _context.loadClass(className);
|
||||
listener = newListenerInstance(listenerClass);
|
||||
if (!(listener instanceof EventListener))
|
||||
{
|
||||
Log.warn("Not an EventListener: " + listener);
|
||||
return;
|
||||
}
|
||||
_listeners = LazyList.add(_listeners, listener);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.warn("Could not instantiate listener " + className, e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
protected Object newListenerInstance(Class clazz) throws InstantiationException, IllegalAccessException
|
||||
{
|
||||
return clazz.newInstance();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
protected void initDistributable(XmlParser.Node node)
|
||||
{
|
||||
// the element has no content, so its simple presence
|
||||
// indicates that the webapp is distributable...
|
||||
if (!_context.isDistributable())
|
||||
_context.setDistributable(true);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
protected void initSessionConfig(XmlParser.Node node)
|
||||
{
|
||||
XmlParser.Node tNode = node.get("session-timeout");
|
||||
if (tNode != null)
|
||||
{
|
||||
int timeout = Integer.parseInt(tNode.toString(false, true));
|
||||
_context.getSessionHandler().getSessionManager().setMaxInactiveInterval(timeout * 60);
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
protected void initMimeConfig(XmlParser.Node node)
|
||||
{
|
||||
String extension = node.getString("extension", false, true);
|
||||
if (extension != null && extension.startsWith(".")) extension = extension.substring(1);
|
||||
String mimeType = node.getString("mime-type", false, true);
|
||||
_context.getMimeTypes().addMimeMapping(extension, mimeType);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
protected void initWelcomeFileList(XmlParser.Node node)
|
||||
{
|
||||
if (_defaultWelcomeFileList)
|
||||
_welcomeFiles = null; // erase welcome files from default web.xml
|
||||
|
||||
_defaultWelcomeFileList = false;
|
||||
Iterator iter = node.iterator("welcome-file");
|
||||
while (iter.hasNext())
|
||||
{
|
||||
XmlParser.Node indexNode = (XmlParser.Node) iter.next();
|
||||
String welcome = indexNode.toString(false, true);
|
||||
_welcomeFiles = LazyList.add(_welcomeFiles, welcome);
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
protected void initLocaleEncodingList(XmlParser.Node node)
|
||||
{
|
||||
Iterator iter = node.iterator("locale-encoding-mapping");
|
||||
while (iter.hasNext())
|
||||
{
|
||||
XmlParser.Node mapping = (XmlParser.Node) iter.next();
|
||||
String locale = mapping.getString("locale", false, true);
|
||||
String encoding = mapping.getString("encoding", false, true);
|
||||
_context.addLocaleEncoding(locale, encoding);
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
protected void initErrorPage(XmlParser.Node node)
|
||||
{
|
||||
String error = node.getString("error-code", false, true);
|
||||
if (error == null || error.length() == 0) error = node.getString("exception-type", false, true);
|
||||
String location = node.getString("location", false, true);
|
||||
|
||||
if (_errorPages == null)
|
||||
_errorPages = new HashMap();
|
||||
_errorPages.put(error, location);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
protected void initTagLib(XmlParser.Node node)
|
||||
{
|
||||
String uri = node.getString("taglib-uri", false, true);
|
||||
String location = node.getString("taglib-location", false, true);
|
||||
|
||||
_context.setResourceAlias(uri, location);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
protected void initJspConfig(XmlParser.Node node)
|
||||
{
|
||||
for (int i = 0; i < node.size(); i++)
|
||||
{
|
||||
Object o = node.get(i);
|
||||
if (o instanceof XmlParser.Node && "taglib".equals(((XmlParser.Node) o).getTag())) initTagLib((XmlParser.Node) o);
|
||||
}
|
||||
|
||||
// Map URLs from jsp property groups to JSP servlet.
|
||||
// this is more JSP stupidness creaping into the servlet spec
|
||||
Iterator iter = node.iterator("jsp-property-group");
|
||||
Object paths = null;
|
||||
while (iter.hasNext())
|
||||
{
|
||||
XmlParser.Node group = (XmlParser.Node) iter.next();
|
||||
Iterator iter2 = group.iterator("url-pattern");
|
||||
while (iter2.hasNext())
|
||||
{
|
||||
String url = ((XmlParser.Node) iter2.next()).toString(false, true);
|
||||
url = normalizePattern(url);
|
||||
paths = LazyList.add(paths, url);
|
||||
}
|
||||
}
|
||||
|
||||
if (LazyList.size(paths) > 0)
|
||||
{
|
||||
String jspName = getJSPServletName();
|
||||
if (jspName != null)
|
||||
{
|
||||
ServletMapping mapping = new ServletMapping();
|
||||
mapping.setServletName(jspName);
|
||||
mapping.setPathSpecs(LazyList.toStringArray(paths));
|
||||
_servletMappings = LazyList.add(_servletMappings, mapping);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
protected void initSecurityConstraint(XmlParser.Node node)
|
||||
{
|
||||
Constraint scBase = new Constraint();
|
||||
|
||||
try
|
||||
{
|
||||
XmlParser.Node auths = node.get("auth-constraint");
|
||||
|
||||
if (auths != null)
|
||||
{
|
||||
scBase.setAuthenticate(true);
|
||||
// auth-constraint
|
||||
Iterator iter = auths.iterator("role-name");
|
||||
Object roles = null;
|
||||
while (iter.hasNext())
|
||||
{
|
||||
String role = ((XmlParser.Node) iter.next()).toString(false, true);
|
||||
roles = LazyList.add(roles, role);
|
||||
}
|
||||
scBase.setRoles(LazyList.toStringArray(roles));
|
||||
}
|
||||
|
||||
XmlParser.Node data = node.get("user-data-constraint");
|
||||
if (data != null)
|
||||
{
|
||||
data = data.get("transport-guarantee");
|
||||
String guarantee = data.toString(false, true).toUpperCase();
|
||||
if (guarantee == null || guarantee.length() == 0 || "NONE".equals(guarantee))
|
||||
scBase.setDataConstraint(Constraint.DC_NONE);
|
||||
else if ("INTEGRAL".equals(guarantee))
|
||||
scBase.setDataConstraint(Constraint.DC_INTEGRAL);
|
||||
else if ("CONFIDENTIAL".equals(guarantee))
|
||||
scBase.setDataConstraint(Constraint.DC_CONFIDENTIAL);
|
||||
else
|
||||
{
|
||||
Log.warn("Unknown user-data-constraint:" + guarantee);
|
||||
scBase.setDataConstraint(Constraint.DC_CONFIDENTIAL);
|
||||
}
|
||||
}
|
||||
Iterator iter = node.iterator("web-resource-collection");
|
||||
while (iter.hasNext())
|
||||
{
|
||||
XmlParser.Node collection = (XmlParser.Node) iter.next();
|
||||
String name = collection.getString("web-resource-name", false, true);
|
||||
Constraint sc = (Constraint) scBase.clone();
|
||||
sc.setName(name);
|
||||
|
||||
Iterator iter2 = collection.iterator("url-pattern");
|
||||
while (iter2.hasNext())
|
||||
{
|
||||
String url = ((XmlParser.Node) iter2.next()).toString(false, true);
|
||||
url = normalizePattern(url);
|
||||
|
||||
Iterator iter3 = collection.iterator("http-method");
|
||||
if (iter3.hasNext())
|
||||
{
|
||||
while (iter3.hasNext())
|
||||
{
|
||||
String method = ((XmlParser.Node) iter3.next()).toString(false, true);
|
||||
ConstraintMapping mapping = new ConstraintMapping();
|
||||
mapping.setMethod(method);
|
||||
mapping.setPathSpec(url);
|
||||
mapping.setConstraint(sc);
|
||||
_constraintMappings = LazyList.add(_constraintMappings, mapping);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ConstraintMapping mapping = new ConstraintMapping();
|
||||
mapping.setPathSpec(url);
|
||||
mapping.setConstraint(sc);
|
||||
_constraintMappings = LazyList.add(_constraintMappings, mapping);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (CloneNotSupportedException e)
|
||||
{
|
||||
Log.warn(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
protected void initLoginConfig(XmlParser.Node node) throws Exception
|
||||
{
|
||||
XmlParser.Node method = node.get("auth-method");
|
||||
if (method != null)
|
||||
{
|
||||
XmlParser.Node name = node.get("realm-name");
|
||||
_securityHandler.setRealmName(name == null ? "default" : name.toString(false, true));
|
||||
_securityHandler.setAuthMethod(method.toString(false, true));
|
||||
|
||||
|
||||
if (Constraint.__FORM_AUTH.equals(_securityHandler.getAuthMethod()))
|
||||
{
|
||||
XmlParser.Node formConfig = node.get("form-login-config");
|
||||
if (formConfig != null)
|
||||
{
|
||||
String loginPageName = null;
|
||||
XmlParser.Node loginPage = formConfig.get("form-login-page");
|
||||
if (loginPage != null)
|
||||
loginPageName = loginPage.toString(false, true);
|
||||
String errorPageName = null;
|
||||
XmlParser.Node errorPage = formConfig.get("form-error-page");
|
||||
if (errorPage != null)
|
||||
errorPageName = errorPage.toString(false, true);
|
||||
_securityHandler.setInitParameter(FormAuthenticator.__FORM_LOGIN_PAGE,loginPageName);
|
||||
_securityHandler.setInitParameter(FormAuthenticator.__FORM_ERROR_PAGE,errorPageName);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalArgumentException("!form-login-config");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
protected void initSecurityRole(XmlParser.Node node)
|
||||
{
|
||||
XmlParser.Node roleNode = node.get("role-name");
|
||||
String role = roleNode.toString(false, true);
|
||||
_roles.add(role);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
protected String getJSPServletName()
|
||||
{
|
||||
if (_jspServletName == null)
|
||||
{
|
||||
Map.Entry entry = _context.getServletHandler().getHolderEntry("test.jsp");
|
||||
if (entry != null)
|
||||
{
|
||||
ServletHolder holder = (ServletHolder) entry.getValue();
|
||||
_jspServletName = holder.getName();
|
||||
}
|
||||
}
|
||||
return _jspServletName;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue