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    }