Java tutorial
/* * Copyright 2008 Toni Menzel * * 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 org.ops4j.pax.exam.rbc.internal; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.Serializable; import java.lang.reflect.InvocationTargetException; import java.rmi.RemoteException; import java.util.Dictionary; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.BundleException; import org.osgi.framework.Constants; import org.osgi.framework.ServiceReference; import org.osgi.service.startlevel.StartLevel; import static org.ops4j.lang.NullArgumentException.*; /** * {@link RemoteBundleContext} implementaton. * * @author Toni Menzel (tonit) * @author Alin Dreghiciu (adreghiciu@gmail.com) * @since 0.1.0, June 10, 2008 */ public class RemoteBundleContextImpl implements RemoteBundleContext, Serializable { /** * JCL Logger. */ private static final Log LOG = LogFactory.getLog(RemoteBundleContextImpl.class); /** * Bundle context (cannot be null). */ private final transient BundleContext m_bundleContext; /** * Constructor. * * @param bundleContext bundle context (cannot be null) * * @throws IllegalArgumentException - If bundle context is null */ public RemoteBundleContextImpl(final BundleContext bundleContext) { validateNotNull(bundleContext, "Bundle context"); m_bundleContext = bundleContext; } /** * {@inheritDoc} */ public Object remoteCall(final Class<?> serviceType, final String methodName, final Class<?>[] methodParams, final long timeoutInMillis, final Object... actualParams) throws NoSuchServiceException, NoSuchMethodException, IllegalAccessException, InvocationTargetException { LOG.info("Remote call of [" + serviceType.getName() + "." + methodName + "]"); return serviceType.getMethod(methodName, methodParams).invoke(getService(serviceType, timeoutInMillis), actualParams); } /** * {@inheritDoc} */ public long installBundle(final String bundleUrl) throws BundleException { LOG.info("Install bundle from URL [" + bundleUrl + "]"); return m_bundleContext.installBundle(bundleUrl).getBundleId(); } /** * {@inheritDoc} */ public long installBundle(final String bundleLocation, final byte[] bundle) throws BundleException { LOG.info("Install bundle [" + bundleLocation + "] from byte array"); final ByteArrayInputStream inp = new ByteArrayInputStream(bundle); try { return m_bundleContext.installBundle(bundleLocation, inp).getBundleId(); } finally { try { inp.close(); } catch (IOException e) { // ignore. } } } /** * {@inheritDoc} */ public void startBundle(long bundleId) throws BundleException { startBundle(m_bundleContext.getBundle(bundleId)); } /** * {@inheritDoc} */ public void stopBundle(long bundleId) throws BundleException { m_bundleContext.getBundle(bundleId).stop(); } /** * {@inheritDoc} */ public void setBundleStartLevel(long bundleId, int startLevel) throws RemoteException, BundleException { try { final StartLevel startLevelService = getService(StartLevel.class, 0); startLevelService.setBundleStartLevel(m_bundleContext.getBundle(bundleId), startLevel); } catch (NoSuchServiceException e) { throw new BundleException("Cannot get the start level service to set bundle start level"); } } /** * {@inheritDoc} */ public void waitForState(final long bundleId, final int state, final long timeoutInMillis) throws TimeoutException { Bundle bundle = m_bundleContext.getBundle(bundleId); if (timeoutInMillis == NO_WAIT && (bundle == null || bundle.getState() < state)) { throw new TimeoutException("There is no waiting timeout set and bundle has state '" + bundleStateToString(bundle.getState()) + "' not '" + bundleStateToString(state) + "' as expected"); } long startedTrying = System.currentTimeMillis(); do { bundle = m_bundleContext.getBundle(bundleId); try { Thread.sleep(50); } catch (InterruptedException e) { Thread.currentThread().interrupt(); break; } } while ((bundle == null || bundle.getState() < state) && (timeoutInMillis == WAIT_FOREVER || System.currentTimeMillis() < startedTrying + timeoutInMillis)); // bundle != null && bundle.getState() >= state // or // timeoutInMillis != WAIT_FOREVER && System.currentTimeMillis() >= startedTrying + timeoutInMillis if (bundle == null || bundle.getState() < state) { throw new TimeoutException( "Timeout passed and bundle has state '" + bundleStateToString(bundle.getState()) + "' not '" + bundleStateToString(state) + "' as expected"); } } /** * Lookup a service in the service registry. * * @param serviceType service class * @param timeoutInMillis number of milliseconds to wait for service before failing * TODO timeout is not used! * * @return a service published under the required service type * * @throws NoSuchServiceException - If service cannot be found in the service registry */ private <T> T getService(final Class<T> serviceType, final long timeoutInMillis) throws NoSuchServiceException { LOG.info("Look up service [" + serviceType.getName() + "], timeout in " + timeoutInMillis + " millis"); final ServiceReference ref = m_bundleContext.getServiceReference(serviceType.getName()); if (ref != null) { final Object service = m_bundleContext.getService(ref); if (service == null) { throw new NoSuchServiceException(serviceType); } return (T) service; } else { throw new NoSuchServiceException(serviceType); } } /** * Starts a bundle. * * @param bundle bundle to be started * * @throws BundleException - If bundle cannot be started */ private void startBundle(final Bundle bundle) throws BundleException { // Don't start if bundle already active int bundleState = bundle.getState(); if (bundleState == Bundle.ACTIVE) { return; } // Don't start if bundle is a fragment bundle Dictionary bundleHeaders = bundle.getHeaders(); if (bundleHeaders.get(Constants.FRAGMENT_HOST) != null) { return; } // Start bundle bundle.start(); bundleState = bundle.getState(); if (bundleState != Bundle.ACTIVE) { long bundleId = bundle.getBundleId(); String bundleName = bundle.getSymbolicName(); String bundleStateStr = bundleStateToString(bundleState); throw new BundleException( "Bundle (" + bundleId + ", " + bundleName + ") not started (still " + bundleStateStr + ")"); } } /** * Coverts a bundle state to its string form. * * @param bundleState bundle state * * @return bundle state as string */ private static String bundleStateToString(int bundleState) { switch (bundleState) { case Bundle.ACTIVE: return "active"; case Bundle.INSTALLED: return "installed"; case Bundle.RESOLVED: return "resolved"; case Bundle.STARTING: return "starting"; case Bundle.STOPPING: return "stopping"; case Bundle.UNINSTALLED: return "uninstalled"; default: return "unknown (" + bundleState + ")"; } } }