gdamour     2005/03/31 05:29:27

  Modified:    modules/core/src/java/org/openejb/server
                        ServiceAccessController.java
                        SimpleSocketService.java StandardServiceStack.java
                        StandardServiceStackGBean.java
  Log:

  GERONIMO-620
  
  o Support IPv6.
  
  o Replace my own lame IP masking with a more IP centric implementation
  using some of the xinetd syntax to qualify IP addresses.
  
  Revision  Changes    Path
  1.8       +365 -30   
openejb/modules/core/src/java/org/openejb/server/ServiceAccessController.java
  
  Index: ServiceAccessController.java
  ===================================================================
  RCS file: 
/home/projects/openejb/scm/openejb/modules/core/src/java/org/openejb/server/ServiceAccessController.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- ServiceAccessController.java      28 Mar 2005 22:50:20 -0000      1.7
  +++ ServiceAccessController.java      31 Mar 2005 10:29:26 -0000      1.8
  @@ -47,6 +47,7 @@
   import java.beans.PropertyEditorSupport;
   import java.io.IOException;
   import java.io.Serializable;
  +import java.net.Inet6Address;
   import java.net.InetAddress;
   import java.net.Inet4Address;
   import java.net.Socket;
  @@ -71,13 +72,13 @@
    */
   public class ServiceAccessController implements ServerService {
       private final ServerService next;
  -    private IPAddressMask[] allowHosts;
  +    private IPAddressPermission[] allowHosts;
   
       public ServiceAccessController(ServerService next) {
           this.next = next;
       }
   
  -    public ServiceAccessController(String name, ServerService next, 
IPAddressMask[] ipAddressMasks) {
  +    public ServiceAccessController(String name, ServerService next, 
IPAddressPermission[] ipAddressMasks) {
           this.next = next;
           this.allowHosts = ipAddressMasks;
       }
  @@ -89,11 +90,11 @@
           next.service(socket);
       }
   
  -    public IPAddressMask[] getAllowHosts() {
  +    public IPAddressPermission[] getAllowHosts() {
           return allowHosts;
       }
   
  -    public void setAllowHosts(IPAddressMask[] ipAddressMasks) {
  +    public void setAllowHosts(IPAddressPermission[] ipAddressMasks) {
           this.allowHosts = ipAddressMasks;
       }
   
  @@ -121,7 +122,9 @@
               InetAddress[] localIps = InetAddress.getAllByName("localhost");
               for (int i = 0; i < localIps.length; i++) {
                   if (localIps[i] instanceof Inet4Address) {
  -                    ipAddressMasksList.add(new 
IPAddressMask(localIps[i].getHostAddress()));
  +                    ipAddressMasksList.add(new 
ExactIPAddressPermission(localIps[i].getAddress()));
  +                } else {
  +                    ipAddressMasksList.add(new 
ExactIPv6AddressPermission(localIps[i].getAddress()));
                   }
               }
           } catch (UnknownHostException e) {
  @@ -130,14 +133,14 @@
   
           String ipString = props.getProperty("only_from");
           if (ipString != null) {
  -            StringTokenizer st = new StringTokenizer(ipString, ",");
  +            StringTokenizer st = new StringTokenizer(ipString, " ");
               while (st.hasMoreTokens()) {
                   String mask = st.nextToken();
  -                ipAddressMasksList.add(new IPAddressMask(mask));
  +                
ipAddressMasksList.add(IPAddressPermissionFactory.getIPAddressMask(mask));
               }
           }
   
  -        allowHosts = (IPAddressMask[]) ipAddressMasksList.toArray(new 
IPAddressMask[ipAddressMasksList.size()]);
  +        allowHosts = (IPAddressPermission[]) ipAddressMasksList.toArray(new 
IPAddressPermission[ipAddressMasksList.size()]);
       }
   
       public void init(Properties props) throws Exception {
  @@ -165,44 +168,292 @@
           return next.getPort();
       }
       
  -    public static class IPAddressMask implements Serializable {
  -        private static final Pattern MASK_VALIDATOR = 
Pattern.compile("^(\\*|\\d{1,3})\\.(\\*|\\d{1,3})\\.(\\*|\\d{1,3})\\.(\\*|\\d{1,3})$");
  +    public interface IPAddressPermission extends Serializable {
  +        public boolean implies(InetAddress address);
  +    }
  +
  +    private static class ExactIPAddressPermission implements 
IPAddressPermission {
  +        private static final Pattern MASK_VALIDATOR = 
Pattern.compile("^(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$");
  +
  +        private static boolean canSupport(String mask) {
  +            Matcher matcher = MASK_VALIDATOR.matcher(mask);
  +            return matcher.matches();
  +        }
   
  -        private final String mask;
  -        private final byte[] byteMask;
  -        private final boolean[] definedBytes;
  +        private final byte[] bytes;
  +        
  +        private ExactIPAddressPermission(byte[] bytes) {
  +            this.bytes = bytes;
  +        }
  +        
  +        private ExactIPAddressPermission(String mask) {
  +            Matcher matcher = MASK_VALIDATOR.matcher(mask);
  +            if (false == matcher.matches()) {
  +                throw new IllegalArgumentException("Mask " + mask + " does 
not match pattern " + MASK_VALIDATOR.pattern());
  +            }
  +            
  +            bytes = new byte[4];
  +            for (int i = 0; i < 4; i++) {
  +                String group = matcher.group(i + 1);
  +                int value = Integer.parseInt(group);
  +                if (value < 0 || 255 < value) {
  +                    throw new IllegalArgumentException("byte #" + i + " is 
not valid.");
  +                }
  +                bytes[i] = (byte) value;
  +            }
  +        }
           
  -        public IPAddressMask(String mask) {
  -            this.mask = mask;
  +        public boolean implies(InetAddress address) {
  +            if (false == address instanceof Inet4Address) {
  +                return false;
  +            }
               
  +            byte[] byteAddress = address.getAddress();
  +            for (int i = 0; i < 4; i++) {
  +                if (byteAddress[i] != bytes[i]) {
  +                    return false;
  +                }
  +            }
  +            return true;
  +        }
  +    }
  +
  +    private static class StartWithIPAddressPermission implements 
IPAddressPermission {
  +        private static final Pattern MASK_VALIDATOR = 
Pattern.compile("^(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.0$");
  +
  +        private static boolean canSupport(String mask) {
  +            Matcher matcher = MASK_VALIDATOR.matcher(mask);
  +            return matcher.matches();
  +        }
  +        
  +        private final byte[] bytes;
  +        
  +        private StartWithIPAddressPermission(String mask) {
               Matcher matcher = MASK_VALIDATOR.matcher(mask);
               if (false == matcher.matches()) {
                   throw new IllegalArgumentException("Mask " + mask + " does 
not match pattern " + MASK_VALIDATOR.pattern());
               }
               
  -            byteMask = new byte[4];
  -            definedBytes = new boolean[4];
  -            for (int i = 1; i < 5; i++) {
  -                String group = matcher.group(i);
  -                if (false == group.equals("*")) {
  +            Byte[] tmpBytes = new Byte[4];
  +            boolean isWildCard = false;
  +            int size = 0;
  +            for (int i = 0; i < 3; i++) {
  +                String group = matcher.group(i + 1);
  +                if (group.equals("0")) {
  +                    isWildCard = true;
  +                } else if (isWildCard) {
  +                    throw new IllegalArgumentException("0 at position " + 
size + " in mask");
  +                } else {
                       int value = Integer.parseInt(group);
                       if (value < 0 || 255 < value) {
                           throw new IllegalArgumentException("byte #" + i + " 
is not valid.");
                       }
  -                    byteMask[i - 1] = (byte) value;
  -                    definedBytes[i - 1] = true;
  +                    tmpBytes[i] = new Byte((byte) value);
  +                    size++;
  +                }
  +            }
  +            
  +            bytes = new byte[size];
  +            for (int i = 0; i < bytes.length; i++) {
  +                bytes[i] = tmpBytes[i].byteValue();
  +            }
  +        }
  +        
  +        public boolean implies(InetAddress address) {
  +            if (false == address instanceof Inet4Address) {
  +                return false;
  +            }
  +            
  +            byte[] byteAddress = address.getAddress();
  +            for (int i = 0; i < bytes.length; i++) {
  +                if (byteAddress[i] != bytes[i]) {
  +                    return false;
  +                }
  +            }
  +            return true;
  +        }
  +    }
  +
  +    private static class FactorizedIPAddressPermission implements 
IPAddressPermission {
  +        private static final Pattern MASK_VALIDATOR = 
Pattern.compile("^((\\d{1,3}){1}(\\.\\d{1,3}){0,2}\\.)?\\{(\\d{1,3}){1}((,\\d{1,3})*)\\}$");
  +
  +        private static boolean canSupport(String mask) {
  +            Matcher matcher = MASK_VALIDATOR.matcher(mask);
  +            return matcher.matches();
  +        }
  +        
  +        private final byte[] prefixBytes;
  +        private final byte[] suffixBytes;
  +        
  +        private FactorizedIPAddressPermission(String mask) {
  +            Matcher matcher = MASK_VALIDATOR.matcher(mask);
  +            if (false == matcher.matches()) {
  +                throw new IllegalArgumentException("Mask " + mask + " does 
not match pattern " + MASK_VALIDATOR.pattern());
  +            }
  +
  +            // group 1 is the factorized IP part.
  +            // e.g. group 1 in "1.2.3.{4,5,6}" is "1.2.3."
  +            String prefix = matcher.group(1);
  +            StringTokenizer tokenizer = new StringTokenizer(prefix, ".");
  +            prefixBytes = new byte[tokenizer.countTokens()];
  +            for (int i = 0; i < prefixBytes.length; i++) {
  +                String token = tokenizer.nextToken();
  +                int value = Integer.parseInt(token);
  +                if (value < 0 || 255 < value) {
  +                    throw new IllegalArgumentException("byte #" + i + " is 
not valid.");
                   }
  +                prefixBytes[i] = (byte) value;
               }
  +            
  +            // group 5 is a comma separated list of optional suffixes.
  +            // e.g. group 5 in "1.2.3.{4,5,6}" is ",5,6"
  +            String suffix = matcher.group(5);
  +            tokenizer = new StringTokenizer(suffix, ",");
  +            suffixBytes = new byte[1 + tokenizer.countTokens()];
  +            
  +            // group 4 is the compulsory and first suffix.
  +            // e.g. group 4 in "1.2.3.{4,5,6}" is "4"
  +            int value = Integer.parseInt(matcher.group(4));
  +            int i = 0;
  +            if (value < 0 || 255 < value) {
  +                throw new IllegalArgumentException("suffix " + i + " is not 
valid.");
  +            }
  +            suffixBytes[i++] = (byte) value;
  +
  +            for (; i < suffixBytes.length; i++) {
  +                String token = tokenizer.nextToken();
  +                value = Integer.parseInt(token);
  +                if (value < 0 || 255 < value) {
  +                    throw new IllegalArgumentException("byte #" + i + " is 
not valid.");
  +                }
  +                suffixBytes[i] = (byte) value;
  +            }
  +        }
  +        
  +        public boolean implies(InetAddress address) {
  +            if (false == address instanceof Inet4Address) {
  +                return false;
  +            }
  +            
  +            byte[] byteAddress = address.getAddress();
  +            for (int i = 0; i < prefixBytes.length; i++) {
  +                if (byteAddress[i] != prefixBytes[i]) {
  +                    return false;
  +                }
  +            }
  +            byte lastByte = byteAddress[prefixBytes.length];
  +            for (int i = 0; i < suffixBytes.length; i++) {
  +                if (lastByte == suffixBytes[i]) {
  +                    return true;
  +                }
  +            }
  +            return false;
  +        }
  +    }
  +
  +    private static class NetmaskIPAddressPermission implements 
IPAddressPermission {
  +        private static final Pattern MASK_VALIDATOR = 
Pattern.compile("^(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/((\\d{1,2})|(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3}))$");
  +
  +        private static boolean canSupport(String mask) {
  +            Matcher matcher = MASK_VALIDATOR.matcher(mask);
  +            return matcher.matches();
           }
           
  -        public String getMask() {
  -            return mask;
  +        private final byte[] networkAddressBytes;
  +        private final byte[] netmaskBytes;
  +        
  +        private NetmaskIPAddressPermission(String mask) {
  +            Matcher matcher = MASK_VALIDATOR.matcher(mask);
  +            if (false == matcher.matches()) {
  +                throw new IllegalArgumentException("Mask " + mask + " does 
not match pattern " + MASK_VALIDATOR.pattern());
  +            }
  +
  +            networkAddressBytes = new byte[4];
  +            for (int i = 0; i < 4; i++) {
  +                String group = matcher.group(i + 1);
  +                int value = Integer.parseInt(group);
  +                if (value < 0 || 255 < value) {
  +                    throw new IllegalArgumentException("byte #" + i + " is 
not valid.");
  +                }
  +                networkAddressBytes[i] = (byte) value;
  +            }
  +
  +            netmaskBytes = new byte[4];
  +            String netmask = matcher.group(6);
  +            if (null != netmask) {
  +                int value = Integer.parseInt(netmask);
  +                int pos = value / 8;
  +                int shift = 8 - value % 8;
  +                for (int i = 0; i < pos; i++) {
  +                    netmaskBytes[i] = (byte) 0xff;
  +                }
  +                netmaskBytes[pos] = (byte) (0xff << shift);
  +            } else {
  +                for (int i = 0; i < 4; i++) {
  +                    String group = matcher.group(i + 7);
  +                    int value = Integer.parseInt(group);
  +                    if (value < 0 || 255 < value) {
  +                        throw new IllegalArgumentException("byte #" + i + " 
is not valid.");
  +                    }
  +                    netmaskBytes[i] = (byte) value;
  +                }
  +            }
           }
           
           public boolean implies(InetAddress address) {
  +            if (false == address instanceof Inet4Address) {
  +                return false;
  +            }
  +            
               byte[] byteAddress = address.getAddress();
               for (int i = 0; i < 4; i++) {
  -                if (definedBytes[i] && byteAddress[i] != byteMask[i]) {
  +                if ((netmaskBytes[i] & byteAddress[i]) != 
networkAddressBytes[i]) {
  +                    return false;
  +                }
  +            }
  +            return true;
  +        }
  +    }
  +
  +    private static class ExactIPv6AddressPermission implements 
IPAddressPermission {
  +        private static final Pattern MASK_VALIDATOR = 
Pattern.compile("^(([a-fA-F0-9]{1,4}:){7})([a-fA-F0-9]{1,4})$");
  +
  +        private static boolean canSupport(String mask) {
  +            Matcher matcher = MASK_VALIDATOR.matcher(mask);
  +            return matcher.matches();
  +        }
  +
  +        private final byte[] bytes;
  +        
  +        private ExactIPv6AddressPermission(byte[] bytes) {
  +            this.bytes = bytes;
  +        }        
  +        
  +        private ExactIPv6AddressPermission(String mask) {
  +            Matcher matcher = MASK_VALIDATOR.matcher(mask);
  +            if (false == matcher.matches()) {
  +                throw new IllegalArgumentException("Mask " + mask + " does 
not match pattern " + MASK_VALIDATOR.pattern());
  +            }
  +            
  +            bytes = new byte[16];
  +            int pos = 0;
  +            StringTokenizer tokenizer = new StringTokenizer(mask, ":");
  +            while (tokenizer.hasMoreTokens()) {
  +                String token = tokenizer.nextToken();
  +                int value = Integer.parseInt(token, 16);
  +                bytes[pos++] = (byte) ((value & 0xff00) >> 8);
  +                bytes[pos++] = (byte) value;
  +            }
  +        }
  +        
  +        public boolean implies(InetAddress address) {
  +            if (false == address instanceof Inet6Address) {
  +                return false;
  +            }
  +            
  +            byte[] byteAddress = address.getAddress();
  +            for (int i = 0; i < 16; i++) {
  +                if (byteAddress[i] != bytes[i]) {
                       return false;
                   }
               }
  @@ -210,12 +461,96 @@
           }
       }
       
  -    public static class IPAddressMaskEditor extends PropertyEditorSupport {
  -        private IPAddressMask addressMask;
  +    private static class NetmaskIPv6AddressPermission implements 
IPAddressPermission {
  +        private static final Pattern MASK_VALIDATOR = 
Pattern.compile("^(([a-fA-F0-9]{1,4}:){7}[a-fA-F0-9]{1,4})/((\\d{1,3})|(([a-fA-F0-9]{1,4}:){7}[a-fA-F0-9]{1,4}))$");
  +
  +        private static boolean canSupport(String mask) {
  +            Matcher matcher = MASK_VALIDATOR.matcher(mask);
  +            return matcher.matches();
  +        }
           
  -        public void setAsText(String text) throws IllegalArgumentException {
  -            addressMask = new IPAddressMask(text);
  +        private final byte[] networkAddressBytes;
  +        private final byte[] netmaskBytes;
  +        
  +        private NetmaskIPv6AddressPermission(String mask) {
  +            Matcher matcher = MASK_VALIDATOR.matcher(mask);
  +            if (false == matcher.matches()) {
  +                throw new IllegalArgumentException("Mask " + mask + " does 
not match pattern " + MASK_VALIDATOR.pattern());
  +            }
  +
  +            networkAddressBytes = new byte[16];
  +            int pos = 0;
  +            StringTokenizer tokenizer = new 
StringTokenizer(matcher.group(1), ":");
  +            while (tokenizer.hasMoreTokens()) {
  +                String token = tokenizer.nextToken();
  +                int value = Integer.parseInt(token, 16);
  +                networkAddressBytes[pos++] = (byte) ((value & 0xff00) >> 8);
  +                networkAddressBytes[pos++] = (byte) value;
  +            }
  +
  +            netmaskBytes = new byte[16];
  +            String netmask = matcher.group(4);
  +            if (null != netmask) {
  +                int value = Integer.parseInt(netmask);
  +                pos = value / 8;
  +                int shift = 8 - value % 8;
  +                for (int i = 0; i < pos; i++) {
  +                    netmaskBytes[i] = (byte) 0xff;
  +                }
  +                netmaskBytes[pos] = (byte) (0xff << shift);
  +            } else {
  +                pos = 0;
  +                tokenizer = new StringTokenizer(matcher.group(5), ":");
  +                while (tokenizer.hasMoreTokens()) {
  +                    String token = tokenizer.nextToken();
  +                    int value = Integer.parseInt(token, 16);
  +                    netmaskBytes[pos++] = (byte) ((value & 0xff00) >> 8);
  +                    netmaskBytes[pos++] = (byte) value;
  +                }
  +            }
  +        }
  +        
  +        public boolean implies(InetAddress address) {
  +            if (false == address instanceof Inet6Address) {
  +                return false;
  +            }
  +            
  +            byte[] byteAddress = address.getAddress();
  +            for (int i = 0; i < 16; i++) {
  +                if ((netmaskBytes[i] & byteAddress[i]) != 
networkAddressBytes[i]) {
  +                    return false;
  +                }
  +            }
  +            return true;
  +        }
  +    }
  +    
  +    public static class IPAddressPermissionFactory {
  +        
  +        public static IPAddressPermission getIPAddressMask(String mask) {
  +            if (StartWithIPAddressPermission.canSupport(mask)) {
  +                return new StartWithIPAddressPermission(mask);
  +            } else if (ExactIPAddressPermission.canSupport(mask)) {
  +                return new ExactIPAddressPermission(mask);
  +            } else if (FactorizedIPAddressPermission.canSupport(mask)) {
  +                return new FactorizedIPAddressPermission(mask);
  +            } else if (NetmaskIPAddressPermission.canSupport(mask)) {
  +                return new NetmaskIPAddressPermission(mask);
  +            } else if (ExactIPv6AddressPermission.canSupport(mask)) {
  +                return new ExactIPv6AddressPermission(mask);
  +            } else if (NetmaskIPv6AddressPermission.canSupport(mask)) {
  +                return new NetmaskIPv6AddressPermission(mask);
  +            }
  +            throw new IllegalArgumentException("Mask " + mask + " is not 
supported.");
           }
  +    }
  +    
  +    public static class IPAddressPermissionEditor extends 
PropertyEditorSupport {
  +        private IPAddressPermission addressMask;
  +        
  +        public void setAsText(String text) throws IllegalArgumentException {
  +            addressMask = IPAddressPermissionFactory.getIPAddressMask(text);
  +         }
   
           public Object getValue() {
               return addressMask;
  
  
  
  1.16      +2 -2      
openejb/modules/core/src/java/org/openejb/server/SimpleSocketService.java
  
  Index: SimpleSocketService.java
  ===================================================================
  RCS file: 
/home/projects/openejb/scm/openejb/modules/core/src/java/org/openejb/server/SimpleSocketService.java,v
  retrieving revision 1.15
  retrieving revision 1.16
  diff -u -r1.15 -r1.16
  --- SimpleSocketService.java  26 Mar 2005 06:32:06 -0000      1.15
  +++ SimpleSocketService.java  31 Mar 2005 10:29:27 -0000      1.16
  @@ -69,7 +69,7 @@
       private static final Log log = 
LogFactory.getLog(SimpleSocketService.class);
       private final ServerService server;
   
  -    public SimpleSocketService(String serviceClassName, 
ServiceAccessController.IPAddressMask[] onlyFrom, ContainerIndex 
containerIndex, ClassLoader cl) throws Exception {
  +    public SimpleSocketService(String serviceClassName, 
ServiceAccessController.IPAddressPermission[] onlyFrom, ContainerIndex 
containerIndex, ClassLoader cl) throws Exception {
           ServerService service;
   
           Class serviceClass = ClassLoading.loadClass(serviceClassName, cl);
  
  
  
  1.6       +4 -4      
openejb/modules/core/src/java/org/openejb/server/StandardServiceStack.java
  
  Index: StandardServiceStack.java
  ===================================================================
  RCS file: 
/home/projects/openejb/scm/openejb/modules/core/src/java/org/openejb/server/StandardServiceStack.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- StandardServiceStack.java 26 Mar 2005 06:32:06 -0000      1.5
  +++ StandardServiceStack.java 31 Mar 2005 10:29:27 -0000      1.6
  @@ -62,7 +62,7 @@
       private ServicePool pool;
       private ServerService server;
   
  -    public StandardServiceStack(String name, int port, InetAddress address, 
ServiceAccessController.IPAddressMask[] allowHosts, String[] logOnSuccess, 
String[] logOnFailure, Executor executor, ServerService server) {
  +    public StandardServiceStack(String name, int port, InetAddress address, 
ServiceAccessController.IPAddressPermission[] allowHosts, String[] 
logOnSuccess, String[] logOnFailure, Executor executor, ServerService server) {
           this.server = server;
           this.name = name;
           this.pool = new ServicePool(server, executor);
  @@ -100,11 +100,11 @@
           return logger.getLogOnFailure();
       }
   
  -    public ServiceAccessController.IPAddressMask[] getAllowHosts() {
  +    public ServiceAccessController.IPAddressPermission[] getAllowHosts() {
           return hba.getAllowHosts();
       }
   
  -    public void setAllowHosts(ServiceAccessController.IPAddressMask[] 
allowHosts) {
  +    public void setAllowHosts(ServiceAccessController.IPAddressPermission[] 
allowHosts) {
           hba.setAllowHosts(allowHosts);
       }
   
  
  
  
  1.5       +2 -2      
openejb/modules/core/src/java/org/openejb/server/StandardServiceStackGBean.java
  
  Index: StandardServiceStackGBean.java
  ===================================================================
  RCS file: 
/home/projects/openejb/scm/openejb/modules/core/src/java/org/openejb/server/StandardServiceStackGBean.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- StandardServiceStackGBean.java    26 Mar 2005 06:32:06 -0000      1.4
  +++ StandardServiceStackGBean.java    31 Mar 2005 10:29:27 -0000      1.5
  @@ -70,7 +70,7 @@
           infoFactory.addAttribute("port", int.class, true);
           infoFactory.addAttribute("soTimeout", int.class, true);
           infoFactory.addAttribute("address", InetAddress.class, true);
  -        infoFactory.addAttribute("allowHosts", 
ServiceAccessController.IPAddressMask[].class, true);
  +        infoFactory.addAttribute("allowHosts", 
ServiceAccessController.IPAddressPermission[].class, true);
           infoFactory.addAttribute("logOnSuccess", String[].class, true);
           infoFactory.addAttribute("logOnFailure", String[].class, true);
   
  
  
  

Reply via email to