URLHelper.java
001 /*
002  *
003  * Licensed to the Apache Software Foundation (ASF) under one
004  * or more contributor license agreements.  See the NOTICE file
005  * distributed with this work for additional information
006  * regarding copyright ownership.  The ASF licenses this file
007  * to you under the Apache License, Version 2.0 (the
008  * "License"); you may not use this file except in compliance
009  * with the License.  You may obtain a copy of the License at
010  *
011  *   http://www.apache.org/licenses/LICENSE-2.0
012  *
013  * Unless required by applicable law or agreed to in writing,
014  * software distributed under the License is distributed on an
015  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
016  * KIND, either express or implied.  See the License for the
017  * specific language governing permissions and limitations
018  * under the License.
019  *
020  */
021 package org.apache.qpid.url;
022 
023 import java.util.HashMap;
024 import java.util.Map;
025 
026 public class URLHelper
027 {
028     public static char DEFAULT_OPTION_SEPERATOR = '&';
029     public static char ALTERNATIVE_OPTION_SEPARATOR = ',';
030     public static char BROKER_SEPARATOR = ';';
031 
032     public static void parseOptions(Map<String, String> optionMap, String optionsthrows URLSyntaxException
033     {
034         // options looks like this
035         // brokerlist='tcp://host:port?option='value',option='value';vm://:3/virtualpath?option='value'',failover='method?option='value',option='value''
036 
037         if ((options == null|| (options.indexOf('='== -1))
038         {
039             return;
040         }
041 
042         int optionIndex = options.indexOf('=');
043 
044         String option = options.substring(0, optionIndex);
045 
046         int length = options.length();
047 
048         int nestedQuotes = 0;
049 
050         // to store index of final "'"
051         int valueIndex = optionIndex;
052 
053         // Walk remainder of url.
054         while ((nestedQuotes > 0|| (valueIndex < length))
055         {
056             valueIndex++;
057 
058             if (valueIndex >= length)
059             {
060                 break;
061             }
062 
063             if (options.charAt(valueIndex== '\'')
064             {
065                 if ((valueIndex + 1< options.length())
066                 {
067                     if ((options.charAt(valueIndex + 1== DEFAULT_OPTION_SEPERATOR)
068                             || (options.charAt(valueIndex + 1== ALTERNATIVE_OPTION_SEPARATOR)
069                             || (options.charAt(valueIndex + 1== BROKER_SEPARATOR)
070                             || (options.charAt(valueIndex + 1== '\''))
071                     {
072                         nestedQuotes--;
073 
074                         if (nestedQuotes == 0)
075                         {
076                             // We've found the value of an option
077                             break;
078                         }
079                     }
080                     else
081                     {
082                         nestedQuotes++;
083                     }
084                 }
085                 else
086                 {
087                     // We are at the end of the string
088                     // Check to see if we are corectly closing quotes
089                     if (options.charAt(valueIndex== '\'')
090                     {
091                         nestedQuotes--;
092                     }
093 
094                     break;
095                 }
096             }
097         }
098 
099         if ((nestedQuotes != 0|| (valueIndex < (optionIndex + 2)))
100         {
101             int sepIndex = 0;
102 
103             // Try and identify illegal separator character
104             if (nestedQuotes > 1)
105             {
106                 for (int i = 0; i < nestedQuotes; i++)
107                 {
108                     sepIndex = options.indexOf('\'', sepIndex);
109                     sepIndex++;
110                 }
111             }
112 
113             if ((sepIndex >= options.length()) || (sepIndex == 0))
114             {
115                 throw parseError(valueIndex, "Unterminated option", options);
116             }
117             else
118             {
119                 throw parseError(sepIndex, "Unterminated option. Possible illegal option separator:'"
120                     + options.charAt(sepIndex"'", options);
121             }
122         }
123 
124         // optionIndex +2 to skip "='"
125         String value = options.substring(optionIndex + 2, valueIndex);
126 
127         optionMap.put(option, value);
128 
129         if (valueIndex < (options.length() 1))
130         {
131             // Recurse to get remaining options
132             parseOptions(optionMap, options.substring(valueIndex + 2));
133         }
134     }
135 
136     public static URLSyntaxException parseError(int index, String error, String url)
137     {
138         return parseError(index, 1, error, url);
139     }
140 
141     public static URLSyntaxException parseError(int index, int length, String error, String url)
142     {
143         return new URLSyntaxException(url, error, index, length);
144     }
145 
146     public static String printOptions(Map<String, String> options)
147     {
148         if (options.isEmpty())
149         {
150             return "";
151         }
152         else
153         {
154             StringBuffer sb = new StringBuffer();
155             sb.append('?');
156             for (String key : options.keySet())
157             {
158                 sb.append(key);
159 
160                 sb.append("='");
161 
162                 sb.append(options.get(key));
163 
164                 sb.append("'");
165                 sb.append(DEFAULT_OPTION_SEPERATOR);
166             }
167 
168             sb.deleteCharAt(sb.length() 1);
169 
170             return sb.toString();
171         }
172     }
173 }