You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aries.apache.org by ma...@apache.org on 2010/09/04 23:35:01 UTC
svn commit: r992685 - in /incubator/aries/trunk/application: application-api/
application-api/src/main/java/org/apache/aries/application/management/
application-api/src/main/java/org/apache/aries/application/management/provider/
application-itests/src/...
Author: mahrwald
Date: Sat Sep 4 21:35:00 2010
New Revision: 992685
URL: http://svn.apache.org/viewvc?rev=992685&view=rev
Log:
ARIES-399: Initial commit
Added:
incubator/aries/trunk/application/application-api/src/main/java/org/apache/aries/application/management/UpdateException.java
incubator/aries/trunk/application/application-api/src/main/java/org/apache/aries/application/management/provider/
incubator/aries/trunk/application/application-api/src/main/java/org/apache/aries/application/management/provider/UpdateStrategy.java
incubator/aries/trunk/application/application-itests/src/test/java/org/apache/aries/application/runtime/itests/UpdateAppTest.java
incubator/aries/trunk/application/application-itests/src/test/java/org/apache/aries/application/runtime/itests/util/
incubator/aries/trunk/application/application-itests/src/test/java/org/apache/aries/application/runtime/itests/util/IsolationTestUtils.java
incubator/aries/trunk/application/application-runtime-isolated/src/test/
Modified:
incubator/aries/trunk/application/application-api/pom.xml
incubator/aries/trunk/application/application-api/src/main/java/org/apache/aries/application/management/AriesApplicationContextManager.java
incubator/aries/trunk/application/application-api/src/main/java/org/apache/aries/application/management/AriesApplicationManager.java
incubator/aries/trunk/application/application-api/src/main/java/org/apache/aries/application/management/BundleConverter.java
incubator/aries/trunk/application/application-api/src/main/java/org/apache/aries/application/management/BundleFrameworkManager.java
incubator/aries/trunk/application/application-itests/src/test/java/org/apache/aries/application/runtime/itests/IsolatedRuntimeTest.java
incubator/aries/trunk/application/application-management/src/main/java/org/apache/aries/application/management/impl/AriesApplicationManagerImpl.java
incubator/aries/trunk/application/application-management/src/test/java/org/apache/aries/application/management/impl/AriesApplicationManagerImplTest.java
incubator/aries/trunk/application/application-runtime-framework-management/src/main/java/org/apache/aries/application/runtime/framework/management/BundleFrameworkManagerImpl.java
incubator/aries/trunk/application/application-runtime-framework-management/src/main/resources/OSGI-INF/blueprint/bundle-framework-management.xml
incubator/aries/trunk/application/application-runtime-isolated/src/main/java/org/apache/aries/application/runtime/isolated/impl/ApplicationContextImpl.java
incubator/aries/trunk/application/application-runtime-isolated/src/main/java/org/apache/aries/application/runtime/isolated/impl/ApplicationContextManagerImpl.java
incubator/aries/trunk/application/application-runtime/src/main/java/org/apache/aries/application/runtime/impl/ApplicationContextManagerImpl.java
Modified: incubator/aries/trunk/application/application-api/pom.xml
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/application/application-api/pom.xml?rev=992685&r1=992684&r2=992685&view=diff
==============================================================================
--- incubator/aries/trunk/application/application-api/pom.xml (original)
+++ incubator/aries/trunk/application/application-api/pom.xml Sat Sep 4 21:35:00 2010
@@ -36,6 +36,7 @@
org.apache.aries.application;
org.apache.aries.application.filesystem;
org.apache.aries.application.management;
+ org.apache.aries.application.management.provider;
org.apache.aries.application.modelling
</aries.osgi.export.pkg>
</properties>
Modified: incubator/aries/trunk/application/application-api/src/main/java/org/apache/aries/application/management/AriesApplicationContextManager.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/application/application-api/src/main/java/org/apache/aries/application/management/AriesApplicationContextManager.java?rev=992685&r1=992684&r2=992685&view=diff
==============================================================================
--- incubator/aries/trunk/application/application-api/src/main/java/org/apache/aries/application/management/AriesApplicationContextManager.java (original)
+++ incubator/aries/trunk/application/application-api/src/main/java/org/apache/aries/application/management/AriesApplicationContextManager.java Sat Sep 4 21:35:00 2010
@@ -21,6 +21,7 @@ package org.apache.aries.application.man
import java.util.Set;
+import org.apache.aries.application.DeploymentMetadata;
import org.osgi.framework.BundleException;
/**
@@ -46,6 +47,13 @@ public interface AriesApplicationContext
public Set<AriesApplicationContext> getApplicationContexts();
/**
+ * Update the AriesApplication and return an updated application context.
+ * @throws UpdateException if the update failed
+ * @throws IllegalArgumentException if the app is not currently installed
+ */
+ public AriesApplicationContext update(AriesApplication app, DeploymentMetadata oldMetadata) throws UpdateException;
+
+ /**
* Remove the provided AriesApplicationContext from the running system.
*
* @param app the application to remove.
Modified: incubator/aries/trunk/application/application-api/src/main/java/org/apache/aries/application/management/AriesApplicationManager.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/application/application-api/src/main/java/org/apache/aries/application/management/AriesApplicationManager.java?rev=992685&r1=992684&r2=992685&view=diff
==============================================================================
--- incubator/aries/trunk/application/application-api/src/main/java/org/apache/aries/application/management/AriesApplicationManager.java (original)
+++ incubator/aries/trunk/application/application-api/src/main/java/org/apache/aries/application/management/AriesApplicationManager.java Sat Sep 4 21:35:00 2010
@@ -22,6 +22,7 @@ package org.apache.aries.application.man
import java.net.URL;
+import org.apache.aries.application.DeploymentMetadata;
import org.apache.aries.application.filesystem.IDirectory;
import org.osgi.framework.BundleException;
@@ -88,6 +89,19 @@ public interface AriesApplicationManager
public void removeApplicationListener(AriesApplicationListener l);
/**
+ * Update an application's deployment and apply the changes to the runtime if the application is deployed
+ * @param app The application to change
+ * @param depMf The new deployment metadata
+ * @return {@link AriesApplicationContext} Returns a new application context if the app
+ * is currently deployed, or null if the app is not currently installed
+ *
+ * @throws UpdateException if the deployment changes could not be effected in the runtime
+ * @throws IllegalArgumentException if the deployment metadata does not correspond to the same application
+ * (same symbolic name and same version)
+ */
+ public AriesApplicationContext update(AriesApplication app, DeploymentMetadata depMf) throws UpdateException;
+
+ /**
* Resolve an AriesApplication against a set of constraints. Each ResolveConstraint
* represents a single proposed change to the content of an application.
* If no constraints are given, a default resolution will be performed.
Modified: incubator/aries/trunk/application/application-api/src/main/java/org/apache/aries/application/management/BundleConverter.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/application/application-api/src/main/java/org/apache/aries/application/management/BundleConverter.java?rev=992685&r1=992684&r2=992685&view=diff
==============================================================================
--- incubator/aries/trunk/application/application-api/src/main/java/org/apache/aries/application/management/BundleConverter.java (original)
+++ incubator/aries/trunk/application/application-api/src/main/java/org/apache/aries/application/management/BundleConverter.java Sat Sep 4 21:35:00 2010
@@ -19,8 +19,6 @@
package org.apache.aries.application.management;
-import java.io.InputStream;
-
import org.apache.aries.application.filesystem.IDirectory;
import org.apache.aries.application.filesystem.IFile;
Modified: incubator/aries/trunk/application/application-api/src/main/java/org/apache/aries/application/management/BundleFrameworkManager.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/application/application-api/src/main/java/org/apache/aries/application/management/BundleFrameworkManager.java?rev=992685&r1=992684&r2=992685&view=diff
==============================================================================
--- incubator/aries/trunk/application/application-api/src/main/java/org/apache/aries/application/management/BundleFrameworkManager.java (original)
+++ incubator/aries/trunk/application/application-api/src/main/java/org/apache/aries/application/management/BundleFrameworkManager.java Sat Sep 4 21:35:00 2010
@@ -20,9 +20,13 @@
package org.apache.aries.application.management;
import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleException;
+import org.apache.aries.application.DeploymentContent;
+import org.apache.aries.application.DeploymentMetadata;
import org.apache.aries.application.management.BundleRepository.BundleSuggestion;
public interface BundleFrameworkManager
@@ -66,6 +70,20 @@ public interface BundleFrameworkManager
AriesApplication app)
throws BundleException;
+ public boolean allowsUpdate(DeploymentMetadata newMetadata, DeploymentMetadata oldMetadata);
+
+ public interface BundleLocator {
+ public Map<DeploymentContent, BundleSuggestion> suggestBundle(Collection<DeploymentContent> bundles) throws ContextException;
+ }
+
+ public void updateBundles(
+ DeploymentMetadata newMetadata,
+ DeploymentMetadata oldMetadata,
+ AriesApplication app,
+ BundleLocator locator,
+ Set<Bundle> bundles,
+ boolean startBundles) throws UpdateException;
+
/**
* Starts a previously installed bundle
* @param b
Added: incubator/aries/trunk/application/application-api/src/main/java/org/apache/aries/application/management/UpdateException.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/application/application-api/src/main/java/org/apache/aries/application/management/UpdateException.java?rev=992685&view=auto
==============================================================================
--- incubator/aries/trunk/application/application-api/src/main/java/org/apache/aries/application/management/UpdateException.java (added)
+++ incubator/aries/trunk/application/application-api/src/main/java/org/apache/aries/application/management/UpdateException.java Sat Sep 4 21:35:00 2010
@@ -0,0 +1,41 @@
+/*
+ * 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.aries.application.management;
+
+public class UpdateException extends Exception {
+ private static final long serialVersionUID = -6118824314732969652L;
+
+ private Exception rollbackFailure;
+ private boolean rolledBack;
+
+ public UpdateException(String message, Exception e, boolean rolledBack, Exception rollbackException) {
+ super(message, e);
+
+ this.rollbackFailure = rollbackException;
+ this.rolledBack = rolledBack;
+ }
+
+ public boolean hasRolledBack() {
+ return rolledBack;
+ }
+
+ public Exception getRollbackException() {
+ return rollbackFailure;
+ }
+}
Added: incubator/aries/trunk/application/application-api/src/main/java/org/apache/aries/application/management/provider/UpdateStrategy.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/application/application-api/src/main/java/org/apache/aries/application/management/provider/UpdateStrategy.java?rev=992685&view=auto
==============================================================================
--- incubator/aries/trunk/application/application-api/src/main/java/org/apache/aries/application/management/provider/UpdateStrategy.java (added)
+++ incubator/aries/trunk/application/application-api/src/main/java/org/apache/aries/application/management/provider/UpdateStrategy.java Sat Sep 4 21:35:00 2010
@@ -0,0 +1,101 @@
+/*
+ * 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.aries.application.management.provider;
+
+import java.util.Collection;
+import java.util.Map;
+
+import org.apache.aries.application.DeploymentContent;
+import org.apache.aries.application.DeploymentMetadata;
+import org.apache.aries.application.management.AriesApplication;
+import org.apache.aries.application.management.BundleFramework;
+import org.apache.aries.application.management.BundleRepository;
+import org.apache.aries.application.management.ContextException;
+import org.apache.aries.application.management.UpdateException;
+import org.apache.aries.application.management.BundleRepository.BundleSuggestion;
+import org.osgi.framework.Bundle;
+
+/**
+ * Plug point for update implementation
+ */
+public interface UpdateStrategy {
+
+ /**
+ * Are the two deployments subject to update or do they require full reinstall
+ */
+ public boolean allowsUpdate(DeploymentMetadata newMetadata, DeploymentMetadata oldMetadata);
+
+ /**
+ * Update an application
+ */
+ public void update(UpdateInfo paramUpdateInfo) throws UpdateException;
+
+ /**
+ * Representation for an update request
+ */
+ public static interface UpdateInfo
+ {
+ /**
+ * Find {@link BundleSuggestion} objects for new bundle requests
+ */
+ public Map<DeploymentContent, BundleRepository.BundleSuggestion> suggestBundle(Collection<DeploymentContent> bundles)
+ throws ContextException;
+
+ /**
+ * Register a new bundle with the application (i.e. a new bundle was installed)
+ */
+ public void register(Bundle bundle);
+
+ /**
+ * Unregister a bundle from the application (i.e. the bundle was uninstalled)
+ */
+ public void unregister(Bundle bundle);
+
+ /**
+ * Get a {@link BundleFramework} object for the shared framework
+ */
+ public BundleFramework getSharedFramework();
+
+ /**
+ * Get a {@link BundleFramework} object for the isolated framework corresponding
+ * to the application to be updated
+ */
+ public BundleFramework getAppFramework();
+
+ /**
+ * Get the {@link DeploymentMetadata} that is currently active and to be phased out
+ */
+ public DeploymentMetadata getOldMetadata();
+
+ /**
+ * Get the {@link DeploymentMetadata} that is to be activated
+ */
+ public DeploymentMetadata getNewMetadata();
+
+ /**
+ * Get the {@link AriesApplication} object being updated
+ */
+ public AriesApplication getApplication();
+
+ /**
+ * Whether to start any newly installed bundles
+ */
+ public boolean startBundles();
+ }
+}
Modified: incubator/aries/trunk/application/application-itests/src/test/java/org/apache/aries/application/runtime/itests/IsolatedRuntimeTest.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/application/application-itests/src/test/java/org/apache/aries/application/runtime/itests/IsolatedRuntimeTest.java?rev=992685&r1=992684&r2=992685&view=diff
==============================================================================
--- incubator/aries/trunk/application/application-itests/src/test/java/org/apache/aries/application/runtime/itests/IsolatedRuntimeTest.java (original)
+++ incubator/aries/trunk/application/application-itests/src/test/java/org/apache/aries/application/runtime/itests/IsolatedRuntimeTest.java Sat Sep 4 21:35:00 2010
@@ -18,33 +18,20 @@
*/
package org.apache.aries.application.runtime.itests;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
+import static org.junit.Assert.*;
import static org.ops4j.pax.exam.CoreOptions.equinox;
import static org.ops4j.pax.exam.CoreOptions.options;
import static org.ops4j.pax.exam.CoreOptions.systemProperty;
import java.io.File;
import java.io.FileOutputStream;
-import java.lang.reflect.Method;
-import java.net.MalformedURLException;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Hashtable;
-import java.util.Set;
-import java.util.jar.Attributes;
-
-import org.apache.aries.application.Content;
-import org.apache.aries.application.DeploymentContent;
import org.apache.aries.application.VersionRange;
import org.apache.aries.application.management.AriesApplication;
import org.apache.aries.application.management.AriesApplicationContext;
import org.apache.aries.application.management.AriesApplicationManager;
-import org.apache.aries.application.management.BundleRepository;
import org.apache.aries.application.management.RepositoryGenerator;
import org.apache.aries.application.management.ResolveConstraint;
-import org.apache.aries.application.modelling.ModelledResource;
-import org.apache.aries.application.modelling.utils.ModellingManager;
+import org.apache.aries.application.runtime.itests.util.IsolationTestUtils;
import org.apache.aries.application.utils.filesystem.FileSystem;
import org.apache.aries.application.utils.manifest.ManifestHeaderProcessor;
import org.apache.aries.isolated.sample.HelloWorld;
@@ -56,15 +43,6 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.ops4j.pax.exam.Option;
import org.ops4j.pax.exam.junit.JUnit4TestRunner;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.BundleException;
-import org.osgi.framework.Constants;
-import org.osgi.framework.Filter;
-import org.osgi.framework.FrameworkUtil;
-import org.osgi.framework.Version;
-import org.osgi.service.framework.CompositeBundle;
-import org.osgi.util.tracker.ServiceTracker;
@RunWith(JUnit4TestRunner.class)
public class IsolatedRuntimeTest extends AbstractIntegrationTest {
@@ -181,6 +159,8 @@ public class IsolatedRuntimeTest extends
ctx.stop();
manager.uninstall(ctx);
+
+ assertNull(IsolationTestUtils.findIsolatedAppBundleContext(bundleContext, "org.apache.aries.sample2"));
ctx = manager.install(app);
ctx.start();
@@ -206,67 +186,7 @@ public class IsolatedRuntimeTest extends
AriesApplicationManager manager = getOsgiService(AriesApplicationManager.class);
AriesApplication app = manager.createApplication(FileSystem.getFSRoot(new File("test2.eba")));
- BundleRepository repo = new BundleRepository() {
- public int getCost() {
- return 1;
- }
-
- public BundleSuggestion suggestBundleToUse(DeploymentContent content) {
- if (content.getContentName().equals("org.apache.aries.isolated.sample")) {
- return new BundleSuggestion() {
-
- public Bundle install(BundleContext ctx, AriesApplication app) throws BundleException {
- File f = new File("sample_2.0.0.jar");
- try {
- return ctx.installBundle(f.toURL().toString());
- } catch (MalformedURLException mue) {
- throw new RuntimeException(mue);
- }
- }
-
- public Version getVersion() {
- return new Version("2.0.0");
- }
-
- public Set<Content> getImportPackage() {
- return Collections.emptySet();
- }
-
- public Set<Content> getExportPackage() {
- return Collections.emptySet();
- }
-
- public int getCost() {
- return 1;
- }
- };
- } else {
- return null;
- }
- }
- };
-
- Hashtable<String, String> props = new Hashtable<String,String>();
- props.put(BundleRepository.REPOSITORY_SCOPE, BundleRepository.GLOBAL_SCOPE);
-
- bundleContext.registerService(BundleRepository.class.getName(), repo, props);
-
- RepositoryGenerator repoGen = getOsgiService(RepositoryGenerator.class);
- RepositoryAdmin repoAdmin = getOsgiService(RepositoryAdmin.class);
-
- Attributes attrs = new Attributes();
- attrs.putValue("Bundle-ManifestVersion", "2");
- attrs.putValue("Bundle-Version", "2.0.0");
- attrs.putValue("Bundle-SymbolicName", "org.apache.aries.isolated.sample");
- attrs.putValue("Manifest-Version", "1");
-
- ModelledResource res = ModellingManager.getModelledResource(
- new File("sample_2.0.0.jar").toURI().toString(),
- attrs,
- Collections.EMPTY_LIST, Collections.EMPTY_LIST);
-
- repoGen.generateRepository("repo.xml", Arrays.asList(res), new FileOutputStream("repo.xml"));
- repoAdmin.addRepository(new File("repo.xml").toURI().toString());
+ IsolationTestUtils.prepareSampleBundleV2(bundleContext, getOsgiService(RepositoryGenerator.class), getOsgiService(RepositoryAdmin.class));
AriesApplication newApp = manager.resolve(app, new ResolveConstraint() {
public String getBundleName() {
@@ -292,54 +212,9 @@ public class IsolatedRuntimeTest extends
private void assertHelloWorldService(String appName, String message) throws Exception
{
- BundleContext appContext = getAppIsolatedBundleContext(appName);
-
- if (appContext != null) {
- // Dive into the context and pull out the composite bundle for the app
- Filter osgiFilter = FrameworkUtil.createFilter("(" + Constants.OBJECTCLASS + "=" + HelloWorld.class.getName() + ")");
- ServiceTracker tracker = new ServiceTracker(appContext,
- osgiFilter,
- null);
- tracker.open();
-
- Object hw = tracker.waitForService(DEFAULT_TIMEOUT);
-
- tracker.close();
-
- // We can cast to our version of HelloWorld as it is in a different classloader
- // so reflect into it to get the single method
- Class returnClass = hw.getClass();
- Method method = returnClass.getDeclaredMethod("getMessage",null);
- String result = (String)method.invoke(hw);
-
- assertEquals(message, result);
- }
- else {
- fail("No service found inside application framework");
- }
-
- }
-
-
- private BundleContext getAppIsolatedBundleContext(String appName)
- {
- for (Bundle sharedBundle : bundleContext.getBundles())
- {
- if (sharedBundle.getSymbolicName().equals("shared.bundle.framework"))
- {
- BundleContext sharedContext = ((CompositeBundle)sharedBundle).getCompositeFramework().getBundleContext();
- for (Bundle appBundle : sharedContext.getBundles())
- {
- if (appBundle.getSymbolicName().equals(appName))
- {
- return ((CompositeBundle)appBundle).getCompositeFramework().getBundleContext();
- }
- }
- break;
- }
- }
-
- return null;
+ HelloWorld hw = IsolationTestUtils.findHelloWorldService(bundleContext, appName);
+ assertNotNull(hw);
+ assertEquals(message, hw.getMessage());
}
@org.ops4j.pax.exam.junit.Configuration
Added: incubator/aries/trunk/application/application-itests/src/test/java/org/apache/aries/application/runtime/itests/UpdateAppTest.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/application/application-itests/src/test/java/org/apache/aries/application/runtime/itests/UpdateAppTest.java?rev=992685&view=auto
==============================================================================
--- incubator/aries/trunk/application/application-itests/src/test/java/org/apache/aries/application/runtime/itests/UpdateAppTest.java (added)
+++ incubator/aries/trunk/application/application-itests/src/test/java/org/apache/aries/application/runtime/itests/UpdateAppTest.java Sat Sep 4 21:35:00 2010
@@ -0,0 +1,280 @@
+/*
+ * 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.aries.application.runtime.itests;
+
+import static org.junit.Assert.*;
+import static org.ops4j.pax.exam.CoreOptions.equinox;
+import static org.ops4j.pax.exam.CoreOptions.options;
+import static org.ops4j.pax.exam.CoreOptions.systemProperty;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.util.Hashtable;
+import java.util.Map;
+
+import org.apache.aries.application.DeploymentContent;
+import org.apache.aries.application.DeploymentMetadata;
+import org.apache.aries.application.VersionRange;
+import org.apache.aries.application.management.AriesApplication;
+import org.apache.aries.application.management.AriesApplicationContext;
+import org.apache.aries.application.management.AriesApplicationManager;
+import org.apache.aries.application.management.BundleFramework;
+import org.apache.aries.application.management.RepositoryGenerator;
+import org.apache.aries.application.management.ResolveConstraint;
+import org.apache.aries.application.management.UpdateException;
+import org.apache.aries.application.management.BundleRepository.BundleSuggestion;
+import org.apache.aries.application.management.provider.UpdateStrategy;
+import org.apache.aries.application.runtime.itests.util.IsolationTestUtils;
+import org.apache.aries.application.utils.filesystem.FileSystem;
+import org.apache.aries.application.utils.manifest.ManifestHeaderProcessor;
+import org.apache.aries.isolated.sample.HelloWorld;
+import org.apache.aries.unittest.fixture.ArchiveFixture;
+import org.apache.aries.unittest.fixture.ArchiveFixture.ZipFixture;
+import org.apache.felix.bundlerepository.RepositoryAdmin;
+import org.junit.Before;
+import org.junit.Test;
+import org.ops4j.pax.exam.Option;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+
+public class UpdateAppTest extends AbstractIntegrationTest {
+ private static final String SAMPLE_APP_NAME = "org.apache.aries.sample2";
+ /* Use @Before not @BeforeClass so as to ensure that these resources
+ * are created in the paxweb temp directory, and not in the svn tree
+ */
+ static boolean createdApplications = false;
+ @Before
+ public static void createApplications() throws Exception {
+
+ if (createdApplications) {
+ return;
+ }
+
+ ZipFixture testEba = ArchiveFixture.newZip()
+ .binary("META-INF/APPLICATION.MF",
+ UpdateAppTest.class.getClassLoader().getResourceAsStream("isolated/APPLICATION.MF"))
+ .jar("sample.jar")
+ .manifest().symbolicName("org.apache.aries.isolated.sample")
+ .attribute("Bundle-Version", "1.0.0")
+ .end()
+ .binary("org/apache/aries/isolated/sample/HelloWorld.class",
+ UpdateAppTest.class.getClassLoader().getResourceAsStream("org/apache/aries/isolated/sample/HelloWorld.class"))
+ .binary("org/apache/aries/isolated/sample/HelloWorldImpl.class",
+ UpdateAppTest.class.getClassLoader().getResourceAsStream("org/apache/aries/isolated/sample/HelloWorldImpl.class"))
+ .binary("OSGI-INF/blueprint/aries.xml",
+ UpdateAppTest.class.getClassLoader().getResourceAsStream("isolated/sample-blueprint.xml"))
+ .end();
+
+ FileOutputStream fout = new FileOutputStream("test.eba");
+ testEba.writeOut(fout);
+ fout.close();
+
+ ZipFixture sample2 = ArchiveFixture.newJar()
+ .manifest().symbolicName("org.apache.aries.isolated.sample")
+ .attribute("Bundle-Version", "2.0.0")
+ .end()
+ .binary("org/apache/aries/isolated/sample/HelloWorld.class",
+ IsolatedRuntimeTest.class.getClassLoader().getResourceAsStream("org/apache/aries/isolated/sample/HelloWorld.class"))
+ .binary("org/apache/aries/isolated/sample/HelloWorldImpl.class",
+ IsolatedRuntimeTest.class.getClassLoader().getResourceAsStream("org/apache/aries/isolated/sample/HelloWorldImpl.class"))
+ .binary("OSGI-INF/blueprint/aries.xml",
+ IsolatedRuntimeTest.class.getClassLoader().getResourceAsStream("isolated/sample2-blueprint.xml"))
+ .end();
+
+ fout = new FileOutputStream("sample_2.0.0.jar");
+ sample2.writeOut(fout);
+ fout.close();
+
+ createdApplications = true;
+ }
+
+ @Test
+ public void testFullUpdate() throws Exception {
+ AriesApplicationManager manager = getOsgiService(AriesApplicationManager.class);
+ AriesApplication app = setupApp();
+
+ updateApp(manager, app);
+
+ assertAppMessage("hello brave new world");
+ }
+
+ @Test
+ public void testFineUpdate() throws Exception {
+ AriesApplicationManager manager = getOsgiService(AriesApplicationManager.class);
+ AriesApplication app = setupApp();
+
+ BundleContext oldCtx = IsolationTestUtils.findIsolatedAppBundleContext(bundleContext, SAMPLE_APP_NAME);
+
+ installMockUpdateStrategy();
+ updateApp(manager, app);
+
+ BundleContext newCtx = IsolationTestUtils.findIsolatedAppBundleContext(bundleContext, SAMPLE_APP_NAME);
+ assertAppMessage("hello brave new world");
+
+ assertTrue("We bounced the app where the update was supposed to do an update in place", oldCtx == newCtx);
+ }
+
+ @Test
+ public void testUpdateThenStart() throws Exception
+ {
+ AriesApplicationManager manager = getOsgiService(AriesApplicationManager.class);
+ AriesApplication app = manager.createApplication(FileSystem.getFSRoot(new File("test.eba")));
+ AriesApplicationContext ctx = manager.install(app);
+ app = ctx.getApplication();
+
+ BundleContext oldCtx = IsolationTestUtils.findIsolatedAppBundleContext(bundleContext, SAMPLE_APP_NAME);
+
+ installMockUpdateStrategy();
+ ctx = updateApp(manager, app);
+
+ BundleContext newCtx = IsolationTestUtils.findIsolatedAppBundleContext(bundleContext, SAMPLE_APP_NAME);
+
+ assertNull("App is not started yet but HelloWorld service is already there",
+ IsolationTestUtils.findHelloWorldService(bundleContext, SAMPLE_APP_NAME));
+
+ ctx.start();
+
+ assertAppMessage("hello brave new world");
+
+ assertTrue("We bounced the app where the update was supposed to do an update in place", oldCtx == newCtx);
+ }
+
+ private void installMockUpdateStrategy()
+ {
+ bundleContext.registerService(UpdateStrategy.class.getName(), new UpdateStrategy() {
+
+ public boolean allowsUpdate(DeploymentMetadata newMetadata, DeploymentMetadata oldMetadata) {
+ return true;
+ }
+
+ public void update(UpdateInfo info) throws UpdateException {
+ BundleFramework fwk = info.getAppFramework();
+
+ Bundle old = null;
+ for (Bundle b : fwk.getBundles()) {
+ if (b.getSymbolicName().equals("org.apache.aries.isolated.sample")) {
+ old = b;
+ break;
+ }
+ }
+
+ if (old == null) throw new RuntimeException("Could not find old bundle");
+
+ try {
+ info.unregister(old);
+ fwk.uninstall(old);
+
+ // only contains one element at most
+ Map<DeploymentContent, BundleSuggestion> suggestions =
+ info.suggestBundle(info.getNewMetadata().getApplicationDeploymentContents());
+
+ BundleSuggestion toInstall = suggestions.values().iterator().next();
+
+ Bundle newBundle = fwk.install(toInstall, info.getApplication());
+ info.register(newBundle);
+ if (info.startBundles()) fwk.start(newBundle);
+
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ }, new Hashtable<String, String>());
+ }
+
+ private AriesApplication setupApp() throws Exception {
+ AriesApplicationManager manager = getOsgiService(AriesApplicationManager.class);
+ AriesApplication app = manager.createApplication(FileSystem.getFSRoot(new File("test.eba")));
+ AriesApplicationContext ctx = manager.install(app);
+ app = ctx.getApplication();
+
+ ctx.start();
+ assertAppMessage("hello world");
+
+ return app;
+ }
+
+ private AriesApplicationContext updateApp(AriesApplicationManager manager, AriesApplication app) throws Exception {
+ IsolationTestUtils.prepareSampleBundleV2(bundleContext, getOsgiService(RepositoryGenerator.class), getOsgiService(RepositoryAdmin.class));
+
+ AriesApplication newApp = manager.resolve(app, new ResolveConstraint() {
+ public String getBundleName() {
+ return "org.apache.aries.isolated.sample";
+ }
+
+ public VersionRange getVersionRange() {
+ return ManifestHeaderProcessor.parseVersionRange("[2.0.0,2.0.0]", true);
+ }
+ });
+
+ return manager.update(app, newApp.getDeploymentMetadata());
+ }
+
+ private void assertAppMessage(String message) throws Exception {
+ HelloWorld hw = IsolationTestUtils.findHelloWorldService(bundleContext, SAMPLE_APP_NAME);
+ assertNotNull(hw);
+ assertEquals(message, hw.getMessage());
+ }
+
+ @org.ops4j.pax.exam.junit.Configuration
+ public static Option[] configuration() {
+ Option[] options = options(
+ // Log
+ mavenBundle("org.ops4j.pax.logging", "pax-logging-api"),
+ mavenBundle("org.ops4j.pax.logging", "pax-logging-service"),
+ // Felix Config Admin
+ mavenBundle("org.apache.felix", "org.apache.felix.configadmin"),
+ // Felix mvn url handler
+ mavenBundle("org.ops4j.pax.url", "pax-url-mvn"),
+
+ // this is how you set the default log level when using pax
+ // logging (logProfile)
+ systemProperty("org.ops4j.pax.logging.DefaultServiceLog.level").value("DEBUG"),
+
+ // Bundles
+ mavenBundle("org.apache.aries.transaction", "org.apache.aries.transaction.blueprint"),
+ mavenBundle("org.apache.aries.application", "org.apache.aries.application.api"),
+ mavenBundle("org.apache.aries.application", "org.apache.aries.application.utils"),
+ mavenBundle("org.apache.aries.application", "org.apache.aries.application.runtime.isolated"),
+ mavenBundle("org.apache.aries.application", "org.apache.aries.application.management"),
+ mavenBundle("org.apache.aries.application", "org.apache.aries.application.deployment.management"),
+ mavenBundle("org.apache.aries.application", "org.apache.aries.application.modeller"),
+ mavenBundle("org.apache.felix", "org.apache.felix.bundlerepository"),
+ mavenBundle("org.apache.aries.application", "org.apache.aries.application.resolver.obr"),
+ mavenBundle("org.apache.aries.application", "org.apache.aries.application.runtime.framework"),
+ mavenBundle("org.apache.aries.application", "org.apache.aries.application.runtime.framework.management"),
+ mavenBundle("org.apache.aries.application", "org.apache.aries.application.runtime.repository"),
+ mavenBundle("org.apache.aries", "org.apache.aries.util"),
+ mavenBundle("org.apache.aries.blueprint", "org.apache.aries.blueprint"),
+ mavenBundle("org.osgi", "org.osgi.compendium"),
+ mavenBundle("org.apache.geronimo.specs","geronimo-jta_1.1_spec"),
+ mavenBundle("org.apache.aries.testsupport", "org.apache.aries.testsupport.unit"),
+
+ // new VMOption("-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5011"),
+
+ /*
+ * and add these imports:
+ import static org.ops4j.pax.exam.CoreOptions.waitForFrameworkStartup;
+ import static org.ops4j.pax.exam.container.def.PaxRunnerOptions.vmOption;
+ */
+ equinox().version("3.5.0"));
+ options = updateOptions(options);
+ return options;
+ }
+}
Added: incubator/aries/trunk/application/application-itests/src/test/java/org/apache/aries/application/runtime/itests/util/IsolationTestUtils.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/application/application-itests/src/test/java/org/apache/aries/application/runtime/itests/util/IsolationTestUtils.java?rev=992685&view=auto
==============================================================================
--- incubator/aries/trunk/application/application-itests/src/test/java/org/apache/aries/application/runtime/itests/util/IsolationTestUtils.java (added)
+++ incubator/aries/trunk/application/application-itests/src/test/java/org/apache/aries/application/runtime/itests/util/IsolationTestUtils.java Sat Sep 4 21:35:00 2010
@@ -0,0 +1,186 @@
+/*
+ * 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.aries.application.runtime.itests.util;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.lang.reflect.Method;
+import java.net.MalformedURLException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Hashtable;
+import java.util.Set;
+import java.util.jar.Attributes;
+
+import org.apache.aries.application.Content;
+import org.apache.aries.application.DeploymentContent;
+import org.apache.aries.application.management.AriesApplication;
+import org.apache.aries.application.management.BundleRepository;
+import org.apache.aries.application.management.RepositoryGenerator;
+import org.apache.aries.application.modelling.ModelledResource;
+import org.apache.aries.application.modelling.utils.ModellingManager;
+import org.apache.aries.isolated.sample.HelloWorld;
+import org.apache.felix.bundlerepository.RepositoryAdmin;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.Constants;
+import org.osgi.framework.Filter;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.Version;
+import org.osgi.service.framework.CompositeBundle;
+import org.osgi.util.tracker.ServiceTracker;
+
+public class IsolationTestUtils {
+ public static final long DEFAULT_TIMEOUT = 10000;
+
+ /**
+ * Retrieve the bundle context for an isolated application framework
+ */
+ public static BundleContext findIsolatedAppBundleContext(BundleContext runtimeCtx, String appName)
+ {
+ for (Bundle sharedBundle : runtimeCtx.getBundles())
+ {
+ if (sharedBundle.getSymbolicName().equals("shared.bundle.framework"))
+ {
+ BundleContext sharedContext = ((CompositeBundle)sharedBundle).getCompositeFramework().getBundleContext();
+ for (Bundle appBundle : sharedContext.getBundles())
+ {
+ if (appBundle.getSymbolicName().equals(appName))
+ {
+ return ((CompositeBundle)appBundle).getCompositeFramework().getBundleContext();
+ }
+ }
+ break;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Set up the necessary resources for installing version 2 of the org.apache.aries.isolated.sample sample bundle,
+ * which returns the message "hello brave new world" rather than "hello world"
+ *
+ * This means setting up a global bundle repository as well as a global OBR repository
+ */
+ public static void prepareSampleBundleV2(BundleContext runtimeCtx, RepositoryGenerator repoGen, RepositoryAdmin repoAdmin)
+ throws Exception
+ {
+ BundleRepository repo = new BundleRepository() {
+ public int getCost() {
+ return 1;
+ }
+
+ public BundleSuggestion suggestBundleToUse(DeploymentContent content) {
+ if (content.getContentName().equals("org.apache.aries.isolated.sample")) {
+ return new BundleSuggestion() {
+
+ public Bundle install(BundleContext ctx, AriesApplication app) throws BundleException {
+ File f = new File("sample_2.0.0.jar");
+ try {
+ return ctx.installBundle(f.toURL().toString());
+ } catch (MalformedURLException mue) {
+ throw new RuntimeException(mue);
+ }
+ }
+
+ public Version getVersion() {
+ return new Version("2.0.0");
+ }
+
+ public Set<Content> getImportPackage() {
+ return Collections.emptySet();
+ }
+
+ public Set<Content> getExportPackage() {
+ return Collections.emptySet();
+ }
+
+ public int getCost() {
+ return 1;
+ }
+ };
+ } else {
+ return null;
+ }
+ }
+ };
+
+ Hashtable<String, String> props = new Hashtable<String,String>();
+ props.put(BundleRepository.REPOSITORY_SCOPE, BundleRepository.GLOBAL_SCOPE);
+
+ runtimeCtx.registerService(BundleRepository.class.getName(), repo, props);
+
+ Attributes attrs = new Attributes();
+ attrs.putValue("Bundle-ManifestVersion", "2");
+ attrs.putValue("Bundle-Version", "2.0.0");
+ attrs.putValue("Bundle-SymbolicName", "org.apache.aries.isolated.sample");
+ attrs.putValue("Manifest-Version", "1");
+
+ ModelledResource res = ModellingManager.getModelledResource(
+ new File("sample_2.0.0.jar").toURI().toString(),
+ attrs,
+ Collections.EMPTY_LIST, Collections.EMPTY_LIST);
+
+ repoGen.generateRepository("repo.xml", Arrays.asList(res), new FileOutputStream("repo.xml"));
+ repoAdmin.addRepository(new File("repo.xml").toURI().toString());
+ }
+
+ /**
+ * Find the {@link HelloWorld} service for the isolated app
+ * @return the service object, suitably proxied so that it can be actually used, or null if the service is not present
+ * @throws IllegalStateException if the isolated app is not installed
+ */
+ public static HelloWorld findHelloWorldService(BundleContext runtimeCtx, String appName) throws Exception
+ {
+ BundleContext appContext = IsolationTestUtils.findIsolatedAppBundleContext(runtimeCtx, appName);
+
+ if (appContext != null) {
+ // Dive into the context and pull out the composite bundle for the app
+ Filter osgiFilter = FrameworkUtil.createFilter("(" + Constants.OBJECTCLASS + "=" + HelloWorld.class.getName() + ")");
+ ServiceTracker tracker = new ServiceTracker(appContext,
+ osgiFilter,
+ null);
+
+ tracker.open();
+ final Object hw = tracker.waitForService(DEFAULT_TIMEOUT);
+ tracker.close();
+
+ if (hw != null) {
+ // proxy because the class space between the sample app and the test bundle is not consistent
+ return new HelloWorld() {
+ public String getMessage() {
+ try {
+ Method m = hw.getClass().getMethod("getMessage");
+ return (String) m.invoke(hw);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ };
+ } else {
+ return null;
+ }
+
+ } else {
+ throw new IllegalStateException("Expected to find isolated app ctx, but didn't");
+ }
+ }
+}
Modified: incubator/aries/trunk/application/application-management/src/main/java/org/apache/aries/application/management/impl/AriesApplicationManagerImpl.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/application/application-management/src/main/java/org/apache/aries/application/management/impl/AriesApplicationManagerImpl.java?rev=992685&r1=992684&r2=992685&view=diff
==============================================================================
--- incubator/aries/trunk/application/application-management/src/main/java/org/apache/aries/application/management/impl/AriesApplicationManagerImpl.java (original)
+++ incubator/aries/trunk/application/application-management/src/main/java/org/apache/aries/application/management/impl/AriesApplicationManagerImpl.java Sat Sep 4 21:35:00 2010
@@ -57,6 +57,7 @@ import org.apache.aries.application.mana
import org.apache.aries.application.management.ManagementException;
import org.apache.aries.application.management.ResolveConstraint;
import org.apache.aries.application.management.ResolverException;
+import org.apache.aries.application.management.UpdateException;
import org.apache.aries.application.management.internal.MessageUtil;
import org.apache.aries.application.management.repository.ApplicationRepository;
import org.apache.aries.application.utils.AppConstants;
@@ -287,7 +288,7 @@ public class AriesApplicationManagerImpl
// Register an Application Repository for this application
Dictionary dict = new Hashtable();
- dict.put(ApplicationRepository.REPOSITORY_SCOPE, app.getApplicationMetadata().getApplicationScope());
+ dict.put(BundleRepository.REPOSITORY_SCOPE, app.getApplicationMetadata().getApplicationScope());
_bundleContext.registerService(BundleRepository.class.getName(),
new ApplicationRepository(app),
dict);
@@ -353,4 +354,38 @@ public class AriesApplicationManagerImpl
return mf;
}
+ public AriesApplicationContext update(AriesApplication app, DeploymentMetadata depMf) throws UpdateException {
+ if (!(app instanceof AriesApplicationImpl)) throw new IllegalArgumentException("Argument is not AriesApplication created by this manager");
+
+ if (!!!app.getApplicationMetadata().getApplicationSymbolicName().equals(depMf.getApplicationSymbolicName())
+ || !!!app.getApplicationMetadata().getApplicationVersion().equals(depMf.getApplicationVersion())) {
+ throw new IllegalArgumentException("The deployment metadata does not match the application.");
+ }
+
+ DeploymentMetadata oldMetadata = app.getDeploymentMetadata();
+
+ AriesApplicationContext foundCtx = null;
+ for (AriesApplicationContext ctx : _applicationContextManager.getApplicationContexts()) {
+ if (ctx.getApplication().equals(app)) {
+ foundCtx = ctx;
+ break;
+ }
+ }
+
+ ((AriesApplicationImpl) app).setDeploymentMetadata(depMf);
+
+ if (foundCtx != null) {
+ try {
+ return _applicationContextManager.update(app, oldMetadata);
+ } catch (UpdateException ue) {
+ if (ue.hasRolledBack()) {
+ ((AriesApplicationImpl) app).setDeploymentMetadata(oldMetadata);
+ }
+
+ throw ue;
+ }
+ } else {
+ return null;
+ }
+ }
}
Modified: incubator/aries/trunk/application/application-management/src/test/java/org/apache/aries/application/management/impl/AriesApplicationManagerImplTest.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/application/application-management/src/test/java/org/apache/aries/application/management/impl/AriesApplicationManagerImplTest.java?rev=992685&r1=992684&r2=992685&view=diff
==============================================================================
--- incubator/aries/trunk/application/application-management/src/test/java/org/apache/aries/application/management/impl/AriesApplicationManagerImplTest.java (original)
+++ incubator/aries/trunk/application/application-management/src/test/java/org/apache/aries/application/management/impl/AriesApplicationManagerImplTest.java Sat Sep 4 21:35:00 2010
@@ -19,9 +19,7 @@
package org.apache.aries.application.management.impl;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.*;
import java.io.File;
import java.io.FileInputStream;
@@ -30,6 +28,7 @@ import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -51,6 +50,8 @@ import org.apache.aries.application.impl
import org.apache.aries.application.impl.DeploymentContentImpl;
import org.apache.aries.application.impl.DeploymentMetadataFactoryImpl;
import org.apache.aries.application.management.AriesApplication;
+import org.apache.aries.application.management.AriesApplicationContext;
+import org.apache.aries.application.management.AriesApplicationContextManager;
import org.apache.aries.application.management.AriesApplicationResolver;
import org.apache.aries.application.management.BundleConversion;
import org.apache.aries.application.management.BundleConverter;
@@ -61,12 +62,15 @@ import org.apache.aries.application.mana
import org.apache.aries.application.management.ManagementException;
import org.apache.aries.application.management.ResolveConstraint;
import org.apache.aries.application.management.ResolverException;
+import org.apache.aries.application.management.UpdateException;
import org.apache.aries.application.modelling.ModelledResource;
import org.apache.aries.application.utils.AppConstants;
import org.apache.aries.application.utils.filesystem.FileSystem;
import org.apache.aries.application.utils.filesystem.IOUtils;
import org.apache.aries.application.utils.management.SimpleBundleInfo;
import org.apache.aries.application.utils.manifest.BundleManifest;
+import org.apache.aries.unittest.mocks.MethodCall;
+import org.apache.aries.unittest.mocks.Skeleton;
import org.apache.aries.unittest.utils.EbaUnitTestUtils;
import org.junit.Before;
import org.junit.BeforeClass;
@@ -375,6 +379,101 @@ public class AriesApplicationManagerImpl
assertEquals (dm.getApplicationVersion(), app.getApplicationMetadata().getApplicationVersion());
}
+ @Test
+ public void testUpdate() throws Exception {
+ AriesApplication app = createApplication(TEST_EBA);
+
+ DeploymentMetadata depMf = createUpdateDepMf();
+
+ AriesApplicationContextManager ctxMgr = Skeleton.newMock(AriesApplicationContextManager.class);
+ _appMgr.setApplicationContextManager(ctxMgr);
+
+ _appMgr.update(app, depMf);
+
+ assertTrue("Deployment.mf should have been updated", app.getDeploymentMetadata() == depMf);
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void testUpdateWithIncorrectDepMf() throws Exception
+ {
+ AriesApplication app = createApplication(TEST_EBA);
+
+ DeploymentMetadata depMf = Skeleton.newMock(DeploymentMetadata.class);
+ Skeleton.getSkeleton(depMf).setReturnValue(new MethodCall(DeploymentMetadata.class, "getApplicationSymbolicName"), "random.app");
+ Skeleton.getSkeleton(depMf).setReturnValue(new MethodCall(DeploymentMetadata.class, "getApplicationVersion"), new Version("1.0.0"));
+
+ AriesApplicationContextManager ctxMgr = Skeleton.newMock(AriesApplicationContextManager.class);
+ _appMgr.setApplicationContextManager(ctxMgr);
+
+ _appMgr.update(app, depMf);
+ }
+
+ @Test
+ public void testFailedUpdate() throws Exception {
+ AriesApplication app = createApplication(TEST_EBA);
+
+ DeploymentMetadata depMf = createUpdateDepMf();
+
+ AriesApplicationContext ctx = Skeleton.newMock(AriesApplicationContext.class);
+ Skeleton.getSkeleton(ctx).setReturnValue(new MethodCall(AriesApplicationContext.class, "getApplication"), app);
+
+ AriesApplicationContextManager ctxMgr = Skeleton.newMock(AriesApplicationContextManager.class);
+ Skeleton.getSkeleton(ctxMgr).setReturnValue(
+ new MethodCall(AriesApplicationContextManager.class, "getApplicationContexts"),
+ Collections.singleton(ctx));
+
+ Skeleton.getSkeleton(ctxMgr).setThrows(
+ new MethodCall(AriesApplicationContextManager.class, "update", AriesApplication.class, DeploymentMetadata.class),
+ new UpdateException("", null, false, null));
+
+ _appMgr.setApplicationContextManager(ctxMgr);
+
+ try {
+ _appMgr.update(app, depMf);
+ fail("Update should have failed.");
+ } catch (UpdateException e) {
+ assertTrue("Deployment.mf should have been updated", app.getDeploymentMetadata() == depMf);
+ }
+ }
+
+ @Test
+ public void testRolledbackUpdate() throws Exception {
+ AriesApplication app = createApplication(TEST_EBA);
+
+ DeploymentMetadata depMf = createUpdateDepMf();
+ DeploymentMetadata oldMf = app.getDeploymentMetadata();
+
+ AriesApplicationContext ctx = Skeleton.newMock(AriesApplicationContext.class);
+ Skeleton.getSkeleton(ctx).setReturnValue(new MethodCall(AriesApplicationContext.class, "getApplication"), app);
+
+ AriesApplicationContextManager ctxMgr = Skeleton.newMock(AriesApplicationContextManager.class);
+ Skeleton.getSkeleton(ctxMgr).setReturnValue(
+ new MethodCall(AriesApplicationContextManager.class, "getApplicationContexts"),
+ Collections.singleton(ctx));
+
+ Skeleton.getSkeleton(ctxMgr).setThrows(
+ new MethodCall(AriesApplicationContextManager.class, "update", AriesApplication.class, DeploymentMetadata.class),
+ new UpdateException("", null, true, null));
+
+ _appMgr.setApplicationContextManager(ctxMgr);
+
+ try {
+ _appMgr.update(app, depMf);
+ fail("Update should have failed.");
+ } catch (UpdateException e) {
+ assertTrue("Deployment.mf should have been rolled back to the old", app.getDeploymentMetadata() == oldMf);
+ }
+ }
+
+ private DeploymentMetadata createUpdateDepMf()
+ {
+ DeploymentMetadata depMf = Skeleton.newMock(DeploymentMetadata.class);
+ Skeleton.getSkeleton(depMf).setReturnValue(new MethodCall(DeploymentMetadata.class, "getApplicationSymbolicName"), "org.apache.aries.application.management.test");
+ Skeleton.getSkeleton(depMf).setReturnValue(new MethodCall(DeploymentMetadata.class, "getApplicationVersion"), new Version("1.0.0"));
+
+ return depMf;
+ }
+
private AriesApplication createApplication (String fileName) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException, ManagementException, ResolverException {
// This next block is a very long winded way of constructing a BundleInfoImpl
// against the existing (BundleManifest bm, String location) constructor. If we
Modified: incubator/aries/trunk/application/application-runtime-framework-management/src/main/java/org/apache/aries/application/runtime/framework/management/BundleFrameworkManagerImpl.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/application/application-runtime-framework-management/src/main/java/org/apache/aries/application/runtime/framework/management/BundleFrameworkManagerImpl.java?rev=992685&r1=992684&r2=992685&view=diff
==============================================================================
--- incubator/aries/trunk/application/application-runtime-framework-management/src/main/java/org/apache/aries/application/runtime/framework/management/BundleFrameworkManagerImpl.java (original)
+++ incubator/aries/trunk/application/application-runtime-framework-management/src/main/java/org/apache/aries/application/runtime/framework/management/BundleFrameworkManagerImpl.java Sat Sep 4 21:35:00 2010
@@ -25,19 +25,24 @@ import static org.apache.aries.applicati
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
+import java.util.Set;
import org.apache.aries.application.Content;
+import org.apache.aries.application.DeploymentContent;
import org.apache.aries.application.DeploymentMetadata;
import org.apache.aries.application.management.AriesApplication;
import org.apache.aries.application.management.BundleFramework;
import org.apache.aries.application.management.BundleFrameworkFactory;
import org.apache.aries.application.management.BundleFrameworkManager;
import org.apache.aries.application.management.ContextException;
+import org.apache.aries.application.management.UpdateException;
import org.apache.aries.application.management.BundleRepository.BundleSuggestion;
+import org.apache.aries.application.management.provider.UpdateStrategy;
import org.apache.aries.application.utils.runtime.InstallUtils;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
@@ -54,6 +59,13 @@ public class BundleFrameworkManagerImpl
BundleFramework _sharedBundleFramework;
BundleFrameworkFactory _bundleFrameworkFactory;
Map<Bundle, BundleFramework> _frameworks = new HashMap<Bundle, BundleFramework>();
+ Map<AriesApplication, BundleFramework> _frameworksByApp = new HashMap<AriesApplication, BundleFramework>();
+ private List<UpdateStrategy> _updateStrategies = Collections.emptyList();
+
+ public void setUpdateStrategies(List<UpdateStrategy> updateStrategies)
+ {
+ _updateStrategies = updateStrategies;
+ }
public void setBundleContext(BundleContext ctx)
{
@@ -89,6 +101,7 @@ public class BundleFrameworkManagerImpl
BundleFramework isolatedFramework = isolatedInstall(bundlesToInstall, app);
_frameworks.put(isolatedFramework.getFrameworkBundle(), isolatedFramework);
+ _frameworksByApp.put(app, isolatedFramework);
return isolatedFramework.getFrameworkBundle();
}
@@ -226,4 +239,79 @@ public class BundleFrameworkManagerImpl
}
// Do not stop shared bundles
}
+
+ public boolean allowsUpdate(DeploymentMetadata newMetadata, DeploymentMetadata oldMetadata)
+ {
+ for (UpdateStrategy strategy : _updateStrategies) {
+ if (strategy.allowsUpdate(newMetadata, oldMetadata)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public void updateBundles(
+ final DeploymentMetadata newMetadata,
+ final DeploymentMetadata oldMetadata,
+ final AriesApplication app,
+ final BundleLocator locator,
+ final Set<Bundle> bundles,
+ final boolean startBundles)
+ throws UpdateException
+ {
+ UpdateStrategy strategy = null;
+
+ for (UpdateStrategy us : _updateStrategies) {
+ if (us.allowsUpdate(newMetadata, oldMetadata)) {
+ strategy = us;
+ break;
+ }
+ }
+
+ if (strategy == null) throw new IllegalArgumentException("No UpdateStrategy supports the supplied DeploymentMetadata changes.");
+
+ final BundleFramework appFwk = _frameworksByApp.get(app);
+
+ strategy.update(new UpdateStrategy.UpdateInfo() {
+
+ public void register(Bundle bundle) {
+ bundles.add(bundle);
+ }
+
+ public void unregister(Bundle bundle) {
+ bundles.remove(bundle);
+ }
+
+ public Map<DeploymentContent, BundleSuggestion> suggestBundle(Collection<DeploymentContent> bundles) throws ContextException {
+ return locator.suggestBundle(bundles);
+ }
+
+ public boolean startBundles() {
+ return startBundles;
+ }
+
+ public BundleFramework getSharedFramework() {
+ return _sharedBundleFramework;
+ }
+
+ public DeploymentMetadata getOldMetadata() {
+ return oldMetadata;
+ }
+
+ public DeploymentMetadata getNewMetadata() {
+ return newMetadata;
+ }
+
+ public AriesApplication getApplication() {
+ return app;
+ }
+
+ public BundleFramework getAppFramework() {
+ return appFwk;
+ }
+ });
+ }
+
+
}
Modified: incubator/aries/trunk/application/application-runtime-framework-management/src/main/resources/OSGI-INF/blueprint/bundle-framework-management.xml
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/application/application-runtime-framework-management/src/main/resources/OSGI-INF/blueprint/bundle-framework-management.xml?rev=992685&r1=992684&r2=992685&view=diff
==============================================================================
--- incubator/aries/trunk/application/application-runtime-framework-management/src/main/resources/OSGI-INF/blueprint/bundle-framework-management.xml (original)
+++ incubator/aries/trunk/application/application-runtime-framework-management/src/main/resources/OSGI-INF/blueprint/bundle-framework-management.xml Sat Sep 4 21:35:00 2010
@@ -22,6 +22,7 @@
<bean id="equinox-bundle-framework-manager" class="org.apache.aries.application.runtime.framework.management.BundleFrameworkManagerImpl" init-method="init">
<property name="bundleFrameworkFactory" ref="bundle-framework-factory"/>
<property name="bundleContext" ref="blueprintBundleContext"/>
+ <property name="updateStrategies" ref="strategies" />
</bean>
<service interface="org.apache.aries.application.management.BundleFrameworkManager"
@@ -30,4 +31,6 @@
<reference id="bundle-framework-factory" interface="org.apache.aries.application.management.BundleFrameworkFactory"/>
+ <reference-list id="strategies" interface="org.apache.aries.application.management.provider.UpdateStrategy" availability="optional" />
+
</blueprint>
Modified: incubator/aries/trunk/application/application-runtime-isolated/src/main/java/org/apache/aries/application/runtime/isolated/impl/ApplicationContextImpl.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/application/application-runtime-isolated/src/main/java/org/apache/aries/application/runtime/isolated/impl/ApplicationContextImpl.java?rev=992685&r1=992684&r2=992685&view=diff
==============================================================================
--- incubator/aries/trunk/application/application-runtime-isolated/src/main/java/org/apache/aries/application/runtime/isolated/impl/ApplicationContextImpl.java (original)
+++ incubator/aries/trunk/application/application-runtime-isolated/src/main/java/org/apache/aries/application/runtime/isolated/impl/ApplicationContextImpl.java Sat Sep 4 21:35:00 2010
@@ -24,6 +24,7 @@ import static org.apache.aries.applicati
import static org.apache.aries.application.utils.AppConstants.LOG_EXIT;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@@ -39,9 +40,9 @@ import org.apache.aries.application.mana
import org.apache.aries.application.management.BundleRepositoryManager;
import org.apache.aries.application.management.ContextException;
import org.apache.aries.application.management.ManagementException;
+import org.apache.aries.application.management.UpdateException;
import org.apache.aries.application.management.BundleRepository.BundleSuggestion;
import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -53,12 +54,11 @@ public class ApplicationContextImpl impl
private AriesApplication _application;
private Set<Bundle> _bundles;
private ApplicationState _state = ApplicationState.UNINSTALLED;
- private BundleContext _bundleContext;
private BundleRepositoryManager _bundleRepositoryManager;
private BundleFrameworkManager _bundleFrameworkManager;
/** deployment metadata associated with aries application */
- private final DeploymentMetadata _deploymentMF;
+ private DeploymentMetadata _deploymentMF;
public ApplicationContextImpl(AriesApplication app, ApplicationContextManagerImpl acm)
throws BundleException, ManagementException
@@ -212,28 +212,28 @@ public class ApplicationContextImpl impl
*/
Map<DeploymentContent, BundleSuggestion> bundlesToBeInstalled = new HashMap<DeploymentContent, BundleSuggestion>();
try {
- bundlesToBeInstalled = _bundleRepositoryManager.getBundleSuggestions(_application
- .getApplicationMetadata().getApplicationSymbolicName(), _application
- .getApplicationMetadata().getApplicationVersion().toString(), bundlesToFind);
+ bundlesToBeInstalled = findBundleSuggestions(bundlesToFind);
} catch (ContextException e) {
numException++;
LOGGER.debug(LOG_EXCEPTION, e);
}
- /**
- * Perform the install of the bundles
- */
- try {
- if (shared)
- _bundles.addAll(_bundleFrameworkManager.installSharedBundles(
- new ArrayList<BundleSuggestion>(bundlesToBeInstalled.values()), _application));
- else
- _bundles.add(_bundleFrameworkManager.installIsolatedBundles(
- new ArrayList<BundleSuggestion>(bundlesToBeInstalled.values()), _application));
-
- } catch (BundleException e) {
- numException++;
- LOGGER.debug(LOG_EXCEPTION, e);
+ if (numException == 0) {
+ /**
+ * Perform the install of the bundles
+ */
+ try {
+ if (shared)
+ _bundles.addAll(_bundleFrameworkManager.installSharedBundles(
+ new ArrayList<BundleSuggestion>(bundlesToBeInstalled.values()), _application));
+ else
+ _bundles.add(_bundleFrameworkManager.installIsolatedBundles(
+ new ArrayList<BundleSuggestion>(bundlesToBeInstalled.values()), _application));
+
+ } catch (BundleException e) {
+ numException++;
+ LOGGER.debug(LOG_EXCEPTION, e);
+ }
}
}
@@ -241,6 +241,14 @@ public class ApplicationContextImpl impl
return (numException == 0);
}
+
+ private Map<DeploymentContent, BundleSuggestion> findBundleSuggestions(Collection<DeploymentContent> bundlesToFind)
+ throws ContextException
+ {
+ return _bundleRepositoryManager.getBundleSuggestions(_application
+ .getApplicationMetadata().getApplicationSymbolicName(), _application
+ .getApplicationMetadata().getApplicationVersion().toString(), bundlesToFind);
+ }
public AriesApplication getApplication()
{
@@ -323,4 +331,69 @@ public class ApplicationContextImpl impl
LOGGER.debug(LOG_EXIT, "setState");
}
+
+ public void update(final DeploymentMetadata newMetadata, final DeploymentMetadata oldMetadata)
+ throws UpdateException
+ {
+ final boolean toStart = getApplicationState() == ApplicationState.ACTIVE;
+
+ if (_bundleFrameworkManager.allowsUpdate(newMetadata, oldMetadata)) {
+ _bundleFrameworkManager.updateBundles(
+ newMetadata, oldMetadata,
+ _application,
+ new BundleFrameworkManager.BundleLocator() {
+ public Map<DeploymentContent, BundleSuggestion> suggestBundle(
+ Collection<DeploymentContent> bundles) throws ContextException {
+ return findBundleSuggestions(bundles);
+ }
+ },
+ _bundles,
+ toStart);
+
+ } else {
+ // fallback do a uninstall, followed by a reinstall
+
+ boolean uninstallSuccess = uninstall();
+
+ if (uninstallSuccess) {
+ _deploymentMF = newMetadata;
+ boolean reinstallSuccess = processContent();
+ Exception installException = null;
+
+ if (reinstallSuccess) {
+ if (toStart) {
+ try {
+ start();
+ } catch (BundleException be) {
+ reinstallSuccess = false;
+ installException = be;
+ }
+ }
+ }
+
+ if (!!!reinstallSuccess) {
+ boolean rollbackSuccess = uninstall();
+ Exception rollbackException = null;
+
+ if (rollbackSuccess) {
+ _deploymentMF = oldMetadata;
+ rollbackSuccess = processContent();
+
+ if (rollbackSuccess && toStart) {
+ try {
+ start();
+ } catch (BundleException be) {
+ rollbackException = be;
+ rollbackSuccess = false;
+ }
+ }
+ }
+
+ throw new UpdateException("Could not install updated application", installException, rollbackSuccess, rollbackException);
+ }
+ } else {
+ throw new UpdateException("Could not uninstall old bundles", null, false, null);
+ }
+ }
+ }
}
Modified: incubator/aries/trunk/application/application-runtime-isolated/src/main/java/org/apache/aries/application/runtime/isolated/impl/ApplicationContextManagerImpl.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/application/application-runtime-isolated/src/main/java/org/apache/aries/application/runtime/isolated/impl/ApplicationContextManagerImpl.java?rev=992685&r1=992684&r2=992685&view=diff
==============================================================================
--- incubator/aries/trunk/application/application-runtime-isolated/src/main/java/org/apache/aries/application/runtime/isolated/impl/ApplicationContextManagerImpl.java (original)
+++ incubator/aries/trunk/application/application-runtime-isolated/src/main/java/org/apache/aries/application/runtime/isolated/impl/ApplicationContextManagerImpl.java Sat Sep 4 21:35:00 2010
@@ -21,7 +21,6 @@ package org.apache.aries.application.run
import static org.apache.aries.application.utils.AppConstants.LOG_ENTRY;
import static org.apache.aries.application.utils.AppConstants.LOG_EXIT;
-import static org.apache.aries.application.utils.AppConstants.LOG_EXCEPTION;
import java.util.HashSet;
import java.util.Iterator;
@@ -30,15 +29,15 @@ import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
+import org.apache.aries.application.DeploymentMetadata;
import org.apache.aries.application.management.AriesApplication;
import org.apache.aries.application.management.AriesApplicationContext;
import org.apache.aries.application.management.AriesApplicationContextManager;
-import org.apache.aries.application.management.BundleFramework;
import org.apache.aries.application.management.BundleFrameworkManager;
import org.apache.aries.application.management.BundleRepositoryManager;
import org.apache.aries.application.management.ManagementException;
+import org.apache.aries.application.management.UpdateException;
import org.apache.aries.application.management.AriesApplicationContext.ApplicationState;
-import org.osgi.framework.Bundle;
import org.osgi.framework.BundleException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -83,7 +82,7 @@ public class ApplicationContextManagerIm
return _bundleRepositoryManager;
}
-
+
public synchronized AriesApplicationContext getApplicationContext(AriesApplication app)
throws BundleException, ManagementException
{
@@ -174,4 +173,18 @@ public class ApplicationContextManagerIm
return _bundleFrameworkManager;
}
+ public AriesApplicationContext update(AriesApplication app, DeploymentMetadata oldMetadata) throws UpdateException {
+ ApplicationContextImpl ctx = _appToContextMap.get(app);
+
+ if (ctx == null) {
+ throw new IllegalArgumentException("AriesApplication "+
+ app.getApplicationMetadata().getApplicationSymbolicName() + "/" + app.getApplicationMetadata().getApplicationVersion() +
+ " cannot be updated because it is not installed");
+ }
+
+ ctx.update(app.getDeploymentMetadata(), oldMetadata);
+
+ return ctx;
+ }
+
}
\ No newline at end of file
Modified: incubator/aries/trunk/application/application-runtime/src/main/java/org/apache/aries/application/runtime/impl/ApplicationContextManagerImpl.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/application/application-runtime/src/main/java/org/apache/aries/application/runtime/impl/ApplicationContextManagerImpl.java?rev=992685&r1=992684&r2=992685&view=diff
==============================================================================
--- incubator/aries/trunk/application/application-runtime/src/main/java/org/apache/aries/application/runtime/impl/ApplicationContextManagerImpl.java (original)
+++ incubator/aries/trunk/application/application-runtime/src/main/java/org/apache/aries/application/runtime/impl/ApplicationContextManagerImpl.java Sat Sep 4 21:35:00 2010
@@ -26,10 +26,12 @@ import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
+import org.apache.aries.application.DeploymentMetadata;
import org.apache.aries.application.management.AriesApplication;
import org.apache.aries.application.management.AriesApplicationContext;
import org.apache.aries.application.management.AriesApplicationContextManager;
import org.apache.aries.application.management.ManagementException;
+import org.apache.aries.application.management.UpdateException;
import org.apache.aries.application.management.AriesApplicationContext.ApplicationState;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
@@ -110,4 +112,28 @@ public class ApplicationContextManagerIm
_appToContextMap.clear();
}
+
+ public AriesApplicationContext update(AriesApplication app, DeploymentMetadata oldMetadata) throws UpdateException {
+ ApplicationContextImpl oldCtx = _appToContextMap.get(app);
+
+ if (oldCtx == null) {
+ throw new IllegalArgumentException("AriesApplication "+
+ app.getApplicationMetadata().getApplicationSymbolicName() + "/" + app.getApplicationMetadata().getApplicationVersion() +
+ " cannot be updated because it is not installed");
+ }
+
+ uninstall(oldCtx);
+ try {
+ AriesApplicationContext newCtx = getApplicationContext(app);
+ if (oldCtx.getApplicationState() == ApplicationState.ACTIVE) {
+ newCtx.start();
+ }
+
+ return newCtx;
+ } catch (BundleException e) {
+ throw new UpdateException("Update failed: "+e.getMessage(), e, false, null);
+ } catch (ManagementException e) {
+ throw new UpdateException("Update failed: "+e.getMessage(), e, false, null);
+ }
+ }
}
\ No newline at end of file