modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/inventory/ResourceContext.java | 74 + modules/core/plugin-api/src/test/java/org/rhq/core/pluginapi/inventory/ResourceContextTest.java | 409 ++++++++++ modules/plugins/jboss-as-5/pom.xml | 14 modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/ApplicationServerComponent.java | 2 modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/JBossMessagingComponent.java | 3 modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/StandaloneManagedDeploymentComponent.java | 47 - modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/deploy/ManagedComponentDeployer.java | 50 - modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/helper/CreateChildResourceFacetDelegate.java | 9 modules/plugins/jboss-as-5/src/test/java/org/rhq/plugins/jbossas5/test/StandaloneManagedDeploymentComponentTest.java | 90 ++ 9 files changed, 625 insertions(+), 73 deletions(-)
New commits: commit 7b36fe4ad315679ea2e66431bbe5067037e1d539 Author: Stefan Negrea snegrea@redhat.com Date: Tue May 22 23:11:57 2012 -0500
[BZ 646631, 790753, 820650] Add unit tests for resource context and deployer code changes.
Remove unnecessary slash from temp folder name.
diff --git a/modules/core/plugin-api/src/test/java/org/rhq/core/pluginapi/inventory/ResourceContextTest.java b/modules/core/plugin-api/src/test/java/org/rhq/core/pluginapi/inventory/ResourceContextTest.java new file mode 100644 index 0000000..fe194c9 --- /dev/null +++ b/modules/core/plugin-api/src/test/java/org/rhq/core/pluginapi/inventory/ResourceContextTest.java @@ -0,0 +1,409 @@ +/* + * RHQ Management Platform + * Copyright (C) 2005-2008 Red Hat, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +package org.rhq.core.pluginapi.inventory; + +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.io.File; +import java.util.UUID; + +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.testng.PowerMockObjectFactory; +import org.testng.Assert; +import org.testng.IObjectFactory; +import org.testng.annotations.ObjectFactory; +import org.testng.annotations.Test; + +import org.rhq.core.domain.resource.Resource; +import org.rhq.core.domain.resource.ResourceType; +import org.rhq.core.util.MessageDigestGenerator; + +@PrepareForTest({ ResourceContext.class }) +public class ResourceContextTest { + + @ObjectFactory + public IObjectFactory getObjectFactory() { + return new PowerMockObjectFactory(); + } + + @Test + @SuppressWarnings({ "unchecked", "rawtypes" }) + public void testBasicResourceDataDirectory() throws Exception { + //generate random data for the test + String[] randomStrings = this.generateRandomStrings(3); + String expectedSHA256 = this.computeSHA256(randomStrings[0], randomStrings[1]); + String inputResourceKey = randomStrings[0]; + String inputParentResourceKey = randomStrings[1]; + String inputResourceUuid = randomStrings[2]; + + //tell the method story as it happens: mock or create dependencies and configure + //those dependencies to get the method under test to completion. + ResourceType mockResourceType = mock(ResourceType.class); + + Resource mockResource = mock(Resource.class); + when(mockResource.getResourceKey()).thenReturn(inputResourceKey); + when(mockResource.getUuid()).thenReturn(inputResourceUuid); + when(mockResource.getResourceType()).thenReturn(mockResourceType); + + ResourceContext<?> parentResourceContext = mock(ResourceContext.class); + when(parentResourceContext.getResourceKey()).thenReturn(inputParentResourceKey); + + File mockNewResourceDirectory = mock(File.class); + when(mockNewResourceDirectory.exists()).thenReturn(true); + + File mockOldResourceDirectory = mock(File.class); + when(mockOldResourceDirectory.exists()).thenReturn(false); + + PowerMockito.whenNew(File.class).withParameterTypes(File.class, String.class) + .withArguments(any(File.class), any(String.class)).thenReturn(mockNewResourceDirectory) + .thenReturn(mockOldResourceDirectory); + + File mockTemporaryDirectory = mock(File.class); + File mockDataDirectory = mock(File.class); + + //create object to test and inject required dependencies + ResourceContext<?> objectUnderTest = new ResourceContext(mockResource, null, parentResourceContext, null, null, + mockTemporaryDirectory, mockDataDirectory, null, null, null, null, null, null); + + //run code under test + File result = objectUnderTest.getResourceDataDirectory(); + + //verify the results (Assert and mock verification) + PowerMockito.verifyNew(File.class, times(1)).withArguments(eq(mockDataDirectory), eq(expectedSHA256)); + PowerMockito.verifyNew(File.class, times(1)).withArguments(eq(mockDataDirectory), eq(inputResourceUuid)); + + verify(mockNewResourceDirectory, times(1)).exists(); + verify(mockNewResourceDirectory, never()).mkdirs(); + verify(mockOldResourceDirectory, times(1)).exists(); + verify(mockOldResourceDirectory, never()).renameTo(any(File.class)); + + Assert.assertEquals(result, mockNewResourceDirectory); + } + + @Test + @SuppressWarnings({ "unchecked", "rawtypes" }) + public void testThreeLevelsAncestryResourceDataDirectory() throws Exception { + //generate random data for the test + String[] randomStrings = this.generateRandomStrings(6); + String expectedSHA256 = this.computeSHA256(randomStrings[0], randomStrings[1], randomStrings[2], + randomStrings[3]); + String inputResourceKey = randomStrings[0]; + String inputParent1ResourceKey = randomStrings[1]; + String inputParent2ResourceKey = randomStrings[2]; + String inputParent3ResourceKey = randomStrings[3]; + + String inputResourceUuid = randomStrings[4]; + + //tell the method story as it happens: mock or create dependencies and configure + //those dependencies to get the method under test to completion. + ResourceType mockResourceType = mock(ResourceType.class); + + Resource mockResource = mock(Resource.class); + when(mockResource.getResourceKey()).thenReturn(inputResourceKey); + when(mockResource.getUuid()).thenReturn(inputResourceUuid); + when(mockResource.getResourceType()).thenReturn(mockResourceType); + + ResourceContext parent3ResourceContext = mock(ResourceContext.class); + when(parent3ResourceContext.getResourceKey()).thenReturn(inputParent3ResourceKey); + + ResourceContext parent2ResourceContext = mock(ResourceContext.class); + when(parent2ResourceContext.getResourceKey()).thenReturn(inputParent2ResourceKey); + when(parent2ResourceContext.getParentResourceContext()).thenReturn((ResourceContext) parent3ResourceContext); + + ResourceContext parent1ResourceContext = mock(ResourceContext.class); + when(parent1ResourceContext.getResourceKey()).thenReturn(inputParent1ResourceKey); + when(parent1ResourceContext.getParentResourceContext()).thenReturn((ResourceContext) parent2ResourceContext); + + File mockNewResourceDirectory = mock(File.class); + when(mockNewResourceDirectory.exists()).thenReturn(true); + + File mockOldResourceDirectory = mock(File.class); + when(mockOldResourceDirectory.exists()).thenReturn(false); + + PowerMockito.whenNew(File.class).withParameterTypes(File.class, String.class) + .withArguments(any(File.class), any(String.class)).thenReturn(mockNewResourceDirectory) + .thenReturn(mockOldResourceDirectory); + + File mockTemporaryDirectory = mock(File.class); + File mockDataDirectory = mock(File.class); + + //create object to test and inject required dependencies + ResourceContext<?> objectUnderTest = new ResourceContext(mockResource, null, parent1ResourceContext, null, + null, mockTemporaryDirectory, mockDataDirectory, null, null, null, null, null, null); + + //run code under test + File result = objectUnderTest.getResourceDataDirectory(); + + //verify the results (Assert and mock verification) + PowerMockito.verifyNew(File.class, times(1)).withArguments(eq(mockDataDirectory), eq(expectedSHA256)); + PowerMockito.verifyNew(File.class, times(1)).withArguments(eq(mockDataDirectory), eq(inputResourceUuid)); + + verify(mockNewResourceDirectory, times(1)).exists(); + verify(mockNewResourceDirectory, never()).mkdirs(); + verify(mockOldResourceDirectory, times(1)).exists(); + verify(mockOldResourceDirectory, never()).renameTo(any(File.class)); + + Assert.assertEquals(result, mockNewResourceDirectory); + } + + @Test + @SuppressWarnings({ "unchecked", "rawtypes" }) + public void testRenameInvocationResourceDataDirectory() throws Exception { + //generate random data for the test + String[] randomStrings = this.generateRandomStrings(3); + String expectedSHA256 = this.computeSHA256(randomStrings[0], randomStrings[1]); + String inputResourceKey = randomStrings[0]; + String inputParentResourceKey = randomStrings[1]; + String inputResourceUuid = randomStrings[2]; + + //tell the method story as it happens: mock or create dependencies and configure + //those dependencies to get the method under test to completion. + ResourceType mockResourceType = mock(ResourceType.class); + + Resource mockResource = mock(Resource.class); + when(mockResource.getResourceKey()).thenReturn(inputResourceKey); + when(mockResource.getUuid()).thenReturn(inputResourceUuid); + when(mockResource.getResourceType()).thenReturn(mockResourceType); + + ResourceContext<?> parentResourceContext = mock(ResourceContext.class); + when(parentResourceContext.getResourceKey()).thenReturn(inputParentResourceKey); + + File mockNewResourceDirectory = mock(File.class); + when(mockNewResourceDirectory.exists()).thenReturn(true); + + File mockOldResourceDirectory = mock(File.class); + when(mockOldResourceDirectory.exists()).thenReturn(true); + + PowerMockito.whenNew(File.class).withParameterTypes(File.class, String.class) + .withArguments(any(File.class), any(String.class)).thenReturn(mockNewResourceDirectory) + .thenReturn(mockOldResourceDirectory); + + File mockTemporaryDirectory = mock(File.class); + File mockDataDirectory = mock(File.class); + + //create object to test and inject required dependencies + ResourceContext<?> objectUnderTest = new ResourceContext(mockResource, null, parentResourceContext, null, null, + mockTemporaryDirectory, mockDataDirectory, null, null, null, null, null, null); + + //run code under test + File result = objectUnderTest.getResourceDataDirectory(); + + //verify the results (Assert and mock verification) + PowerMockito.verifyNew(File.class, times(1)).withArguments(eq(mockDataDirectory), eq(expectedSHA256)); + PowerMockito.verifyNew(File.class, times(1)).withArguments(eq(mockDataDirectory), eq(inputResourceUuid)); + + verify(mockNewResourceDirectory, times(1)).exists(); + verify(mockNewResourceDirectory, never()).mkdirs(); + verify(mockOldResourceDirectory, times(1)).exists(); + verify(mockOldResourceDirectory, times(1)).renameTo(eq(mockNewResourceDirectory)); + + Assert.assertEquals(result, mockNewResourceDirectory); + } + + @Test + @SuppressWarnings({ "unchecked", "rawtypes" }) + public void testMkdirsInvocationResourceDataDirectory() throws Exception { + //generate random data for the test + String[] randomStrings = this.generateRandomStrings(3); + String expectedSHA256 = this.computeSHA256(randomStrings[0], randomStrings[1]); + String inputResourceKey = randomStrings[0]; + String inputParentResourceKey = randomStrings[1]; + String inputResourceUuid = randomStrings[2]; + + //tell the method story as it happens: mock or create dependencies and configure + //those dependencies to get the method under test to completion. + ResourceType mockResourceType = mock(ResourceType.class); + + Resource mockResource = mock(Resource.class); + when(mockResource.getResourceKey()).thenReturn(inputResourceKey); + when(mockResource.getUuid()).thenReturn(inputResourceUuid); + when(mockResource.getResourceType()).thenReturn(mockResourceType); + + ResourceContext<?> parentResourceContext = mock(ResourceContext.class); + when(parentResourceContext.getResourceKey()).thenReturn(inputParentResourceKey); + + File mockNewResourceDirectory = mock(File.class); + when(mockNewResourceDirectory.exists()).thenReturn(false); + + File mockOldResourceDirectory = mock(File.class); + when(mockOldResourceDirectory.exists()).thenReturn(false); + + PowerMockito.whenNew(File.class).withParameterTypes(File.class, String.class) + .withArguments(any(File.class), any(String.class)).thenReturn(mockNewResourceDirectory) + .thenReturn(mockOldResourceDirectory); + + File mockTemporaryDirectory = mock(File.class); + File mockDataDirectory = mock(File.class); + + //create object to test and inject required dependencies + ResourceContext<?> objectUnderTest = new ResourceContext(mockResource, null, parentResourceContext, null, null, + mockTemporaryDirectory, mockDataDirectory, null, null, null, null, null, null); + + //run code under test + File result = objectUnderTest.getResourceDataDirectory(); + + //verify the results (Assert and mock verification) + PowerMockito.verifyNew(File.class, times(1)).withArguments(eq(mockDataDirectory), eq(expectedSHA256)); + PowerMockito.verifyNew(File.class, times(1)).withArguments(eq(mockDataDirectory), eq(inputResourceUuid)); + + verify(mockNewResourceDirectory, times(1)).exists(); + verify(mockNewResourceDirectory, times(1)).mkdirs(); + verify(mockOldResourceDirectory, times(1)).exists(); + verify(mockOldResourceDirectory, never()).renameTo(any(File.class)); + + Assert.assertEquals(result, mockNewResourceDirectory); + } + + @Test + @SuppressWarnings({ "unchecked", "rawtypes" }) + public void testOldResouceDirectoryThrowsException() throws Exception { + //generate random data for the test + String[] randomStrings = this.generateRandomStrings(3); + String expectedSHA256 = this.computeSHA256(randomStrings[0], randomStrings[1]); + String inputResourceKey = randomStrings[0]; + String inputParentResourceKey = randomStrings[1]; + String inputResourceUuid = randomStrings[2]; + + //tell the method story as it happens: mock or create dependencies and configure + //those dependencies to get the method under test to completion. + ResourceType mockResourceType = mock(ResourceType.class); + + Resource mockResource = mock(Resource.class); + when(mockResource.getResourceKey()).thenReturn(inputResourceKey); + when(mockResource.getUuid()).thenReturn(inputResourceUuid); + when(mockResource.getResourceType()).thenReturn(mockResourceType); + + ResourceContext<?> parentResourceContext = mock(ResourceContext.class); + when(parentResourceContext.getResourceKey()).thenReturn(inputParentResourceKey); + + File mockNewResourceDirectory = mock(File.class); + when(mockNewResourceDirectory.exists()).thenReturn(false); + + File mockOldResourceDirectory = mock(File.class); + when(mockOldResourceDirectory.exists()).thenThrow(new SecurityException()); + + PowerMockito.whenNew(File.class).withParameterTypes(File.class, String.class) + .withArguments(any(File.class), any(String.class)).thenReturn(mockNewResourceDirectory) + .thenReturn(mockOldResourceDirectory); + + File mockTemporaryDirectory = mock(File.class); + File mockDataDirectory = mock(File.class); + + //create object to test and inject required dependencies + ResourceContext<?> objectUnderTest = new ResourceContext(mockResource, null, parentResourceContext, null, null, + mockTemporaryDirectory, mockDataDirectory, null, null, null, null, null, null); + + //run code under test + File result = objectUnderTest.getResourceDataDirectory(); + + //verify the results (Assert and mock verification) + PowerMockito.verifyNew(File.class, times(1)).withArguments(eq(mockDataDirectory), eq(expectedSHA256)); + PowerMockito.verifyNew(File.class, times(1)).withArguments(eq(mockDataDirectory), eq(inputResourceUuid)); + + verify(mockNewResourceDirectory, times(1)).exists(); + verify(mockNewResourceDirectory, times(1)).mkdirs(); + verify(mockOldResourceDirectory, times(1)).exists(); + verify(mockOldResourceDirectory, never()).renameTo(any(File.class)); + + Assert.assertEquals(result, mockNewResourceDirectory); + } + + @Test + @SuppressWarnings({ "unchecked", "rawtypes" }) + public void testThreeLevelsAncestryFutureChildDataDirectory() throws Exception { + //generate random data for the test + String[] randomStrings = this.generateRandomStrings(6); + String expectedSHA256 = this.computeSHA256(randomStrings[0], randomStrings[1], randomStrings[2], + randomStrings[3], randomStrings[4]); + String inputChildResourceKey = randomStrings[0]; + String inputResourceKey = randomStrings[1]; + String inputParent1ResourceKey = randomStrings[2]; + String inputParent2ResourceKey = randomStrings[3]; + String inputParent3ResourceKey = randomStrings[4]; + + String inputResourceUuid = randomStrings[5]; + + //tell the method story as it happens: mock or create dependencies and configure + //those dependencies to get the method under test to completion. + ResourceType mockResourceType = mock(ResourceType.class); + + Resource mockResource = mock(Resource.class); + when(mockResource.getResourceKey()).thenReturn(inputResourceKey); + when(mockResource.getUuid()).thenReturn(inputResourceUuid); + when(mockResource.getResourceType()).thenReturn(mockResourceType); + + ResourceContext parent3ResourceContext = mock(ResourceContext.class); + when(parent3ResourceContext.getResourceKey()).thenReturn(inputParent3ResourceKey); + + ResourceContext parent2ResourceContext = mock(ResourceContext.class); + when(parent2ResourceContext.getResourceKey()).thenReturn(inputParent2ResourceKey); + when(parent2ResourceContext.getParentResourceContext()).thenReturn((ResourceContext) parent3ResourceContext); + + ResourceContext parent1ResourceContext = mock(ResourceContext.class); + when(parent1ResourceContext.getResourceKey()).thenReturn(inputParent1ResourceKey); + when(parent1ResourceContext.getParentResourceContext()).thenReturn((ResourceContext) parent2ResourceContext); + + File mockChildResourceDirectory = mock(File.class); + when(mockChildResourceDirectory.exists()).thenReturn(false); + + PowerMockito.whenNew(File.class).withParameterTypes(File.class, String.class) + .withArguments(any(File.class), any(String.class)).thenReturn(mockChildResourceDirectory); + + File mockTemporaryDirectory = mock(File.class); + File mockDataDirectory = mock(File.class); + + //create object to test and inject required dependencies + ResourceContext<?> objectUnderTest = new ResourceContext(mockResource, null, parent1ResourceContext, null, + null, mockTemporaryDirectory, mockDataDirectory, null, null, null, null, null, null); + + //run code under test + File result = objectUnderTest.getFutureChildResourceDataDirectory(inputChildResourceKey); + + //verify the results (Assert and mock verification) + PowerMockito.verifyNew(File.class, times(1)).withArguments(eq(mockDataDirectory), eq(expectedSHA256)); + + verify(mockChildResourceDirectory, times(1)).exists(); + verify(mockChildResourceDirectory, times(1)).mkdirs(); + + Assert.assertEquals(result, mockChildResourceDirectory); + } + + private String[] generateRandomStrings(int length) { + String[] randomUuids = new String[length]; + for (int i = 0; i < length; i++) { + randomUuids[i] = UUID.randomUUID().getLeastSignificantBits() + ""; + } + return randomUuids; + } + + private String computeSHA256(String... values) { + MessageDigestGenerator messageDigest = new MessageDigestGenerator(MessageDigestGenerator.SHA_256); + for (String value : values) { + messageDigest.add(value.getBytes()); + } + return messageDigest.getDigestString(); + } +} \ No newline at end of file diff --git a/modules/plugins/jboss-as-5/pom.xml b/modules/plugins/jboss-as-5/pom.xml index 906eb1c..b6b730a 100644 --- a/modules/plugins/jboss-as-5/pom.xml +++ b/modules/plugins/jboss-as-5/pom.xml @@ -150,6 +150,20 @@ <scope>test</scope> </dependency>
+ <dependency> + <groupId>org.powermock</groupId> + <artifactId>powermock-module-testng</artifactId> + <version>${powermock.version}</version> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.powermock</groupId> + <artifactId>powermock-api-mockito</artifactId> + <version>${powermock.version}</version> + <scope>test</scope> + </dependency> + </dependencies>
<build> diff --git a/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/StandaloneManagedDeploymentComponent.java b/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/StandaloneManagedDeploymentComponent.java index f1eac1a..3f9d44b 100644 --- a/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/StandaloneManagedDeploymentComponent.java +++ b/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/StandaloneManagedDeploymentComponent.java @@ -459,7 +459,7 @@ public class StandaloneManagedDeploymentComponent extends AbstractManagedDeploym
private File writeNewAppBitsToTempFile(ContentServices contentServices, ResourcePackageDetails packageDetails) throws Exception { - File tempDir = new File(getResourceContext().getTemporaryDirectory(), "/deploy" + File tempDir = new File(getResourceContext().getTemporaryDirectory(), "deploy" + UUID.randomUUID().getLeastSignificantBits()); tempDir.mkdirs();
diff --git a/modules/plugins/jboss-as-5/src/test/java/org/rhq/plugins/jbossas5/test/StandaloneManagedDeploymentComponentTest.java b/modules/plugins/jboss-as-5/src/test/java/org/rhq/plugins/jbossas5/test/StandaloneManagedDeploymentComponentTest.java index d645f5a..b920c45 100644 --- a/modules/plugins/jboss-as-5/src/test/java/org/rhq/plugins/jbossas5/test/StandaloneManagedDeploymentComponentTest.java +++ b/modules/plugins/jboss-as-5/src/test/java/org/rhq/plugins/jbossas5/test/StandaloneManagedDeploymentComponentTest.java @@ -19,25 +19,38 @@ package org.rhq.plugins.jbossas5.test;
import static org.mockito.Matchers.any; +import static org.mockito.Matchers.argThat; +import static org.mockito.Matchers.eq; import static org.mockito.Matchers.isNull; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when;
+import java.io.BufferedOutputStream; import java.io.File; +import java.io.FileOutputStream; import java.lang.reflect.Field; +import java.lang.reflect.Method; import java.util.Set;
+import org.mockito.ArgumentMatcher; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.testng.PowerMockObjectFactory; import org.testng.Assert; import org.testng.IObjectFactory; import org.testng.annotations.ObjectFactory; +import org.testng.annotations.Test;
+import org.rhq.core.domain.content.PackageDetailsKey; import org.rhq.core.domain.content.PackageType; import org.rhq.core.domain.content.transfer.ResourcePackageDetails; +import org.rhq.core.pluginapi.content.ContentContext; +import org.rhq.core.pluginapi.content.ContentServices; import org.rhq.core.pluginapi.content.FileContentDelegate; +import org.rhq.core.pluginapi.inventory.ResourceContext; import org.rhq.plugins.jbossas5.AbstractManagedDeploymentComponent; import org.rhq.plugins.jbossas5.StandaloneManagedDeploymentComponent;
@@ -90,4 +103,81 @@ public class StandaloneManagedDeploymentComponentTest {
verify(mockFileContentDelegate).saveDeploymentSHA(any(File.class), any(File.class), any(File.class)); } + + @Test + public void testWriteNewAppBitsToTimpFile() throws Exception { + //tell the method story as it happens: mock or create dependencies and configure + //those dependencies to get the method under test to completion. + File mockResourceTemporaryDir = mock(File.class); + + ResourceContext mockResourceContext = mock(ResourceContext.class); + when(mockResourceContext.getTemporaryDirectory()).thenReturn(mockResourceTemporaryDir); + + ContentServices mockContentServices = mock(ContentServices.class); + ResourcePackageDetails mockResourcePackageDetails = mock(ResourcePackageDetails.class); + + File mockTempDir = mock(File.class); + File mockTempFile = mock(File.class); + when(mockTempFile.exists()).thenReturn(true); + + PowerMockito.whenNew(File.class).withParameterTypes(File.class, String.class) + .withArguments(any(File.class), any(String.class)).thenReturn(mockTempDir).thenReturn(mockTempFile); + + File mockDeploymentFile = mock(File.class); + when(mockDeploymentFile.getName()).thenReturn("testFileName"); + + FileOutputStream mockFileOutputStream = mock(FileOutputStream.class); + + PowerMockito.whenNew(FileOutputStream.class).withParameterTypes(File.class).withArguments(any(File.class)) + .thenReturn(mockFileOutputStream); + + //create object to test and inject required dependencies + StandaloneManagedDeploymentComponent objectUnderTest = spy(new StandaloneManagedDeploymentComponent()); + when(objectUnderTest.getResourceContext()).thenReturn(mockResourceContext); + + Field[] fields = AbstractManagedDeploymentComponent.class.getDeclaredFields(); + for (Field field : fields) { + if (field.getName().equals("deploymentFile")) { + field.setAccessible(true); + field.set(objectUnderTest, mockDeploymentFile); + } + } + + //run code under test + //will run through reflection since the method is private + Method[] methods = StandaloneManagedDeploymentComponent.class.getDeclaredMethods(); + for (Method method : methods) { + if (method.getName().equals("writeNewAppBitsToTempFile")) { + method.setAccessible(true); + method.invoke(objectUnderTest, mockContentServices, mockResourcePackageDetails); + } + } + + //verify the results (Assert and mock verification) + PowerMockito.verifyNew(File.class, times(1)).withArguments(eq(mockResourceTemporaryDir), + argThat(new ArgumentMatcher<String>() { + @Override + public boolean matches(Object argumentObj) { + String argument = argumentObj.toString(); + if (!argument.startsWith("deploy") || argument.length() < 7) { + return false; + } + + try { + String uuidPortion = argument.substring(6); + Long.parseLong(uuidPortion); + } catch (Exception e) { + return false; + } + + return true; + } + })); + PowerMockito.verifyNew(File.class, times(1)).withArguments(eq(mockTempDir), eq("testFileName")); + + verify(mockTempDir).mkdirs(); + verify(mockTempFile).exists(); + verify(mockContentServices).downloadPackageBits(any(ContentContext.class), any(PackageDetailsKey.class), + any(BufferedOutputStream.class), eq(true)); + } } \ No newline at end of file
commit 28f5c74ec24267eecf6ffe1e36a01a012e5c7198 Author: Stefan Negrea snegrea@redhat.com Date: Tue May 22 15:44:57 2012 -0500
[BZ 646631, 790753, 820650] Updated AS5 deployer use a unique temp folder instead of a unique temp war name. The war name is used as-is by the AS5 deployer to determine the name of the application be deployed. Updated the deployer for new resources to correctly create the SHA256 file for exploded deployments.
diff --git a/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/inventory/ResourceContext.java b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/inventory/ResourceContext.java index 0dcf021..4b21719 100644 --- a/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/inventory/ResourceContext.java +++ b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/inventory/ResourceContext.java @@ -48,6 +48,7 @@ import org.rhq.core.system.ProcessInfo; import org.rhq.core.system.SystemInfo; import org.rhq.core.system.SystemInfoFactory; import org.rhq.core.system.pquery.ProcessInfoQuery; +import org.rhq.core.util.MessageDigestGenerator;
/** * The context object that {@link ResourceComponent} objects will have access - it will have all the information that @@ -67,6 +68,7 @@ public class ResourceContext<T extends ResourceComponent<?>> { private static final Log LOG = LogFactory.getLog(ResourceContext.class);
private final String resourceKey; + private final String resourceUuid; private final ResourceType resourceType; private final String version; private final T parentResourceComponent; @@ -76,7 +78,6 @@ public class ResourceContext<T extends ResourceComponent<?>> { private final ResourceDiscoveryComponent<T> resourceDiscoveryComponent; private final File temporaryDirectory; private final File dataDirectory; - private final File resourceDataDirectory; private final String pluginContainerName; private final EventContext eventContext; private final OperationContext operationContext; @@ -163,7 +164,6 @@ public class ResourceContext<T extends ResourceComponent<?>> { this.systemInformation = systemInfo; this.pluginConfiguration = resource.getPluginConfiguration(); this.dataDirectory = dataDirectory; - this.resourceDataDirectory = new File(dataDirectory, resource.getUuid()); this.pluginContainerName = pluginContainerName; this.pluginContainerDeployment = pluginContainerDeployment; if (temporaryDirectory == null) { @@ -183,6 +183,8 @@ public class ResourceContext<T extends ResourceComponent<?>> { parentResourceUuid = resource.getParentResource().getUuid(); } this.trackedProcesses = getTrackedProcesses(parentResourceUuid, resourceType); + + this.resourceUuid = resource.getUuid(); }
/** @@ -217,16 +219,44 @@ public class ResourceContext<T extends ResourceComponent<?>> { }
/** - * The {@link Resource#getUuid() uuid} of the resource this context is associated with. + * The data directory of the resource this context is associated with. * - * @return the resource's uuid string + * @return resource data directory */ public File getResourceDataDirectory() { + File resourceDataDirectory = new File(dataDirectory, this.getAncestryBasedResourceKey()); + + try { + File oldResourceDataDirectory = new File(dataDirectory, this.resourceUuid); + if (oldResourceDataDirectory.exists()) { + oldResourceDataDirectory.renameTo(resourceDataDirectory); + } + } catch (Exception e) { + //Just prevent an exception related to renaming of the old + //data resource directory from causing this method fail. + //This method should continue and create the new folder + //as if the old folder never existed. + } + if (!resourceDataDirectory.exists()) { resourceDataDirectory.mkdirs(); }
- return this.resourceDataDirectory; + return resourceDataDirectory; + } + + /** + * The data directory of a child to be created for the resource this context is associated with. + * + * @return child resource data directory + */ + public File getFutureChildResourceDataDirectory(String childResourceKey) { + File childResourceDataDirectory = new File(dataDirectory, this.getAncestryBasedResourceKey(childResourceKey)); + if (!childResourceDataDirectory.exists()) { + childResourceDataDirectory.mkdirs(); + } + + return childResourceDataDirectory; }
/** @@ -505,4 +535,38 @@ public class ResourceContext<T extends ResourceComponent<?>> { return ret; } } + + /** + * Calculates a unique key based on parents' resource keys. The final key is the SHA256 + * all the ancestry resource keys. + * + * @return key + */ + private String getAncestryBasedResourceKey() { + return this.getAncestryBasedResourceKey(null); + } + + /** + * Calculates a unique key based on parents' resource keys. + * + * @param prefixKey extra key to be appended at the beginning of the digest process + * @return key + */ + private String getAncestryBasedResourceKey(String prefixKey) { + MessageDigestGenerator messageDigest = new MessageDigestGenerator(MessageDigestGenerator.SHA_256); + + if (prefixKey != null) { + messageDigest.add(prefixKey.getBytes()); + } + + messageDigest.add(this.resourceKey.getBytes()); + + ResourceContext<?> ancestor = this.parentResourceContext; + while (ancestor != null) { + messageDigest.add(ancestor.getResourceKey().getBytes()); + ancestor = ancestor.getParentResourceContext(); + } + + return messageDigest.getDigestString(); + } } \ No newline at end of file diff --git a/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/ApplicationServerComponent.java b/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/ApplicationServerComponent.java index e5f8fe6..d0839a8 100644 --- a/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/ApplicationServerComponent.java +++ b/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/ApplicationServerComponent.java @@ -190,7 +190,7 @@ public class ApplicationServerComponent<T extends ResourceComponent<?>> implemen this.contentFacetDelegate = new ApplicationServerContentFacetDelegate(workflowManager, configPath, resourceContext.getContentContext());
- this.createChildResourceDelegate = new CreateChildResourceFacetDelegate(this); + this.createChildResourceDelegate = new CreateChildResourceFacetDelegate(this, this.getResourceContext());
// prepare to perform async avail checking Configuration pc = resourceContext.getPluginConfiguration(); diff --git a/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/JBossMessagingComponent.java b/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/JBossMessagingComponent.java index e5656f5..83e3ae8 100644 --- a/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/JBossMessagingComponent.java +++ b/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/JBossMessagingComponent.java @@ -24,7 +24,6 @@ package org.rhq.plugins.jbossas5;
import java.util.Set;
-import org.rhq.core.domain.measurement.AvailabilityType; import org.rhq.core.domain.measurement.MeasurementReport; import org.rhq.core.domain.measurement.MeasurementScheduleRequest; import org.rhq.core.pluginapi.inventory.CreateChildResourceFacet; @@ -45,7 +44,7 @@ public class JBossMessagingComponent extends ManagedComponentComponent implement
public void start(ResourceContext<ProfileServiceComponent<?>> resourceContext) throws Exception { super.start(resourceContext); - this.createChildResourceDelegate = new CreateChildResourceFacetDelegate(this); + this.createChildResourceDelegate = new CreateChildResourceFacetDelegate(this, this.getResourceContext()); }
public void stop() { diff --git a/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/StandaloneManagedDeploymentComponent.java b/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/StandaloneManagedDeploymentComponent.java index f18c564..f1eac1a 100644 --- a/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/StandaloneManagedDeploymentComponent.java +++ b/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/StandaloneManagedDeploymentComponent.java @@ -274,26 +274,6 @@ public class StandaloneManagedDeploymentComponent extends AbstractManagedDeploym + "' to '" + backupOfOriginalFile + "'."); }
- // Now stop the original app. - try { - DeploymentManager deploymentManager = getConnection().getDeploymentManager(); - DeploymentProgress progress = deploymentManager.stop(this.deploymentName); - DeploymentUtils.run(progress); - } catch (Exception e) { - throw new RuntimeException("Failed to stop deployment [" + this.deploymentName + "].", e); - } - - // And then remove it (this will delete the physical file/dir from the deploy dir). - try { - DeploymentManager deploymentManager = getConnection().getDeploymentManager(); - DeploymentProgress progress = deploymentManager.remove(this.deploymentName); - DeploymentUtils.run(progress); - } catch (Exception e) { - throw new RuntimeException("Failed to remove deployment [" + this.deploymentName + "].", e); - } - - // Deploy away! - log.debug("Deploying '" + tempFile + "'..."); DeploymentManager deploymentManager = getConnection().getDeploymentManager();
// as crazy as it might sound, there is apparently no way for you to ask the profile service @@ -328,7 +308,25 @@ public class StandaloneManagedDeploymentComponent extends AbstractManagedDeploym } }
+ // Now stop the original app. + try { + DeploymentProgress progress = deploymentManager.stop(this.deploymentName); + DeploymentUtils.run(progress); + } catch (Exception e) { + throw new RuntimeException("Failed to stop deployment [" + this.deploymentName + "].", e); + } + + // And then remove it (this will delete the physical file/dir from the deploy dir). + try { + DeploymentProgress progress = deploymentManager.remove(this.deploymentName); + DeploymentUtils.run(progress); + } catch (Exception e) { + throw new RuntimeException("Failed to remove deployment [" + this.deploymentName + "].", e); + } + + // Deploy away! try { + log.debug("Deploying '" + tempFile + "'..."); DeploymentUtils.deployArchive(deploymentManager, tempFile, deployExploded); } catch (Exception e) { // Deploy failed - rollback to the original app file... @@ -383,7 +381,7 @@ public class StandaloneManagedDeploymentComponent extends AbstractManagedDeploym
// Remove temporary files created by this deployment. deleteTemporaryFile(backupDir); - deleteTemporaryFile(tempFile); + deleteTemporaryFile(tempFile.getParentFile());
DeployPackagesResponse response = new DeployPackagesResponse(ContentResponseResult.SUCCESS); DeployIndividualPackageResponse packageResponse = new DeployIndividualPackageResponse(packageDetails.getKey(), @@ -461,8 +459,11 @@ public class StandaloneManagedDeploymentComponent extends AbstractManagedDeploym
private File writeNewAppBitsToTempFile(ContentServices contentServices, ResourcePackageDetails packageDetails) throws Exception { - File tempDir = getResourceContext().getTemporaryDirectory(); - File tempFile = new File(tempDir, this.deploymentFile.getName() + UUID.randomUUID().getLeastSignificantBits()); + File tempDir = new File(getResourceContext().getTemporaryDirectory(), "/deploy" + + UUID.randomUUID().getLeastSignificantBits()); + tempDir.mkdirs(); + + File tempFile = new File(tempDir, this.deploymentFile.getName());
OutputStream tempOutputStream = null; try { diff --git a/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/deploy/ManagedComponentDeployer.java b/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/deploy/ManagedComponentDeployer.java index de6a174..f5eaec3 100644 --- a/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/deploy/ManagedComponentDeployer.java +++ b/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/deploy/ManagedComponentDeployer.java @@ -19,13 +19,9 @@ package org.rhq.plugins.jbossas5.deploy;
import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; import java.net.URI; import java.util.Collection; import java.util.Set; -import java.util.jar.Attributes; -import java.util.jar.Manifest;
import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -43,8 +39,9 @@ import org.rhq.core.domain.content.PackageDetailsKey; import org.rhq.core.domain.content.transfer.ResourcePackageDetails; import org.rhq.core.domain.resource.CreateResourceStatus; import org.rhq.core.domain.resource.ResourceType; +import org.rhq.core.pluginapi.content.FileContentDelegate; import org.rhq.core.pluginapi.inventory.CreateResourceReport; -import org.rhq.core.util.MessageDigestGenerator; +import org.rhq.core.pluginapi.inventory.ResourceContext; import org.rhq.plugins.jbossas5.connection.ProfileServiceConnection; import org.rhq.plugins.jbossas5.util.ConversionUtils; import org.rhq.plugins.jbossas5.util.DeploymentUtils; @@ -62,10 +59,13 @@ public class ManagedComponentDeployer implements Deployer {
private PackageDownloader downloader; private ProfileServiceConnection profileServiceConnection; + private ResourceContext<?> parentResourceContext;
- public ManagedComponentDeployer(ProfileServiceConnection profileServiceConnection, PackageDownloader downloader) { + public ManagedComponentDeployer(ProfileServiceConnection profileServiceConnection, PackageDownloader downloader, + ResourceContext<?> parentResourceContext) { this.downloader = downloader; this.profileServiceConnection = profileServiceConnection; + this.parentResourceContext = parentResourceContext; }
public void deploy(CreateResourceReport createResourceReport, ResourceType resourceType) { @@ -89,7 +89,6 @@ public class ManagedComponentDeployer implements Deployer { abortIfApplicationAlreadyDeployed(resourceType, archiveFile);
Configuration deployTimeConfig = details.getDeploymentTimeConfiguration(); - @SuppressWarnings({ "ConstantConditions" }) boolean deployExploded = deployTimeConfig.getSimple("deployExploded").getBooleanValue();
DeploymentManager deploymentManager = this.profileServiceConnection.getDeploymentManager(); @@ -135,43 +134,14 @@ public class ManagedComponentDeployer implements Deployer { // If deployed exploded, we need to store the SHA of source package in META-INF/MANIFEST.MF for correct // versioning. if (deployExploded) { - MessageDigestGenerator sha256Generator = new MessageDigestGenerator(MessageDigestGenerator.SHA_256); - String shaString = sha256Generator.calcDigestString(archiveFile); URI deploymentURI = URI.create(deploymentName); // e.g.: /C:/opt/jboss-6.0.0.Final/server/default/deploy/foo.war String deploymentPath = deploymentURI.getPath(); File deploymentFile = new File(deploymentPath); - if (deploymentFile.isDirectory()) { - File manifestFile = new File(deploymentFile, "META-INF/MANIFEST.MF"); - Manifest manifest; - if (manifestFile.exists()) { - FileInputStream inputStream = new FileInputStream(manifestFile); - try { - manifest = new Manifest(inputStream); - } finally { - inputStream.close(); - } - } else { - File metaInf = new File(deploymentFile, "META-INF"); - if (!metaInf.exists()) - if (!metaInf.mkdir()) - throw new Exception("Could not create directory " + deploymentFile + "META-INF."); - - manifestFile = new File(metaInf, "MANIFEST.MF"); - manifest = new Manifest(); - } - Attributes attribs = manifest.getMainAttributes(); - attribs.putValue("RHQ-Sha256", shaString); - FileOutputStream outputStream = new FileOutputStream(manifestFile); - try { - manifest.write(outputStream); - } finally { - outputStream.close(); - } - } else { - LOG.error("Exploded deployment '" + deploymentFile - + "' does not exist or is not a directory - unable to add RHQ versioning metadata to META-INF/MANIFEST.MF."); - } + FileContentDelegate fileContentDelegate = new FileContentDelegate(); + + fileContentDelegate.saveDeploymentSHA(archiveFile, deploymentFile, + parentResourceContext.getFutureChildResourceDataDirectory(archiveName)); }
// Reload the management view to pickup the ManagedDeployment for the app we just deployed. diff --git a/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/helper/CreateChildResourceFacetDelegate.java b/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/helper/CreateChildResourceFacetDelegate.java index 5a9bed1..af18723 100644 --- a/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/helper/CreateChildResourceFacetDelegate.java +++ b/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/helper/CreateChildResourceFacetDelegate.java @@ -5,11 +5,13 @@ import java.util.Map;
import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.jboss.deployers.spi.management.ManagementView; import org.jboss.managed.api.ComponentType; import org.jboss.managed.api.DeploymentTemplateInfo; import org.jboss.managed.api.ManagedProperty; import org.jboss.profileservice.spi.NoSuchDeploymentException; + import org.rhq.core.domain.configuration.Configuration; import org.rhq.core.domain.configuration.Property; import org.rhq.core.domain.configuration.PropertySimple; @@ -21,6 +23,7 @@ import org.rhq.core.domain.resource.ResourceCreationDataType; import org.rhq.core.domain.resource.ResourceType; import org.rhq.core.pluginapi.inventory.CreateChildResourceFacet; import org.rhq.core.pluginapi.inventory.CreateResourceReport; +import org.rhq.core.pluginapi.inventory.ResourceContext; import org.rhq.core.system.SystemInfo; import org.rhq.plugins.jbossas5.ApplicationServerPluginConfigurationProperties; import org.rhq.plugins.jbossas5.ManagedComponentComponent; @@ -49,9 +52,11 @@ public class CreateChildResourceFacetDelegate implements CreateChildResourceFace private final Log log = LogFactory.getLog(this.getClass());
private ProfileServiceComponent component; + private ResourceContext<?> parentResourceContext;
- public CreateChildResourceFacetDelegate(ProfileServiceComponent component) { + public CreateChildResourceFacetDelegate(ProfileServiceComponent component, ResourceContext<?> parentResourceContext) { this.component = component; + this.parentResourceContext = parentResourceContext; }
public CreateResourceReport createResource(CreateResourceReport createResourceReport) { @@ -158,7 +163,7 @@ public class CreateChildResourceFacetDelegate implements CreateChildResourceFace SystemInfo systemInfo = component.getResourceContext().getSystemInformation(); return new ScriptDeployer(jbossHome, systemInfo, downloader); } else { - return new ManagedComponentDeployer(profileServiceConnection, downloader); + return new ManagedComponentDeployer(profileServiceConnection, downloader, parentResourceContext); } }
rhq-commits@lists.fedorahosted.org