blob: f946c59ef0d2233f25286b009db55305f44fc489 [file] [log] [blame]
//
// ========================================================================
// Copyright (c) 1995-2014 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.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletContext;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.resource.Resource;
/**
* MetaData
*
* All data associated with the configuration and deployment of a web application.
*/
public class MetaData
{
private static final Logger LOG = Log.getLogger(MetaData.class);
public static final String ORDERED_LIBS = "javax.servlet.context.orderedLibs";
protected Map<String, OriginInfo> _origins =new HashMap<String,OriginInfo>();
protected WebDescriptor _webDefaultsRoot;
protected WebDescriptor _webXmlRoot;
protected final List<WebDescriptor> _webOverrideRoots=new ArrayList<WebDescriptor>();
protected boolean _metaDataComplete;
protected final List<DiscoveredAnnotation> _annotations = new ArrayList<DiscoveredAnnotation>();
protected final List<DescriptorProcessor> _descriptorProcessors = new ArrayList<DescriptorProcessor>();
protected final List<FragmentDescriptor> _webFragmentRoots = new ArrayList<FragmentDescriptor>();
protected final Map<String,FragmentDescriptor> _webFragmentNameMap = new HashMap<String,FragmentDescriptor>();
protected final Map<Resource, FragmentDescriptor> _webFragmentResourceMap = new HashMap<Resource, FragmentDescriptor>();
protected final Map<Resource, List<DiscoveredAnnotation>> _webFragmentAnnotations = new HashMap<Resource, List<DiscoveredAnnotation>>();
protected final List<Resource> _webInfJars = new ArrayList<Resource>();
protected final List<Resource> _orderedWebInfJars = new ArrayList<Resource>();
protected final List<Resource> _orderedContainerJars = new ArrayList<Resource>();
protected Ordering _ordering;//can be set to RelativeOrdering by web-default.xml, web.xml, web-override.xml
protected boolean allowDuplicateFragmentNames = false;
public static class OriginInfo
{
protected String name;
protected Origin origin;
protected Descriptor descriptor;
public OriginInfo (String n, Descriptor d)
{
name = n;
descriptor = d;
if (d == null)
throw new IllegalArgumentException("No descriptor");
if (d instanceof FragmentDescriptor)
origin = Origin.WebFragment;
else if (d instanceof OverrideDescriptor)
origin = Origin.WebOverride;
else if (d instanceof DefaultsDescriptor)
origin = Origin.WebDefaults;
else
origin = Origin.WebXml;
}
public OriginInfo (String n)
{
name = n;
origin = Origin.Annotation;
}
public OriginInfo(String n, Origin o)
{
name = n;
origin = o;
}
public String getName()
{
return name;
}
public Origin getOriginType()
{
return origin;
}
public Descriptor getDescriptor()
{
return descriptor;
}
}
public MetaData ()
{
}
/**
* Empty ready for reuse
*/
public void clear ()
{
_webDefaultsRoot = null;
_origins.clear();
_webXmlRoot = null;
_webOverrideRoots.clear();
_metaDataComplete = false;
_annotations.clear();
_descriptorProcessors.clear();
_webFragmentRoots.clear();
_webFragmentNameMap.clear();
_webFragmentResourceMap.clear();
_webFragmentAnnotations.clear();
_webInfJars.clear();
_orderedWebInfJars.clear();
_orderedContainerJars.clear();
_ordering = null;
allowDuplicateFragmentNames = false;
}
public void setDefaults (Resource webDefaults)
throws Exception
{
_webDefaultsRoot = new DefaultsDescriptor(webDefaults);
_webDefaultsRoot.parse();
if (_webDefaultsRoot.isOrdered())
{
if (_ordering == null)
_ordering = new Ordering.AbsoluteOrdering(this);
List<String> order = _webDefaultsRoot.getOrdering();
for (String s:order)
{
if (s.equalsIgnoreCase("others"))
((Ordering.AbsoluteOrdering)_ordering).addOthers();
else
((Ordering.AbsoluteOrdering)_ordering).add(s);
}
}
}
public void setWebXml (Resource webXml)
throws Exception
{
_webXmlRoot = new WebDescriptor(webXml);
_webXmlRoot.parse();
_metaDataComplete=_webXmlRoot.getMetaDataComplete() == MetaDataComplete.True;
if (_webXmlRoot.isOrdered())
{
if (_ordering == null)
_ordering = new Ordering.AbsoluteOrdering(this);
List<String> order = _webXmlRoot.getOrdering();
for (String s:order)
{
if (s.equalsIgnoreCase("others"))
((Ordering.AbsoluteOrdering)_ordering).addOthers();
else
((Ordering.AbsoluteOrdering)_ordering).add(s);
}
}
}
public void addOverride (Resource override)
throws Exception
{
OverrideDescriptor webOverrideRoot = new OverrideDescriptor(override);
webOverrideRoot.setValidating(false);
webOverrideRoot.parse();
switch(webOverrideRoot.getMetaDataComplete())
{
case True:
_metaDataComplete=true;
break;
case False:
_metaDataComplete=false;
break;
case NotSet:
break;
}
if (webOverrideRoot.isOrdered())
{
if (_ordering == null)
_ordering = new Ordering.AbsoluteOrdering(this);
List<String> order = webOverrideRoot.getOrdering();
for (String s:order)
{
if (s.equalsIgnoreCase("others"))
((Ordering.AbsoluteOrdering)_ordering).addOthers();
else
((Ordering.AbsoluteOrdering)_ordering).add(s);
}
}
_webOverrideRoots.add(webOverrideRoot);
}
/**
* Add a web-fragment.xml
*
* @param jarResource the jar the fragment is contained in
* @param xmlResource the resource representing the xml file
* @throws Exception
*/
public void addFragment (Resource jarResource, Resource xmlResource)
throws Exception
{
if (_metaDataComplete)
return; //do not process anything else if web.xml/web-override.xml set metadata-complete
//Metadata-complete is not set, or there is no web.xml
FragmentDescriptor descriptor = new FragmentDescriptor(xmlResource);
_webFragmentResourceMap.put(jarResource, descriptor);
_webFragmentRoots.add(descriptor);
descriptor.parse();
if (descriptor.getName() != null)
{
Descriptor existing = _webFragmentNameMap.get(descriptor.getName());
if (existing != null && !isAllowDuplicateFragmentNames())
{
throw new IllegalStateException("Duplicate fragment name: "+descriptor.getName()+" for "+existing.getResource()+" and "+descriptor.getResource());
}
else
_webFragmentNameMap.put(descriptor.getName(), descriptor);
}
//If web.xml has specified an absolute ordering, ignore any relative ordering in the fragment
if (_ordering != null && _ordering.isAbsolute())
return;
if (_ordering == null && descriptor.isOrdered())
_ordering = new Ordering.RelativeOrdering(this);
}
/**
* Annotations not associated with a WEB-INF/lib fragment jar.
* These are from WEB-INF/classes or the ??container path??
* @param annotations
*/
public void addDiscoveredAnnotations(List<DiscoveredAnnotation> annotations)
{
if (annotations == null)
return;
for (DiscoveredAnnotation a:annotations)
{
Resource r = a.getResource();
if (r == null || !_webInfJars.contains(r))
_annotations.add(a);
else
addDiscoveredAnnotation(a.getResource(), a);
}
}
public void addDiscoveredAnnotation(Resource resource, DiscoveredAnnotation annotation)
{
List<DiscoveredAnnotation> list = _webFragmentAnnotations.get(resource);
if (list == null)
{
list = new ArrayList<DiscoveredAnnotation>();
_webFragmentAnnotations.put(resource, list);
}
list.add(annotation);
}
public void addDiscoveredAnnotations(Resource resource, List<DiscoveredAnnotation> annotations)
{
List<DiscoveredAnnotation> list = _webFragmentAnnotations.get(resource);
if (list == null)
{
list = new ArrayList<DiscoveredAnnotation>();
_webFragmentAnnotations.put(resource, list);
}
list.addAll(annotations);
}
public void addDescriptorProcessor(DescriptorProcessor p)
{
_descriptorProcessors.add(p);
}
public void orderFragments ()
{
//if we have already ordered them don't do it again
if (_orderedWebInfJars.size()==_webInfJars.size())
return;
if (_ordering != null)
_orderedWebInfJars.addAll(_ordering.order(_webInfJars));
else
_orderedWebInfJars.addAll(_webInfJars);
}
/**
* Resolve all servlet/filter/listener metadata from all sources: descriptors and annotations.
*
*/
public void resolve (WebAppContext context)
throws Exception
{
LOG.debug("metadata resolve {}",context);
//Ensure origins is fresh
_origins.clear();
// Set the ordered lib attribute
if (_ordering != null)
{
List<String> orderedLibs = new ArrayList<String>();
for (Resource webInfJar:_orderedWebInfJars)
{
//get just the name of the jar file
String fullname = webInfJar.getName();
int i = fullname.indexOf(".jar");
int j = fullname.lastIndexOf("/", i);
orderedLibs.add(fullname.substring(j+1,i+4));
}
context.setAttribute(ServletContext.ORDERED_LIBS, orderedLibs);
}
// set the webxml version
if (_webXmlRoot != null)
{
context.getServletContext().setEffectiveMajorVersion(_webXmlRoot.getMajorVersion());
context.getServletContext().setEffectiveMinorVersion(_webXmlRoot.getMinorVersion());
}
for (DescriptorProcessor p:_descriptorProcessors)
{
p.process(context,getWebDefault());
p.process(context,getWebXml());
for (WebDescriptor wd : getOverrideWebs())
{
LOG.debug("process {} {}",context,wd);
p.process(context,wd);
}
}
for (DiscoveredAnnotation a:_annotations)
{
LOG.debug("apply {}",a);
a.apply();
}
List<Resource> resources = getOrderedWebInfJars();
for (Resource r:resources)
{
FragmentDescriptor fd = _webFragmentResourceMap.get(r);
if (fd != null)
{
for (DescriptorProcessor p:_descriptorProcessors)
{
LOG.debug("process {} {}",context,fd);
p.process(context,fd);
}
}
List<DiscoveredAnnotation> fragAnnotations = _webFragmentAnnotations.get(r);
if (fragAnnotations != null)
{
for (DiscoveredAnnotation a:fragAnnotations)
{
LOG.debug("apply {}",a);
a.apply();
}
}
}
}
public boolean isDistributable ()
{
boolean distributable = (
(_webDefaultsRoot != null && _webDefaultsRoot.isDistributable())
|| (_webXmlRoot != null && _webXmlRoot.isDistributable()));
for (WebDescriptor d : _webOverrideRoots)
distributable&=d.isDistributable();
List<Resource> orderedResources = getOrderedWebInfJars();
for (Resource r: orderedResources)
{
FragmentDescriptor d = _webFragmentResourceMap.get(r);
if (d!=null)
distributable = distributable && d.isDistributable();
}
return distributable;
}
public WebDescriptor getWebXml ()
{
return _webXmlRoot;
}
public List<WebDescriptor> getOverrideWebs ()
{
return _webOverrideRoots;
}
public WebDescriptor getWebDefault ()
{
return _webDefaultsRoot;
}
public List<FragmentDescriptor> getFragments ()
{
return _webFragmentRoots;
}
public List<Resource> getOrderedWebInfJars()
{
return _orderedWebInfJars == null? new ArrayList<Resource>(): _orderedWebInfJars;
}
public List<FragmentDescriptor> getOrderedFragments ()
{
List<FragmentDescriptor> list = new ArrayList<FragmentDescriptor>();
if (_orderedWebInfJars == null)
return list;
for (Resource r:_orderedWebInfJars)
{
FragmentDescriptor fd = _webFragmentResourceMap.get(r);
if (fd != null)
list.add(fd);
}
return list;
}
public Ordering getOrdering()
{
return _ordering;
}
public void setOrdering (Ordering o)
{
_ordering = o;
}
public FragmentDescriptor getFragment (Resource jar)
{
return _webFragmentResourceMap.get(jar);
}
public FragmentDescriptor getFragment(String name)
{
return _webFragmentNameMap.get(name);
}
public Resource getJarForFragment (String name)
{
FragmentDescriptor f = getFragment(name);
if (f == null)
return null;
Resource jar = null;
for (Resource r: _webFragmentResourceMap.keySet())
{
if (_webFragmentResourceMap.get(r).equals(f))
jar = r;
}
return jar;
}
public Map<String,FragmentDescriptor> getNamedFragments ()
{
return Collections.unmodifiableMap(_webFragmentNameMap);
}
public Origin getOrigin (String name)
{
OriginInfo x = _origins.get(name);
if (x == null)
return Origin.NotSet;
return x.getOriginType();
}
public Descriptor getOriginDescriptor (String name)
{
OriginInfo o = _origins.get(name);
if (o == null)
return null;
return o.getDescriptor();
}
public void setOrigin (String name, Descriptor d)
{
OriginInfo x = new OriginInfo (name, d);
_origins.put(name, x);
}
public void setOrigin (String name)
{
if (name == null)
return;
OriginInfo x = new OriginInfo (name, Origin.Annotation);
_origins.put(name, x);
}
public void setOrigin(String name, Origin origin)
{
if (name == null)
return;
OriginInfo x = new OriginInfo (name, origin);
_origins.put(name, x);
}
public boolean isMetaDataComplete()
{
return _metaDataComplete;
}
public void addWebInfJar(Resource newResource)
{
_webInfJars.add(newResource);
}
public List<Resource> getWebInfJars()
{
return Collections.unmodifiableList(_webInfJars);
}
public List<Resource> getOrderedContainerJars()
{
return _orderedContainerJars;
}
public void addContainerJar(Resource jar)
{
_orderedContainerJars.add(jar);
}
public boolean isAllowDuplicateFragmentNames()
{
return allowDuplicateFragmentNames;
}
public void setAllowDuplicateFragmentNames(boolean allowDuplicateFragmentNames)
{
this.allowDuplicateFragmentNames = allowDuplicateFragmentNames;
}
}