| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You 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.apache.ignite.spi.deployment.uri; |
| |
| import org.apache.ignite.internal.util.tostring.GridToStringExclude; |
| import org.apache.ignite.internal.util.typedef.internal.S; |
| |
| /** |
| * Helper class which encodes given string. |
| * It replaces all occurrences of space with '%20', percent sign |
| * with '%25' and semicolon with '%3B' if given string corresponds to |
| * expected format. |
| * <p> |
| * Expected format is (schema):(//)URL(?|#)(parameters) |
| */ |
| class GridUriDeploymentUriParser { |
| /** Input string which should be parsed and encoded. */ |
| private final String input; |
| |
| /** Encoded string. */ |
| @GridToStringExclude private String encoded; |
| |
| /** |
| * Creates new instance of parser for the given input string. |
| * |
| * @param input Input string which will be parsed. |
| */ |
| GridUriDeploymentUriParser(String input) { |
| assert input != null; |
| |
| this.input = input; |
| |
| encoded = input; |
| } |
| |
| /** |
| * Parses {@link #input} by extracting URL without schema and parameters |
| * and than encodes this URL. |
| * <p> |
| * Expected {@link #input} format is (schema):(//)URL(?|#)(parameters) |
| * |
| * @return Either encoded string or unchanged if it does not match format. |
| */ |
| String parse() { |
| int n = input.length(); |
| |
| // Scheme. |
| int p = scan(0, n, "/?#", ":"); |
| |
| if (p > 0 && at(p, n, ':')) { |
| p++; // Skip ':' |
| |
| if (at(p, n, '/')) { |
| if (at(p, n, '/') && at(p + 1, n, '/')) { |
| p += 2; |
| |
| // Seek authority. |
| int q = scan(p, n, "", "/?#"); |
| |
| if (q > p) |
| p = q; |
| } |
| |
| int q = scan(p, n, "", "?#"); |
| |
| StringBuilder buf = new StringBuilder(input.substring(0, p)); |
| |
| buf.append(encodePath(input.substring(p, q))); |
| buf.append(input.substring(q, n)); |
| |
| encoded = buf.toString(); |
| } |
| } |
| |
| return encoded; |
| } |
| |
| /** |
| * Scan forward from the given start position. Stop at the first char |
| * in the err string (in which case -1 is returned), or the first char |
| * in the stop string (in which case the index of the preceding char is |
| * returned), or the end of the input string (in which case the length |
| * of the input string is returned). May return the start position if |
| * none matches. |
| * |
| * @param start Start scan position. |
| * @param end End scan position. |
| * @param err Error characters. |
| * @param stop Stoppers. |
| * @return {@code -1} if character from the error characters list was found; |
| * index of first character occurrence is on stop character list; end |
| * position if {@link #input} does not contain any characters |
| * from {@code error} or {@code stop}; start if start > end. |
| */ |
| private int scan(int start, int end, String err, String stop) { |
| int p = start; |
| |
| while (p < end) { |
| char c = input.charAt(p); |
| |
| if (err.indexOf(c) >= 0) |
| return -1; |
| |
| if (stop.indexOf(c) >= 0) |
| break; |
| |
| p++; |
| } |
| |
| return p; |
| } |
| |
| /** |
| * Tests whether {@link #input} contains {@code c} at position {@code start} |
| * and {@code start} less than {@code end}. |
| * |
| * @param start Start position. |
| * @param end End position. |
| * @param c Character {@link #input} is tested against |
| * @return {@code true} only if {@link #input} contains {@code c} at position |
| * {@code start} and {@code start} less than {@code end}. |
| */ |
| private boolean at(int start, int end, char c) { |
| return start < end && input.charAt(start) == c; |
| } |
| |
| /** |
| * Encodes given path by replacing all occurrences of space with '%20', |
| * percent sign with '%25' and semicolon with '%3B'. |
| * |
| * @param path Path to be encoded. |
| * @return Encoded path. |
| */ |
| private String encodePath(String path) { |
| StringBuilder buf = new StringBuilder(path.length()); |
| |
| for (int i = 0; i < path.length(); i++) { |
| char c = path.charAt(i); |
| |
| switch (c) { |
| case ' ': { |
| buf.append("%20"); break; |
| } |
| |
| case '%': { |
| buf.append("%25"); break; |
| } |
| case ';': { |
| buf.append("%3B"); break; |
| } |
| |
| default: { |
| buf.append(c); |
| } |
| } |
| } |
| |
| return buf.toString(); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public String toString() { |
| return S.toString(GridUriDeploymentUriParser.class, this); |
| } |
| } |