001    /* 
002     * Copyright 2008-2009 the original author or authors.
003     * The contents of this file are subject to the Mozilla Public License
004     * Version 1.1 (the "License"); you may not use this file except in
005     * compliance with the License. You may obtain a copy of the License at
006     * http://www.mozilla.org/MPL/
007     *
008     * Software distributed under the License is distributed on an "AS IS"
009     * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
010     * License for the specific language governing rights and limitations
011     * under the License.
012     */
013     
014    package com.mtgi.analytics.aop.config.v11;
015    
016    import java.util.ArrayList;
017    import java.util.regex.Pattern;
018    
019    import org.springframework.beans.factory.support.BeanDefinitionBuilder;
020    import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
021    import org.springframework.beans.factory.xml.ParserContext;
022    import org.springframework.util.StringUtils;
023    import org.w3c.dom.Element;
024    import org.w3c.dom.NodeList;
025    
026    import com.mtgi.analytics.servlet.ServletRequestBehaviorTrackingAdapter;
027    
028    /**
029     * Parses bean definitions for {@link ServletRequestBehaviorTrackingAdapter} based on occurrances of
030     * <code>bt:http-requests</code> nested in <code>bt:manager</code>.  These instances of {@link ServletRequestBehaviorTrackingAdapter}
031     * are then invoked by the {@link ServletRequestBehaviorTrackingAdapter}, which will have automatically
032     * registered itself within the calling web application.
033     */
034    public class BtHttpRequestsBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
035    
036            private static final String ATT_EVENT_TYPE = "event-type";
037            private static final String ATT_PARAMETERS = "parameters";
038            private static final String ATT_URI_PATTERN = "uri-pattern";
039    
040            @Override
041            protected Class<?> getBeanClass(Element element) {
042                    return ServletRequestBehaviorTrackingAdapter.class;
043            }
044    
045            @Override
046            protected boolean shouldGenerateId() {
047                    return true;
048            }
049    
050            @Override
051            protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
052    
053                    //compile required constructor arguments from attributes and nested elements.  first up, event type.
054                    builder.addConstructorArg(element.getAttribute(ATT_EVENT_TYPE));
055    
056                    //manager ID from enclosing tag.
057                    String managerId = (String)parserContext.getContainingBeanDefinition().getAttribute("id");
058                    builder.addConstructorArgReference(managerId);
059    
060                    //parameter list for logging, if any.
061                    String paramList = element.getAttribute(ATT_PARAMETERS);
062                    if (StringUtils.hasText(paramList))
063                            builder.addConstructorArg(paramList.split("[,;]+"));
064                    else
065                            builder.addConstructorArg(null);
066    
067                    //URI patterns, if any.  can be specified as attribute or nested elements.
068                    ArrayList<Pattern> accum = new ArrayList<Pattern>();
069                    if (element.hasAttribute(ATT_URI_PATTERN))
070                            accum.add(Pattern.compile(element.getAttribute(ATT_URI_PATTERN)));
071                    
072                    NodeList nl = element.getElementsByTagNameNS("*", ATT_URI_PATTERN);
073                    for (int i = 0; i < nl.getLength(); ++i) {
074                            Element e = (Element)nl.item(i);
075                            String pattern = e.getTextContent();
076                            if (StringUtils.hasText(pattern))
077                                    accum.add(Pattern.compile(pattern));
078                    }
079                    
080                    if (accum.isEmpty())
081                            builder.addConstructorArg(null);
082                    else
083                            builder.addConstructorArg(accum.toArray(new Pattern[accum.size()]));
084    
085                    parserContext.getReaderContext().registerWithGeneratedName(builder.getBeanDefinition());
086            }
087    
088            
089            
090    }