<commit_before>/*-
 * <<
 * UAVStack
 * ==
 * Copyright (C) 2016 - 2017 UAVStack
 * ==
 * 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 com.creditease.uav.util;

import java.lang.management.ManagementFactory;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;

import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;

import com.creditease.agent.helpers.NetworkHelper;
import com.creditease.agent.helpers.StringHelper;
import com.creditease.monitor.UAVServer;
import com.creditease.monitor.UAVServer.ServerVendor;
import com.creditease.monitor.captureframework.spi.CaptureConstants;
import com.creditease.monitor.captureframework.spi.MonitorElement;
import com.creditease.monitor.captureframework.spi.MonitorElementInstance;

public class MonitorServerUtil {

    /**
     * 
     * OracleTokenBuffer description: 解析Oracle数据库连接字符串，God
     *
     */
    public static class OracleTokenBuffer {

        private StringBuilder curStr;

        private boolean isMatch = false;

        private List<String> iphosts = new ArrayList<String>();

        private String dbName;

        public OracleTokenBuffer(String str) {
            this.curStr = new StringBuilder(str);
        }

        public void match() {

            // single ip
            if (this.curStr.indexOf("=") == -1) {
                int st = this.curStr.indexOf("@");
                String ipstr = this.curStr.substring(st + 1);
                String[] ipInfo = ipstr.split(":");
                // 兼容使用"/"分割数据库名场景，样例 ip:port/dbName
                if (ipInfo.length == 2 && ipInfo[1].indexOf("/") > -1) {
                    String[] temp = ipInfo[1].split("/");
                    this.dbName = temp[1];
                    iphosts.add(ipInfo[0] + ":" + temp[0]);
                }
                else {
                    iphosts.add(ipInfo[0] + ":" + ipInfo[1]);
                    this.dbName = ipInfo[2];
                }
                return;
            }

            // cluster
            while (true) {

                match("HOST");

                if (isMatch == false) {
                    break;
                }
            }

            match("SERVICE_NAME");
        }

        @Override
        public String toString() {

            this.match();

            StringBuilder sb = new StringBuilder();

            sb.append("jdbc:oracle://");

            int index = 0;
            for (String iphost : iphosts) {
                sb.append(iphost);

                if (index < iphosts.size() - 1) {
                    sb.append(",");
                }

                index++;
            }

            sb.append("/").append(this.dbName);

            return sb.toString();
        }

        private void match(String token) {

            String str = curStr.toString();

            int index = str.indexOf(token);

            if (index == -1) {
                index = str.indexOf(token.toLowerCase());
            }

            if (index == -1) {
                this.isMatch = false;
                return;
            }

            str = str.substring(index);

            int end = str.indexOf(")");

            if (end == -1) {
                this.isMatch = false;
                return;
            }

            String match = str.substring(0, end);

            String val = match.split("=")[1].trim();

            if (token.equalsIgnoreCase("HOST")) {
                iphosts.add(val);
            }
            else if (token.equalsIgnoreCase("PORT")) {
                String host = iphosts.get(iphosts.size() - 1);
                iphosts.remove(iphosts.size() - 1);
                iphosts.add(host + ":" + val);
            }
            else if (token.equalsIgnoreCase("SERVICE_NAME")) {
                this.dbName = val;
            }

            str = str.substring(end + 1);

            this.curStr = new StringBuilder(str);

            this.isMatch = true;

            if (token.equalsIgnoreCase("HOST")) {

                match("PORT");
            }
        }
    }

    private static String[] filterExts = new String[] { ".js", ".css", ".jpg", ".jpeg", ".gif", ".png", ".bmp", ".xlsx",
            ".pptx", ".docx", ".doc", ".woff2", ".ico", ".txt" };

    private static String[] filterPageExts = new String[] { ".jsp", ".html", "*.htm" };

    private static String[] browserUAFeatures = new String[] { "Mozilla", "Opera", "Trident", "AppleWebKit", "Chrome",
            "Firefox", "Safari" };

    private MonitorServerUtil() {

    }

    /**
     * get the real client ip
     * 
     * @param remoteAddr
     * @param xForwardHeader
     * @param xRealIPHeader
     * @return
     */
    public static String getClientIP(String remoteAddr, String xForwardHeader) {

        String ip = xForwardHeader;
        if (ip != null && !"unKnown".equalsIgnoreCase(ip)) {
            int index = ip.indexOf(",");
            if (index != -1) {
                ip = ip.substring(0, index);
            }

            ip = getLocalHostToIP(ip);

        }
        else {
            ip = getLocalHostToIP(remoteAddr);
        }

        return ip;
    }

    /**
     * getLocalHostToIP
     * 
     * @param ip
     * @return
     */
    public static String getLocalHostToIP(String ip) {

        if (ip == null) {
            return ip;
        }

        if (ip.equals("127.0.0.1") || "0:0:0:0:0:0:0:1".equals(ip) || "localhost".equals(ip)) {
            return NetworkHelper.getLocalIP();
        }

        if (ip.indexOf("127.0.0.1") > -1 || ip.indexOf("localhost") > -1 || ip.indexOf("0:0:0:0:0:0:0:1") > -1) {
            String localip = NetworkHelper.getLocalIP();
            ip = ip.replace("127.0.0.1", localip).replace("localhost", localip).replace("0:0:0:0:0:0:0:1", localip);
        }

        return ip;
    }

    /**
     * get JMX MBeanServer
     * 
     * @return
     */
    public static MBeanServer getMBeanServer() {

        MBeanServer server;

        if (!MBeanServerFactory.findMBeanServer(null).isEmpty()) {
            server = MBeanServerFactory.findMBeanServer(null).get(0);

        }
        else {
            server = ManagementFactory.getPlatformMBeanServer();
        }

        return server;
    }

    /**
     * doSumTimeAndCounter
     * 
     * @param inst
     * @param respTime
     */
    public static void doSumTimeAndCounter(MonitorElementInstance inst, long respTime) {

        if (null == inst || respTime < 0) {
            return;
        }

        long sumValue = inst.sumValue(CaptureConstants.MEI_RESP_SUMTIME, respTime);
        /**
         * we should consider if the number is over Long.MAX_VALUE at that time, the number will become minus number
         * then we set the base number to the new value so there should be jump in Sum Value & Counter, we should handle
         * this jump in Health Manager
         */
        if (sumValue < 0) {
            inst.setValue(CaptureConstants.MEI_RESP_SUMTIME, new AtomicLong(respTime));
            inst.setValue(CaptureConstants.MEI_COUNTER, new AtomicLong(1));
        }
        else {
            inst.increValue(CaptureConstants.MEI_COUNTER);
        }
    }

    /**
     * get the standard action tag
     * 
     * @param action
     * @return
     */
    public static String getActionTag(String action) {

        return CaptureConstants.MEI_AC + action.toLowerCase();
    }

    /**
     * get the standard action err tag
     * 
     * @param action
     * @return
     */
    public static String getActionErrorTag(String action) {

        return CaptureConstants.MEI_AC_ERROR + action.toLowerCase();
    }

    /**
     * get application id through context root or basePath
     * 
     * @param contextroot
     * @param basePath
     * @return
     */
    public static String getApplicationId(String contextroot, String basePath) {

        String appid = "";

        if ("".equals(contextroot)) {

            /*
             * NOTE: springboot's basePath is a random temp directory,so we use main(usually the jar name) as the appid
             */
            if (UAVServer.instance().getServerInfo(CaptureConstants.INFO_APPSERVER_VENDOR)
                    .equals(UAVServer.ServerVendor.SPRINGBOOT)) {

                String javaCommand = System.getProperty("sun.java.command");

                appid = javaCommand.split(" ")[0];

            }
            else {
                String tmp = basePath.replace("\\", "/");
                int index = tmp.lastIndexOf("/");

                appid = tmp.substring(index + 1);
            }
        }
        else {
            appid = contextroot;
        }

        if (appid.indexOf("/") == 0) {
            appid = appid.substring(1);
        }
<commit_msg>fix invokechain NPE when appid contains special character<commit_after>/*-
 * <<
 * UAVStack
 * ==
 * Copyright (C) 2016 - 2017 UAVStack
 * ==
 * 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 com.creditease.uav.util;

import java.lang.management.ManagementFactory;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;

import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;

import com.creditease.agent.helpers.NetworkHelper;
import com.creditease.agent.helpers.StringHelper;
import com.creditease.monitor.UAVServer;
import com.creditease.monitor.UAVServer.ServerVendor;
import com.creditease.monitor.captureframework.spi.CaptureConstants;
import com.creditease.monitor.captureframework.spi.MonitorElement;
import com.creditease.monitor.captureframework.spi.MonitorElementInstance;

public class MonitorServerUtil {

    /**
     * 
     * OracleTokenBuffer description: 解析Oracle数据库连接字符串，God
     *
     */
    public static class OracleTokenBuffer {

        private StringBuilder curStr;

        private boolean isMatch = false;

        private List<String> iphosts = new ArrayList<String>();

        private String dbName;

        public OracleTokenBuffer(String str) {
            this.curStr = new StringBuilder(str);
        }

        public void match() {

            // single ip
            if (this.curStr.indexOf("=") == -1) {
                int st = this.curStr.indexOf("@");
                String ipstr = this.curStr.substring(st + 1);
                String[] ipInfo = ipstr.split(":");
                // 兼容使用"/"分割数据库名场景，样例 ip:port/dbName
                if (ipInfo.length == 2 && ipInfo[1].indexOf("/") > -1) {
                    String[] temp = ipInfo[1].split("/");
                    this.dbName = temp[1];
                    iphosts.add(ipInfo[0] + ":" + temp[0]);
                }
                else {
                    iphosts.add(ipInfo[0] + ":" + ipInfo[1]);
                    this.dbName = ipInfo[2];
                }
                return;
            }

            // cluster
            while (true) {

                match("HOST");

                if (isMatch == false) {
                    break;
                }
            }

            match("SERVICE_NAME");
        }

        @Override
        public String toString() {

            this.match();

            StringBuilder sb = new StringBuilder();

            sb.append("jdbc:oracle://");

            int index = 0;
            for (String iphost : iphosts) {
                sb.append(iphost);

                if (index < iphosts.size() - 1) {
                    sb.append(",");
                }

                index++;
            }

            sb.append("/").append(this.dbName);

            return sb.toString();
        }

        private void match(String token) {

            String str = curStr.toString();

            int index = str.indexOf(token);

            if (index == -1) {
                index = str.indexOf(token.toLowerCase());
            }

            if (index == -1) {
                this.isMatch = false;
                return;
            }

            str = str.substring(index);

            int end = str.indexOf(")");

            if (end == -1) {
                this.isMatch = false;
                return;
            }

            String match = str.substring(0, end);

            String val = match.split("=")[1].trim();

            if (token.equalsIgnoreCase("HOST")) {
                iphosts.add(val);
            }
            else if (token.equalsIgnoreCase("PORT")) {
                String host = iphosts.get(iphosts.size() - 1);
                iphosts.remove(iphosts.size() - 1);
                iphosts.add(host + ":" + val);
            }
            else if (token.equalsIgnoreCase("SERVICE_NAME")) {
                this.dbName = val;
            }

            str = str.substring(end + 1);

            this.curStr = new StringBuilder(str);

            this.isMatch = true;

            if (token.equalsIgnoreCase("HOST")) {

                match("PORT");
            }
        }
    }

    private static String[] filterExts = new String[] { ".js", ".css", ".jpg", ".jpeg", ".gif", ".png", ".bmp", ".xlsx",
            ".pptx", ".docx", ".doc", ".woff2", ".ico", ".txt" };

    private static String[] filterPageExts = new String[] { ".jsp", ".html", "*.htm" };

    private static String[] browserUAFeatures = new String[] { "Mozilla", "Opera", "Trident", "AppleWebKit", "Chrome",
            "Firefox", "Safari" };

    private MonitorServerUtil() {

    }

    /**
     * get the real client ip
     * 
     * @param remoteAddr
     * @param xForwardHeader
     * @param xRealIPHeader
     * @return
     */
    public static String getClientIP(String remoteAddr, String xForwardHeader) {

        String ip = xForwardHeader;
        if (ip != null && !"unKnown".equalsIgnoreCase(ip)) {
            int index = ip.indexOf(",");
            if (index != -1) {
                ip = ip.substring(0, index);
            }

            ip = getLocalHostToIP(ip);

        }
        else {
            ip = getLocalHostToIP(remoteAddr);
        }

        return ip;
    }

    /**
     * getLocalHostToIP
     * 
     * @param ip
     * @return
     */
    public static String getLocalHostToIP(String ip) {

        if (ip == null) {
            return ip;
        }

        if (ip.equals("127.0.0.1") || "0:0:0:0:0:0:0:1".equals(ip) || "localhost".equals(ip)) {
            return NetworkHelper.getLocalIP();
        }

        if (ip.indexOf("127.0.0.1") > -1 || ip.indexOf("localhost") > -1 || ip.indexOf("0:0:0:0:0:0:0:1") > -1) {
            String localip = NetworkHelper.getLocalIP();
            ip = ip.replace("127.0.0.1", localip).replace("localhost", localip).replace("0:0:0:0:0:0:0:1", localip);
        }

        return ip;
    }

    /**
     * get JMX MBeanServer
     * 
     * @return
     */
    public static MBeanServer getMBeanServer() {

        MBeanServer server;

        if (!MBeanServerFactory.findMBeanServer(null).isEmpty()) {
            server = MBeanServerFactory.findMBeanServer(null).get(0);

        }
        else {
            server = ManagementFactory.getPlatformMBeanServer();
        }

        return server;
    }

    /**
     * doSumTimeAndCounter
     * 
     * @param inst
     * @param respTime
     */
    public static void doSumTimeAndCounter(MonitorElementInstance inst, long respTime) {

        if (null == inst || respTime < 0) {
            return;
        }

        long sumValue = inst.sumValue(CaptureConstants.MEI_RESP_SUMTIME, respTime);
        /**
         * we should consider if the number is over Long.MAX_VALUE at that time, the number will become minus number
         * then we set the base number to the new value so there should be jump in Sum Value & Counter, we should handle
         * this jump in Health Manager
         */
        if (sumValue < 0) {
            inst.setValue(CaptureConstants.MEI_RESP_SUMTIME, new AtomicLong(respTime));
            inst.setValue(CaptureConstants.MEI_COUNTER, new AtomicLong(1));
        }
        else {
            inst.increValue(CaptureConstants.MEI_COUNTER);
        }
    }

    /**
     * get the standard action tag
     * 
     * @param action
     * @return
     */
    public static String getActionTag(String action) {

        return CaptureConstants.MEI_AC + action.toLowerCase();
    }

    /**
     * get the standard action err tag
     * 
     * @param action
     * @return
     */
    public static String getActionErrorTag(String action) {

        return CaptureConstants.MEI_AC_ERROR + action.toLowerCase();
    }

    /**
     * get application id through context root or basePath
     * 
     * @param contextroot
     * @param basePath
     * @return
     */
    public static String getApplicationId(String contextroot, String basePath) {

        String appid = "";

        if ("".equals(contextroot)) {

            /*
             * NOTE: springboot's basePath is a random temp directory,so we use main(usually the jar name) as the appid
             */
            if (UAVServer.instance().getServerInfo(CaptureConstants.INFO_APPSERVER_VENDOR)
                    .equals(UAVServer.ServerVendor.SPRINGBOOT)) {

                String javaCommand = System.getProperty("sun.java.command");

                appid = javaCommand.split(" ")[0];

            }
            else {
                String tmp = basePath.replace("\\", "/");
                int index = tmp.lastIndexOf("/");

                appid = tmp.substring(index + 1);
            }
        }
        else {
            appid = contextroot;
        }

        // 去除最开始的"/"
        if (appid.indexOf("/") == 0) {
            appid = appid.substring(1);
        }
        /**
         * tomcat等容器在配置了多层虚拟路径以后，appid会存在特殊字符"/"，如：
         * <Context docBase="/data/source" path="/test/test" reloadable="true" /> 由于存在使用appid创建文件的情况，此处统一将特殊字符进行转义
         */
        if (appid.indexOf("/") > -1) {
            appid = appid.replace("/", "--");
        }
        if (appid.indexOf("\\") > -1) {
            appid = appid.replace("\\", "--");
        }

{'fraction_non_alphanumeric': 0.12420115243583028, 'fraction_numerical': 0.009533787323205867, 'mean_word_length': 1.7075592114593674, 'pattern_counts': {'":': 8, '<': 18, '<?xml version=': 0, '>': 22, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 6, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6966182', 'n_tokens_mistral': 5649, 'n_tokens_neox': 5359, 'n_words': 1244}