1 /**
2 *
3 * Copyright 2006 The Apache Software Foundation
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 package org.apache.geronimo.gbean;
19
20 import java.io.Serializable;
21 import java.net.URI;
22 import java.net.URISyntaxException;
23 import java.util.ArrayList;
24 import java.util.Collections;
25 import java.util.HashSet;
26 import java.util.Iterator;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.Set;
30 import java.util.TreeMap;
31 import java.util.TreeSet;
32
33 import org.apache.geronimo.kernel.repository.Artifact;
34
35 /**
36 * @version $Rev: 430508 $ $Date: 2006-08-10 12:56:47 -0700 (Thu, 10 Aug 2006) $
37 */
38 public class AbstractNameQuery implements Serializable {
39 private static final long serialVersionUID = 7444620122607155678L;
40
41 private final Artifact artifact;
42 private final Map name;
43 private final Set interfaceTypes;
44
45 private final URI uri;
46
47 public AbstractNameQuery(AbstractName abstractName) {
48 this(abstractName, null);
49 }
50
51 public AbstractNameQuery(AbstractName abstractName, Set interfaceTypes) {
52 this.artifact = abstractName.getArtifact();
53 this.name = abstractName.getName();
54 this.interfaceTypes = interfaceTypes == null ? Collections.EMPTY_SET : interfaceTypes;
55 this.uri = createURI(artifact, name, this.interfaceTypes);
56 }
57
58 public AbstractNameQuery(Artifact artifact, Map name) {
59 this.artifact = artifact;
60 this.name = name;
61 this.interfaceTypes = Collections.EMPTY_SET;
62 this.uri = createURI(artifact, name, interfaceTypes);
63 }
64
65 public AbstractNameQuery(Artifact artifact, Map name, String interfaceType) {
66 this.artifact = artifact;
67 this.name = name;
68 if (interfaceType != null) {
69 this.interfaceTypes = Collections.singleton(interfaceType);
70 } else {
71 this.interfaceTypes = Collections.EMPTY_SET;
72 }
73 this.uri = createURI(artifact, name, interfaceTypes);
74 }
75
76 public AbstractNameQuery(String interfaceType) {
77 this.artifact = null;
78 this.name = Collections.EMPTY_MAP;
79 this.interfaceTypes = Collections.singleton(interfaceType);
80 this.uri = createURI(artifact, name, interfaceTypes);
81 }
82
83 public AbstractNameQuery(Artifact artifact, Map name, Set interfaceTypes) {
84 this.artifact = artifact;
85 this.name = name;
86 if (interfaceTypes == null) interfaceTypes = Collections.EMPTY_SET;
87 this.interfaceTypes = interfaceTypes;
88 this.uri = createURI(artifact, name, this.interfaceTypes);
89 }
90
91 public AbstractNameQuery(URI uri) {
92 if (uri == null) throw new NullPointerException("uri is null");
93
94
95
96
97 String artifactString = uri.getPath();
98
99
100
101 if (artifactString != null && artifactString.length() > 0) {
102 List artifactParts = split(artifactString, '/');
103 if (artifactParts.size() != 4) {
104 throw new IllegalArgumentException("uri path must be in the form [groupId]/[artifactId]/[version]/[type] : " + artifactString);
105 }
106
107 String groupId = (String) artifactParts.get(0);
108 if (groupId.length() == 0) groupId = null;
109
110 String artifactId = (String) artifactParts.get(1);
111 if (artifactId.length() == 0) artifactId = null;
112
113 String version = (String) artifactParts.get(2);
114 if (version.length() == 0) version = null;
115
116 String type = (String) artifactParts.get(3);
117 if (type.length() == 0) type = null;
118
119 artifact = new Artifact(groupId, artifactId, version, type);
120 } else {
121 artifact = null;
122 }
123
124
125
126
127 name = new TreeMap();
128 String nameString = uri.getQuery();
129 List nameParts = split(nameString, ',');
130 for (Iterator iterator = nameParts.iterator(); iterator.hasNext();) {
131 String namePart = (String) iterator.next();
132 List keyValue = split(namePart, '=');
133 if (keyValue.size() != 2) {
134 throw new IllegalArgumentException("uri query string must be in the form [vendorId]/artifactId/[version]/[type] : " + nameString);
135 }
136 String key = (String) keyValue.get(0);
137 String value = (String) keyValue.get(1);
138 if (name.containsKey(key)) {
139 throw new IllegalArgumentException("uri query string contains the key '" + key + "' twice : " + nameString);
140 }
141 name.put(key, value);
142 }
143
144
145
146
147 String interfaceString = uri.getFragment();
148 List interfaces = split(interfaceString, ',');
149 interfaceTypes = new HashSet(interfaces);
150
151
152
153
154 this.uri = createURI(artifact, name, interfaceTypes);
155 }
156
157 private static List split(String source, char delim) {
158 List parts = new ArrayList();
159 if (source != null && source.length() > 0) {
160 for (int index = source.indexOf(delim); index >= 0; index = source.indexOf(delim)) {
161 String part = source.substring(0, index);
162 source = source.substring(index + 1);
163 parts.add(part);
164 }
165 parts.add(source);
166 }
167 return parts;
168 }
169
170 private static URI createURI(Artifact artifact, Map name, Set interfaceTypes) {
171 StringBuffer queryString = new StringBuffer();
172 TreeMap treeMap = new TreeMap(name);
173 for (Iterator iterator = treeMap.entrySet().iterator(); iterator.hasNext();) {
174 Map.Entry entry = (Map.Entry) iterator.next();
175 String key = (String) entry.getKey();
176 String value = (String) entry.getValue();
177 queryString.append(key).append('=').append(value);
178 if (iterator.hasNext()) {
179 queryString.append(',');
180 }
181 }
182 StringBuffer fragmentString = new StringBuffer();
183 TreeSet treeSet = new TreeSet(interfaceTypes);
184 for (Iterator iterator = treeSet.iterator(); iterator.hasNext();) {
185 String interfaceType = (String) iterator.next();
186 fragmentString.append(interfaceType);
187 if (iterator.hasNext()) {
188 fragmentString.append(',');
189 }
190 }
191 try {
192 return new URI(null, null, artifact == null? null: artifact.toString(), queryString.toString(), fragmentString.toString());
193 } catch (URISyntaxException e) {
194 IllegalArgumentException illegalArgumentException = new IllegalArgumentException();
195 illegalArgumentException.initCause(e);
196 throw illegalArgumentException;
197 }
198 }
199
200
201 public Artifact getArtifact() {
202 return artifact;
203 }
204
205 public Map getName() {
206 return name;
207 }
208
209 public Set getInterfaceTypes() {
210 return interfaceTypes;
211 }
212
213 public String toString() {
214 return uri.toString();
215 }
216
217 public URI toURI() {
218 return uri;
219 }
220
221 public boolean equals(Object o) {
222 if (this == o) return true;
223 if (o == null || getClass() != o.getClass()) return false;
224
225 final AbstractNameQuery that = (AbstractNameQuery) o;
226
227 if (artifact != null ? !artifact.equals(that.artifact) : that.artifact != null) return false;
228 if (interfaceTypes != null ? !interfaceTypes.equals(that.interfaceTypes) : that.interfaceTypes != null)
229 return false;
230 return !(name != null ? !name.equals(that.name) : that.name != null);
231
232 }
233
234 public int hashCode() {
235 int result;
236 result = (artifact != null ? artifact.hashCode() : 0);
237 result = 29 * result + (name != null ? name.hashCode() : 0);
238 result = 29 * result + (interfaceTypes != null ? interfaceTypes.hashCode() : 0);
239 return result;
240 }
241
242
243 public boolean matches(AbstractName info, Set targetInterfaceTypes) {
244 if (!info.getName().entrySet().containsAll(name.entrySet())) {
245 return false;
246 }
247 if (!targetInterfaceTypes.containsAll(interfaceTypes)) {
248 return false;
249 }
250 if (artifact == null) {
251 return true;
252 }
253 Artifact otherArtifact = info.getArtifact();
254 return artifact.matches(otherArtifact);
255 }
256
257 /**
258 * N.B. parameter info is supposed to be more specific than this.
259 * This is the opposite of the meaning of Artifact.matches.
260 *
261 * @param info
262 * @return if info is a more specific version of this name query.
263 */
264 public boolean matches(AbstractNameQuery info) {
265 if (!info.getName().entrySet().containsAll(name.entrySet())) {
266 return false;
267 }
268 if (!info.getInterfaceTypes().containsAll(interfaceTypes)) {
269 return false;
270 }
271 if (artifact == null) {
272 return true;
273 }
274 Artifact otherArtifact = info.getArtifact();
275 return artifact.matches(otherArtifact);
276 }
277 }