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: 476049 $ $Date: 2006-11-16 23:35:17 -0500 (Thu, 16 Nov 2006) $ 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) throw new IllegalArgumentException("uri does not contain a query part used for the name map"); 122 List nameParts = split(nameString, ','); 123 for (Iterator iterator = nameParts.iterator(); iterator.hasNext();) { 124 String namePart = (String) iterator.next(); 125 List keyValue = split(namePart, '='); 126 if (keyValue.size() != 2) { 127 throw new IllegalArgumentException("uri query string must be in the form ?key=value[,key=value]*] : " + nameString); 128 } 129 String key = (String) keyValue.get(0); 130 String value = (String) keyValue.get(1); 131 if (name.containsKey(key)) { 132 throw new IllegalArgumentException("uri query string contains the key '"+ key + "' twice : " + nameString); 133 } 134 name.put(key, value); 135 } 136 if (name.isEmpty()) { 137 throw new IllegalArgumentException("name is empty: " + nameString); 138 } 139 140 // 141 // uri 142 // 143 this.uri = createURI(artifact, name); 144 145 // 146 // object name 147 // 148 this.objectName = Jsr77Naming.createObjectName(name); 149 } 150 151 private static URI createURI(Artifact artifact, Map name) { 152 StringBuffer queryString = new StringBuffer(); 153 TreeMap treeMap = new TreeMap(name); 154 for (Iterator iterator = treeMap.entrySet().iterator(); iterator.hasNext();) { 155 Map.Entry entry = (Map.Entry) iterator.next(); 156 String key = (String) entry.getKey(); 157 String value = (String) entry.getValue(); 158 queryString.append(key).append('=').append(value); 159 if (iterator.hasNext()) { 160 queryString.append(','); 161 } 162 } 163 try { 164 return new URI(null, null, artifact.toString(), queryString.toString(), null); 165 } catch (URISyntaxException e) { 166 IllegalArgumentException illegalArgumentException = new IllegalArgumentException(); 167 illegalArgumentException.initCause(e); 168 throw illegalArgumentException; 169 } 170 } 171 172 // why not use String.split? Because String.split works using regular expressions 173 // and this should be way faster, but write a benchmark it out if you have time. 174 // Also this code is way simpler. 175 private static List split(String source, char delim) { 176 List parts = new ArrayList(); 177 for (int index = source.indexOf(delim); index >= 0; index = source.indexOf(delim)) { 178 String part = source.substring(0, index); 179 source = source.substring(index + 1); 180 parts.add(part); 181 } 182 parts.add(source); 183 return parts; 184 } 185 186 public Artifact getArtifact() { 187 return artifact; 188 } 189 190 public Map getName() { 191 return Collections.unmodifiableMap(name); 192 } 193 194 public String getNameProperty(String key) { 195 return (String) name.get(key); 196 } 197 198 public ObjectName getObjectName() { 199 return objectName; 200 } 201 202 public URI toURI() { 203 return uri; 204 } 205 206 public String toString() { 207 return uri.toString(); 208 } 209 210 public boolean equals(Object o) { 211 if (this == o) return true; 212 if (o == null || getClass() != o.getClass()) return false; 213 214 final AbstractName that = (AbstractName) o; 215 216 if (artifact != null ? !artifact.equals(that.artifact) : that.artifact != null) return false; 217 return !(name != null ? !name.equals(that.name) : that.name != null); 218 219 } 220 221 public int hashCode() { 222 int result; 223 result = (artifact != null ? artifact.hashCode() : 0); 224 result = 29 * result + (name != null ? name.hashCode() : 0); 225 return result; 226 } 227 228 }