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 fullURL) throws 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 (URLSyntaxException) uris;
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 userinfo) throws 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 }
|