All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.glowroot.instrumentation.servlet.boot.ServletInstrumentationProperties Maven / Gradle / Ivy

There is a newer version: 0.14.9
Show newest version
/*
 * Copyright 2011-2019 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.glowroot.instrumentation.servlet.boot;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.regex.Pattern;

import org.glowroot.instrumentation.api.Agent;
import org.glowroot.instrumentation.api.checker.Nullable;
import org.glowroot.instrumentation.api.config.ConfigListener;
import org.glowroot.instrumentation.api.config.ConfigService;
import org.glowroot.instrumentation.api.util.ImmutableList;
import org.glowroot.instrumentation.api.util.ImmutableSet;

public class ServletInstrumentationProperties {

    public static final String HTTP_SESSION_ID_ATTR = "::id";

    private static final ConfigService configService = Agent.getConfigService("servlet");

    private static List captureRequestParameters = Collections.emptyList();
    private static List maskRequestParameters = Collections.emptyList();
    private static List captureRequestHeaders = Collections.emptyList();
    private static List captureRequestCookies = Collections.emptyList();

    private static boolean someRequestHostAndPortDetail;
    private static boolean captureRequestRemoteAddress;
    private static boolean captureRequestRemoteHostname;
    private static boolean captureRequestRemotePort;
    private static boolean captureRequestLocalAddress;
    private static boolean captureRequestLocalHostname;
    private static boolean captureRequestLocalPort;
    private static boolean captureRequestServerHostname;
    private static boolean captureRequestServerPort;
    private static boolean captureRequestScheme;

    private static List captureResponseHeaders = Collections.emptyList();
    private static boolean captureResponseHeadersNonEmpty;
    private static boolean captureContentLengthResponseHeader;
    private static boolean captureContentTypeResponseHeader;
    private static boolean captureContentLanguageResponseHeader;

    private static @Nullable SessionAttributePath userAttributePath;

    private static List captureSessionAttributePaths =
            Collections.emptyList();
    private static Set captureSessionAttributeNames = Collections.emptySet();
    private static boolean captureSessionAttributeNamesContainsId;

    private static boolean traceErrorOn4xxResponseCode;

    static {
        configService.registerConfigListener(new ConfigListenerImpl());
    }

    private ServletInstrumentationProperties() {}

    public static List captureRequestParameters() {
        return captureRequestParameters;
    }

    public static List maskRequestParameters() {
        return maskRequestParameters;
    }

    public static List captureRequestHeaders() {
        return captureRequestHeaders;
    }

    public static List captureRequestCookies() {
        return captureRequestCookies;
    }

    public static boolean captureSomeRequestHostAndPortDetail() {
        return someRequestHostAndPortDetail;
    }

    public static boolean captureRequestRemoteAddress() {
        return captureRequestRemoteAddress;
    }

    public static boolean captureRequestRemoteHostname() {
        return captureRequestRemoteHostname;
    }

    public static boolean captureRequestRemotePort() {
        return captureRequestRemotePort;
    }

    public static boolean captureRequestLocalAddress() {
        return captureRequestLocalAddress;
    }

    public static boolean captureRequestLocalHostname() {
        return captureRequestLocalHostname;
    }

    public static boolean captureRequestLocalPort() {
        return captureRequestLocalPort;
    }

    public static boolean captureRequestServerHostname() {
        return captureRequestServerHostname;
    }

    public static boolean captureRequestServerPort() {
        return captureRequestServerPort;
    }

    public static boolean captureRequestScheme() {
        return captureRequestScheme;
    }

    public static List captureResponseHeaders() {
        return captureResponseHeaders;
    }

    public static boolean captureResponseHeadersNonEmpty() {
        return captureResponseHeadersNonEmpty;
    }

    public static boolean captureContentLengthResponseHeader() {
        return captureContentLengthResponseHeader;
    }

    public static boolean captureContentTypeResponseHeader() {
        return captureContentTypeResponseHeader;
    }

    public static boolean captureContentLanguageResponseHeader() {
        return captureContentLanguageResponseHeader;
    }

    public static @Nullable SessionAttributePath userAttributePath() {
        return userAttributePath;
    }

    public static boolean sessionUserAttributeIsId() {
        return userAttributePath != null && userAttributePath.isSessionId();
    }

    public static List captureSessionAttributePaths() {
        return captureSessionAttributePaths;
    }

    // only the first-level attribute names (e.g. "one", "abc") as opposed to full paths (e.g.
    // "one.two", "abc.def") returned by captureSessionAttributePaths()
    public static Set captureSessionAttributeNames() {
        return captureSessionAttributeNames;
    }

    public static boolean captureSessionAttributeNamesContainsId() {
        return captureSessionAttributeNamesContainsId;
    }

    public static boolean traceErrorOn4xxResponseCode() {
        return traceErrorOn4xxResponseCode;
    }

    public static class SessionAttributePath {

        private final String attributeName;
        private final List nestedPath;
        private final boolean wildcard;

        private final String fullPath; // attributeName + nestedPath, cached for optimization

        private SessionAttributePath(String attributeName, List nestedPath,
                boolean wildcard, String fullPath) {
            this.attributeName = attributeName;
            this.nestedPath = nestedPath;
            this.wildcard = wildcard;
            this.fullPath = fullPath;
        }

        public String getAttributeName() {
            return attributeName;
        }

        public List getNestedPath() {
            return nestedPath;
        }

        public boolean isWildcard() {
            return wildcard;
        }

        public String getFullPath() {
            return fullPath;
        }

        public boolean isAttributeNameWildcard() {
            return attributeName.equals("*") && nestedPath.isEmpty() && !wildcard;
        }

        public boolean isSessionId() {
            return attributeName.equals(ServletInstrumentationProperties.HTTP_SESSION_ID_ATTR)
                    && nestedPath.isEmpty() && !wildcard;
        }
    }

    private static class ConfigListenerImpl implements ConfigListener {

        @Override
        public void onChange() {
            recalculateProperties();
        }

        private static void recalculateProperties() {
            captureRequestParameters = buildPatternList("captureRequestParameters");
            maskRequestParameters = buildPatternList("maskRequestParameters");
            captureRequestHeaders = buildPatternList("captureRequestHeaders");
            captureRequestCookies = buildCaseSensitivePatternList("captureRequestCookies");
            captureRequestRemoteAddress =
                    configService.getBooleanProperty("captureRequestRemoteAddr").value();
            captureRequestRemoteHostname =
                    configService.getBooleanProperty("captureRequestRemoteHostname").value();
            captureRequestRemotePort =
                    configService.getBooleanProperty("captureRequestRemotePort").value();
            captureRequestLocalAddress =
                    configService.getBooleanProperty("captureRequestLocalAddr").value();
            captureRequestLocalHostname =
                    configService.getBooleanProperty("captureRequestLocalHostname").value();
            captureRequestLocalPort =
                    configService.getBooleanProperty("captureRequestLocalPort").value();
            captureRequestServerHostname =
                    configService.getBooleanProperty("captureRequestServerHostname").value();
            captureRequestServerPort =
                    configService.getBooleanProperty("captureRequestServerPort").value();
            captureRequestScheme = configService.getBooleanProperty("captureRequestScheme").value();
            someRequestHostAndPortDetail =
                    captureRequestRemoteAddress || captureRequestRemoteHostname
                            || captureRequestRemotePort || captureRequestLocalAddress
                            || captureRequestLocalHostname || captureRequestLocalPort
                            || captureRequestServerHostname || captureRequestServerPort
                            || captureRequestScheme;
            captureResponseHeaders = buildPatternList("captureResponseHeaders");
            captureResponseHeadersNonEmpty = !captureResponseHeaders.isEmpty();
            captureContentLengthResponseHeader =
                    Patterns.matchesOneOf("content-length", captureResponseHeaders);
            captureContentTypeResponseHeader =
                    Patterns.matchesOneOf("content-type", captureResponseHeaders);
            captureContentLanguageResponseHeader =
                    Patterns.matchesOneOf("content-language", captureResponseHeaders);
            userAttributePath = buildSessionAttributePath(
                    configService.getStringProperty("sessionUserAttribute").value());
            captureSessionAttributePaths = buildSessionAttributePaths(
                    configService.getListProperty("captureSessionAttributes").value());
            captureSessionAttributeNames = buildCaptureSessionAttributeNames();
            captureSessionAttributeNamesContainsId =
                    captureSessionAttributeNames.contains(HTTP_SESSION_ID_ATTR);
            traceErrorOn4xxResponseCode =
                    configService.getBooleanProperty("traceErrorOn4xxResponseCode").value();
        }

        private static List buildPatternList(String propertyName) {
            List values = configService.getListProperty(propertyName).value();
            List patterns = new ArrayList();
            for (String value : values) {
                // converted to lower case for case-insensitive matching
                patterns.add(buildRegexPattern(value.trim().toLowerCase(Locale.ENGLISH)));
            }
            return ImmutableList.copyOf(patterns);
        }

        private static List buildCaseSensitivePatternList(String propertyName) {
            List values = configService.getListProperty(propertyName).value();
            List patterns = new ArrayList();
            for (String value : values) {
                patterns.add(buildRegexPattern(value.trim()));
            }
            return ImmutableList.copyOf(patterns);
        }

        private static List buildSessionAttributePaths(
                List sessionAttributes) {
            List attributePaths = new ArrayList();
            for (String sessionAttribute : sessionAttributes) {
                attributePaths.add(buildSessionAttributePath(sessionAttribute.trim()));
            }
            return ImmutableList.copyOf(attributePaths);
        }

        private static SessionAttributePath buildSessionAttributePath(String sessionAttribute) {
            boolean wildcard = sessionAttribute.endsWith(".*");
            String sessionAttr = sessionAttribute;
            if (wildcard) {
                sessionAttr = sessionAttribute.substring(0, sessionAttribute.length() - 2);
            }
            int index = sessionAttr.indexOf('.');
            if (index == -1) {
                return new SessionAttributePath(sessionAttr, Collections.emptyList(),
                        wildcard, sessionAttr);
            } else {
                String attributeName = sessionAttr.substring(0, index);
                String remaining = sessionAttr.substring(index + 1);
                List nestedPath = Strings.split(remaining, '.');
                return new SessionAttributePath(attributeName, nestedPath, wildcard, sessionAttr);
            }
        }

        private static Set buildCaptureSessionAttributeNames() {
            Set names = new HashSet();
            for (SessionAttributePath sessionAttributePath : captureSessionAttributePaths) {
                names.add(sessionAttributePath.attributeName);
            }
            return ImmutableSet.copyOf(names);
        }

        private static Pattern buildRegexPattern(String wildcardPattern) {
            // convert * into .* and quote the rest of the text using \Q...\E
            String regex = "\\Q" + wildcardPattern.replace("*", "\\E.*\\Q") + "\\E";
            // strip off unnecessary \\Q\\E in case * appeared at beginning or end of part
            regex = regex.replace("\\Q\\E", "");
            return Pattern.compile(regex);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy