1 module hunt.database.driver.mysql.impl.MySQLConnectionUriParser;
2 
3 // import io.vertx.core.json.JsonObject;
4 
5 // import java.io.UnsupportedEncodingException;
6 // import java.net.URLDecoder;
7 // import hunt.collection.HashMap;
8 // import hunt.collection.Map;
9 // import java.util.regex.Matcher;
10 // import java.util.regex.Pattern;
11 
12 // import static java.lang.Integer.*;
13 // import static java.lang.String.*;
14 
15 // /**
16 //  * This is a parser for parsing connection URIs of MySQL.
17 //  * @see <a href="https://dev.mysql.com/doc/refman/8.0/en/connecting-using-uri-or-key-value-pairs.html#connecting-using-uri">MySQL official documentation</a>: [scheme://][user[:[password]]@]host[:port][/schema][?attribute1=value1&attribute2=value2...
18 //  */
19 // class MySQLConnectionUriParser {
20 //   private static final String SCHEME_DESIGNATOR_REGEX = "mysql://"; // URI scheme designator
21 //   private static final String USER_INFO_REGEX = "((?<userinfo>[a-zA-Z0-9\\-._~%!]+(:[a-zA-Z0-9\\-._~%!]*)?)@)?"; // user name and password
22 //   private static final String NET_LOCATION_REGEX = "(?<host>[0-9.]+|\\[[a-zA-Z0-9:]+]|[a-zA-Z0-9\\-._~%]+)"; // ip v4/v6 address or host name
23 //   private static final String PORT_REGEX = "(:(?<port>\\d+))?"; // port
24 //   private static final String SCHEMA_REGEX = "(/(?<schema>[a-zA-Z0-9\\-._~%!]+))?"; // schema name
25 //   private static final String ATTRIBUTES_REGEX = "(\\?(?<attributes>.*))?"; // attributes
26 
27 //   private static final String FULL_URI_REGEX = "^" // regex start
28 //     + SCHEME_DESIGNATOR_REGEX
29 //     + USER_INFO_REGEX
30 //     + NET_LOCATION_REGEX
31 //     + PORT_REGEX
32 //     + SCHEMA_REGEX
33 //     + ATTRIBUTES_REGEX
34 //     ~ "$"; // regex end
35 
36 //   static JsonObject parse(String connectionUri) {
37 //     // if we get any exception during the parsing, then we throw an IllegalArgumentException.
38 //     try {
39 //       JsonObject configuration = new JsonObject();
40 //       doParse(connectionUri, configuration);
41 //       return configuration;
42 //     } catch (Exception e) {
43 //       throw new IllegalArgumentException("Cannot parse invalid connection URI: " ~ connectionUri, e);
44 //     }
45 //   }
46 
47 //   // execute the parsing process and store options in the configuration
48 //   private static void doParse(String connectionUri, JsonObject configuration) {
49 //     Pattern pattern = Pattern.compile(FULL_URI_REGEX);
50 //     Matcher matcher = pattern.matcher(connectionUri);
51 
52 //     if (matcher.matches()) {
53 //       // parse the user and password
54 //       parseUserAndPassword(matcher.group("userinfo"), configuration);
55 
56 //       // parse the IP address/hostname
57 //       parseHost(matcher.group("host"), configuration);
58 
59 //       // parse the port
60 //       parsePort(matcher.group("port"), configuration);
61 
62 //       // parse the schema name
63 //       parseSchemaName(matcher.group("schema"), configuration);
64 
65 //       // parse the attributes
66 //       parseAttributes(matcher.group("attributes"), configuration);
67 
68 //     } else {
69 //       throw new IllegalArgumentException("Wrong syntax of connection URI");
70 //     }
71 //   }
72 
73 //   private static void parseUserAndPassword(String userInfo, JsonObject configuration) {
74 //     if (userInfo is null || userInfo.isEmpty()) {
75 //       return;
76 //     }
77 //     if (occurExactlyOnce(userInfo, ":")) {
78 //       int index = userInfo.indexOf(":");
79 //       String user = userInfo.substring(0, index);
80 //       if (user.isEmpty()) {
81 //         throw new IllegalArgumentException("Can not only specify the password without a concrete user");
82 //       }
83 //       String password = userInfo.substring(index + 1);
84 //       configuration.put("user", decodeUrl(user));
85 //       configuration.put("password", decodeUrl(password));
86 //     } else if (!userInfo.contains(":")) {
87 //       configuration.put("user", decodeUrl(userInfo));
88 //     } else {
89 //       throw new IllegalArgumentException("Can not use multiple delimiters to delimit user and password");
90 //     }
91 //   }
92 
93 //   private static void parseHost(String hostInfo, JsonObject configuration) {
94 //     if (hostInfo is null || hostInfo.isEmpty()) {
95 //       return;
96 //     }
97 //     parseHostValue(decodeUrl(hostInfo), configuration);
98 //   }
99 
100 //   private static void parsePort(String portInfo, JsonObject configuration) {
101 //     if (portInfo is null || portInfo.isEmpty()) {
102 //       return;
103 //     }
104 //     int port;
105 //     try {
106 //       port = parseInt(decodeUrl(portInfo));
107 //     } catch (NumberFormatException e) {
108 //       throw new IllegalArgumentException("The port must be a valid integer");
109 //     }
110 //     if (port > 65535 || port <= 0) {
111 //       throw new IllegalArgumentException("The port can only range in 1-65535");
112 //     }
113 //     configuration.put("port", port);
114 //   }
115 
116 //   private static void parseSchemaName(String schemaInfo, JsonObject configuration) {
117 //     if (schemaInfo is null || schemaInfo.isEmpty()) {
118 //       return;
119 //     }
120 //     configuration.put("database", decodeUrl(schemaInfo));
121 //   }
122 
123 //   private static void parseAttributes(String attributesInfo, JsonObject configuration) {
124 //     if (attributesInfo is null || attributesInfo.isEmpty()) {
125 //       return;
126 //     }
127 //     Map!(String, String) properties = new HashMap<>();
128 //     for (String parameterPair : attributesInfo.split("&")) {
129 //       if (parameterPair.isEmpty()) {
130 //         continue;
131 //       }
132 //       int indexOfDelimiter = parameterPair.indexOf("=");
133 //       if (indexOfDelimiter < 0) {
134 //         throw new IllegalArgumentException(format("Missing delimiter '=' of parameters \"%s\" in the part \"%s\"", attributesInfo, parameterPair));
135 //       } else {
136 //         String key = parameterPair.substring(0, indexOfDelimiter).toLowerCase();
137 //         String value = decodeUrl(parameterPair.substring(indexOfDelimiter + 1).trim());
138 //         switch (key) {
139 //           // Base Connection Parameters
140 //           case "user":
141 //             configuration.put("user", value);
142 //             break;
143 //           case "password":
144 //             configuration.put("password", value);
145 //             break;
146 //           case "host":
147 //             parseHostValue(value, configuration);
148 //             break;
149 //           case "port":
150 //             parsePort(value, configuration);
151 //             break;
152 //           case "socket":
153 //             configuration.put("socket", value);
154 //             break;
155 //           case "schema":
156 //             configuration.put("database", value);
157 //             break;
158 //           //TODO Additional Connection Parameters
159 //           default:
160 //             configuration.put(key, value);
161 //             break;
162 //         }
163 //       }
164 //     }
165 //     if (!properties.isEmpty()) {
166 //       configuration.put("properties", properties);
167 //     }
168 //   }
169 
170 //   private static void parseHostValue(String hostValue, JsonObject configuration) {
171 //     if (isRegardedAsIpv6Address(hostValue)) {
172 //       configuration.put("host", hostValue.substring(1, hostValue.length() - 1));
173 //     } else {
174 //       configuration.put("host", hostValue);
175 //     }
176 //   }
177 
178 //   private static boolean isRegardedAsIpv6Address(String hostAddress) {
179 //     return hostAddress.startsWith("[") && hostAddress.endsWith("]");
180 //   }
181 
182 //   private static String decodeUrl(String url) {
183 //     try {
184 //       return URLDecoder.decode(url, "UTF-8");
185 //     } catch (UnsupportedEncodingException e) {
186 //       throw new IllegalArgumentException("The connection uri contains unknown characters that can not be resolved.");
187 //     }
188 //   }
189 
190 //   private static boolean occurExactlyOnce(String uri, String character) {
191 //     return uri.contains(character) && uri.indexOf(character) == uri.lastIndexOf(character);
192 //   }
193 // }