View Javadoc

1   /*
2    * Copyright 2006-2008 the original author or authors.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.springframework.osgi.mock;
18  
19  import java.util.Dictionary;
20  import java.util.Enumeration;
21  import java.util.Hashtable;
22  
23  import org.osgi.framework.Bundle;
24  import org.osgi.framework.Constants;
25  import org.osgi.framework.ServiceReference;
26  import org.osgi.framework.ServiceRegistration;
27  
28  /**
29   * ServiceReference mock.
30   * 
31   * <p/> This mock tries to adhere to the OSGi spec as much as possible by
32   * providing the mandatory serviceId properties such as
33   * {@link Constants#SERVICE_ID}, {@link Constants#OBJECTCLASS} and
34   * {@link Constants#SERVICE_RANKING}.
35   * 
36   * @author Costin Leau
37   * 
38   */
39  public class MockServiceReference implements ServiceReference {
40  
41  	private Bundle bundle;
42  
43  	private static long GLOBAL_SERVICE_ID = System.currentTimeMillis();
44  
45  	private long serviceId;
46  
47  	// private ServiceRegistration registration;
48  	private Dictionary properties;
49  
50  	private String[] objectClass = new String[] { Object.class.getName() };
51  
52  
53  	public MockServiceReference() {
54  		this(null, null, null);
55  	}
56  
57  	public MockServiceReference(Bundle bundle) {
58  		this(bundle, null, null);
59  	}
60  
61  	public MockServiceReference(String[] classes) {
62  		this(null, null, null, classes);
63  
64  	}
65  
66  	public MockServiceReference(Bundle bundle, String[] classes) {
67  		this(bundle, null, null, classes);
68  	}
69  
70  	public MockServiceReference(ServiceRegistration registration) {
71  		this(null, null, registration);
72  	}
73  
74  	public MockServiceReference(Bundle bundle, Dictionary properties, ServiceRegistration registration) {
75  		this(bundle, properties, registration, null);
76  	}
77  
78  	public MockServiceReference(Bundle bundle, Dictionary properties, ServiceRegistration registration, String[] classes) {
79  		this.bundle = (bundle == null ? new MockBundle() : bundle);
80  		// this.registration = (registration == null ? new
81  		// MockServiceRegistration() :
82  		// registration);
83  		this.properties = (properties == null ? new Hashtable() : properties);
84  		if (classes != null && classes.length > 0)
85  			this.objectClass = classes;
86  		addMandatoryProperties(this.properties);
87  	}
88  
89  	private void addMandatoryProperties(Dictionary dict) {
90  		// add mandatory properties
91  		Object id = dict.get(Constants.SERVICE_ID);
92  		if (id == null || !(id instanceof Long))
93  			dict.put(Constants.SERVICE_ID, new Long(GLOBAL_SERVICE_ID++));
94  
95  		if (dict.get(Constants.OBJECTCLASS) == null)
96  			dict.put(Constants.OBJECTCLASS, objectClass);
97  
98  		Object ranking = dict.get(Constants.SERVICE_RANKING);
99  		if (ranking == null || !(ranking instanceof Integer))
100 			dict.put(Constants.SERVICE_RANKING, new Integer(0));
101 
102 		serviceId = ((Long) dict.get(Constants.SERVICE_ID)).longValue();
103 	}
104 
105 	public Bundle getBundle() {
106 		return bundle;
107 	}
108 
109 	public Object getProperty(String key) {
110 		return properties.get(key);
111 	}
112 
113 	public String[] getPropertyKeys() {
114 		String[] keys = new String[this.properties.size()];
115 		Enumeration ks = this.properties.keys();
116 
117 		for (int i = 0; i < keys.length && ks.hasMoreElements(); i++) {
118 			keys[i] = (String) ks.nextElement();
119 		}
120 
121 		return keys;
122 	}
123 
124 	public Bundle[] getUsingBundles() {
125 		return new Bundle[] {};
126 	}
127 
128 	public boolean isAssignableTo(Bundle bundle, String className) {
129 		return false;
130 	}
131 
132 	public void setProperties(Dictionary properties) {
133 		if (properties != null) {
134 			// copy mandatory properties
135 			properties.put(Constants.SERVICE_ID, this.properties.get(Constants.SERVICE_ID));
136 			properties.put(Constants.OBJECTCLASS, this.properties.get(Constants.OBJECTCLASS));
137 			// optional property
138 			if (properties.get(Constants.SERVICE_RANKING) == null)
139 				properties.put(Constants.SERVICE_RANKING, this.properties.get(Constants.SERVICE_RANKING));
140 
141 			this.properties = properties;
142 		}
143 	}
144 
145 	/**
146 	 * Two mock service references are equal if they contain the same service
147 	 * id.
148 	 */
149 	public boolean equals(Object obj) {
150 		if (this == obj)
151 			return true;
152 		if (obj instanceof MockServiceReference) {
153 			return this.hashCode() == ((MockServiceReference) obj).hashCode();
154 		}
155 		return false;
156 	}
157 
158 	/**
159 	 * Return a hash code based on the class and service id.
160 	 */
161 	public int hashCode() {
162 		return MockServiceReference.class.hashCode() * 13 + (int) serviceId;
163 	}
164 
165 	public String toString() {
166 		return "mock service reference [owning bundle id=" + bundle.hashCode() + "|props : " + properties + "]";
167 	}
168 
169 	public int compareTo(Object reference) {
170 		ServiceReference other = (ServiceReference) reference;
171 
172 		// compare based on service ranking
173 
174 		Object ranking = this.getProperty(Constants.SERVICE_RANKING);
175 		// if the property is not supplied or of incorrect type, use the default
176 		int rank1 = ((ranking != null && ranking instanceof Integer) ? ((Integer) ranking).intValue() : 0);
177 		ranking = other.getProperty(Constants.SERVICE_RANKING);
178 		int rank2 = ((ranking != null && ranking instanceof Integer) ? ((Integer) ranking).intValue() : 0);
179 
180 		int result = rank1 - rank2;
181 
182 		if (result == 0) {
183 			long id1 = serviceId;
184 			long id2 = ((Long) other.getProperty(Constants.SERVICE_ID)).longValue();
185 
186 			// when comparing IDs, make sure to return inverse results (i.e. lower
187 			// id, means higher service)
188 			return (int) (id2 - id1);
189 		}
190 
191 		return result;
192 	}
193 }