1 /** 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. 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.Iterator; 26 import java.util.List; 27 import java.util.Map; 28 import java.util.TreeMap; 29 import javax.management.ObjectName; 30 31 import org.apache.geronimo.kernel.repository.Artifact; 32 import org.apache.geronimo.kernel.Jsr77Naming; 33 34 /** 35 * @version $Rev: 654755 $ $Date: 2008-05-09 04:05:07 -0700 (Fri, 09 May 2008) $ 36 */ 37 public class AbstractName implements Serializable { 38 private static final long serialVersionUID = 3584199042821734754L; 39 40 private final Artifact artifact; 41 private final Map name; 42 private final ObjectName objectName; 43 private final URI uri; 44 45 public AbstractName(Artifact artifact, Map name) { 46 if (artifact == null) throw new NullPointerException("artifact is null"); 47 if (name == null) throw new NullPointerException("name is null"); 48 if (name.isEmpty()) throw new IllegalArgumentException("name is empty"); 49 50 this.artifact = artifact; 51 this.name = name; 52 53 this.objectName = Jsr77Naming.createObjectName(name); 54 55 this.uri = createURI(artifact, name); 56 } 57 58 public AbstractName(Artifact artifact, Map name, ObjectName objectName) { 59 if (artifact == null) throw new NullPointerException("artifact is null"); 60 if (name == null) throw new NullPointerException("name is null"); 61 if (name.isEmpty()) throw new IllegalArgumentException("name is empty"); 62 if (objectName == null) throw new NullPointerException("objectName is null"); 63 64 this.artifact = artifact; 65 this.name = name; 66 this.objectName = objectName; 67 68 this.uri = createURI(artifact, name); 69 } 70 71 /** 72 * Contructs an AbstractName object from the given URI. 73 * 74 * The artifactId for the AbstractName is constructed from the URI path 75 * (everything up to the ? character) and is composed of four parts delimited by 76 * slashes. The artifactId is the only mandatory part, all slashes are mandatory. 77 * 78 * The name map for the AbstractName is constructed from key=value pairs. 79 * Each key=value pair is delimited by a ',' character and the key is separated 80 * from the value by the '=' character. Each key must be unique. 81 * At least one key=value pair must be specified in the query string. 82 * 83 * The URI has the following format: 84 * [vendorId]/artifactId/[version]/[type]?key=value[,key=value][,...] 85 * 86 * @param uri The URI to be used to generate an AbstractName. 87 */ 88 public AbstractName(URI uri) { 89 if (uri == null) throw new NullPointerException("uri is null"); 90 91 // 92 // Artifact 93 // 94 String artifactString = uri.getPath(); 95 if (artifactString == null) throw new IllegalArgumentException("uri does not contain a path part used for the artifact"); 96 97 List artifactParts = split(artifactString, '/'); 98 if (artifactParts.size() != 4) { 99 throw new IllegalArgumentException("uri path must be in the form [vendorId]/artifactId/[version]/[type] : " + artifactString); 100 } 101 102 String groupId = (String) artifactParts.get(0); 103 if (groupId.length() == 0) groupId = null; 104 105 String artifactId = (String) artifactParts.get(1); 106 if (artifactId.length() == 0) artifactId = null; 107 108 String version = (String) artifactParts.get(2); 109 if (version.length() == 0) version = null; 110 111 String type = (String) artifactParts.get(3); 112 if (type.length() == 0) type = null; 113 114 artifact = new Artifact(groupId, artifactId, version, type); 115 116 // 117 // name map 118 // 119 name = new TreeMap(); 120 String nameString = uri.getQuery(); 121 if (nameString == null) { 122 throw new IllegalArgumentException("uri does not contain a query part used for the name map; uri: " + uri); 123 } 124 125 List nameParts = split(nameString, ','); 126 for (Iterator iterator = nameParts.iterator(); iterator.hasNext();) { 127 String namePart = (String) iterator.next(); 128 List keyValue = split(namePart, '='); 129 if (keyValue.size() != 2) { 130 throw new IllegalArgumentException("uri query string must be in the form ?key=value[,key=value]*] : " + nameString); 131 } 132 String key = (String) keyValue.get(0); 133 String value = (String) keyValue.get(1); 134 if (name.containsKey(key)) { 135 throw new IllegalArgumentException("uri query string contains the key '"+ key + "' twice : " + nameString); 136 } 137 name.put(key, value); 138 } 139 if (name.isEmpty()) { 140 throw new IllegalArgumentException("name is empty: " + nameString); 141 } 142 143 // 144 // uri 145 // 146 this.uri = createURI(artifact, name); 147 148 // 149 // object name 150 // 151 this.objectName = Jsr77Naming.createObjectName(name); 152 } 153 154 private static URI createURI(Artifact artifact, Map name) { 155 StringBuffer queryString = new StringBuffer(); 156 TreeMap treeMap = new TreeMap(name); 157 for (Iterator iterator = treeMap.entrySet().iterator(); iterator.hasNext();) { 158 Map.Entry entry = (Map.Entry) iterator.next(); 159 String key = (String) entry.getKey(); 160 String value = (String) entry.getValue(); 161 queryString.append(key).append('=').append(value); 162 if (iterator.hasNext()) { 163 queryString.append(','); 164 } 165 } 166 try { 167 return new URI(null, null, artifact.toString(), queryString.toString(), null); 168 } catch (URISyntaxException e) { 169 IllegalArgumentException illegalArgumentException = new IllegalArgumentException(); 170 illegalArgumentException.initCause(e); 171 throw illegalArgumentException; 172 } 173 } 174 175 // why not use String.split? Because String.split works using regular expressions 176 // and this should be way faster, but write a benchmark it out if you have time. 177 // Also this code is way simpler. 178 private static List split(String source, char delim) { 179 List parts = new ArrayList(); 180 for (int index = source.indexOf(delim); index >= 0; index = source.indexOf(delim)) { 181 String part = source.substring(0, index); 182 source = source.substring(index + 1); 183 parts.add(part); 184 } 185 parts.add(source); 186 return parts; 187 } 188 189 public Artifact getArtifact() { 190 return artifact; 191 } 192 193 public Map getName() { 194 return Collections.unmodifiableMap(name); 195 } 196 197 public String getNameProperty(String key) { 198 return (String) name.get(key); 199 } 200 201 public ObjectName getObjectName() { 202 return objectName; 203 } 204 205 public URI toURI() { 206 return uri; 207 } 208 209 public String toString() { 210 return uri.toString(); 211 } 212 213 public boolean equals(Object o) { 214 if (this == o) return true; 215 if (o == null || getClass() != o.getClass()) return false; 216 217 final AbstractName that = (AbstractName) o; 218 219 if (artifact != null ? !artifact.equals(that.artifact) : that.artifact != null) return false; 220 return !(name != null ? !name.equals(that.name) : that.name != null); 221 222 } 223 224 public int hashCode() { 225 int result; 226 result = (artifact != null ? artifact.hashCode() : 0); 227 result = 29 * result + (name != null ? name.hashCode() : 0); 228 return result; 229 } 230 231 }