URLParser.java
001 package org.apache.qpid.client.url;
002 /*
003  
004  * Licensed to the Apache Software Foundation (ASF) under one
005  * or more contributor license agreements.  See the NOTICE file
006  * distributed with this work for additional information
007  * regarding copyright ownership.  The ASF licenses this file
008  * to you under the Apache License, Version 2.0 (the
009  * "License"); you may not use this file except in compliance
010  * with the License.  You may obtain a copy of the License at
011  
012  *   http://www.apache.org/licenses/LICENSE-2.0
013  
014  * Unless required by applicable law or agreed to in writing,
015  * software distributed under the License is distributed on an
016  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017  * KIND, either express or implied.  See the License for the
018  * specific language governing permissions and limitations
019  * under the License.
020  
021  */
022 
023 
024 import java.net.URI;
025 import java.net.URISyntaxException;
026 import java.util.StringTokenizer;
027 
028 import org.apache.qpid.client.AMQBrokerDetails;
029 import org.apache.qpid.client.AMQConnectionFactory;
030 import org.apache.qpid.client.AMQConnectionURL;
031 import org.apache.qpid.framing.AMQShortString;
032 import org.apache.qpid.url.URLHelper;
033 import org.apache.qpid.url.URLSyntaxException;
034 
035 public class URLParser
036 {
037     private AMQConnectionURL _url;
038 
039     public URLParser(AMQConnectionURL url)throws URLSyntaxException
040     {
041         _url = url;
042         parseURL(_url.getURL());
043     }
044 
045     private void parseURL(String fullURLthrows URLSyntaxException
046     {
047         // Connection URL format
048         // amqp://[user:pass@][clientid]/virtualhost?brokerlist='tcp://host:port?option=\'value\',option=\'value\';vm://:3/virtualpath?option=\'value\'',failover='method?option=\'value\',option='value''"
049         // Options are of course optional except for requiring a single broker in the broker list.
050         try
051         {
052             URI connection = new URI(fullURL);
053 
054             if ((connection.getScheme() == null|| !(connection.getScheme().equalsIgnoreCase(AMQConnectionURL.AMQ_PROTOCOL)))
055             {
056                 throw new URISyntaxException(fullURL, "Not an AMQP URL");
057             }
058 
059             if ((connection.getHost() == null|| connection.getHost().equals(""))
060             {
061                 String uid = AMQConnectionFactory.getUniqueClientID();
062                 if (uid == null)
063                 {
064                     throw URLHelper.parseError(-1"Client Name not specified", fullURL);
065                 }
066                 else
067                 {
068                     _url.setClientName(uid);
069                 }
070 
071             }
072             else
073             {
074                 _url.setClientName(connection.getHost());
075             }
076 
077             String userInfo = connection.getUserInfo();
078 
079             if (userInfo == null)
080             {
081                 // Fix for Java 1.5 which doesn't parse UserInfo for non http URIs
082                 userInfo = connection.getAuthority();
083 
084                 if (userInfo != null)
085                 {
086                     int atIndex = userInfo.indexOf('@');
087 
088                     if (atIndex != -1)
089                     {
090                         userInfo = userInfo.substring(0, atIndex);
091                     }
092                     else
093                     {
094                         userInfo = null;
095                     }
096                 }
097 
098             }
099 
100             if (userInfo == null)
101             {
102                 throw URLHelper.parseError(AMQConnectionURL.AMQ_PROTOCOL.length() 3"User information not found on url", fullURL);
103             }
104             else
105             {
106                 parseUserInfo(userInfo);
107             }
108 
109             String virtualHost = connection.getPath();
110 
111             if ((virtualHost != null&& (!virtualHost.equals("")))
112             {
113                 _url.setVirtualHost(virtualHost);
114             }
115             else
116             {
117                 int authLength = connection.getAuthority().length();
118                 int start = AMQConnectionURL.AMQ_PROTOCOL.length() 3;
119                 int testIndex = start + authLength;
120                 if ((testIndex < fullURL.length()) && (fullURL.charAt(testIndex== '?'))
121                 {
122                     throw URLHelper.parseError(start, testIndex - start, "Virtual host found", fullURL);
123                 }
124                 else
125                 {
126                     throw URLHelper.parseError(-1"Virtual host not specified", fullURL);
127                 }
128 
129             }
130 
131             URLHelper.parseOptions(_url.getOptions(), connection.getQuery());
132 
133             processOptions();
134         }
135         catch (URISyntaxException uris)
136         {
137             if (uris instanceof URLSyntaxException)
138             {
139                 throw (URLSyntaxExceptionuris;
140             }
141 
142             int slash = fullURL.indexOf("\\");
143 
144             if (slash == -1)
145             {
146                 throw URLHelper.parseError(uris.getIndex(), uris.getReason(), uris.getInput());
147             }
148             else
149             {
150                 if ((slash != 0&& (fullURL.charAt(slash - 1== ':'))
151                 {
152                     throw URLHelper.parseError(slash - 2, fullURL.indexOf('?'- slash + 2,
153                         "Virtual host looks like a windows path, forward slash not allowed in URL", fullURL);
154                 }
155                 else
156                 {
157                     throw URLHelper.parseError(slash, "Forward slash not allowed in URL", fullURL);
158                 }
159             }
160 
161         }
162     }
163 
164     private void parseUserInfo(String userinfothrows URLSyntaxException
165     {
166         // user info = user:pass
167 
168         int colonIndex = userinfo.indexOf(':');
169 
170         if (colonIndex == -1)
171         {
172             throw URLHelper.parseError(AMQConnectionURL.AMQ_PROTOCOL.length() 3, userinfo.length(),
173                                        "Null password in user information not allowed.", _url.getURL());
174         }
175         else
176         {
177             _url.setUsername(userinfo.substring(0, colonIndex));
178             _url.setPassword(userinfo.substring(colonIndex + 1));
179         }
180 
181     }
182 
183     private void processOptions() throws URLSyntaxException
184     {
185         if (_url.getOptions().containsKey(AMQConnectionURL.OPTIONS_BROKERLIST))
186         {
187             String brokerlist = _url.getOptions().get(AMQConnectionURL.OPTIONS_BROKERLIST);
188 
189             // brokerlist tcp://host:port?option='value',option='value';vm://:3/virtualpath?option='value'
190             StringTokenizer st = new StringTokenizer(brokerlist, "" + URLHelper.BROKER_SEPARATOR);
191 
192             while (st.hasMoreTokens())
193             {
194                 String broker = st.nextToken();
195 
196                 _url.addBrokerDetails(new AMQBrokerDetails(broker));
197             }
198 
199             _url.getOptions().remove(AMQConnectionURL.OPTIONS_BROKERLIST);
200         }
201 
202         if (_url.getOptions().containsKey(AMQConnectionURL.OPTIONS_FAILOVER))
203         {
204             String failover = _url.getOptions().get(AMQConnectionURL.OPTIONS_FAILOVER);
205 
206             // failover='method?option='value',option='value''
207 
208             int methodIndex = failover.indexOf('?');
209 
210             if (methodIndex > -1)
211             {
212                 _url.setFailoverMethod(failover.substring(0, methodIndex));
213                 URLHelper.parseOptions(_url.getFailoverOptions(), failover.substring(methodIndex + 1));
214             }
215             else
216             {
217                 _url.setFailoverMethod(failover);
218             }
219 
220             _url.getOptions().remove(AMQConnectionURL.OPTIONS_FAILOVER);
221         }
222 
223         if (_url.getOptions().containsKey(AMQConnectionURL.OPTIONS_DEFAULT_TOPIC_EXCHANGE))
224         {
225             _url.setDefaultTopicExchangeName(new AMQShortString(_url.getOptions().get(AMQConnectionURL.OPTIONS_DEFAULT_TOPIC_EXCHANGE)));
226         }
227 
228         if (_url.getOptions().containsKey(AMQConnectionURL.OPTIONS_DEFAULT_QUEUE_EXCHANGE))
229         {
230             _url.setDefaultQueueExchangeName(new AMQShortString(_url.getOptions().get(AMQConnectionURL.OPTIONS_DEFAULT_QUEUE_EXCHANGE)));
231         }
232 
233         if (_url.getOptions().containsKey(AMQConnectionURL.OPTIONS_TEMPORARY_QUEUE_EXCHANGE))
234         {
235             _url.setTemporaryQueueExchangeName(new AMQShortString(_url.getOptions().get(AMQConnectionURL.OPTIONS_TEMPORARY_QUEUE_EXCHANGE)));
236         }
237 
238         if (_url.getOptions().containsKey(AMQConnectionURL.OPTIONS_TEMPORARY_TOPIC_EXCHANGE))
239         {
240             _url.setTemporaryTopicExchangeName(new AMQShortString(_url.getOptions().get(AMQConnectionURL.OPTIONS_TEMPORARY_TOPIC_EXCHANGE)));
241         }
242     }
243 
244 }