/* * Copyright (c) 2008-2017, Hazelcast, Inc. All Rights Reserved. * * Licensed 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 com.hazelcast.osgi; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.BundleException; import org.osgi.framework.BundleListener; import org.osgi.framework.Filter; import org.osgi.framework.FrameworkListener; import org.osgi.framework.InvalidSyntaxException; import org.osgi.framework.ServiceListener; import org.osgi.framework.ServiceReference; import org.osgi.framework.ServiceRegistration; import java.io.File; import java.io.InputStream; import java.util.ArrayList; import java.util.Dictionary; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; class TestBundleContext implements BundleContext { private final AtomicInteger counter = new AtomicInteger(); private final Object mutex = new Object(); private final Map<String, List<ServiceReference>> serviceReferenceMap = new HashMap<String, List<ServiceReference>>(); private final TestBundle testBundle; private final TestBundle.RegisterDeregisterListener registerDeregisterListener; TestBundleContext(TestBundle testBundle) { this.testBundle = testBundle; this.registerDeregisterListener = null; } TestBundleContext(TestBundle testBundle, TestBundle.RegisterDeregisterListener registerDeregisterListener) { this.testBundle = testBundle; this.registerDeregisterListener = registerDeregisterListener; } @Override public TestBundle getBundle() { return testBundle; } @Override public Bundle getBundle(long id) { if (id == testBundle.getBundleId()) { return testBundle; } return null; } @Override public Bundle[] getBundles() { return new Bundle[]{testBundle}; } @Override public ServiceRegistration registerService(String[] clazzes, Object service, Dictionary properties) { TestServiceReference serviceReference = new TestServiceReference(testBundle, service, counter.incrementAndGet()); for (String clazz : clazzes) { registerServiceInternal(clazz, serviceReference); } return new TestServiceRegistration(serviceReference); } @Override public ServiceRegistration registerService(String clazz, Object service, Dictionary properties) { TestServiceReference serviceReference = new TestServiceReference(testBundle, service, counter.incrementAndGet()); registerServiceInternal(clazz, serviceReference); return new TestServiceRegistration(serviceReference); } private void registerServiceInternal(String clazz, TestServiceReference serviceReference) { synchronized (mutex) { List<ServiceReference> serviceReferences = serviceReferenceMap.get(clazz); if (serviceReferences == null) { serviceReferences = new ArrayList<ServiceReference>(); serviceReferenceMap.put(clazz, serviceReferences); } serviceReferences.add(serviceReference); if (registerDeregisterListener != null) { registerDeregisterListener.onRegister(clazz, serviceReference); } } } @Override public ServiceReference[] getServiceReferences(String clazz, String filter) throws InvalidSyntaxException { // we simply ignore filter since we don't use filer in our tests synchronized (mutex) { List<ServiceReference> serviceReferences = serviceReferenceMap.get(clazz); if (serviceReferences != null && !serviceReferences.isEmpty()) { return serviceReferences.toArray(new ServiceReference[serviceReferences.size()]); } } return null; } @Override public ServiceReference[] getAllServiceReferences(String clazz, String filter) throws InvalidSyntaxException { // we simply ignore filter since we don't use filer in our tests synchronized (mutex) { List<ServiceReference> serviceReferences = serviceReferenceMap.get(clazz); if (serviceReferences != null && !serviceReferences.isEmpty()) { return serviceReferences.toArray(new ServiceReference[serviceReferences.size()]); } } return null; } ServiceReference[] getAllServiceReferences() { List<ServiceReference> allServiceReferences = new ArrayList<ServiceReference>(); // we simply ignore filter since we don't use filer in our tests synchronized (mutex) { for (Map.Entry<String, List<ServiceReference>> entry : serviceReferenceMap.entrySet()) { List<ServiceReference> serviceReferences = entry.getValue(); allServiceReferences.addAll(serviceReferences); } } return allServiceReferences.toArray(new ServiceReference[allServiceReferences.size()]); } @Override public ServiceReference getServiceReference(String clazz) { synchronized (mutex) { List<ServiceReference> serviceReferences = serviceReferenceMap.get(clazz); if (serviceReferences == null || serviceReferences.isEmpty()) { return null; } else { /* * In fact, this is not sync with spec since spec says that: * ============================================================================================= * If multiple such services exist, the service with the highest ranking (as * specified in its {@link org.osgi.framework.Constants#SERVICE_RANKING} property) is returned. * * If there is a tie in ranking, the service with the lowest service ID (as * specified in its {@link org.osgi.framework.Constants#SERVICE_ID} property); that is, the * service that was registered first is returned. * ============================================================================================= */ return serviceReferences.get(0); } } } @Override public Object getService(ServiceReference reference) { if (reference instanceof TestServiceReference) { return ((TestServiceReference) reference).getService(); } else { throw new IllegalArgumentException("Only `TestServiceReference` instances are supported!"); } } @Override public boolean ungetService(ServiceReference reference) { if (reference instanceof TestServiceReference) { synchronized (mutex) { boolean removed = false; for (Map.Entry<String, List<ServiceReference>> entry : serviceReferenceMap.entrySet()) { List<ServiceReference> serviceReferences = entry.getValue(); if (serviceReferences.remove(reference)) { removed = true; if (registerDeregisterListener != null) { registerDeregisterListener.onDeregister(entry.getKey(), (TestServiceReference) reference); } } } return removed; } } else { throw new IllegalArgumentException("Only `TestServiceReference` instances are supported!"); } } @Override public String getProperty(String key) { throw new UnsupportedOperationException(); } @Override public Bundle installBundle(String location, InputStream input) throws BundleException { throw new UnsupportedOperationException(); } @Override public Bundle installBundle(String location) throws BundleException { throw new UnsupportedOperationException(); } @Override public void addServiceListener(ServiceListener listener, String filter) throws InvalidSyntaxException { throw new UnsupportedOperationException(); } @Override public void addServiceListener(ServiceListener listener) { throw new UnsupportedOperationException(); } @Override public void removeServiceListener(ServiceListener listener) { throw new UnsupportedOperationException(); } @Override public void addBundleListener(BundleListener listener) { throw new UnsupportedOperationException(); } @Override public void removeBundleListener(BundleListener listener) { throw new UnsupportedOperationException(); } @Override public void addFrameworkListener(FrameworkListener listener) { throw new UnsupportedOperationException(); } @Override public void removeFrameworkListener(FrameworkListener listener) { throw new UnsupportedOperationException(); } @Override public File getDataFile(String filename) { throw new UnsupportedOperationException(); } @Override public Filter createFilter(String filter) throws InvalidSyntaxException { throw new UnsupportedOperationException(); } }