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 }