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: 706640 $ $Date: 2008-10-21 14:44:05 +0000 (Tue, 21 Oct 2008) $
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 artifact = Artifact.createPartial(artifactString);
103 } else {
104 artifact = null;
105 }
106
107 //
108 // name map
109 //
110 name = new TreeMap();
111 String nameString = uri.getQuery();
112 List nameParts = split(nameString, ',');
113 for (Iterator iterator = nameParts.iterator(); iterator.hasNext();) {
114 String namePart = (String) iterator.next();
115 List keyValue = split(namePart, '=');
116 if (keyValue.size() != 2) {
117 throw new IllegalArgumentException("uri query string must be in the form [vendorId]/artifactId/[version]/[type] : " + nameString);
118 }
119 String key = (String) keyValue.get(0);
120 String value = (String) keyValue.get(1);
121 if (name.containsKey(key)) {
122 throw new IllegalArgumentException("uri query string contains the key '" + key + "' twice : " + nameString);
123 }
124 name.put(key, value);
125 }
126 // if (name.isEmpty()) {
127 // throw new IllegalArgumentException("name is empty: " + nameString);
128 // }
129
130 String interfaceString = uri.getFragment();
131 List interfaces = split(interfaceString, ',');
132 interfaceTypes = new HashSet(interfaces);
133
134 //
135 // uri
136 //
137 this.uri = createURI(artifact, name, interfaceTypes);
138 }
139
140 private static List split(String source, char delim) {
141 List parts = new ArrayList();
142 if (source != null && source.length() > 0) {
143 for (int index = source.indexOf(delim); index >= 0; index = source.indexOf(delim)) {
144 String part = source.substring(0, index);
145 source = source.substring(index + 1);
146 parts.add(part);
147 }
148 parts.add(source);
149 }
150 return parts;
151 }
152
153 private static URI createURI(Artifact artifact, Map name, Set interfaceTypes) {
154 StringBuffer queryString = new StringBuffer();
155 TreeMap treeMap = new TreeMap(name);
156 for (Iterator iterator = treeMap.entrySet().iterator(); iterator.hasNext();) {
157 Map.Entry entry = (Map.Entry) iterator.next();
158 String key = (String) entry.getKey();
159 String value = (String) entry.getValue();
160 queryString.append(key).append('=').append(value);
161 if (iterator.hasNext()) {
162 queryString.append(',');
163 }
164 }
165 StringBuffer fragmentString = new StringBuffer();
166 TreeSet treeSet = new TreeSet(interfaceTypes);
167 for (Iterator iterator = treeSet.iterator(); iterator.hasNext();) {
168 String interfaceType = (String) iterator.next();
169 fragmentString.append(interfaceType);
170 if (iterator.hasNext()) {
171 fragmentString.append(',');
172 }
173 }
174 try {
175 return new URI(null, null, artifact == null? null: artifact.toString(), queryString.toString(), fragmentString.toString());
176 } catch (URISyntaxException e) {
177 IllegalArgumentException illegalArgumentException = new IllegalArgumentException();
178 illegalArgumentException.initCause(e);
179 throw illegalArgumentException;
180 }
181 }
182
183
184 public Artifact getArtifact() {
185 return artifact;
186 }
187
188 public Map getName() {
189 return name;
190 }
191
192 public Set getInterfaceTypes() {
193 return interfaceTypes;
194 }
195
196 public String toString() {
197 return uri.toString();
198 }
199
200 public URI toURI() {
201 return uri;
202 }
203
204 public boolean equals(Object o) {
205 if (this == o) return true;
206 if (o == null || getClass() != o.getClass()) return false;
207
208 final AbstractNameQuery that = (AbstractNameQuery) o;
209
210 if (artifact != null ? !artifact.equals(that.artifact) : that.artifact != null) return false;
211 if (interfaceTypes != null ? !interfaceTypes.equals(that.interfaceTypes) : that.interfaceTypes != null)
212 return false;
213 return !(name != null ? !name.equals(that.name) : that.name != null);
214
215 }
216
217 public int hashCode() {
218 int result;
219 result = (artifact != null ? artifact.hashCode() : 0);
220 result = 29 * result + (name != null ? name.hashCode() : 0);
221 result = 29 * result + (interfaceTypes != null ? interfaceTypes.hashCode() : 0);
222 return result;
223 }
224
225
226 public boolean matches(AbstractName info, Set targetInterfaceTypes) {
227 try {
228 if (!info.getName().entrySet().containsAll(name.entrySet())) {
229 return false;
230 }
231 if (!targetInterfaceTypes.containsAll(interfaceTypes)) {
232 return false;
233 }
234 if (artifact == null) {
235 return true;
236 }
237 Artifact otherArtifact = info.getArtifact();
238 return artifact.matches(otherArtifact);
239 } catch (NullPointerException e) {
240 e.printStackTrace();
241 return false;
242 }
243 }
244
245 /**
246 * N.B. parameter info is supposed to be more specific than this.
247 * This is the opposite of the meaning of Artifact.matches.
248 *
249 * @param info
250 * @return if info is a more specific version of this name query.
251 */
252 public boolean matches(AbstractNameQuery info) {
253 if (!info.getName().entrySet().containsAll(name.entrySet())) {
254 return false;
255 }
256 if (!info.getInterfaceTypes().containsAll(interfaceTypes)) {
257 return false;
258 }
259 if (artifact == null) {
260 return true;
261 }
262 Artifact otherArtifact = info.getArtifact();
263 return artifact.matches(otherArtifact);
264 }
265 }