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 }