webtier@glassfish.java.net

revised valve-patch

From: Wolfram Rittmeyer <w.rittmeyer_at_jsptutorial.org>
Date: Thu, 12 Feb 2009 22:45:24 +0100

Hi,

I have added the patches for the web and deployment projects as
diff-files. Also I have added the two new classes
com.sun.enterprise.deployment.node.runtime.web.ValveNode and
com.sun.enterprise.deployment.runtime.web.Valve that belong into the dol
project of the deployment projects.

Due to the new DTD (sun-web-app_3_0-0.dtd) some minor changes had to be
added to the DTDRegistry (dol project) and WebBundleRuntimeNode. These
changes have not been part of my first patch.

Jan, you mentioned in one of your earlier mails that I should deprecate
property-based valve handling. This actually only applied to the
addValve(java.lang.String) method, if I am not mistaken. I did add a
deprecation-annotation and comment but I guess more relevant would be
the documentation which momentarily mentions the property usage.


Thanks for your help and comments to my first patch,

--
Wolfram Rittmeyer



Property changes on: javaee-core
___________________________________________________________________
Added: svn:ignore
   + target


Index: dol/src/main/java/com/sun/enterprise/deployment/runtime/web/SunWebApp.java
===================================================================
--- dol/src/main/java/com/sun/enterprise/deployment/runtime/web/SunWebApp.java (revision 24754)
+++ dol/src/main/java/com/sun/enterprise/deployment/runtime/web/SunWebApp.java (working copy)
@@ -62,7 +62,7 @@
     public static final String IDEMPOTENT_URL_PATTERN = "IdempotentUrlPattern";
     public static final String ERROR_URL = "ErrorUrl";
     public static final String HTTPSERVLET_SECURITY_PROVIDER = "HttpServletSecurityProvider";
-
+ public static final String VALVE = "Valve";
     
     public SunWebApp()
     {
@@ -424,4 +424,47 @@
         }
         return ret.booleanValue();
     }
+
+ // This attribute is a valve to be added at the specified index
+ public void setValve(int index, Valve value)
+ {
+ this.setValue(VALVE, index, value);
+ }
+
+ // The return value is the valve at the specified index
+ public Valve getValve(int index)
+ {
+ return (Valve)this.getValue(VALVE, index);
+ }
+
+ // This attribute is an array, possibly empty
+ public void setValve(Valve[] value)
+ {
+ this.setValue(VALVE, value);
+ }
+
+ // This return value is an array, possibly empty
+ public Valve[] getValve()
+ {
+ return (Valve[])this.getValues(VALVE);
+ }
+
+ // Return the number of valves
+ public int sizeValve()
+ {
+ return this.size(VALVE);
+ }
+
+ // Add a new element returning its index in the list
+ public int addValve(Valve value)
+ {
+ return this.addValue(VALVE, value);
+ }
+
+ // Remove an element using its reference
+ public int removeValve(Valve value)
+ {
+ return this.removeValue(VALVE, value);
+ }
+
 }
Index: dol/src/main/java/com/sun/enterprise/deployment/node/runtime/RuntimeDescriptorFactory.java
===================================================================
--- dol/src/main/java/com/sun/enterprise/deployment/node/runtime/RuntimeDescriptorFactory.java (revision 24754)
+++ dol/src/main/java/com/sun/enterprise/deployment/node/runtime/RuntimeDescriptorFactory.java (working copy)
@@ -108,6 +108,7 @@
         //common
         register(new XMLElement(RuntimeTagNames.PRINCIPAL_NAME), PrincipalNameDescriptor.class);
         register(new XMLElement(RuntimeTagNames.SECURITY_ROLE_MAPPING), SecurityRoleMapping.class);
+ register(new XMLElement(RuntimeTagNames.VALVE), Valve.class);
      }
     /**
      * register a new descriptor class handling a particular XPATH in the DTD.
Index: dol/src/main/java/com/sun/enterprise/deployment/node/runtime/web/WebBundleRuntimeNode.java
===================================================================
--- dol/src/main/java/com/sun/enterprise/deployment/node/runtime/web/WebBundleRuntimeNode.java (revision 24754)
+++ dol/src/main/java/com/sun/enterprise/deployment/node/runtime/web/WebBundleRuntimeNode.java (working copy)
@@ -131,6 +131,9 @@
                                 MessageDestinationRuntimeNode.class);
         registerElementHandler(new XMLElement(WebServicesTagNames.WEB_SERVICE),
                                      WebServiceRuntimeNode.class);
+ registerElementHandler(new XMLElement(RuntimeTagNames.VALVE),
+ ValveNode.class);
+
     }
     
     /**
@@ -144,14 +147,14 @@
      * @return the DOCTYPE that should be written to the XML file
      */
     public String getDocType() {
- return DTDRegistry.SUN_WEBAPP_250_DTD_PUBLIC_ID;
+ return DTDRegistry.SUN_WEBAPP_300_DTD_PUBLIC_ID;
     }
     
     /**
      * @return the SystemID of the XML file
      */
     public String getSystemID() {
- return DTDRegistry.SUN_WEBAPP_250_DTD_SYSTEM_ID;
+ return DTDRegistry.SUN_WEBAPP_300_DTD_SYSTEM_ID;
     }
 
     /**
@@ -173,6 +176,7 @@
        publicIDToDTD.put(DTDRegistry.SUN_WEBAPP_240_DTD_PUBLIC_ID, DTDRegistry.SUN_WEBAPP_240_DTD_SYSTEM_ID);
        publicIDToDTD.put(DTDRegistry.SUN_WEBAPP_241_DTD_PUBLIC_ID, DTDRegistry.SUN_WEBAPP_241_DTD_SYSTEM_ID);
        publicIDToDTD.put(DTDRegistry.SUN_WEBAPP_250_DTD_PUBLIC_ID, DTDRegistry.SUN_WEBAPP_250_DTD_SYSTEM_ID);
+ publicIDToDTD.put(DTDRegistry.SUN_WEBAPP_300_DTD_PUBLIC_ID, DTDRegistry.SUN_WEBAPP_300_DTD_SYSTEM_ID);
        if (!restrictDTDDeclarations()) {
           publicIDToDTD.put(DTDRegistry.SUN_WEBAPP_240beta_DTD_PUBLIC_ID, DTDRegistry.SUN_WEBAPP_240beta_DTD_SYSTEM_ID);
        }
@@ -296,6 +300,9 @@
         } else if (newDescriptor instanceof WebProperty) {
             descriptor.getSunDescriptor().addWebProperty(
                 (WebProperty)newDescriptor);
+ } else if (newDescriptor instanceof Valve) {
+ descriptor.getSunDescriptor().addValve(
+ (Valve)newDescriptor);
         }
         else super.addDescriptor(descriptor);
     }
@@ -501,6 +508,12 @@
             props.writeDescriptor(web, RuntimeTagNames.PROPERTY, sunWebApp.getWebProperty());
         }
         
+ // valve*
+ if (sunWebApp.getValve()!=null) {
+ ValveNode valve = new ValveNode();
+ valve.writeDescriptor(web, RuntimeTagNames.VALVE, sunWebApp.getValve());
+ }
+
         // message-destination*
         RuntimeDescriptorNode.writeMessageDestinationInfo(web, bundleDescriptor);
 
Index: dol/src/main/java/com/sun/enterprise/deployment/xml/RuntimeTagNames.java
===================================================================
--- dol/src/main/java/com/sun/enterprise/deployment/xml/RuntimeTagNames.java (revision 24754)
+++ dol/src/main/java/com/sun/enterprise/deployment/xml/RuntimeTagNames.java (working copy)
@@ -286,6 +286,8 @@
     public static final String JAVA_METHOD = "java-method";
     public final static String METHOD_PARAMS = "method-params";
     public final static String METHOD_PARAM = "method-param";
+
+ public final static String VALVE = "valve";
     
     // Java Web Start-support related
     public final static String JAVA_WEB_START_ACCESS = "java-web-start-access";
Index: dol/src/main/java/com/sun/enterprise/deployment/xml/DTDRegistry.java
===================================================================
--- dol/src/main/java/com/sun/enterprise/deployment/xml/DTDRegistry.java (revision 24754)
+++ dol/src/main/java/com/sun/enterprise/deployment/xml/DTDRegistry.java (working copy)
@@ -223,6 +223,10 @@
     public static final String SUN_WEBAPP_250_DTD_SYSTEM_ID =
         "http://www.sun.com/software/appserver/dtds/sun-web-app_2_5-0.dtd";
     
+ public static final String SUN_WEBAPP_300_DTD_PUBLIC_ID =
+ "-//Sun Microsystems, Inc.//DTD GlassFish v3 Servlet 3.0//EN";
+ public static final String SUN_WEBAPP_300_DTD_SYSTEM_ID =
+ "http://www.sun.com/software/appserver/dtds/sun-web-app_3_0-0.dtd";
     
     /**
      * Application Client Container: Sun ONE App Server specific dtd info.
Index: dtds/src/main/resources/glassfish/lib/dtds/sun-web-app_3_0-0.dtd
===================================================================
--- dtds/src/main/resources/glassfish/lib/dtds/sun-web-app_3_0-0.dtd (revision 24754)
+++ dtds/src/main/resources/glassfish/lib/dtds/sun-web-app_3_0-0.dtd (working copy)
@@ -17,7 +17,7 @@
                        ejb-ref*, resource-ref*, resource-env-ref*, service-ref*,
                        message-destination-ref*, cache?, class-loader?,
                        jsp-config?, locale-charset-info?, parameter-encoding?,
- property*, message-destination*, webservice-description*)>
+ property*, valve*, message-destination*, webservice-description*)>
 <!ATTLIST sun-web-app error-url CDATA ""
                       httpservlet-security-provider CDATA #IMPLIED>
 
@@ -321,6 +321,9 @@
 -->
 <!ELEMENT value (#PCDATA)>
 
+<!ELEMENT valve (description?, property*)>
+<!ATTLIST valve name CDATA #REQUIRED
+ class-name CDATA #REQUIRED>
 
 <!--
                                           W E B S E R V I C E S


Index: war-util/src/main/resources/com/sun/logging/enterprise/system/container/web/LogStrings.properties
===================================================================
--- war-util/src/main/resources/com/sun/logging/enterprise/system/container/web/LogStrings.properties (revision 24754)
+++ war-util/src/main/resources/com/sun/logging/enterprise/system/container/web/LogStrings.properties (working copy)
@@ -221,6 +221,11 @@
 webmodule.alternateDocBase.illegalUrlPattern=WEB0504: URL pattern {0} for alternate docbase is invalid
 webmodule.alternateDocBase.crlfInUrlPattern=WEB0505: URL pattern {0} for alternate docbase contains CR or LF or both
 webmodule.noservercontext=WEB0506: No ServerContext in WebModule [{0}]
+webmodule.valve.specifiedMethodMissing=There is no method [{0}(java.lang.String)] defined on valve [{1}] of web module [{2}]
+webmodule.valve.setterCausedException=Exception during execution of method [{0}] on valve [{1}] of web module [{2}]
+webmodule.valve.missingName=Web module [{0}] has a valve without any name
+webmodule.valve.missingClassname=Valve [{0}] of web module [{1}] has no class name
+webmodule.valve.missingPropertyName=Valve [{0}] of web module [{1}] has a property without any name
 
 webModuleContextConfig.webModuleDisabled=WEB0600: WebModule [{0}] failed to deploy and has been disabled
 webModuleContextConfig.missingDefaultWeb.xml=WEB0601: Missing default web.xml, using application web.xml only
Index: web-glue/src/main/java/com/sun/enterprise/web/WebModule.java
===================================================================
--- web-glue/src/main/java/com/sun/enterprise/web/WebModule.java (revision 24754)
+++ web-glue/src/main/java/com/sun/enterprise/web/WebModule.java (working copy)
@@ -85,6 +85,8 @@
 import com.sun.enterprise.web.session.PersistenceType;
 import com.sun.enterprise.web.session.SessionCookieConfig;
 import com.sun.logging.LogDomains;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
 import org.apache.catalina.Container;
 import org.apache.catalina.ContainerListener;
 import org.apache.catalina.InstanceListener;
@@ -468,6 +470,9 @@
         // Configure catalina listeners and valves. This can only happen
         // after this web module has been started, in order to be able to
         // load the specified listener and valve classes.
+
+ configureValves();
+
         configureCatalinaProperties();
 
         webModuleStartedEvent();
@@ -871,7 +876,21 @@
     }
     
    
+
     /**
+ * Configure the <code>WebModule</code> valves.
+ */
+ protected void configureValves(){
+ if (iasBean.getValve() != null && iasBean.sizeValve() > 0) {
+ com.sun.enterprise.deployment.runtime.web.Valve[] valves = iasBean.getValve();
+ for (com.sun.enterprise.deployment.runtime.web.Valve valve: valves) {
+ addValve(valve);
+ }
+ }
+
+ }
+
+ /**
      * Configure the <code>WebModule</code< properties.
      */
     protected void configureCatalinaProperties(){
@@ -921,8 +940,9 @@
     
 
     /**
- * Add a <code>Valve</code> to a <code>VirtualServer</code> pipeline.
- * @param valveName the fully qualified class name of the Valve.
+ * Constructs a <tt>Valve</tt> and adds it to the
+ * <tt>Pipeline</tt> of this WebModule.
+ * @param valveName the fully qualified class name of the Valve.
      */
     protected void addValve(String valveName) {
         Object valve = loadInstance(valveName);
@@ -937,7 +957,74 @@
         }
     }
     
+ /**
+ * Constructs a <tt>Valve</tt> from the given <tt>valveDescriptor</tt>
+ * and adds it to the <tt>Pipeline</tt> of this WebModule.
+ * @param valveDescriptor the object containing the information to create the valve.
+ */
+ protected void addValve(com.sun.enterprise.deployment.runtime.web.Valve valveDescriptor) {
+ String valveName = valveDescriptor.getAttributeValue(
+ com.sun.enterprise.deployment.runtime.web.Valve.NAME);
+ String className = valveDescriptor.getAttributeValue(
+ com.sun.enterprise.deployment.runtime.web.Valve.CLASS_NAME);
+ if (valveName == null) {
+ logger.log(Level.WARNING, "webmodule.valve.missingName", getName());
+ return;
+ }
+ if (className == null) {
+ logger.log(Level.WARNING, "webmodule.valve.missingClassname", new Object[]{valveName, getName()});
+ return;
+ }
+ Object valve = loadInstance(className);
+ if (valve == null) {
+ return;
+ }
+ if (!(valve instanceof GlassFishValve) &&
+ !(valve instanceof Valve)) {
+ logger.log(Level.WARNING,
+ "Object of type classname " + className +
+ " not an instance of Valve or GlassFishValve");
+ }
+ WebProperty[] props = valveDescriptor.getWebProperty();
+ if (props != null && props.length > 0) {
+ for (WebProperty property: props) {
+ String propName = getSetterName(property.getAttributeValue(WebProperty.NAME));
+ if (propName != null && propName.length() != 0) {
+ String value = property.getAttributeValue(WebProperty.VALUE);
+ try {
+ Method method = valve.getClass().getMethod(propName, String.class);
+ method.invoke(valve, value);
+ } catch (NoSuchMethodException ex) {
+ String msg = rb.getString("webmodule.valve.specifiedMethodMissing");
+ msg = MessageFormat.format(msg, new Object[] { propName,
+ valveName,
+ getName()});
+ logger.log(Level.SEVERE, msg, ex);
+ } catch (Throwable t) {
+ String msg = rb.getString("webmodule.valve.setterCausedException");
+ msg = MessageFormat.format(msg, new Object[] { propName,
+ valveName,
+ getName()});
+ logger.log(Level.SEVERE, msg, t);
+ }
+ }
+ else {
+ String msg = rb.getString("webmodule.valve.missingPropertyName");
+ msg = MessageFormat.format(msg, new Object[] {valveName});
+ logger.log(Level.WARNING, "webmodule.valve.missingPropertyName", new Object[]{valveName, getName()});
+ return;
+ }
+ }
+ }
+ if (valve instanceof Valve) {
+ super.addValve((Valve) valve);
+ } else if (valve instanceof GlassFishValve) {
+ super.addValve((GlassFishValve) valve);
+ }
+ }
     
+
+
     /**
      * Add a Catalina listener to a <code>ContractProvider</code>
      * @param listenerName the fully qualified class name of the listener.
@@ -973,6 +1060,19 @@
         return null;
     }
 
+
+ private String getSetterName(String propName) {
+ if (propName != null) {
+ if (propName.length() > 1) {
+ propName = "set" + Character.toUpperCase(propName.charAt(0)) +
+ propName.substring(1);
+ }
+ else {
+ propName = "set" + Character.toUpperCase(propName.charAt(0));
+ }
+ }
+ return propName;
+ }
     
     public com.sun.enterprise.config.serverbeans.WebModule getBean() {
         return bean;


package com.sun.enterprise.deployment.node.runtime.web;

import com.sun.enterprise.deployment.node.XMLElement;
import com.sun.enterprise.deployment.runtime.web.Valve;
import com.sun.enterprise.deployment.runtime.web.WebProperty;
import com.sun.enterprise.deployment.xml.RuntimeTagNames;
import org.w3c.dom.Element;
import org.w3c.dom.Node;


/**
 * Node representing a valve tag.
 */
public class ValveNode extends WebRuntimeNode {

    public ValveNode() {
        registerElementHandler(new XMLElement(RuntimeTagNames.PROPERTY),
                WebPropertyNode.class, "addWebProperty");
    }

    @Override
    protected boolean setAttributeValue(XMLElement elementName, XMLElement attributeName, String value) {
        Valve descriptor = (Valve) getRuntimeDescriptor();
        if (descriptor == null) {
            throw new RuntimeException("Trying to set values on a null descriptor");
        }
        if (attributeName.getQName().equals(RuntimeTagNames.NAME)) {
            descriptor.setAttributeValue(Valve.NAME, value);
            return true;
        } else if (attributeName.getQName().equals(RuntimeTagNames.CLASS_NAME)) {
            descriptor.setAttributeValue(Valve.CLASS_NAME, value);
            return true;
        }
        return false;
    }

    /**
     * write the descriptor class to a DOM tree and return it
     *
     * @param parent node for the DOM tree
     * @param node name
     * @param the descriptor to write
     * @return the DOM tree top node
     */
    public Node writeDescriptor(Node parent, String nodeName, Valve descriptor) {

        Element valve = (Element) super.writeDescriptor(parent, nodeName, descriptor);

        WebPropertyNode wpn = new WebPropertyNode();

        // sub-element property*
        wpn.writeDescriptor(valve, RuntimeTagNames.PROPERTY, descriptor.getWebProperty());

        // attributes classname and name
        setAttribute(valve, RuntimeTagNames.NAME, (String) descriptor.getAttributeValue(Valve.NAME));
        setAttribute(valve, RuntimeTagNames.CLASS_NAME, (String) descriptor.getAttributeValue(Valve.CLASS_NAME));

        return valve;
    }
}


package com.sun.enterprise.deployment.runtime.web;

public class Valve extends WebPropertyContainer {

    static public final String CLASS_NAME = "ClassName";

}