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.Iterator; 026 import java.util.List; 027 import java.util.Map; 028 import java.util.TreeMap; 029 import javax.management.ObjectName; 030 031 import org.apache.geronimo.kernel.repository.Artifact; 032 import org.apache.geronimo.kernel.Jsr77Naming; 033 034 /** 035 * @version $Rev: 706640 $ $Date: 2008-10-21 14:44:05 +0000 (Tue, 21 Oct 2008) $ 036 */ 037 public class AbstractName implements Serializable { 038 private static final long serialVersionUID = 3584199042821734754L; 039 040 private final Artifact artifact; 041 private final Map name; 042 private final ObjectName objectName; 043 private final URI uri; 044 045 public AbstractName(Artifact artifact, Map name) { 046 if (artifact == null) throw new NullPointerException("artifact is null"); 047 if (name == null) throw new NullPointerException("name is null"); 048 if (name.isEmpty()) throw new IllegalArgumentException("name is empty"); 049 050 this.artifact = artifact; 051 this.name = name; 052 053 this.objectName = Jsr77Naming.createObjectName(name); 054 055 this.uri = createURI(artifact, name); 056 } 057 058 public AbstractName(Artifact artifact, Map name, ObjectName objectName) { 059 if (artifact == null) throw new NullPointerException("artifact is null"); 060 if (name == null) throw new NullPointerException("name is null"); 061 if (name.isEmpty()) throw new IllegalArgumentException("name is empty"); 062 if (objectName == null) throw new NullPointerException("objectName is null"); 063 064 this.artifact = artifact; 065 this.name = name; 066 this.objectName = objectName; 067 068 this.uri = createURI(artifact, name); 069 } 070 071 /** 072 * Contructs an AbstractName object from the given URI. 073 * 074 * The artifactId for the AbstractName is constructed from the URI path 075 * (everything up to the ? character) and is composed of four parts delimited by 076 * slashes. The artifactId is the only mandatory part, all slashes are mandatory. 077 * 078 * The name map for the AbstractName is constructed from key=value pairs. 079 * Each key=value pair is delimited by a ',' character and the key is separated 080 * from the value by the '=' character. Each key must be unique. 081 * At least one key=value pair must be specified in the query string. 082 * 083 * The URI has the following format: 084 * [vendorId]/artifactId/[version]/[type]?key=value[,key=value][,...] 085 * 086 * @param uri The URI to be used to generate an AbstractName. 087 */ 088 public AbstractName(URI uri) { 089 if (uri == null) throw new NullPointerException("uri is null"); 090 091 // 092 // Artifact 093 // 094 String artifactString = uri.getPath(); 095 if (artifactString == null) throw new IllegalArgumentException("uri does not contain a path part used for the artifact"); 096 097 List artifactParts = split(artifactString, '/'); 098 if (artifactParts.size() != 4) { 099 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 }