Search in sources :

Example 1 with Descriptor

use of org.eclipse.jetty.webapp.Descriptor in project jetty.project by eclipse.

the class PlusDescriptorProcessor method visitResourceRef.

/**
     * Common Annotations Spec section 2.3:
     * <p>
     *  resource-ref is for:
     * <ul>
     * <li>javax.sql.DataSource</li>
     * <li>javax.jms.ConnectionFactory</li>
     * <li>javax.jms.QueueConnectionFactory</li>
     * <li>javax.jms.TopicConnectionFactory</li>
     * <li>javax.mail.Session</li>
     * <li>java.net.URL</li>
     * <li>javax.resource.cci.ConnectionFactory</li>
     * <li>org.omg.CORBA_2_3.ORB</li>
     * <li>any other connection factory defined by a resource adapter</li>
     * </ul>
     *
     * If web.xml contains a resource-ref with injection targets, all resource-ref entries
     * of the same name are ignored in web fragments. If web.xml does not contain any
     * injection-targets, then they are merged from all the fragments.
     * If web.xml does not contain a resource-ref element of same name, but 2 fragments
     * declare the same name it is an error.
     * 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
     * 
     * <p>
     * Maintenance update 3.0a to spec:
     * <p>
     *   Update Section 8.2.3.h.ii with the following -  If a resource reference
     *   element is specified in two fragments, while absent from the main web.xml,
     *   and all the attributes and child elements of the resource reference element
     *   are identical, the resource reference will be merged  into the main web.xml.
     *   It is considered an error if a resource reference element has the same name
     *   specified in two fragments, while absent from the main web.xml and the attributes
     *   and child elements are not identical in the two fragments. For example, if two
     *   web fragments declare a <code>&lt;resource-ref&gt;</code> with the same <code>&lt;resource-ref-name&gt;</code> element
     *   but the type in one is specified as javax.sql.DataSource while the type in the
     *   other is that of a java mail resource, then an error must be reported and the
     *   application MUST fail to deploy.
     *   
     * @param context the context  
     * @param descriptor the descriptor
     * @param node the xml node
     * @throws Exception if unable to bind nodes, or load classes
     */
public void visitResourceRef(WebAppContext context, Descriptor descriptor, 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);
    Origin o = context.getMetaData().getOrigin("resource-ref." + jndiName);
    switch(o) {
        case NotSet:
            {
                //No descriptor or annotation previously declared a resource-ref of this name.
                context.getMetaData().setOrigin("resource-ref." + jndiName, descriptor);
                //check for <injection> elements
                Class<?> typeClass = TypeUtil.fromName(type);
                if (typeClass == null)
                    typeClass = context.loadClass(type);
                addInjections(context, descriptor, node, jndiName, typeClass);
                bindResourceRef(context, jndiName, typeClass);
                break;
            }
        case WebXml:
        case WebDefaults:
        case WebOverride:
            {
                //A web xml previously declared the resource-ref.
                if (!(descriptor instanceof FragmentDescriptor)) {
                    //We're processing web-defaults, web.xml or web-override. Any of them can
                    //set or change the resource-ref.
                    context.getMetaData().setOrigin("resource-ref." + jndiName, descriptor);
                    //check for <injection> elements
                    Class<?> typeClass = TypeUtil.fromName(type);
                    if (typeClass == null)
                        typeClass = context.loadClass(type);
                    addInjections(context, descriptor, node, jndiName, typeClass);
                    //bind the entry into jndi
                    bindResourceRef(context, jndiName, typeClass);
                } else {
                    //A web xml declared the resource-ref and we're processing a
                    //web-fragment. Check to see if any injections were declared for it by web.xml.
                    //If any injection was declared in web.xml then don't merge any injections.
                    //If it was declared in a web-fragment, then we can keep merging fragments.
                    Descriptor d = context.getMetaData().getOriginDescriptor("resource-ref." + jndiName + ".injection");
                    if (d == null || d instanceof FragmentDescriptor) {
                        Class<?> typeClass = TypeUtil.fromName(type);
                        if (typeClass == null)
                            typeClass = context.loadClass(type);
                        addInjections(context, descriptor, node, jndiName, TypeUtil.fromName(type));
                    }
                }
                break;
            }
        case WebFragment:
            {
                Descriptor otherFragment = context.getMetaData().getOriginDescriptor("resource-ref." + jndiName);
                XmlParser.Node otherFragmentRoot = otherFragment.getRoot();
                Iterator<Object> iter = otherFragmentRoot.iterator();
                XmlParser.Node otherNode = null;
                while (iter.hasNext() && otherNode == null) {
                    Object obj = iter.next();
                    if (!(obj instanceof XmlParser.Node))
                        continue;
                    XmlParser.Node n = (XmlParser.Node) obj;
                    if ("resource-ref".equals(n.getTag()) && jndiName.equals(n.getString("res-ref-name", false, true)))
                        otherNode = n;
                }
                //If declared in another web-fragment
                if (otherNode != null) {
                    //declarations of the resource-ref must be the same in both fragment descriptors
                    String otherType = otherNode.getString("res-type", false, true);
                    String otherAuth = otherNode.getString("res-auth", false, true);
                    String otherShared = otherNode.getString("res-sharing-scope", false, true);
                    //otherType, otherAuth and otherShared must be the same as type, auth, shared
                    type = (type == null ? "" : type);
                    otherType = (otherType == null ? "" : otherType);
                    auth = (auth == null ? "" : auth);
                    otherAuth = (otherAuth == null ? "" : otherAuth);
                    shared = (shared == null ? "" : shared);
                    otherShared = (otherShared == null ? "" : otherShared);
                    //ServletSpec p.75. No declaration of resource-ref in web xml, but different in multiple web-fragments. Error.
                    if (!type.equals(otherType) || !auth.equals(otherAuth) || !shared.equals(otherShared))
                        throw new IllegalStateException("Conflicting resource-ref " + jndiName + " in " + descriptor.getResource());
                    //same in multiple web-fragments, merge the injections
                    addInjections(context, descriptor, node, jndiName, TypeUtil.fromName(type));
                } else
                    throw new IllegalStateException("resource-ref." + jndiName + " not found in declaring descriptor " + otherFragment);
            }
    }
}
Also used : Origin(org.eclipse.jetty.webapp.Origin) XmlParser(org.eclipse.jetty.xml.XmlParser) Iterator(java.util.Iterator) FragmentDescriptor(org.eclipse.jetty.webapp.FragmentDescriptor) Descriptor(org.eclipse.jetty.webapp.Descriptor) FragmentDescriptor(org.eclipse.jetty.webapp.FragmentDescriptor)

Example 2 with Descriptor

use of org.eclipse.jetty.webapp.Descriptor in project jetty.project by eclipse.

the class PlusDescriptorProcessor method visitMessageDestinationRef.

/**
     * Common Annotations Spec section 2.3:
     * <p>
     * message-destination-ref is for:
     * <ul>
     * <li>javax.jms.Queue</li>
     * <li>javax.jms.Topic</li>
     * </ul>
     *     
     * @param context the context 
     * @param descriptor the descriptor 
     * @param node the xml node
     * @throws Exception if unable to load classes or bind jndi entries
     */
public void visitMessageDestinationRef(WebAppContext context, Descriptor descriptor, 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);
    Origin o = context.getMetaData().getOrigin("message-destination-ref." + jndiName);
    switch(o) {
        case NotSet:
            {
                //A message-destination-ref of this name has not been previously declared
                Class<?> typeClass = TypeUtil.fromName(type);
                if (typeClass == null)
                    typeClass = context.loadClass(type);
                addInjections(context, descriptor, node, jndiName, typeClass);
                bindMessageDestinationRef(context, jndiName, typeClass);
                context.getMetaData().setOrigin("message-destination-ref." + jndiName, descriptor);
                break;
            }
        case WebXml:
        case WebDefaults:
        case WebOverride:
            {
                //Only allow other web-default, web.xml, web-override to change it.
                if (!(descriptor instanceof FragmentDescriptor)) {
                    Class<?> typeClass = TypeUtil.fromName(type);
                    if (typeClass == null)
                        typeClass = context.loadClass(type);
                    addInjections(context, descriptor, node, jndiName, typeClass);
                    bindMessageDestinationRef(context, jndiName, typeClass);
                    context.getMetaData().setOrigin("message-destination-ref." + jndiName, descriptor);
                } else {
                    //A web-fragment has declared a message-destination-ref with the same name as a web xml.
                    //It can only contribute injections, and only if the web xml didn't declare any.
                    Descriptor d = context.getMetaData().getOriginDescriptor("message-destination-ref." + jndiName + ".injection");
                    if (d == null || d instanceof FragmentDescriptor) {
                        Class<?> typeClass = TypeUtil.fromName(type);
                        if (typeClass == null)
                            typeClass = context.loadClass(type);
                        addInjections(context, descriptor, node, jndiName, typeClass);
                    }
                }
                break;
            }
        case WebFragment:
            {
                Descriptor otherFragment = context.getMetaData().getOriginDescriptor("message-destination-ref." + jndiName);
                XmlParser.Node otherFragmentRoot = otherFragment.getRoot();
                Iterator<Object> iter = otherFragmentRoot.iterator();
                XmlParser.Node otherNode = null;
                while (iter.hasNext() && otherNode == null) {
                    Object obj = iter.next();
                    if (!(obj instanceof XmlParser.Node))
                        continue;
                    XmlParser.Node n = (XmlParser.Node) obj;
                    if ("message-destination-ref".equals(n.getTag()) && jndiName.equals(n.getString("message-destination-ref-name", false, true)))
                        otherNode = n;
                }
                if (otherNode != null) {
                    String otherType = node.getString("message-destination-type", false, true);
                    String otherUsage = node.getString("message-destination-usage", false, true);
                    type = (type == null ? "" : type);
                    usage = (usage == null ? "" : usage);
                    if (!type.equals(otherType) || !usage.equalsIgnoreCase(otherUsage))
                        throw new IllegalStateException("Conflicting message-destination-ref " + jndiName + " in " + descriptor.getResource());
                    //same in multiple web-fragments, merge the injections
                    addInjections(context, descriptor, node, jndiName, TypeUtil.fromName(type));
                } else
                    throw new IllegalStateException("message-destination-ref." + jndiName + " not found in declaring descriptor " + otherFragment);
            }
    }
}
Also used : Origin(org.eclipse.jetty.webapp.Origin) XmlParser(org.eclipse.jetty.xml.XmlParser) Iterator(java.util.Iterator) FragmentDescriptor(org.eclipse.jetty.webapp.FragmentDescriptor) Descriptor(org.eclipse.jetty.webapp.Descriptor) FragmentDescriptor(org.eclipse.jetty.webapp.FragmentDescriptor)

Example 3 with Descriptor

use of org.eclipse.jetty.webapp.Descriptor in project jetty.project by eclipse.

the class PlusDescriptorProcessor method visitEnvEntry.

/**
     * JavaEE 5.4.1.3
     * 
     * @param context the context 
     * @param descriptor the descriptor 
     * @param node the xml node
     * @throws Exception if unable to process jndi bindings
     */
public void visitEnvEntry(WebAppContext context, Descriptor descriptor, 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);
    //nor processing injection entries
    if (valueStr == null || valueStr.equals("")) {
        LOG.warn("No value for env-entry-name " + name);
        return;
    }
    Origin o = context.getMetaData().getOrigin("env-entry." + name);
    switch(o) {
        case NotSet:
            {
                //no descriptor has configured an env-entry of this name previously
                context.getMetaData().setOrigin("env-entry." + name, descriptor);
                //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?
                addInjections(context, descriptor, node, name, TypeUtil.fromName(type));
                Object value = TypeUtil.valueOf(type, valueStr);
                bindEnvEntry(name, value);
                break;
            }
        case WebXml:
        case WebDefaults:
        case WebOverride:
            {
                //the web.xml did not declare any injections.
                if (!(descriptor instanceof FragmentDescriptor)) {
                    //We're processing web-defaults, web.xml or web-override. Any of them can
                    //set or change the env-entry.
                    context.getMetaData().setOrigin("env-entry." + name, descriptor);
                    addInjections(context, descriptor, node, name, TypeUtil.fromName(type));
                    Object value = TypeUtil.valueOf(type, valueStr);
                    bindEnvEntry(name, value);
                } else {
                    //A web.xml declared the env-entry. Check to see if any injections have been
                    //declared for it. If it was declared in web.xml then don't merge any injections.
                    //If it was declared in a web-fragment, then we can keep merging fragments.
                    Descriptor d = context.getMetaData().getOriginDescriptor("env-entry." + name + ".injection");
                    if (d == null || d instanceof FragmentDescriptor)
                        addInjections(context, descriptor, node, name, TypeUtil.fromName(type));
                }
                break;
            }
        case WebFragment:
            {
                //ServletSpec p.75. No declaration in web.xml, but in multiple web-fragments. Error.
                throw new IllegalStateException("Conflicting env-entry " + name + " in " + descriptor.getResource());
            }
    }
}
Also used : Origin(org.eclipse.jetty.webapp.Origin) FragmentDescriptor(org.eclipse.jetty.webapp.FragmentDescriptor) Descriptor(org.eclipse.jetty.webapp.Descriptor) FragmentDescriptor(org.eclipse.jetty.webapp.FragmentDescriptor)

Example 4 with Descriptor

use of org.eclipse.jetty.webapp.Descriptor in project jetty.project by eclipse.

the class PlusDescriptorProcessor method visitResourceEnvRef.

/**
     * Common Annotations Spec section 2.3:
     * <p>
     * resource-env-ref is for:
     * <ul>
     * <li>javax.transaction.UserTransaction</li>
     * <li>javax.resource.cci.InteractionSpec</li>
     * <li>anything else that is not a connection factory</li>
     * </ul>
     * 
     * @param context the context 
     * @param descriptor the descriptor 
     * @param node the xml node
     * @throws Exception if unable to load classes, or bind jndi entries
     */
public void visitResourceEnvRef(WebAppContext context, Descriptor descriptor, 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);
    Origin o = context.getMetaData().getOrigin("resource-env-ref." + jndiName);
    switch(o) {
        case NotSet:
            {
                //First declaration of resource-env-ref with this jndiName
                //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);
                addInjections(context, descriptor, node, jndiName, typeClass);
                bindResourceEnvRef(context, jndiName, typeClass);
                break;
            }
        case WebXml:
        case WebDefaults:
        case WebOverride:
            {
                //Only allow other web-default, web.xml, web-override to change it.
                if (!(descriptor instanceof FragmentDescriptor)) {
                    //We're processing web-defaults, web.xml or web-override. Any of them can
                    //set or change the resource-env-ref.
                    context.getMetaData().setOrigin("resource-env-ref." + jndiName, descriptor);
                    Class<?> typeClass = TypeUtil.fromName(type);
                    if (typeClass == null)
                        typeClass = context.loadClass(type);
                    addInjections(context, descriptor, node, jndiName, typeClass);
                    bindResourceEnvRef(context, jndiName, typeClass);
                } else {
                    //We're processing a web-fragment. It can only contribute injections if the
                    //there haven't been any injections declared yet, or they weren't declared in a WebXml file.
                    Descriptor d = context.getMetaData().getOriginDescriptor("resource-env-ref." + jndiName + ".injection");
                    if (d == null || d instanceof FragmentDescriptor) {
                        Class<?> typeClass = TypeUtil.fromName(type);
                        if (typeClass == null)
                            typeClass = context.loadClass(type);
                        addInjections(context, descriptor, node, jndiName, typeClass);
                    }
                }
                break;
            }
        case WebFragment:
            {
                Descriptor otherFragment = context.getMetaData().getOriginDescriptor("resource-env-ref." + jndiName);
                XmlParser.Node otherFragmentRoot = otherFragment.getRoot();
                Iterator<Object> iter = otherFragmentRoot.iterator();
                XmlParser.Node otherNode = null;
                while (iter.hasNext() && otherNode == null) {
                    Object obj = iter.next();
                    if (!(obj instanceof XmlParser.Node))
                        continue;
                    XmlParser.Node n = (XmlParser.Node) obj;
                    if ("resource-env-ref".equals(n.getTag()) && jndiName.equals(n.getString("resource-env-ref-name", false, true)))
                        otherNode = n;
                }
                if (otherNode != null) {
                    //declarations of the resource-ref must be the same in both fragment descriptors
                    String otherType = otherNode.getString("resource-env-ref-type", false, true);
                    //types must be the same
                    type = (type == null ? "" : type);
                    otherType = (otherType == null ? "" : otherType);
                    //ServletSpec p.75. No declaration of resource-ref in web xml, but different in multiple web-fragments. Error.
                    if (!type.equals(otherType))
                        throw new IllegalStateException("Conflicting resource-env-ref " + jndiName + " in " + descriptor.getResource());
                    //same in multiple web-fragments, merge the injections
                    addInjections(context, descriptor, node, jndiName, TypeUtil.fromName(type));
                } else
                    throw new IllegalStateException("resource-env-ref." + jndiName + " not found in declaring descriptor " + otherFragment);
            }
    }
}
Also used : Origin(org.eclipse.jetty.webapp.Origin) XmlParser(org.eclipse.jetty.xml.XmlParser) Iterator(java.util.Iterator) FragmentDescriptor(org.eclipse.jetty.webapp.FragmentDescriptor) Descriptor(org.eclipse.jetty.webapp.Descriptor) FragmentDescriptor(org.eclipse.jetty.webapp.FragmentDescriptor)

Example 5 with Descriptor

use of org.eclipse.jetty.webapp.Descriptor in project jetty.project by eclipse.

the class PlusDescriptorProcessorTest method testWebXmlResourceDeclarations.

@Test
public void testWebXmlResourceDeclarations() throws Exception {
    //if declared in web.xml, fragment declarations ignored
    ClassLoader oldLoader = Thread.currentThread().getContextClassLoader();
    Thread.currentThread().setContextClassLoader(context.getClassLoader());
    try {
        PlusDescriptorProcessor pdp = new PlusDescriptorProcessor();
        pdp.process(context, webDescriptor);
        Descriptor d = context.getMetaData().getOriginDescriptor("resource-ref.jdbc/mydatasource");
        assertNotNull(d);
        assertTrue(d == webDescriptor);
        pdp.process(context, fragDescriptor1);
        pdp.process(context, fragDescriptor2);
    } finally {
        Thread.currentThread().setContextClassLoader(oldLoader);
    }
}
Also used : WebAppClassLoader(org.eclipse.jetty.webapp.WebAppClassLoader) Descriptor(org.eclipse.jetty.webapp.Descriptor) FragmentDescriptor(org.eclipse.jetty.webapp.FragmentDescriptor) WebDescriptor(org.eclipse.jetty.webapp.WebDescriptor) Test(org.junit.Test)

Aggregations

Descriptor (org.eclipse.jetty.webapp.Descriptor)9 FragmentDescriptor (org.eclipse.jetty.webapp.FragmentDescriptor)7 Origin (org.eclipse.jetty.webapp.Origin)4 Iterator (java.util.Iterator)3 WebAppClassLoader (org.eclipse.jetty.webapp.WebAppClassLoader)3 WebDescriptor (org.eclipse.jetty.webapp.WebDescriptor)3 XmlParser (org.eclipse.jetty.xml.XmlParser)3 Test (org.junit.Test)3 Servlet (javax.servlet.Servlet)2 ServletHolder (org.eclipse.jetty.servlet.ServletHolder)2 MetaData (org.eclipse.jetty.webapp.MetaData)2 InvocationTargetException (java.lang.reflect.InvocationTargetException)1 MultipartConfigElement (javax.servlet.MultipartConfigElement)1 MultipartConfig (javax.servlet.annotation.MultipartConfig)1 RunAsCollection (org.eclipse.jetty.plus.annotation.RunAsCollection)1