| /* |
| * 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.connect; |
| |
| import java.io.File; |
| import java.io.InputStream; |
| import java.util.Arrays; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.Comparator; |
| import java.util.Dictionary; |
| import java.util.Iterator; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import org.apache.felix.connect.felix.framework.HookRegistry; |
| import org.apache.felix.connect.felix.framework.ServiceRegistry; |
| import org.apache.felix.connect.felix.framework.capabilityset.SimpleFilter; |
| import org.apache.felix.connect.felix.framework.util.EventDispatcher; |
| import org.apache.felix.connect.felix.framework.util.ShrinkableCollection; |
| import org.apache.felix.connect.felix.framework.util.Util; |
| 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.FrameworkEvent; |
| import org.osgi.framework.FrameworkListener; |
| import org.osgi.framework.FrameworkUtil; |
| import org.osgi.framework.InvalidSyntaxException; |
| import org.osgi.framework.ServiceEvent; |
| import org.osgi.framework.ServiceException; |
| import org.osgi.framework.ServiceFactory; |
| import org.osgi.framework.ServiceListener; |
| import org.osgi.framework.ServiceObjects; |
| import org.osgi.framework.ServiceReference; |
| import org.osgi.framework.ServiceRegistration; |
| import org.osgi.framework.hooks.service.FindHook; |
| |
| class PojoSRBundleContext implements BundleContext |
| { |
| private final Bundle m_bundle; |
| private final ServiceRegistry m_reg; |
| private final EventDispatcher m_dispatcher; |
| private final Map<Long, Bundle> m_bundles; |
| private final Map<String, Object> m_config; |
| |
| public PojoSRBundleContext(Bundle bundle, ServiceRegistry reg, |
| EventDispatcher dispatcher, Map<Long, Bundle> bundles, Map<String, Object> config) |
| { |
| m_bundle = bundle; |
| m_reg = reg; |
| m_dispatcher = dispatcher; |
| m_bundles = bundles; |
| m_config = config; |
| } |
| |
| public boolean ungetService(ServiceReference reference) |
| { |
| return m_reg.ungetService(m_bundle, reference, null); |
| } |
| |
| public void removeServiceListener(ServiceListener listener) |
| { |
| m_dispatcher.removeListener(this, ServiceListener.class, |
| listener); |
| } |
| |
| public void removeFrameworkListener(FrameworkListener listener) |
| { |
| m_dispatcher |
| .removeListener(this, FrameworkListener.class, listener); |
| } |
| |
| public void removeBundleListener(BundleListener listener) |
| { |
| m_dispatcher.removeListener(this, BundleListener.class, listener); |
| } |
| |
| public ServiceRegistration registerService(String clazz, Object service, |
| Dictionary properties) |
| { |
| return registerService(new String[]{clazz}, service, properties); |
| } |
| |
| public ServiceRegistration registerService(String[] clazzes, |
| Object service, Dictionary properties) |
| { |
| ServiceRegistration reg = m_reg.registerService(m_bundle, clazzes, service, |
| properties); |
| |
| // Check to see if this a listener hook; if so, then we need |
| // to invoke the callback with all existing service listeners. |
| if (HookRegistry.isHook( |
| clazzes, org.osgi.framework.hooks.service.ListenerHook.class, service)) |
| { |
| org.osgi.framework.hooks.service.ListenerHook lh = |
| (org.osgi.framework.hooks.service.ListenerHook) |
| m_reg.getService(m_bundle, reg.getReference(), false); |
| |
| if (lh != null) |
| { |
| try |
| { |
| lh.added(m_dispatcher.getAllServiceListeners()); |
| } |
| catch (Throwable th) |
| { |
| System.out.println("Problem invoking service registry hook"); |
| th.printStackTrace(); |
| } |
| finally |
| { |
| m_reg.ungetService(m_bundle, reg.getReference(), null); |
| } |
| } |
| } |
| |
| m_dispatcher.fireServiceEvent(new ServiceEvent(ServiceEvent.REGISTERED, reg.getReference()), null, m_bundles.get(0L)); |
| |
| return reg; |
| } |
| |
| public Bundle installBundle(String location) throws BundleException |
| { |
| throw new BundleException("pojosr can't do that"); |
| } |
| |
| public Bundle installBundle(String location, InputStream input) |
| throws BundleException |
| { |
| |
| throw new BundleException("pojosr can't do that"); |
| } |
| |
| public ServiceReference<?>[] getServiceReferences(String clazz, String filter) |
| throws InvalidSyntaxException |
| { |
| return getServiceReferences(clazz, filter, true); |
| } |
| |
| public ServiceReference<?> getServiceReference(String clazz) |
| { |
| try |
| { |
| return getBestServiceReference(getServiceReferences(clazz, null)); |
| } |
| catch (InvalidSyntaxException e) |
| { |
| throw new IllegalStateException(e); |
| } |
| } |
| |
| private ServiceReference<?> getBestServiceReference(ServiceReference<?>[] refs) |
| { |
| if (refs == null) |
| { |
| return null; |
| } |
| |
| if (refs.length == 1) |
| { |
| return refs[0]; |
| } |
| |
| // Loop through all service references and return |
| // the "best" one according to its rank and ID. |
| ServiceReference bestRef = refs[0]; |
| for (int i = 1; i < refs.length; i++) |
| { |
| if (bestRef.compareTo(refs[i]) < 0) |
| { |
| bestRef = refs[i]; |
| } |
| } |
| |
| return bestRef; |
| } |
| |
| public <S> S getService(ServiceReference<S> reference) |
| { |
| try |
| { |
| return m_reg.getService(m_bundle, reference, false); |
| } |
| catch ( ServiceException ex ) |
| { |
| m_dispatcher.fireFrameworkEvent(new FrameworkEvent(FrameworkEvent.ERROR, m_bundle, ex)); |
| } |
| return null; |
| } |
| |
| @Override |
| public <S> ServiceObjects<S> getServiceObjects(ServiceReference<S> reference) { |
| return new ServiceObjectsImpl<S>(reference); |
| } |
| |
| |
| // |
| // ServiceObjects implementation |
| // |
| class ServiceObjectsImpl<S> implements ServiceObjects<S> |
| { |
| private final ServiceReference<S> m_ref; |
| |
| public ServiceObjectsImpl(final ServiceReference<S> ref) |
| { |
| this.m_ref = ref; |
| } |
| |
| public S getService() { |
| return m_reg.getService(m_bundle, m_ref, true); |
| } |
| |
| public void ungetService(final S srvObj) {// Unget the specified service. |
| if ( !m_reg.ungetService(m_bundle, m_ref, srvObj)) |
| { |
| throw new IllegalArgumentException(); |
| } |
| } |
| |
| public ServiceReference<S> getServiceReference() |
| { |
| return m_ref; |
| } |
| } |
| public String getProperty(String key) |
| { |
| Object result = m_config.get(key); |
| |
| return result == null ? System.getProperty(key) : result.toString(); |
| } |
| |
| public File getDataFile(String filename) |
| { |
| File root = new File("bundle" + m_bundle.getBundleId()); |
| String storage = getProperty("org.osgi.framework.storage"); |
| if (storage != null) |
| { |
| root = new File(new File(storage), root.getName()); |
| } |
| root.mkdirs(); |
| return filename.trim().length() > 0 ? new File(root, filename) : root; |
| } |
| |
| public Bundle[] getBundles() |
| { |
| Bundle[] result = m_bundles.values().toArray( |
| new Bundle[m_bundles.size()]); |
| Arrays.sort(result, new Comparator<Bundle>() |
| { |
| |
| public int compare(Bundle o1, Bundle o2) |
| { |
| return (int) (o1.getBundleId() - o2.getBundleId()); |
| } |
| }); |
| return result; |
| } |
| |
| public Bundle getBundle(long id) |
| { |
| return m_bundles.get(id); |
| } |
| |
| public Bundle getBundle() |
| { |
| return m_bundle; |
| } |
| |
| public ServiceReference[] getAllServiceReferences(String clazz, |
| String filter) throws InvalidSyntaxException |
| { |
| return getServiceReferences(clazz, filter, false); |
| } |
| |
| /** |
| * Retrieves an array of {@link ServiceReference} objects based on calling bundle, |
| * service class name, and filter expression. Optionally checks for isAssignable to |
| * make sure that the service can be cast to the |
| * @param className Service Classname or <code>null</code> for all |
| * @param expr Filter Criteria or <code>null</code> |
| * @return Array of ServiceReference objects that meet the criteria |
| * @throws InvalidSyntaxException |
| */ |
| ServiceReference[] getServiceReferences( |
| final String className, |
| final String expr, final boolean checkAssignable) |
| throws InvalidSyntaxException |
| { |
| // Define filter if expression is not null. |
| SimpleFilter filter = null; |
| if (expr != null) |
| { |
| try |
| { |
| filter = SimpleFilter.parse(expr); |
| } |
| catch (Exception ex) |
| { |
| throw new InvalidSyntaxException(ex.getMessage(), expr); |
| } |
| } |
| |
| // Ask the service registry for all matching service references. |
| final Collection<ServiceReference<?>> refList = (Collection) m_reg.getServiceReferences(className, filter); |
| |
| // Filter on assignable references |
| if (checkAssignable) |
| { |
| for (Iterator it = refList.iterator(); it.hasNext();) |
| { |
| // Get the current service reference. |
| ServiceReference ref = (ServiceReference) it.next(); |
| // Now check for castability. |
| if (!Util.isServiceAssignable(m_bundle, ref)) |
| { |
| it.remove(); |
| } |
| } |
| } |
| |
| // activate findhooks |
| Set<ServiceReference<FindHook>> findHooks = m_reg.getHookRegistry().getHooks(org.osgi.framework.hooks.service.FindHook.class); |
| for (ServiceReference<org.osgi.framework.hooks.service.FindHook> sr : findHooks) |
| { |
| org.osgi.framework.hooks.service.FindHook fh = m_reg.getService(getBundle(0), sr, false); |
| if (fh != null) |
| { |
| try |
| { |
| fh.find(this, |
| className, |
| expr, |
| !checkAssignable, |
| new ShrinkableCollection<ServiceReference<?>>(refList)); |
| } |
| catch (Throwable th) |
| { |
| System.err.println("Problem invoking service registry hook"); |
| th.printStackTrace(); |
| } |
| finally |
| { |
| m_reg.ungetService(getBundle(0), sr, null); |
| } |
| } |
| } |
| |
| if (refList.size() > 0) |
| { |
| return refList.toArray(new ServiceReference[refList.size()]); |
| } |
| |
| return null; |
| } |
| |
| public Filter createFilter(String filter) throws InvalidSyntaxException |
| { |
| return FrameworkUtil.createFilter(filter); |
| } |
| |
| public void addServiceListener(ServiceListener listener) |
| { |
| try |
| { |
| addServiceListener(listener, null); |
| } |
| catch (InvalidSyntaxException e) |
| { |
| // TODO Auto-generated catch block |
| e.printStackTrace(); |
| } |
| } |
| |
| public void addServiceListener(final ServiceListener listener, String filter) |
| throws InvalidSyntaxException |
| { |
| m_dispatcher.addListener(this, ServiceListener.class, listener, |
| filter == null ? null : FrameworkUtil.createFilter(filter)); |
| } |
| |
| public void addFrameworkListener(FrameworkListener listener) |
| { |
| m_dispatcher.addListener(this, FrameworkListener.class, listener, |
| null); |
| } |
| |
| public void addBundleListener(BundleListener listener) |
| { |
| m_dispatcher |
| .addListener(this, BundleListener.class, listener, null); |
| } |
| |
| @SuppressWarnings("unchecked") |
| public <S> ServiceRegistration<S> registerService(Class<S> clazz, S service, Dictionary<String, ?> properties) |
| { |
| return (ServiceRegistration<S>) registerService(clazz.getName(), service, properties); |
| } |
| |
| @Override |
| public <S> ServiceRegistration<S> registerService(Class<S> clazz, ServiceFactory<S> factory, Dictionary<String, ?> properties) { |
| return (ServiceRegistration<S>) registerService(clazz.getName(), factory, properties); |
| } |
| |
| @SuppressWarnings("unchecked") |
| public <S> ServiceReference<S> getServiceReference(Class<S> clazz) |
| { |
| return (ServiceReference<S>) getServiceReference(clazz.getName()); |
| } |
| |
| @SuppressWarnings("unchecked") |
| public <S> Collection<ServiceReference<S>> getServiceReferences(Class<S> clazz, String filter) |
| throws InvalidSyntaxException |
| { |
| ServiceReference<S>[] refs = (ServiceReference<S>[]) getServiceReferences(clazz.getName(), filter); |
| if (refs == null) |
| { |
| return Collections.emptyList(); |
| } |
| return Arrays.asList(refs); |
| } |
| |
| public Bundle getBundle(String location) |
| { |
| for (Bundle bundle : m_bundles.values()) |
| { |
| if (location.equals(bundle.getLocation())) |
| { |
| return bundle; |
| } |
| } |
| return null; |
| } |
| } |