001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018 package org.apache.geronimo.gbean;
019
020 import java.io.Serializable;
021 import java.net.URI;
022 import java.net.URISyntaxException;
023 import java.util.ArrayList;
024 import java.util.Collections;
025 import java.util.HashSet;
026 import java.util.Iterator;
027 import java.util.List;
028 import java.util.Map;
029 import java.util.Set;
030 import java.util.TreeMap;
031 import java.util.TreeSet;
032
033 import org.apache.geronimo.kernel.repository.Artifact;
034
035 /**
036 * @version $Rev: 476049 $ $Date: 2006-11-16 23:35:17 -0500 (Thu, 16 Nov 2006) $
037 */
038 public class AbstractNameQuery implements Serializable {
039 private static final long serialVersionUID = 7444620122607155678L;
040
041 private final Artifact artifact;
042 private final Map name;
043 private final Set interfaceTypes;
044
045 private final URI uri;
046
047 public AbstractNameQuery(AbstractName abstractName) {
048 this(abstractName, null);
049 }
050
051 public AbstractNameQuery(AbstractName abstractName, Set interfaceTypes) {
052 this.artifact = abstractName.getArtifact();
053 this.name = abstractName.getName();
054 this.interfaceTypes = interfaceTypes == null ? Collections.EMPTY_SET : interfaceTypes;
055 this.uri = createURI(artifact, name, this.interfaceTypes);
056 }
057
058 public AbstractNameQuery(Artifact artifact, Map name) {
059 this.artifact = artifact;
060 this.name = name;
061 this.interfaceTypes = Collections.EMPTY_SET;
062 this.uri = createURI(artifact, name, interfaceTypes);
063 }
064
065 public AbstractNameQuery(Artifact artifact, Map name, String interfaceType) {
066 this.artifact = artifact;
067 this.name = name;
068 if (interfaceType != null) {
069 this.interfaceTypes = Collections.singleton(interfaceType);
070 } else {
071 this.interfaceTypes = Collections.EMPTY_SET;
072 }
073 this.uri = createURI(artifact, name, interfaceTypes);
074 }
075
076 public AbstractNameQuery(String interfaceType) {
077 this.artifact = null;
078 this.name = Collections.EMPTY_MAP;
079 this.interfaceTypes = Collections.singleton(interfaceType);
080 this.uri = createURI(artifact, name, interfaceTypes);
081 }
082
083 public AbstractNameQuery(Artifact artifact, Map name, Set interfaceTypes) {
084 this.artifact = artifact;
085 this.name = name;
086 if (interfaceTypes == null) interfaceTypes = Collections.EMPTY_SET;
087 this.interfaceTypes = interfaceTypes;
088 this.uri = createURI(artifact, name, this.interfaceTypes);
089 }
090
091 public AbstractNameQuery(URI uri) {
092 if (uri == null) throw new NullPointerException("uri is null");
093
094 //
095 // Artifact
096 //
097 String artifactString = uri.getPath();
098 //this doesn't seem to happen
099 // if (artifactString == null) throw new IllegalArgumentException("uri does not contain a path part used for the artifact");
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 // name map
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 // if (name.isEmpty()) {
144 // throw new IllegalArgumentException("name is empty: " + nameString);
145 // }
146
147 String interfaceString = uri.getFragment();
148 List interfaces = split(interfaceString, ',');
149 interfaceTypes = new HashSet(interfaces);
150
151 //
152 // uri
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 }