karaf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From anierb...@apache.org
Subject svn commit: r1483884 - in /karaf/trunk: features/core/src/main/java/org/apache/karaf/features/internal/ shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/ shell/console/src/main/java/org/apache/karaf/shell/commands/basic/ shell/console/...
Date Fri, 17 May 2013 15:55:06 GMT
Author: anierbeck
Date: Fri May 17 15:55:05 2013
New Revision: 1483884

URL: http://svn.apache.org/r1483884
Log:
[KARAF-2003] - Interrupt a running command in shell

Modified:
    karaf/trunk/features/core/src/main/java/org/apache/karaf/features/internal/BundleManager.java
    karaf/trunk/features/core/src/main/java/org/apache/karaf/features/internal/RepositoryImpl.java
    karaf/trunk/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/MoreAction.java
    karaf/trunk/shell/console/src/main/java/org/apache/karaf/shell/commands/basic/AbstractCommand.java
    karaf/trunk/shell/console/src/main/java/org/apache/karaf/shell/console/AbstractAction.java

Modified: karaf/trunk/features/core/src/main/java/org/apache/karaf/features/internal/BundleManager.java
URL: http://svn.apache.org/viewvc/karaf/trunk/features/core/src/main/java/org/apache/karaf/features/internal/BundleManager.java?rev=1483884&r1=1483883&r2=1483884&view=diff
==============================================================================
--- karaf/trunk/features/core/src/main/java/org/apache/karaf/features/internal/BundleManager.java
(original)
+++ karaf/trunk/features/core/src/main/java/org/apache/karaf/features/internal/BundleManager.java
Fri May 17 15:55:05 2013
@@ -18,8 +18,10 @@ package org.apache.karaf.features.intern
 
 import java.io.BufferedInputStream;
 import java.io.File;
+import java.io.FilterInputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.InterruptedIOException;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.ArrayList;
@@ -60,366 +62,440 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 public class BundleManager {
-    private static final Logger LOGGER = LoggerFactory.getLogger(BundleManager.class);
-    private final BundleContext bundleContext;
-    private final RegionsPersistence regionsPersistence;
-    private final long refreshTimeout;
-
-    public BundleManager(BundleContext bundleContext) {
-        this(bundleContext, null);
-    }
-    
-    public BundleManager(BundleContext bundleContext, RegionsPersistence regionsPersistence)
{
-        this(bundleContext, regionsPersistence, 5000);
-    }
-    
-    public BundleManager(BundleContext bundleContext, RegionsPersistence regionsPersistence,
long refreshTimeout) {
-        this.bundleContext = bundleContext;
-        this.regionsPersistence = regionsPersistence;
-        this.refreshTimeout = refreshTimeout;
-    }
-    
-    public BundleInstallerResult installBundleIfNeeded(String bundleLocation, int startLevel,
String regionName) throws IOException, BundleException {
-        BundleInstallerResult result = doInstallBundleIfNeeded(bundleLocation, startLevel);
-        installToRegion(regionName, result.bundle, result.isNew);
-        return result;
-    }
-
-    private BundleInstallerResult doInstallBundleIfNeeded(String bundleLocation, int startLevel)
throws IOException, BundleException {
-        InputStream is = getInputStreamForBundle(bundleLocation);
-        try {
-            is.mark(256 * 1024);
-            JarInputStream jar = new JarInputStream(is);
-            Manifest m = jar.getManifest();
-            if(m == null) {
-                throw new BundleException("Manifest not present in the first entry of the
zip " + bundleLocation);
-            }
-            String sn = m.getMainAttributes().getValue(Constants.BUNDLE_SYMBOLICNAME);
-            if (sn == null) {
-                throw new BundleException("Jar is not a bundle, no Bundle-SymbolicName "
+ bundleLocation);
-            }
-            // remove attributes from the symbolic name (like ;blueprint.graceperiod:=false
suffix)
-            int attributeIndexSep = sn.indexOf(';');
-            if (attributeIndexSep != -1) {
-                sn = sn.substring(0, attributeIndexSep);
-            }
-            String vStr = m.getMainAttributes().getValue(Constants.BUNDLE_VERSION);
-            Version v = vStr == null ? Version.emptyVersion : Version.parseVersion(vStr);
-            Bundle existingBundle = findInstalled(sn, v);
-            if (existingBundle != null) {
-                LOGGER.debug("Found installed bundle: " + existingBundle);
-                return new BundleInstallerResult(existingBundle, false);
-            }
-            try {
-                is.reset();
-            } catch (IOException e) {
-                is.close();
-                is = new BufferedInputStream(new URL(bundleLocation).openStream());
-            }
-            LOGGER.debug("Installing bundle " + bundleLocation);
-            Bundle b = bundleContext.installBundle(bundleLocation, is);
-            
-            if (startLevel > 0) {
-                b.adapt(BundleStartLevel.class).setStartLevel(startLevel);
-            }
-
-            return new BundleInstallerResult(b, true);
-        } finally {
-            is.close();
-        }
-    }
-
-    private Bundle findInstalled(String symbolicName, Version version) {
-        String vStr;
-        for (Bundle b : bundleContext.getBundles()) {
-            if (b.getSymbolicName() != null && b.getSymbolicName().equals(symbolicName))
{
-                vStr = (String) b.getHeaders().get(Constants.BUNDLE_VERSION);
-                Version bv = vStr == null ? Version.emptyVersion : Version.parseVersion(vStr);
-                if (version.equals(bv)) {
-                    return b;
-                }
-            }
-        }
-        return null;
-    }
-
-    private InputStream getInputStreamForBundle(String bundleLocation) throws MalformedURLException,
IOException {
-        InputStream is;
-        LOGGER.debug("Checking " + bundleLocation);
-        try {
-            int protocolIndex = bundleLocation.indexOf(":");
-            if (protocolIndex != -1) {
-                String protocol = bundleLocation.substring(0, protocolIndex);
-                waitForUrlHandler(protocol);
-            }
-            URL bundleUrl = new URL(bundleLocation);
-            is = new BufferedInputStream(bundleUrl.openStream());
-        } catch (RuntimeException e) {
-            LOGGER.error(e.getMessage());
-            throw e;
-        }
-        return is;
-    }
-    
-    private void installToRegion(String region, Bundle b, boolean isNew) throws BundleException
{
-        if (region != null && isNew) {
-            if (regionsPersistence != null) {
-                regionsPersistence.install(b, region);
-            } else {
-                throw new RuntimeException("Unable to find RegionsPersistence service, while
installing "+ region);
-            }
-        }    
-    }
-
-    /**
-     * Will wait for the {@link URLStreamHandlerService} service for the specified protocol
to be registered.
-     * @param protocol
-     */
-    private void waitForUrlHandler(String protocol) {
-        try {
-            Filter filter = bundleContext.createFilter("(&(" + Constants.OBJECTCLASS
+ "=" + URLStreamHandlerService.class.getName() + ")(url.handler.protocol=" + protocol + "))");
-            if (filter == null) {
-                return;
-            }
-            ServiceTracker<URLStreamHandlerService, URLStreamHandlerService> urlHandlerTracker
= new ServiceTracker<URLStreamHandlerService, URLStreamHandlerService>(bundleContext,
filter, null);
-            try {
-                urlHandlerTracker.open();
-                urlHandlerTracker.waitForService(30000);
-            } catch (InterruptedException e) {
-                LOGGER.debug("Interrupted while waiting for URL handler for protocol {}.",
protocol);
-            } finally {
-                urlHandlerTracker.close();
-            }
-        } catch (Exception ex) {
-            LOGGER.error("Error creating service tracker.", ex);
-        }
-    }
-    
-    protected Set<Bundle> findBundlesToRefresh(Set<Bundle> existing, Set<Bundle>
installed) {
-        Set<Bundle> bundles = new HashSet<Bundle>();
-        bundles.addAll(findBundlesWithOptionalPackagesToRefresh(existing, installed));
-        bundles.addAll(findBundlesWithFragmentsToRefresh(existing, installed));
-        return bundles;
-    }
-
-    protected Set<Bundle> findBundlesWithFragmentsToRefresh(Set<Bundle> existing,
Set<Bundle> installed) {
-        Set<Bundle> bundles = new HashSet<Bundle>();
-        Set<Bundle> oldBundles = new HashSet<Bundle>(existing);
-        oldBundles.removeAll(installed);
-        if (!oldBundles.isEmpty()) {
-            for (Bundle b : installed) {
-                String hostHeader = (String) b.getHeaders().get(Constants.FRAGMENT_HOST);
-                if (hostHeader != null) {
-                    Clause[] clauses = Parser.parseHeader(hostHeader);
-                    if (clauses != null && clauses.length > 0) {
-                        Clause path = clauses[0];
-                        for (Bundle hostBundle : oldBundles) {
-                            if (hostBundle.getSymbolicName().equals(path.getName())) {
-                                String ver = path.getAttribute(Constants.BUNDLE_VERSION_ATTRIBUTE);
-                                if (ver != null) {
-                                    VersionRange v = VersionRange.parseVersionRange(ver);
-                                    if (v.contains(hostBundle.getVersion())) {
-                                        bundles.add(hostBundle);
-                                    }
-                                } else {
-                                    bundles.add(hostBundle);
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-        }
-        return bundles;
-    }
-
-    protected Set<Bundle> findBundlesWithOptionalPackagesToRefresh(Set<Bundle>
existing, Set<Bundle> installed) {
-        // First pass: include all bundles contained in these features
-        Set<Bundle> bundles = new HashSet<Bundle>(existing);
-        bundles.removeAll(installed);
-        if (bundles.isEmpty()) {
-            return bundles;
-        }
-        // Second pass: for each bundle, check if there is any unresolved optional package
that could be resolved
-        Map<Bundle, List<Clause>> imports = new HashMap<Bundle, List<Clause>>();
-        for (Iterator<Bundle> it = bundles.iterator(); it.hasNext();) {
-            Bundle b = it.next();
-            String importsStr = (String) b.getHeaders().get(Constants.IMPORT_PACKAGE);
-            List<Clause> importsList = getOptionalImports(importsStr);
-            if (importsList.isEmpty()) {
-                it.remove();
-            } else {
-                imports.put(b, importsList);
-            }
-        }
-        if (bundles.isEmpty()) {
-            return bundles;
-        }
-        // Third pass: compute a list of packages that are exported by our bundles and see
if
-        //             some exported packages can be wired to the optional imports
-        List<Clause> exports = new ArrayList<Clause>();
-        for (Bundle b : installed) {
-            String exportsStr = (String) b.getHeaders().get(Constants.EXPORT_PACKAGE);
-            if (exportsStr != null) {
-                Clause[] exportsList = Parser.parseHeader(exportsStr);
-                exports.addAll(Arrays.asList(exportsList));
-            }
-        }
-        for (Iterator<Bundle> it = bundles.iterator(); it.hasNext();) {
-            Bundle b = it.next();
-            List<Clause> importsList = imports.get(b);
-            for (Iterator<Clause> itpi = importsList.iterator(); itpi.hasNext();) {
-                Clause pi = itpi.next();
-                boolean matching = false;
-                for (Clause pe : exports) {
-                    if (pi.getName().equals(pe.getName())) {
-                        String evStr = pe.getAttribute(Constants.VERSION_ATTRIBUTE);
-                        String ivStr = pi.getAttribute(Constants.VERSION_ATTRIBUTE);
-                        Version exported = evStr != null ? Version.parseVersion(evStr) :
Version.emptyVersion;
-                        VersionRange imported = ivStr != null ? VersionRange.parseVersionRange(ivStr)
: VersionRange.ANY_VERSION;
-                        if (imported.contains(exported)) {
-                            matching = true;
-                            break;
-                        }
-                    }
-                }
-                if (!matching) {
-                    itpi.remove();
-                }
-            }
-            if (importsList.isEmpty()) {
-                it.remove();
-            } else {
-                LOGGER.debug("Refeshing bundle {} ({}) to solve the following optional imports",
b.getSymbolicName(), b.getBundleId());
-                for (Clause p : importsList) {
-                    LOGGER.debug("    {}", p);
-                }
-
-            }
-        }
-        return bundles;
-    }
-
-    /*
-     * Get the list of optional imports from an OSGi Import-Package string
-     */
-    protected List<Clause> getOptionalImports(String importsStr) {
-        Clause[] imports = Parser.parseHeader(importsStr);
-        List<Clause> result = new LinkedList<Clause>();
-        for (Clause anImport : imports) {
-            String resolution = anImport.getDirective(Constants.RESOLUTION_DIRECTIVE);
-            if (Constants.RESOLUTION_OPTIONAL.equals(resolution)) {
-                result.add(anImport);
-            }
-        }
-        return result;
-    }
-    
-    protected void refreshPackages(Collection<Bundle> bundles) {
-        final Object refreshLock = new Object();
-        FrameworkWiring wiring = bundleContext.getBundle().adapt(FrameworkWiring.class);
-        if (wiring != null) {
-            synchronized (refreshLock) {
-                wiring.refreshBundles(bundles, new FrameworkListener() {
-                    public void frameworkEvent(FrameworkEvent event) {
-                        if (event.getType() == FrameworkEvent.PACKAGES_REFRESHED) {
-                            synchronized (refreshLock) {
-                                refreshLock.notifyAll();
-                            }
-                        }
-                    }
-                });
-                try {
-                    refreshLock.wait(refreshTimeout);
-                } catch (InterruptedException e) {
-                    LOGGER.warn(e.getMessage(), e);
-                }
-            }
-        }
-    }
-    
-
-    public void uninstall(Set<Bundle> bundles) {
-        for (Bundle b : bundles) {
-            try {
-                b.uninstall();
-            } catch (Exception e2) {
-                // Ignore
-            }
-        }
-    }
-    
-    public void uninstallById(Set<Long> bundles) throws BundleException, InterruptedException
{
-        for (long bundleId : bundles) {
-            Bundle b = bundleContext.getBundle(bundleId);
-            if (b != null) {
-                b.uninstall();
-            }
-        }
-        refreshPackages(null);
-    }
-    
-    public File getDataFile(String fileName) {
-        return bundleContext.getDataFile(fileName);
-    }
-    
-    EventAdminListener createAndRegisterEventAdminListener() {
-        EventAdminListener listener = null;
-        try {
-            getClass().getClassLoader().loadClass("org.bundles.service.event.EventAdmin");
-            listener = new EventAdminListener(bundleContext);
-        } catch (Throwable t) {
-            // Ignore, if the EventAdmin package is not available, just don't use it
-            LOGGER.debug("EventAdmin package is not available, just don't use it");
-        }
-        return listener;
-    }
-    
-    @SuppressWarnings({ "rawtypes", "unchecked" })
-    public ServiceTracker createServiceTrackerForResolverName(String resolver) throws InvalidSyntaxException
{
-        String filter = "(&(" + Constants.OBJECTCLASS + "=" + Resolver.class.getName()
+ ")(name=" + resolver + "))";
-        return new ServiceTracker(bundleContext, FrameworkUtil.createFilter(filter), null);
-    }
-
-    public void refreshBundles(Set<Bundle> existing, Set<Bundle> installed, EnumSet<Option>
options) {
-        boolean print = options.contains(Option.PrintBundlesToRefresh);
-        boolean refresh = !options.contains(Option.NoAutoRefreshBundles);
-        if (print || refresh) {
-            Set<Bundle> bundlesToRefresh = findBundlesToRefresh(existing, installed);
-            StringBuilder sb = new StringBuilder();
-            for (Bundle b : bundlesToRefresh) {
-                if (sb.length() > 0) {
-                    sb.append(", ");
-                }
-                sb.append(b.getSymbolicName()).append(" (").append(b.getBundleId()).append(")");
-            }
-            LOGGER.debug("Bundles to refresh: {}", sb.toString());
-            if (!bundlesToRefresh.isEmpty()) {
-                if (print) {
-                    if (refresh) {
-                        System.out.println("Refreshing bundles " + sb.toString());
-                    } else {
-                        System.out.println("The following bundles may need to be refreshed:
" + sb.toString());
-                    }
-                }
-                if (refresh) {
-                    LOGGER.debug("Refreshing bundles: {}", sb.toString());
-                    refreshPackages(bundlesToRefresh);
-                }
-            }
-        }
-    }
-    
-    public static class BundleInstallerResult {
-        Bundle bundle;
-        boolean isNew;
-
-        public BundleInstallerResult(Bundle bundle, boolean isNew) {
-            super();
-            this.bundle = bundle;
-            this.isNew = isNew;
-        }
+	private static final Logger LOGGER = LoggerFactory
+			.getLogger(BundleManager.class);
+	private final BundleContext bundleContext;
+	private final RegionsPersistence regionsPersistence;
+	private final long refreshTimeout;
+
+	public BundleManager(BundleContext bundleContext) {
+		this(bundleContext, null);
+	}
+
+	public BundleManager(BundleContext bundleContext,
+			RegionsPersistence regionsPersistence) {
+		this(bundleContext, regionsPersistence, 5000);
+	}
+
+	public BundleManager(BundleContext bundleContext,
+			RegionsPersistence regionsPersistence, long refreshTimeout) {
+		this.bundleContext = bundleContext;
+		this.regionsPersistence = regionsPersistence;
+		this.refreshTimeout = refreshTimeout;
+	}
+
+	public BundleInstallerResult installBundleIfNeeded(String bundleLocation,
+			int startLevel, String regionName) throws IOException,
+			BundleException {
+		BundleInstallerResult result = doInstallBundleIfNeeded(bundleLocation,
+				startLevel);
+		installToRegion(regionName, result.bundle, result.isNew);
+		return result;
+	}
+
+	private BundleInstallerResult doInstallBundleIfNeeded(
+			String bundleLocation, int startLevel) throws IOException,
+			BundleException {
+		InputStream is = getInputStreamForBundle(bundleLocation);
+		try {
+			is.mark(256 * 1024);
+			JarInputStream jar = new JarInputStream(is);
+			Manifest m = jar.getManifest();
+			if (m == null) {
+				throw new BundleException(
+						"Manifest not present in the first entry of the zip "
+								+ bundleLocation);
+			}
+			String sn = m.getMainAttributes().getValue(
+					Constants.BUNDLE_SYMBOLICNAME);
+			if (sn == null) {
+				throw new BundleException(
+						"Jar is not a bundle, no Bundle-SymbolicName "
+								+ bundleLocation);
+			}
+			// remove attributes from the symbolic name (like
+			// ;blueprint.graceperiod:=false suffix)
+			int attributeIndexSep = sn.indexOf(';');
+			if (attributeIndexSep != -1) {
+				sn = sn.substring(0, attributeIndexSep);
+			}
+			String vStr = m.getMainAttributes().getValue(
+					Constants.BUNDLE_VERSION);
+			Version v = vStr == null ? Version.emptyVersion : Version
+					.parseVersion(vStr);
+			Bundle existingBundle = findInstalled(sn, v);
+			if (existingBundle != null) {
+				LOGGER.debug("Found installed bundle: " + existingBundle);
+				return new BundleInstallerResult(existingBundle, false);
+			}
+			try {
+				is.reset();
+			} catch (IOException e) {
+				is.close();
+				is = new URL(bundleLocation).openStream();
+				// is = new BufferedInputStream(new
+				// URL(bundleLocation).openStream());
+			}
+			is = new BufferedInputStream(new FilterInputStream(is) {
+				@Override
+				public int read(byte b[], int off, int len) throws IOException {
+					if (Thread.currentThread().isInterrupted()) {
+						throw new InterruptedIOException();
+					}
+					return super.read(b, off, len);
+				}
+			});
+
+			LOGGER.debug("Installing bundle " + bundleLocation);
+			Bundle b = bundleContext.installBundle(bundleLocation, is);
+
+			if (startLevel > 0) {
+				b.adapt(BundleStartLevel.class).setStartLevel(startLevel);
+			}
+
+			return new BundleInstallerResult(b, true);
+		} finally {
+			is.close();
+		}
+	}
+
+	private Bundle findInstalled(String symbolicName, Version version) {
+		String vStr;
+		for (Bundle b : bundleContext.getBundles()) {
+			if (b.getSymbolicName() != null
+					&& b.getSymbolicName().equals(symbolicName)) {
+				vStr = (String) b.getHeaders().get(Constants.BUNDLE_VERSION);
+				Version bv = vStr == null ? Version.emptyVersion : Version
+						.parseVersion(vStr);
+				if (version.equals(bv)) {
+					return b;
+				}
+			}
+		}
+		return null;
+	}
+
+	private InputStream getInputStreamForBundle(String bundleLocation)
+			throws MalformedURLException, IOException {
+		InputStream is;
+		LOGGER.debug("Checking " + bundleLocation);
+		try {
+			int protocolIndex = bundleLocation.indexOf(":");
+			if (protocolIndex != -1) {
+				String protocol = bundleLocation.substring(0, protocolIndex);
+				waitForUrlHandler(protocol);
+			}
+			URL bundleUrl = new URL(bundleLocation);
+			is = new BufferedInputStream(bundleUrl.openStream());
+		} catch (RuntimeException e) {
+			LOGGER.error(e.getMessage());
+			throw e;
+		}
+		return is;
+	}
+
+	private void installToRegion(String region, Bundle b, boolean isNew)
+			throws BundleException {
+		if (region != null && isNew) {
+			if (regionsPersistence != null) {
+				regionsPersistence.install(b, region);
+			} else {
+				throw new RuntimeException(
+						"Unable to find RegionsPersistence service, while installing "
+								+ region);
+			}
+		}
+	}
+
+	/**
+	 * Will wait for the {@link URLStreamHandlerService} service for the
+	 * specified protocol to be registered.
+	 * 
+	 * @param protocol
+	 */
+	private void waitForUrlHandler(String protocol) {
+		try {
+			Filter filter = bundleContext.createFilter("(&("
+					+ Constants.OBJECTCLASS + "="
+					+ URLStreamHandlerService.class.getName()
+					+ ")(url.handler.protocol=" + protocol + "))");
+			if (filter == null) {
+				return;
+			}
+			ServiceTracker<URLStreamHandlerService, URLStreamHandlerService> urlHandlerTracker
= new ServiceTracker<URLStreamHandlerService, URLStreamHandlerService>(
+					bundleContext, filter, null);
+			try {
+				urlHandlerTracker.open();
+				urlHandlerTracker.waitForService(30000);
+			} catch (InterruptedException e) {
+				LOGGER.debug(
+						"Interrupted while waiting for URL handler for protocol {}.",
+						protocol);
+			} finally {
+				urlHandlerTracker.close();
+			}
+		} catch (Exception ex) {
+			LOGGER.error("Error creating service tracker.", ex);
+		}
+	}
+
+	protected Set<Bundle> findBundlesToRefresh(Set<Bundle> existing,
+			Set<Bundle> installed) {
+		Set<Bundle> bundles = new HashSet<Bundle>();
+		bundles.addAll(findBundlesWithOptionalPackagesToRefresh(existing,
+				installed));
+		bundles.addAll(findBundlesWithFragmentsToRefresh(existing, installed));
+		return bundles;
+	}
+
+	protected Set<Bundle> findBundlesWithFragmentsToRefresh(
+			Set<Bundle> existing, Set<Bundle> installed) {
+		Set<Bundle> bundles = new HashSet<Bundle>();
+		Set<Bundle> oldBundles = new HashSet<Bundle>(existing);
+		oldBundles.removeAll(installed);
+		if (!oldBundles.isEmpty()) {
+			for (Bundle b : installed) {
+				String hostHeader = (String) b.getHeaders().get(
+						Constants.FRAGMENT_HOST);
+				if (hostHeader != null) {
+					Clause[] clauses = Parser.parseHeader(hostHeader);
+					if (clauses != null && clauses.length > 0) {
+						Clause path = clauses[0];
+						for (Bundle hostBundle : oldBundles) {
+							if (hostBundle.getSymbolicName().equals(
+									path.getName())) {
+								String ver = path
+										.getAttribute(Constants.BUNDLE_VERSION_ATTRIBUTE);
+								if (ver != null) {
+									VersionRange v = VersionRange
+											.parseVersionRange(ver);
+									if (v.contains(hostBundle.getVersion())) {
+										bundles.add(hostBundle);
+									}
+								} else {
+									bundles.add(hostBundle);
+								}
+							}
+						}
+					}
+				}
+			}
+		}
+		return bundles;
+	}
+
+	protected Set<Bundle> findBundlesWithOptionalPackagesToRefresh(
+			Set<Bundle> existing, Set<Bundle> installed) {
+		// First pass: include all bundles contained in these features
+		Set<Bundle> bundles = new HashSet<Bundle>(existing);
+		bundles.removeAll(installed);
+		if (bundles.isEmpty()) {
+			return bundles;
+		}
+		// Second pass: for each bundle, check if there is any unresolved
+		// optional package that could be resolved
+		Map<Bundle, List<Clause>> imports = new HashMap<Bundle, List<Clause>>();
+		for (Iterator<Bundle> it = bundles.iterator(); it.hasNext();) {
+			Bundle b = it.next();
+			String importsStr = (String) b.getHeaders().get(
+					Constants.IMPORT_PACKAGE);
+			List<Clause> importsList = getOptionalImports(importsStr);
+			if (importsList.isEmpty()) {
+				it.remove();
+			} else {
+				imports.put(b, importsList);
+			}
+		}
+		if (bundles.isEmpty()) {
+			return bundles;
+		}
+		// Third pass: compute a list of packages that are exported by our
+		// bundles and see if
+		// some exported packages can be wired to the optional imports
+		List<Clause> exports = new ArrayList<Clause>();
+		for (Bundle b : installed) {
+			String exportsStr = (String) b.getHeaders().get(
+					Constants.EXPORT_PACKAGE);
+			if (exportsStr != null) {
+				Clause[] exportsList = Parser.parseHeader(exportsStr);
+				exports.addAll(Arrays.asList(exportsList));
+			}
+		}
+		for (Iterator<Bundle> it = bundles.iterator(); it.hasNext();) {
+			Bundle b = it.next();
+			List<Clause> importsList = imports.get(b);
+			for (Iterator<Clause> itpi = importsList.iterator(); itpi.hasNext();) {
+				Clause pi = itpi.next();
+				boolean matching = false;
+				for (Clause pe : exports) {
+					if (pi.getName().equals(pe.getName())) {
+						String evStr = pe
+								.getAttribute(Constants.VERSION_ATTRIBUTE);
+						String ivStr = pi
+								.getAttribute(Constants.VERSION_ATTRIBUTE);
+						Version exported = evStr != null ? Version
+								.parseVersion(evStr) : Version.emptyVersion;
+						VersionRange imported = ivStr != null ? VersionRange
+								.parseVersionRange(ivStr)
+								: VersionRange.ANY_VERSION;
+						if (imported.contains(exported)) {
+							matching = true;
+							break;
+						}
+					}
+				}
+				if (!matching) {
+					itpi.remove();
+				}
+			}
+			if (importsList.isEmpty()) {
+				it.remove();
+			} else {
+				LOGGER.debug(
+						"Refeshing bundle {} ({}) to solve the following optional imports",
+						b.getSymbolicName(), b.getBundleId());
+				for (Clause p : importsList) {
+					LOGGER.debug("    {}", p);
+				}
+
+			}
+		}
+		return bundles;
+	}
+
+	/*
+	 * Get the list of optional imports from an OSGi Import-Package string
+	 */
+	protected List<Clause> getOptionalImports(String importsStr) {
+		Clause[] imports = Parser.parseHeader(importsStr);
+		List<Clause> result = new LinkedList<Clause>();
+		for (Clause anImport : imports) {
+			String resolution = anImport
+					.getDirective(Constants.RESOLUTION_DIRECTIVE);
+			if (Constants.RESOLUTION_OPTIONAL.equals(resolution)) {
+				result.add(anImport);
+			}
+		}
+		return result;
+	}
+
+	protected void refreshPackages(Collection<Bundle> bundles) {
+		final Object refreshLock = new Object();
+		FrameworkWiring wiring = bundleContext.getBundle().adapt(
+				FrameworkWiring.class);
+		if (wiring != null) {
+			synchronized (refreshLock) {
+				wiring.refreshBundles(bundles, new FrameworkListener() {
+					public void frameworkEvent(FrameworkEvent event) {
+						if (event.getType() == FrameworkEvent.PACKAGES_REFRESHED) {
+							synchronized (refreshLock) {
+								refreshLock.notifyAll();
+							}
+						}
+					}
+				});
+				try {
+					refreshLock.wait(refreshTimeout);
+				} catch (InterruptedException e) {
+					LOGGER.warn(e.getMessage(), e);
+				}
+			}
+		}
+	}
+
+	public void uninstall(Set<Bundle> bundles) {
+		for (Bundle b : bundles) {
+			try {
+				b.uninstall();
+			} catch (Exception e2) {
+				// Ignore
+			}
+		}
+	}
+
+	public void uninstallById(Set<Long> bundles) throws BundleException,
+			InterruptedException {
+		for (long bundleId : bundles) {
+			Bundle b = bundleContext.getBundle(bundleId);
+			if (b != null) {
+				b.uninstall();
+			}
+		}
+		refreshPackages(null);
+	}
+
+	public File getDataFile(String fileName) {
+		return bundleContext.getDataFile(fileName);
+	}
+
+	EventAdminListener createAndRegisterEventAdminListener() {
+		EventAdminListener listener = null;
+		try {
+			getClass().getClassLoader().loadClass(
+					"org.bundles.service.event.EventAdmin");
+			listener = new EventAdminListener(bundleContext);
+		} catch (Throwable t) {
+			// Ignore, if the EventAdmin package is not available, just don't
+			// use it
+			LOGGER.debug("EventAdmin package is not available, just don't use it");
+		}
+		return listener;
+	}
+
+	@SuppressWarnings({ "rawtypes", "unchecked" })
+	public ServiceTracker createServiceTrackerForResolverName(String resolver)
+			throws InvalidSyntaxException {
+		String filter = "(&(" + Constants.OBJECTCLASS + "="
+				+ Resolver.class.getName() + ")(name=" + resolver + "))";
+		return new ServiceTracker(bundleContext,
+				FrameworkUtil.createFilter(filter), null);
+	}
+
+	public void refreshBundles(Set<Bundle> existing, Set<Bundle> installed,
+			EnumSet<Option> options) {
+		boolean print = options.contains(Option.PrintBundlesToRefresh);
+		boolean refresh = !options.contains(Option.NoAutoRefreshBundles);
+		if (print || refresh) {
+			Set<Bundle> bundlesToRefresh = findBundlesToRefresh(existing,
+					installed);
+			StringBuilder sb = new StringBuilder();
+			for (Bundle b : bundlesToRefresh) {
+				if (sb.length() > 0) {
+					sb.append(", ");
+				}
+				sb.append(b.getSymbolicName()).append(" (")
+						.append(b.getBundleId()).append(")");
+			}
+			LOGGER.debug("Bundles to refresh: {}", sb.toString());
+			if (!bundlesToRefresh.isEmpty()) {
+				if (print) {
+					if (refresh) {
+						System.out.println("Refreshing bundles "
+								+ sb.toString());
+					} else {
+						System.out
+								.println("The following bundles may need to be refreshed: "
+										+ sb.toString());
+					}
+				}
+				if (refresh) {
+					LOGGER.debug("Refreshing bundles: {}", sb.toString());
+					refreshPackages(bundlesToRefresh);
+				}
+			}
+		}
+	}
+
+	public static class BundleInstallerResult {
+		Bundle bundle;
+		boolean isNew;
+
+		public BundleInstallerResult(Bundle bundle, boolean isNew) {
+			super();
+			this.bundle = bundle;
+			this.isNew = isNew;
+		}
 
-    }
+	}
 
 }

Modified: karaf/trunk/features/core/src/main/java/org/apache/karaf/features/internal/RepositoryImpl.java
URL: http://svn.apache.org/viewvc/karaf/trunk/features/core/src/main/java/org/apache/karaf/features/internal/RepositoryImpl.java?rev=1483884&r1=1483883&r2=1483884&view=diff
==============================================================================
--- karaf/trunk/features/core/src/main/java/org/apache/karaf/features/internal/RepositoryImpl.java
(original)
+++ karaf/trunk/features/core/src/main/java/org/apache/karaf/features/internal/RepositoryImpl.java
Fri May 17 15:55:05 2013
@@ -16,8 +16,11 @@
  */
 package org.apache.karaf.features.internal;
 
+import java.io.BufferedInputStream;
+import java.io.FilterInputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.InterruptedIOException;
 import java.net.URI;
 import org.apache.karaf.features.Repository;
 import org.apache.karaf.features.internal.model.Features;
@@ -65,6 +68,15 @@ public class RepositoryImpl implements R
         if (features == null) {
             try {
                 InputStream inputStream = uri.toURL().openStream();
+                inputStream = new FilterInputStream(inputStream) {
+    				@Override
+    				public int read(byte b[], int off, int len) throws IOException {
+    					if (Thread.currentThread().isInterrupted()) {
+    						throw new InterruptedIOException();
+    					}
+    					return super.read(b, off, len);
+    				}
+    			};
                 try {
                     features = JaxbUtil.unmarshal(inputStream, false);
                 } finally {

Modified: karaf/trunk/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/MoreAction.java
URL: http://svn.apache.org/viewvc/karaf/trunk/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/MoreAction.java?rev=1483884&r1=1483883&r2=1483884&view=diff
==============================================================================
--- karaf/trunk/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/MoreAction.java
(original)
+++ karaf/trunk/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/MoreAction.java
Fri May 17 15:55:05 2013
@@ -43,6 +43,7 @@ public class MoreAction extends Abstract
             String line;
             while ((line = reader.readLine()) != null) {
                 System.out.println(line);
+                checkInterrupted();
             }
             return null;
         } else {
@@ -62,6 +63,7 @@ public class MoreAction extends Abstract
                             return null;
                         }
                         System.out.println(line);
+                        checkInterrupted();
                     } while (++count < lines - 2);
                     c = -1;
                     while (c == -1) {
@@ -97,6 +99,9 @@ public class MoreAction extends Abstract
                     }
                 } while (c != 'q');
                 return null;
+            } catch (InterruptedException ie) {
+            	log.debug("Interupted by user");
+            	return null;
             } finally {
                 term.setEchoEnabled(echo);
             }

Modified: karaf/trunk/shell/console/src/main/java/org/apache/karaf/shell/commands/basic/AbstractCommand.java
URL: http://svn.apache.org/viewvc/karaf/trunk/shell/console/src/main/java/org/apache/karaf/shell/commands/basic/AbstractCommand.java?rev=1483884&r1=1483883&r2=1483884&view=diff
==============================================================================
--- karaf/trunk/shell/console/src/main/java/org/apache/karaf/shell/commands/basic/AbstractCommand.java
(original)
+++ karaf/trunk/shell/console/src/main/java/org/apache/karaf/shell/commands/basic/AbstractCommand.java
Fri May 17 15:55:05 2013
@@ -58,5 +58,5 @@ public abstract class AbstractCommand im
     protected ActionPreparator getPreparator() throws Exception {
         return new DefaultActionPreparator();
     }
-
+    
 }

Modified: karaf/trunk/shell/console/src/main/java/org/apache/karaf/shell/console/AbstractAction.java
URL: http://svn.apache.org/viewvc/karaf/trunk/shell/console/src/main/java/org/apache/karaf/shell/console/AbstractAction.java?rev=1483884&r1=1483883&r2=1483884&view=diff
==============================================================================
--- karaf/trunk/shell/console/src/main/java/org/apache/karaf/shell/console/AbstractAction.java
(original)
+++ karaf/trunk/shell/console/src/main/java/org/apache/karaf/shell/console/AbstractAction.java
Fri May 17 15:55:05 2013
@@ -34,5 +34,17 @@ public abstract class AbstractAction imp
     }
 
     protected abstract Object doExecute() throws Exception;
+    
+    /**
+     * This is for long running commands to be interrupted by ctrl-c
+     * 
+     * @throws InterruptedException
+     */
+    public static void checkInterrupted() throws InterruptedException {
+        Thread.yield(); 
+        if (Thread.currentThread().isInterrupted()) {
+            throw new InterruptedException();
+        }
+    }
 
 }



Mime
View raw message