blob: c7312fb4bbf384a1ffe34f90e6d00a0ff0ab1a3c [file] [log] [blame]
/*
* 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;
}
}