| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| package org.apache.felix.ipojo.dependency.impl; |
| |
| import org.apache.felix.ipojo.dependency.interceptors.TransformedServiceReference; |
| import org.osgi.framework.Bundle; |
| import org.osgi.framework.Constants; |
| import org.osgi.framework.ServiceReference; |
| |
| import java.util.*; |
| |
| /** |
| * Implements transformed service reference. |
| */ |
| public class TransformedServiceReferenceImpl<S> implements TransformedServiceReference<S> { |
| |
| private final ServiceReference<S> m_origin; |
| private Map<String, Object> m_properties = new HashMap<String, Object>(); |
| |
| public TransformedServiceReferenceImpl(ServiceReference<S> origin) { |
| this.m_origin = origin; |
| // Copy properties |
| for (String key : origin.getPropertyKeys()) { |
| m_properties.put(key, origin.getProperty(key)); |
| } |
| } |
| |
| public TransformedServiceReferenceImpl<S> addProperty(String name, Object value) { |
| if (FORBIDDEN_KEYS.contains(name)) { |
| throw new IllegalArgumentException("Cannot change the property " + name); |
| } |
| m_properties.put(name, value); |
| return this; |
| } |
| |
| public TransformedServiceReference<S> addPropertyIfAbsent(String name, Object value) { |
| if (! contains(name)) { |
| addProperty(name, value); |
| } |
| return this; |
| } |
| |
| public Object get(String name) { |
| return m_properties.get(name); |
| } |
| |
| public TransformedServiceReferenceImpl<S> removeProperty(String name) { |
| if (FORBIDDEN_KEYS.contains(name)) { |
| throw new IllegalArgumentException("Cannot change the property " + name); |
| } |
| // Store a null value. |
| m_properties.put(name, null); |
| return this; |
| } |
| |
| public boolean contains(String name) { |
| return m_properties.get(name) != null; |
| } |
| |
| public ServiceReference<S> getWrappedReference() { |
| if (m_origin instanceof TransformedServiceReferenceImpl) { |
| return ((TransformedServiceReferenceImpl<S>) m_origin).getWrappedReference(); |
| } else { |
| return m_origin; |
| } |
| } |
| |
| public Object getProperty(String key) { |
| return m_properties.get(key); |
| } |
| |
| public String[] getPropertyKeys() { |
| List<String> keys = new ArrayList<String>(); |
| for (Map.Entry<String, Object> entry : m_properties.entrySet()) { |
| if (entry.getValue() != null) { |
| keys.add(entry.getKey()); |
| } |
| } |
| return keys.toArray(new String[keys.size()]); |
| } |
| |
| public Bundle getBundle() { |
| return m_origin.getBundle(); |
| } |
| |
| public Bundle[] getUsingBundles() { |
| return m_origin.getUsingBundles(); |
| } |
| |
| public boolean isAssignableTo(Bundle bundle, String className) { |
| return m_origin.isAssignableTo(bundle, className); |
| } |
| |
| /** |
| * Compares two service references. |
| * This method is not delegated as we may have modified some of the properties using for the ranking. |
| * @param reference the reference |
| * @return 0, 1 or -1 depending of the reference. |
| */ |
| public int compareTo(Object reference) { |
| ServiceReference other = (ServiceReference) reference; |
| |
| Long id = (Long) getProperty(Constants.SERVICE_ID); |
| Long otherId = (Long) other.getProperty(Constants.SERVICE_ID); |
| |
| if (id.equals(otherId)) { |
| return 0; // same service |
| } |
| |
| Object rankObj = getProperty(Constants.SERVICE_RANKING); |
| Object otherRankObj = other.getProperty(Constants.SERVICE_RANKING); |
| |
| // If no rank, then spec says it defaults to zero. |
| rankObj = (rankObj == null) ? new Integer(0) : rankObj; |
| otherRankObj = (otherRankObj == null) ? new Integer(0) : otherRankObj; |
| |
| // If rank is not Integer, then spec says it defaults to zero. |
| Integer rank = (rankObj instanceof Integer) |
| ? (Integer) rankObj : new Integer(0); |
| Integer otherRank = (otherRankObj instanceof Integer) |
| ? (Integer) otherRankObj : new Integer(0); |
| |
| // Sort by rank in ascending order. |
| if (rank.compareTo(otherRank) < 0) { |
| return -1; // lower rank |
| } else if (rank.compareTo(otherRank) > 0) { |
| return 1; // higher rank |
| } |
| |
| // If ranks are equal, then sort by service id in descending order. |
| return (id.compareTo(otherId) < 0) ? 1 : -1; |
| } |
| |
| @Override |
| public boolean equals(Object o) { |
| if (o instanceof ServiceReference) { |
| Object id1 = ((ServiceReference) o).getProperty(Constants.SERVICE_ID); |
| Object id2 = this.getProperty(Constants.SERVICE_ID); |
| return (id1 != null && id1.equals(id2)) || (id1 == id2); |
| } |
| return m_origin.equals(o); |
| } |
| |
| @Override |
| public int hashCode() { |
| return m_origin.hashCode(); |
| } |
| |
| @Override |
| public String toString() { |
| return getWrappedReference().toString() + m_properties; |
| } |
| } |