FELIX-2115: The api offers no way to have a timeout or cancel the resolution if it takes too long
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@912549 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/ResolverImpl.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/ResolverImpl.java
index 5f6dd3d..32b6318 100644
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/ResolverImpl.java
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/ResolverImpl.java
@@ -301,6 +301,7 @@
{
for (Iterator iter = m_addedSet.iterator(); iter.hasNext(); )
{
+ checkInterrupt();
Resource resource = (Resource) iter.next();
Capability[] caps = resource.getCapabilities();
for (int capIdx = 0; (caps != null) && (capIdx < caps.length); capIdx++)
@@ -322,6 +323,7 @@
{
for (Iterator iterator = m_resolveSet.iterator(); iterator.hasNext(); )
{
+ checkInterrupt();
Resource resource = (Resource) iterator.next();
Capability[] caps = resource.getCapabilities();
for (int capIdx = 0; (caps != null) && (capIdx < caps.length); capIdx++)
@@ -348,6 +350,7 @@
Resource[] resources = m_local.getResources();
for (int resIdx = 0; (resources != null) && (resIdx < resources.length); resIdx++)
{
+ checkInterrupt();
// We don't need to look at resources we've already looked at.
if (!m_failedSet.contains(resources[resIdx])
&& !m_resolveSet.contains(resources[resIdx]))
@@ -382,6 +385,7 @@
Resource[] resources = repos[repoIdx].getResources();
for (int resIdx = 0; (resources != null) && (resIdx < resources.length); resIdx++)
{
+ checkInterrupt();
// We don't need to look at resources we've already looked at.
if (!m_failedSet.contains(resources[resIdx])
&& !m_resolveSet.contains(resources[resIdx]))
@@ -473,6 +477,14 @@
return (best == null) ? null : best;
}
+ private void checkInterrupt()
+ {
+ if (Thread.interrupted())
+ {
+ throw new InterrupteResolutionException();
+ }
+ }
+
public synchronized void deploy(boolean start)
{
// Must resolve if not already resolved.
diff --git a/bundlerepository/src/test/java/org/apache/felix/bundlerepository/ResolverImplTest.java b/bundlerepository/src/test/java/org/apache/felix/bundlerepository/ResolverImplTest.java
index 6a14a04..5f71856 100644
--- a/bundlerepository/src/test/java/org/apache/felix/bundlerepository/ResolverImplTest.java
+++ b/bundlerepository/src/test/java/org/apache/felix/bundlerepository/ResolverImplTest.java
@@ -22,6 +22,7 @@
import junit.framework.TestCase;
+import org.osgi.service.obr.InterrupteResolutionException;
import org.osgi.service.obr.Repository;
import org.osgi.service.obr.Requirement;
import org.osgi.service.obr.Resolver;
@@ -76,6 +77,26 @@
assertTrue(resolver.resolve());
}
+ public void testResolveInterrupt() throws Exception
+ {
+ RepositoryAdminImpl repoAdmin = createRepositoryAdmin();
+ repoAdmin.addRepository(getClass().getResource("/repo_for_resolvertest.xml"));
+
+ Resolver resolver = repoAdmin.resolver();
+ resolver.add(repoAdmin.requirement("package", "(package=org.apache.felix.test.osgi)"));
+
+ Thread.currentThread().interrupt();
+ try
+ {
+ resolver.resolve();
+ fail("An excepiton should have been thrown");
+ }
+ catch (InterrupteResolutionException e)
+ {
+ // ok
+ }
+ }
+
public static void main(String[] args) throws Exception
{
new ResolverImplTest().testReferral1();
diff --git a/org.osgi.service.obr/src/main/java/org/osgi/service/obr/InterrupteResolutionException.java b/org.osgi.service.obr/src/main/java/org/osgi/service/obr/InterrupteResolutionException.java
new file mode 100644
index 0000000..c12b3c5
--- /dev/null
+++ b/org.osgi.service.obr/src/main/java/org/osgi/service/obr/InterrupteResolutionException.java
@@ -0,0 +1,48 @@
+/*
+ * 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.osgi.service.obr;
+
+/**
+ *
+ * Exception thrown by the resolver if the resolution has been interrupted.
+ */
+public class InterrupteResolutionException extends RuntimeException
+{
+
+ public InterrupteResolutionException()
+ {
+ }
+
+ public InterrupteResolutionException(String message)
+ {
+ super(message);
+ }
+
+ public InterrupteResolutionException(String message, Throwable cause)
+ {
+ super(message, cause);
+ }
+
+ public InterrupteResolutionException(Throwable cause)
+ {
+ super(cause);
+ }
+
+}
+
diff --git a/org.osgi.service.obr/src/main/java/org/osgi/service/obr/Resolver.java b/org.osgi.service.obr/src/main/java/org/osgi/service/obr/Resolver.java
index a8a552d..fd096a4 100644
--- a/org.osgi.service.obr/src/main/java/org/osgi/service/obr/Resolver.java
+++ b/org.osgi.service.obr/src/main/java/org/osgi/service/obr/Resolver.java
@@ -70,6 +70,15 @@
Resource[] getRequiredResources();
+ /**
+ * Start the resolution process and return whether the constraints have
+ * been successfully met or not.
+ * The resolution can be interrupted by a call to Thread.interrupt() at any
+ * time. The result will be to stop the resolver and throw an InterruptedException.
+ *
+ * @return <code>true</code> if the resolution has succeeded else <code>false</code>
+ * @throws InterrupteResolutionException if the resolution has been interrupted
+ */
boolean resolve();
void deploy(boolean start);