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/12/03 10:07:51 UTC

svn commit: r1041737 - in /incubator/aries/trunk/application/application-deployment-management/src: main/java/org/apache/aries/application/deployment/management/impl/ main/resources/org/apache/aries/application/deployment/management/messages/ test/java...

Author: mahrwald
Date: Fri Dec  3 09:07:50 2010
New Revision: 1041737

URL: http://svn.apache.org/viewvc?rev=1041737&view=rev
Log:
ARIES-506: Commit fix for invalid multi-provision scenarios

Modified:
    incubator/aries/trunk/application/application-deployment-management/src/main/java/org/apache/aries/application/deployment/management/impl/DeploymentManifestManagerImpl.java
    incubator/aries/trunk/application/application-deployment-management/src/main/resources/org/apache/aries/application/deployment/management/messages/DeploymentManagementMessages.properties
    incubator/aries/trunk/application/application-deployment-management/src/test/java/org/apache/aries/application/deployment/management/DeploymentGeneratorTest.java

Modified: incubator/aries/trunk/application/application-deployment-management/src/main/java/org/apache/aries/application/deployment/management/impl/DeploymentManifestManagerImpl.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/application/application-deployment-management/src/main/java/org/apache/aries/application/deployment/management/impl/DeploymentManifestManagerImpl.java?rev=1041737&r1=1041736&r2=1041737&view=diff
==============================================================================
--- incubator/aries/trunk/application/application-deployment-management/src/main/java/org/apache/aries/application/deployment/management/impl/DeploymentManifestManagerImpl.java (original)
+++ incubator/aries/trunk/application/application-deployment-management/src/main/java/org/apache/aries/application/deployment/management/impl/DeploymentManifestManagerImpl.java Fri Dec  3 09:07:50 2010
@@ -67,6 +67,7 @@ import org.apache.aries.application.util
 import org.apache.aries.application.utils.filesystem.FileSystem;
 import org.apache.aries.application.utils.filesystem.IOUtils;
 import org.apache.aries.application.utils.manifest.ManifestHeaderProcessor;
+import org.apache.aries.application.utils.manifest.ManifestHeaderProcessor.NameValueMap;
 import org.osgi.framework.Constants;
 import org.osgi.framework.Filter;
 import org.osgi.service.blueprint.container.ServiceUnavailableException;
@@ -76,7 +77,7 @@ import org.slf4j.LoggerFactory;
 public class DeploymentManifestManagerImpl implements DeploymentManifestManager
 {
 
-  private Logger _logger = LoggerFactory.getLogger(DeploymentManifestManagerImpl.class);
+  private final Logger _logger = LoggerFactory.getLogger(DeploymentManifestManagerImpl.class);
   private AriesApplicationResolver resolver;
   private PostResolveTransformer postResolveTransformer = null;
 
@@ -130,7 +131,7 @@ public class DeploymentManifestManagerIm
    * @throws ResolverException
    */
   @Override
-  public Manifest generateDeploymentManifest( AriesApplication app,  ResolveConstraint... constraints ) throws ResolverException
+  public Manifest generateDeploymentManifest(AriesApplication app,  ResolveConstraint... constraints ) throws ResolverException
   {
 
     _logger.debug(LOG_ENTRY, "generateDeploymentManifest", new Object[]{app, constraints});
@@ -332,6 +333,8 @@ public class DeploymentManifestManagerIm
         throw (rx);
       }
     }
+    
+    checkForIsolatedContentInProvisionBundle(appSymbolicName, deployedBundles);
       
     if (postResolveTransformer != null) try {  
       deployedBundles = postResolveTransformer.postResolveProcess (appMetadata, deployedBundles);
@@ -526,6 +529,61 @@ public class DeploymentManifestManagerIm
 
     return suspects;
   }
+  
+  /**
+   * Check whether there are isolated bundles deployed into both deployed content and provision bundles. This almost
+   * always indicates a resolution problem hence we throw a ResolverException.
+   * Note that we check provision bundles rather than provision bundles and deployed use bundles. So in any corner case
+   * where the rejected deployment is actually intended, it can still be achieved by introducing a use bundle clause.
+   * 
+   * @param applicationSymbolicName
+   * @param appContentBundles
+   * @param provisionBundles
+   * @throws ResolverException
+   */
+  private void checkForIsolatedContentInProvisionBundle(String applicationSymbolicName, DeployedBundles db)
+    throws ResolverException
+  {
+    for (ModelledResource isolatedBundle : db.getDeployedContent()) {
+      for (ModelledResource provisionBundle : db.getDeployedProvisionBundle()) {
+        if (isolatedBundle.getSymbolicName().equals(provisionBundle.getSymbolicName()) 
+            && providesPackage(provisionBundle, db.getImportPackage())) {
+          
+          throw new ResolverException(
+              MessageUtil.getMessage("ISOLATED_CONTENT_PROVISIONED", 
+                  applicationSymbolicName,
+                  isolatedBundle.getSymbolicName(),
+                  isolatedBundle.getVersion(),
+                  provisionBundle.getVersion()));
+        }
+      }
+    }
+  }
+  
+  /**
+   * Can the modelled resource provide a package against the given import specificiation
+   * @param bundle
+   * @param importPackages
+   * @return
+   */
+  private boolean providesPackage(ModelledResource bundle, String importPackages)
+  {
+    Map<String, NameValueMap<String, String>> imports = ManifestHeaderProcessor.parseImportString(importPackages);
+    
+    try {
+      for (Map.Entry<String, NameValueMap<String,String>> e : imports.entrySet()) {
+        ImportedPackage importPackage = modellingManager.getImportedPackage(e.getKey(), e.getValue());
+        
+        for (ExportedPackage export : bundle.getExportedPackages()) {
+          if (importPackage.isSatisfied(export)) return true;
+        }
+      }
+    } catch (InvalidAttributeException iae) {
+      _logger.error(MessageUtil.getMessage("UNEXPECTED_EXCEPTION_PARSING_IMPORTS", iae, importPackages), iae);
+    }
+    
+    return false;
+  }
 
   /**
    * Covert a collection of contents to a collection of ImportedBundle objects

Modified: incubator/aries/trunk/application/application-deployment-management/src/main/resources/org/apache/aries/application/deployment/management/messages/DeploymentManagementMessages.properties
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/application/application-deployment-management/src/main/resources/org/apache/aries/application/deployment/management/messages/DeploymentManagementMessages.properties?rev=1041737&r1=1041736&r2=1041737&view=diff
==============================================================================
--- incubator/aries/trunk/application/application-deployment-management/src/main/resources/org/apache/aries/application/deployment/management/messages/DeploymentManagementMessages.properties (original)
+++ incubator/aries/trunk/application/application-deployment-management/src/main/resources/org/apache/aries/application/deployment/management/messages/DeploymentManagementMessages.properties Fri Dec  3 09:07:50 2010
@@ -23,3 +23,6 @@ SUSPECTED_CIRCULAR_DEPENDENCIES=Resoluti
 
 EMPTY_DEPLOYMENT_CONTENT=Enterprise application {0} contains no content. 
 POST_RESOLVE_TRANSFORMER_UNAVAILABLE=An instance of the PostResolveTransformer was injected earlier but is currently inaccessible. Exception: {0}
+
+ISOLATED_CONTENT_PROVISIONED=Enterprise application {0} has resolved to a configuration where bundle {1} is deployed as part of the deployment content at version {2} and also as part of provisioned content at version {3}.
+UNEXPECTED_EXCEPTION_PARSING_IMPORTS=An unexpected exception {0} was encountered during parsing the generated import package statement {1}.
\ No newline at end of file

Modified: incubator/aries/trunk/application/application-deployment-management/src/test/java/org/apache/aries/application/deployment/management/DeploymentGeneratorTest.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/application/application-deployment-management/src/test/java/org/apache/aries/application/deployment/management/DeploymentGeneratorTest.java?rev=1041737&r1=1041736&r2=1041737&view=diff
==============================================================================
--- incubator/aries/trunk/application/application-deployment-management/src/test/java/org/apache/aries/application/deployment/management/DeploymentGeneratorTest.java (original)
+++ incubator/aries/trunk/application/application-deployment-management/src/test/java/org/apache/aries/application/deployment/management/DeploymentGeneratorTest.java Fri Dec  3 09:07:50 2010
@@ -25,6 +25,7 @@ import static org.junit.Assert.fail;
 
 import java.io.File;
 import java.io.IOException;
+import java.lang.reflect.Array;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -211,9 +212,10 @@ public class DeploymentGeneratorTest
     ModelledResource mb = createModelledResource(bundleName, bundleVersion,
         Arrays.asList(importedPackages) , Arrays.asList(exportedPackages));
     
-   return mb.getExportedPackages().iterator().next();
-
+    
+    return mb.getExportedPackages().iterator().next();
   }
+  
   static {
     try {
       CAPABILITY_A = createExportedPackage ("aries.test.a", "1.0.0", new String[] {"aries.test.a"}, 
@@ -252,11 +254,11 @@ public class DeploymentGeneratorTest
     Attributes attrs = man.getMainAttributes();
     
     assertEquals("aries.test", attrs.getValue(AppConstants.APPLICATION_SYMBOLIC_NAME));
-    assertEquals("1.0.0", (String)attrs.getValue(AppConstants.APPLICATION_VERSION));
+    assertEquals("1.0.0", attrs.getValue(AppConstants.APPLICATION_VERSION));
     
-    String content = (String)attrs.getValue(AppConstants.DEPLOYMENT_CONTENT);
-    String useBundle = (String) attrs.getValue(AppConstants.DEPLOYMENT_USE_BUNDLE);
-    String provisioned =(String)attrs.getValue(AppConstants.DEPLOYMENT_PROVISION_BUNDLE);
+    String content = attrs.getValue(AppConstants.DEPLOYMENT_CONTENT);
+    String useBundle = attrs.getValue(AppConstants.DEPLOYMENT_USE_BUNDLE);
+    String provisioned =attrs.getValue(AppConstants.DEPLOYMENT_PROVISION_BUNDLE);
     
     assertTrue(content.contains("aries.test.a;deployed-version=1.0.0"));
     assertTrue(content.contains("aries.test.b;deployed-version=1.1.0"));
@@ -370,6 +372,114 @@ public class DeploymentGeneratorTest
     }
   }
   
+  @Test
+  public void checkBundleInAppContentAndProvisionContent() throws Exception
+  {
+    List<ModelledResource> cmr = new ArrayList<ModelledResource>();
+    cmr.add(createModelledResource("test.api", "1.1.0", Collections.<String>emptyList(), Arrays.asList("test.api.pack;version=1.1.0")));
+    cmr.add(createModelledResource("test.api", "1.0.0", Collections.<String>emptyList(), Arrays.asList("test.api.pack;version=1.0.0")));
+    cmr.add(createModelledResource("test.consumer", "1.0.0", Arrays.asList("test.api.pack;version=\"[1.0.0,2.0.0)\""), Collections.<String>emptyList()));
+    cmr.add(createModelledResource("test.provider", "1.0.0", Arrays.asList("test.api.pack;version=\"[1.0.0,1.1.0)\""), Collections.<String>emptyList()));
+
+    // The second time DeploymentGenerator calls the Resolver, it will provide just 
+    // test.shared. The resolver will return test.shared _plus_ test.isolated. 
+    _resolver.addResult(cmr);
+    Skeleton.getSkeleton(appMetadata).setReturnValue(
+        new MethodCall(ApplicationMetadata.class, "getApplicationContents"), 
+        Arrays.asList(
+            mockContent("test.api" , "1.1.0"),
+            mockContent("test.consumer" , "1.0.0"),
+            mockContent("test.provider", "1.0.0")));
+
+    app = Skeleton.newMock(AriesApplication.class);
+    Skeleton.getSkeleton(app).setReturnValue(new MethodCall(AriesApplication.class, "getApplicationMetadata"), appMetadata);
+    
+    try {
+      DeployedBundles deployedBundles = deplMFMgr.generateDeployedBundles (appMetadata, 
+          Arrays.asList(new ModelledResource[] {cmr.get(0), cmr.get(2), cmr.get(3)}), 
+          new ArrayList<Content>());
+      deplMFMgr.generateDeploymentManifest(appMetadata.getApplicationSymbolicName(),
+          appMetadata.getApplicationVersion().toString(), deployedBundles);
+      
+      fail("Expected exception because we can't provision an isolated bundle twice");
+    } catch (ResolverException rx) {}
+  }
+  
+  /**
+   * Similar to the checkBundleInAppContentAndProvisionContent scenario. However, this time the provisioned bundle does not provide
+   * a package or service to the isolated content, so there is no problem.
+   * @throws Exception
+   */
+  @Test
+  public void checkBundleInAppContentAndProvisionContentButNothingSharedToIsolatedContent() throws Exception
+  {
+    List<ModelledResource> cmr = new ArrayList<ModelledResource>();
+    cmr.add(createModelledResource("test.util", "1.1.0", Collections.<String>emptyList(), Arrays.asList("test.api.pack;version=1.1.0")));
+    cmr.add(createModelledResource("test.bundle", "1.0.0", Arrays.asList("test.api.pack;version=\"[1.1.0,2.0.0)\""), Collections.<String>emptyList()));
+    cmr.add(createModelledResource("test.provisioned", "1.0.0", Arrays.asList("test.api.pack;version=\"[1.0.0,1.1.0)\""), Collections.<String>emptyList()));
+    cmr.add(createModelledResource("test.util", "1.0.0", Collections.<String>emptyList(), Arrays.asList("test.api.pack;version=1.0.0")));
+
+    // The second time DeploymentGenerator calls the Resolver, it will provide just 
+    // test.shared. The resolver will return test.shared _plus_ test.isolated. 
+    _resolver.addResult(cmr);
+    Skeleton.getSkeleton(appMetadata).setReturnValue(
+        new MethodCall(ApplicationMetadata.class, "getApplicationContents"), 
+        Arrays.asList(
+            mockContent("test.util" , "1.1.0"),
+            mockContent("test.bundle", "1.0.0")));
+
+    app = Skeleton.newMock(AriesApplication.class);
+    Skeleton.getSkeleton(app).setReturnValue(new MethodCall(AriesApplication.class, "getApplicationMetadata"), appMetadata);
+    
+    DeployedBundles deployedBundles = deplMFMgr.generateDeployedBundles (appMetadata, 
+        Arrays.asList(new ModelledResource[] {cmr.get(0), cmr.get(1)}), 
+        new ArrayList<Content>());
+    Manifest mf = deplMFMgr.generateDeploymentManifest(appMetadata.getApplicationSymbolicName(),
+        appMetadata.getApplicationVersion().toString(), deployedBundles);
+    
+    assertTrue(mf.getMainAttributes().getValue("Deployed-Content").contains("test.util;deployed-version=1.1.0"));
+    assertTrue(mf.getMainAttributes().getValue("Provision-Bundle").contains("test.util;deployed-version=1.0.0"));
+  }
+  
+  @Test
+  public void checkBundleInAppContentAndUseContent() throws Exception
+  {
+    List<ModelledResource> cmr = new ArrayList<ModelledResource>();
+    cmr.add(createModelledResource("test.api", "1.1.0", Collections.<String>emptyList(), Arrays.asList("test.api.pack;version=1.1.0")));
+    cmr.add(createModelledResource("test.api", "1.0.0", Collections.<String>emptyList(), Arrays.asList("test.api.pack;version=1.0.0")));
+    cmr.add(createModelledResource("test.consumer", "1.0.0", Arrays.asList("test.api.pack;version=\"[1.0.0,2.0.0)\""), Collections.<String>emptyList()));
+    cmr.add(createModelledResource("test.provider", "1.0.0", Arrays.asList("test.api.pack;version=\"[1.0.0,1.1.0)\""), Collections.<String>emptyList()));
+
+    // The second time DeploymentGenerator calls the Resolver, it will provide just 
+    // test.shared. The resolver will return test.shared _plus_ test.isolated. 
+    _resolver.addResult(cmr);
+    
+    Skeleton.getSkeleton(appMetadata).setReturnValue(
+        new MethodCall(ApplicationMetadata.class, "getApplicationContents"), 
+        Arrays.asList(
+            mockContent("test.api" , "1.1.0"),
+            mockContent("test.consumer" , "1.0.0"),
+            mockContent("test.provider", "1.0.0")));
+    
+    Skeleton.getSkeleton(appMetadata).setReturnValue(
+        new MethodCall(ApplicationMetadata.class, "getUseBundles"),
+        Arrays.asList(mockContent("test.api", "1.0.0")));
+
+    app = Skeleton.newMock(AriesApplication.class);
+    Skeleton.getSkeleton(app).setReturnValue(new MethodCall(AriesApplication.class, "getApplicationMetadata"), appMetadata);
+    
+    DeployedBundles deployedBundles = deplMFMgr.generateDeployedBundles (appMetadata, 
+        Arrays.asList(new ModelledResource[] {cmr.get(0), cmr.get(2), cmr.get(3)}), 
+        new ArrayList<Content>());
+    
+    Manifest mf = deplMFMgr.generateDeploymentManifest(appMetadata.getApplicationSymbolicName(),
+        appMetadata.getApplicationVersion().toString(), deployedBundles);
+    
+    mf.write(System.out);
+    assertTrue(mf.getMainAttributes().getValue("Deployed-Content").contains("test.api;deployed-version=1.1.0"));
+    assertTrue(mf.getMainAttributes().getValue("Deployed-Use-Bundle").contains("test.api;deployed-version=1.0.0"));
+  }
+  
   public static ModelledResource createModelledResource(String bundleName, String bundleVersion, 
       Collection<String> importedPackages, Collection<String> exportedPackages) throws InvalidAttributeException {
     Attributes att = new Attributes();