[rhq] modules/enterprise
by John Sanda
modules/enterprise/server/plugins/drift-mongodb/src/test/java/org/rhq/enterprise/server/plugins/drift/mongodb/GridFSTest.java | 18 +++++++++-
1 file changed, 17 insertions(+), 1 deletion(-)
New commits:
commit 8bf3efd2ae96d482edcc4764070b39b218e4dfde
Author: John Sanda <jsanda(a)redhat.com>
Date: Thu Sep 15 22:19:29 2011 -0400
Update test/example to write and read file using GridFS
diff --git a/modules/enterprise/server/plugins/drift-mongodb/src/test/java/org/rhq/enterprise/server/plugins/drift/mongodb/GridFSTest.java b/modules/enterprise/server/plugins/drift-mongodb/src/test/java/org/rhq/enterprise/server/plugins/drift/mongodb/GridFSTest.java
index 5a76a2b..057dfc5 100644
--- a/modules/enterprise/server/plugins/drift-mongodb/src/test/java/org/rhq/enterprise/server/plugins/drift/mongodb/GridFSTest.java
+++ b/modules/enterprise/server/plugins/drift-mongodb/src/test/java/org/rhq/enterprise/server/plugins/drift/mongodb/GridFSTest.java
@@ -19,6 +19,7 @@
package org.rhq.enterprise.server.plugins.drift.mongodb;
+import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
@@ -33,6 +34,11 @@ import org.bson.types.ObjectId;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
+import org.rhq.core.util.stream.StreamUtil;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+
public class GridFSTest {
Mongo connection;
@@ -48,7 +54,7 @@ public class GridFSTest {
}
@Test(enabled = false)
- public void writeFile() throws Exception {
+ public void writeAndReadFile() throws Exception {
GridFS gridFS = new GridFS(db);
File file = new File("/home/jsanda/clojure-plugin.tar");
GridFSInputFile inputFile = gridFS.createFile(new FileInputStream(file), file.getName());
@@ -58,6 +64,16 @@ public class GridFSTest {
FileOutputStream stream = new FileOutputStream("/home/jsanda/gridfs-test.tar");
GridFSDBFile gridFSDBFile = gridFS.findOne((ObjectId) inputFile.getId());
gridFSDBFile.writeTo(stream);
+
+ GridFSDBFile dbFile = gridFS.findOne(file.getName());
+ assertNotNull(dbFile);
+
+ File outputFile = new File("/tmp/clojure-plugin.tar");
+ outputFile.delete();
+
+ StreamUtil.copy(dbFile.getInputStream(), new BufferedOutputStream(new FileOutputStream(outputFile)), true);
+
+ assertEquals(outputFile.length(), file.length());
}
}
12 years, 9 months
[rhq] modules/core
by John Sanda
modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/sync/DriftSyncManager.java | 26 +++++
modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/sync/DriftSynchronizer.java | 46 ++++++++++
modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/sync/RuntimeSynchronizer.java | 14 +++
modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/sync/StartupSynchronizer.java | 10 ++
4 files changed, 96 insertions(+)
New commits:
commit 5f59b538976e11ac8f68fff53c174e13eb3f0cc5
Author: John Sanda <jsanda(a)redhat.com>
Date: Thu Sep 15 21:37:18 2011 -0400
adding javadocs
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/sync/DriftSyncManager.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/sync/DriftSyncManager.java
index efb27cc..b9df2ce 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/sync/DriftSyncManager.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/sync/DriftSyncManager.java
@@ -36,6 +36,14 @@ import org.rhq.core.pc.inventory.InventoryManager;
import static org.rhq.core.domain.drift.DriftConfigurationComparator.CompareMode.BOTH_BASE_INFO_AND_DIRECTORY_SPECIFICATIONS;
+/**
+ * This class handles syncing drift configurations during inventory sync. This class is
+ * intended to server as the public interface (so to speak) to {@link InventoryManager} for
+ * syncing drift configurations.
+ * <br/><br/>
+ * Please review the docs for each of the setter methods to determine which properties
+ * should be set before invoking any business logic methods.
+ */
public class DriftSyncManager {
private final Log log = LogFactory.getLog(DriftSyncManager.class);
@@ -47,18 +55,36 @@ public class DriftSyncManager {
private File dataDir;
+ /**
+ * @param driftServer The interface to the remote server. This property must be set.
+ * It is injected to facilitate testing with stubs or mocks.
+ */
public void setDriftServer(DriftServerService driftServer) {
this.driftServer = driftServer;
}
+ /**
+ * @param driftManager The drift manager singleton created by the plugin container.
+ * This property must be set even if drift manager is not yet initialized. It is
+ * injected to facilitate testing with stubs or mocks.
+ */
public void setDriftManager(DriftManager driftManager) {
driftMgr = driftManager;
}
+ /**
+ * @param inventoryManager The inventory manager singleton created by the plugin
+ * container. This property must be set. It is injected to facilitate testing with stubs
+ * or mocks.
+ */
public void setInventoryManager(InventoryManager inventoryManager) {
inventoryMgr = inventoryManager;
}
+ /**
+ * @param dataDirectory The plugin container data directory where inventory files are
+ * stored. This property must be set. It is injected to facilitate testing.
+ */
public void setDataDirectory(File dataDirectory) {
dataDir = dataDirectory;
}
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/sync/DriftSynchronizer.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/sync/DriftSynchronizer.java
index 79ac3ad..757abe6 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/sync/DriftSynchronizer.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/sync/DriftSynchronizer.java
@@ -24,15 +24,61 @@ import java.util.Set;
import org.rhq.core.domain.drift.DriftConfiguration;
+/**
+ * A DriftSynchronizer is responsible for sycning {@link DriftConfiguration}s in the
+ * server's with those in the local inventory.
+ */
public interface DriftSynchronizer {
+ /**
+ * Determines which drift configurations for a resource have been deleted on the server
+ * and need to be purged from the local inventory. This method should not make any
+ * changes to the local inventory.
+ *
+ * @param resourceId
+ * @param configurationsFromServer A set of drift configurations belonging to the
+ * resource with the specified id. The set uses a {@link org.rhq.core.domain.drift.DriftConfigurationComparator DriftConfigurationComparator}
+ * with the compare mode set to {@link org.rhq.core.domain.drift.DriftConfigurationComparator.CompareMode#BOTH_BASE_INFO_AND_DIRECTORY_SPECIFICATIONS BOTH_BASE_INFO_AND_DIRECTORY_SPECIFICATIONS}.
+ * @return A list of drift configurations that need to be purged from the local inventory.
+ */
List<DriftConfiguration> getDeletedConfigurations(int resourceId,
Set<DriftConfiguration> configurationsFromServer);
+ /**
+ * Removes the drift configurations from local inventory. Implementations are responsible
+ * for deciding how that is to be done. For example, if the plugin container is not
+ * fully initialized, then purging will involve removing configurations from the
+ * {@link org.rhq.core.pc.inventory.ResourceContainer ResourceContainer}. But if the
+ * plugin container is initialized, then drift detection will have to be unscheduled.
+ *
+ * @param resourceId
+ * @param configurations The drift configurations to purge from local inventory
+ */
void purgeFromLocalInventory(int resourceId, List<DriftConfiguration> configurations);
+ /**
+ * Determines which drift configurations for a resource have been added on the server
+ * and need to be added to the local inventory. This method should not make any changes
+ * to the local inventory.
+ *
+ * @param resourceId
+ * @param configurationsFromServer A set of drift configurations belonging to the
+ * resource with the specified id. The set uses a {@link org.rhq.core.domain.drift.DriftConfigurationComparator DriftConfigurationComparator}
+ * with the compare mode set to {@link org.rhq.core.domain.drift.DriftConfigurationComparator.CompareMode#BOTH_BASE_INFO_AND_DIRECTORY_SPECIFICATIONS BOTH_BASE_INFO_AND_DIRECTORY_SPECIFICATIONS}.
+ * @return A list of drift configurations that need to be purged from the local inventory.
+ */
List<DriftConfiguration> getAddedConfigurations(int resourceId, Set<DriftConfiguration> configurationsFromServer);
+ /**
+ * Adds the drift configurations to the local inventory. Implementations are responsible
+ * for deciding how that is to be done. For example, if the plugin container is not
+ * fully initialized, then adding a configuration will involve adding it to the
+ * {@link org.rhq.core.pc.inventory.ResourceContainer ResourceContainer}. But if the
+ * plugin container is initialized, drift detection will have to be scheduled.
+ *
+ * @param resourceId
+ * @param configurations The drift configurations to add to the local inventory.
+ */
void addToLocalInventory(int resourceId, List<DriftConfiguration> configurations);
}
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/sync/RuntimeSynchronizer.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/sync/RuntimeSynchronizer.java
index e7b4aa0..9fe0a7b 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/sync/RuntimeSynchronizer.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/sync/RuntimeSynchronizer.java
@@ -34,6 +34,20 @@ import org.rhq.core.pc.drift.ScheduleQueue;
import static org.rhq.core.domain.drift.DriftConfigurationComparator.CompareMode.BOTH_BASE_INFO_AND_DIRECTORY_SPECIFICATIONS;
+/**
+ * As its name implies, this class synchronizes drift configurations at runtime. By runtime
+ * we mean when {@link DriftManager} is fully initialized. Updating the local inventory is
+ * done through DriftManager. When this class determines that a drift configuration needs
+ * to be purged from the local inventory, it does so by calling DriftManager to unschedule
+ * drift detection. Likewise when this class determines that a drift configuration needs
+ * to be added to the local inventory, it does so by calling DriftManager to schedule
+ * detection.
+ * <br/><br/>
+ * Note that inventory sync happens regularly after the plugin container is initialized.
+ * Discovery scans are performed at fixed intervals. The results of a discovery scan are
+ * reported to the server, and the server sends back {@link org.rhq.core.domain.discovery.ResourceSyncInfo resource sync info}
+ * which is then used to sync with the local inventory.
+ */
class RuntimeSynchronizer implements DriftSynchronizer {
private final Log log = LogFactory.getLog(RuntimeSynchronizer.class);
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/sync/StartupSynchronizer.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/sync/StartupSynchronizer.java
index 4309bf8..7a472ad 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/sync/StartupSynchronizer.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/sync/StartupSynchronizer.java
@@ -33,6 +33,16 @@ import org.rhq.core.pc.inventory.ResourceContainer;
import static org.rhq.core.util.file.FileUtil.purge;
+/**
+ * As its name implies, this class synchronizes drift configurations at start up or any
+ * time when the plugin container is not fully initialized. If the plugin container is not
+ * fully initialized, then that means {@link org.rhq.core.pc.drift.DriftManager DriftManager}
+ * is not available to call into to schedule or unschedule drift detection.
+ * StartupSynchronizer therefore deals only with the drift configurations attached to
+ * {@link ResourceContainer} objects. As part of its initialization DriftManager
+ * creates or recreates detection schedules from the configurations attached to the
+ * resource containers.
+ */
class StartupSynchronizer implements DriftSynchronizer {
private final Log log = LogFactory.getLog(StartupSynchronizer.class);
12 years, 9 months
[rhq] modules/core
by John Sanda
modules/core/plugin-container/mvn.out | 96 -------
modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/sync/DriftSyncManager.java | 121 +++++++++
modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/sync/DriftSynchronizer.java | 38 ++
modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/sync/DriftSynchronizerFactory.java | 37 ++
modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/sync/RuntimeSynchronizer.java | 123 +++++++++
modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/sync/StartupSynchronizer.java | 127 +++++++++
modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java | 130 +---------
modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/ResourceContainer.java | 6
8 files changed, 465 insertions(+), 213 deletions(-)
New commits:
commit 6f788d1ec4e183b26483267e9653dada84ea2b1a
Author: John Sanda <jsanda(a)redhat.com>
Date: Thu Sep 15 16:41:22 2011 -0400
Refactoring drift config sync code out of InventoryManager
There are several drivers behind this refactoring. First, there was
drift specific logic that spilled over into InventoryManager. Secondly,
there was some code duplication. Third, the refactoring will hopefully
make the code easier to test, particularly at the unit test level.
Fourth, the refactoring makes the code more self-documenting.
diff --git a/modules/core/plugin-container/mvn.out b/modules/core/plugin-container/mvn.out
deleted file mode 100644
index d269e4d..0000000
--- a/modules/core/plugin-container/mvn.out
+++ /dev/null
@@ -1,96 +0,0 @@
-[INFO]
-NOTE: Maven is executing in offline mode. Any artifacts not already in your local
-repository will be inaccessible.
-
-[INFO] Scanning for projects...
-[INFO] ------------------------------------------------------------------------
-[INFO] Building RHQ Plugin Container
-[INFO] task-segment: [clean, install]
-[INFO] ------------------------------------------------------------------------
-[INFO] [clean:clean {execution: default-clean}]
-[INFO] Deleting /home/jsanda/Development/redhat/rhq/modules/core/plugin-container/target
-[INFO] [enforcer:enforce {execution: enforce-versions}]
-[INFO] [build-helper:maven-version {execution: default}]
-[INFO] [resources:resources {execution: default-resources}]
-[INFO] Using 'ISO-8859-1' encoding to copy filtered resources.
-[INFO] skip non existing resourceDirectory /home/jsanda/Development/redhat/rhq/modules/core/plugin-container/src/main/resources
-[INFO] [compiler:compile {execution: default-compile}]
-[INFO] Compiling 105 source files to /home/jsanda/Development/redhat/rhq/modules/core/plugin-container/target/classes
-[WARNING] /home/jsanda/Development/redhat/rhq/modules/core/plugin-container/src/main/java/org/rhq/core/pc/plugin/FileSystemPluginFinder.java:[124,32] [deprecation] toURL() in java.io.File has been deprecated
-[WARNING] /home/jsanda/Development/redhat/rhq/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/ResourceContainer.java:[465,49] [unchecked] unchecked conversion
-found : java.util.concurrent.Callable
-required: java.util.concurrent.Callable<T>
-[WARNING] /home/jsanda/Development/redhat/rhq/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/ResourceContainer.java:[465,48] [unchecked] unchecked method invocation: <T>submit(java.util.concurrent.Callable<T>) in java.util.concurrent.ExecutorService is applied to (java.util.concurrent.Callable)
-[WARNING] /home/jsanda/Development/redhat/rhq/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java:[321,76] [unchecked] unchecked call to discoverResources(org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext<T>) as a member of the raw type org.rhq.core.pluginapi.inventory.ResourceDiscoveryComponent
-[WARNING] /home/jsanda/Development/redhat/rhq/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java:[321,76] [unchecked] unchecked conversion
-found : java.util.Set
-required: java.util.Set<org.rhq.core.pluginapi.inventory.DiscoveredResourceDetails>
-[WARNING] /home/jsanda/Development/redhat/rhq/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java:[357,69] [unchecked] unchecked call to discoverResource(org.rhq.core.domain.configuration.Configuration,org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext<T>) as a member of the raw type org.rhq.core.pluginapi.inventory.ManualAddFacet
-[WARNING] /home/jsanda/Development/redhat/rhq/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java:[394,52] [unchecked] unchecked call to ResourceDiscoveryContext(org.rhq.core.domain.resource.ResourceType,T,org.rhq.core.pluginapi.inventory.ResourceContext,org.rhq.core.system.SystemInfo,java.util.List<org.rhq.core.pluginapi.inventory.ProcessScanResult>,java.util.List<org.rhq.core.domain.configuration.Configuration>,java.lang.String,org.rhq.core.pluginapi.inventory.PluginContainerDeployment) as a member of the raw type org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext
-[WARNING] /home/jsanda/Development/redhat/rhq/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java:[406,60] [unchecked] unchecked call to getAdditionalClasspathUrls(org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext<T>,org.rhq.core.pluginapi.inventory.DiscoveredResourceDetails) as a member of the raw type org.rhq.core.pluginapi.inventory.ClassLoaderFacet
-[WARNING] /home/jsanda/Development/redhat/rhq/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java:[406,60] [unchecked] unchecked conversion
-found : java.util.List
-required: java.util.List<java.net.URL>
-[WARNING] /home/jsanda/Development/redhat/rhq/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java:[1534,87] [unchecked] unchecked conversion
-found : org.rhq.core.pluginapi.inventory.ResourceDiscoveryComponent
-required: org.rhq.core.pluginapi.inventory.ResourceDiscoveryComponent<org.rhq.core.pluginapi.inventory.ResourceComponent<capture#841 of ?>>
-[WARNING] /home/jsanda/Development/redhat/rhq/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java:[1534,59] [unchecked] unchecked method invocation: <T>createResourceContext(org.rhq.core.domain.resource.Resource,T,org.rhq.core.pluginapi.inventory.ResourceDiscoveryComponent<T>) in org.rhq.core.pc.inventory.InventoryManager is applied to (org.rhq.core.domain.resource.Resource,org.rhq.core.pluginapi.inventory.ResourceComponent<capture#841 of ?>,org.rhq.core.pluginapi.inventory.ResourceDiscoveryComponent)
-[WARNING] /home/jsanda/Development/redhat/rhq/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java:[2383,47] [unchecked] unchecked call to ResourceDiscoveryContext(org.rhq.core.domain.resource.ResourceType,T,org.rhq.core.pluginapi.inventory.ResourceContext,org.rhq.core.system.SystemInfo,java.util.List<org.rhq.core.pluginapi.inventory.ProcessScanResult>,java.util.List<org.rhq.core.domain.configuration.Configuration>,java.lang.String,org.rhq.core.pluginapi.inventory.PluginContainerDeployment) as a member of the raw type org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext
-[WARNING] /home/jsanda/Development/redhat/rhq/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java:[2436,30] [unchecked] unchecked conversion
-found : java.util.Set
-required: java.util.Set<org.rhq.core.domain.resource.Resource>
-[WARNING] /home/jsanda/Development/redhat/rhq/modules/core/plugin-container/src/main/java/org/rhq/core/pc/measurement/MeasurementCollectorRunner.java:[111,85] [unchecked] unchecked cast
-found : java.util.Set<capture#736 of ? extends org.rhq.core.domain.measurement.MeasurementScheduleRequest>
-required: java.util.Set<org.rhq.core.domain.measurement.MeasurementScheduleRequest>
-[WARNING] /home/jsanda/Development/redhat/rhq/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryFile.java:[116,85] [unchecked] unchecked cast
-found : java.lang.Object
-required: java.util.Map<java.lang.String,org.rhq.core.pc.inventory.ResourceContainer>
-[WARNING] /home/jsanda/Development/redhat/rhq/modules/core/plugin-container/src/main/java/org/rhq/core/pc/util/InventoryPrinter.java:[285,41] [unchecked] unchecked call to HashSet(java.util.Collection<? extends E>) as a member of the raw type java.util.HashSet
-[WARNING] /home/jsanda/Development/redhat/rhq/modules/core/plugin-container/src/main/java/org/rhq/core/pc/util/InventoryPrinter.java:[285,41] [unchecked] unchecked conversion
-found : java.util.HashSet
-required: java.util.Set<org.rhq.core.domain.resource.Resource>
-[WARNING] /home/jsanda/Development/redhat/rhq/modules/core/plugin-container/src/main/java/org/rhq/core/pc/configuration/StructuredAndRawConfigManagement.java:[58,25] [unchecked] unchecked conversion
-found : java.util.Set
-required: java.util.Set<org.rhq.core.domain.configuration.RawConfiguration>
-[WARNING] /home/jsanda/Development/redhat/rhq/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/SnapshotGenerator.java:[106,19] [unchecked] unchecked call to add(E) as a member of the raw type java.util.Collection
-[INFO] [resources:testResources {execution: default-testResources}]
-[INFO] Using 'ISO-8859-1' encoding to copy filtered resources.
-[INFO] Copying 5 resources
-[WARNING] DEPRECATED [tasks]: Use target instead
-[INFO] [antrun:run {execution: process-test-resources}]
-[WARNING] Parameter tasks is deprecated, use target instead
-[INFO] Executing tasks
-
-main:
- [echo] SIGAR java library version used is 1.6.5.132
- [echo] Copying/unzipping SIGAR native libraries (version 1.6.5.132) to local build directory
- [mkdir] Created dir: /home/jsanda/Development/redhat/rhq/modules/core/plugin-container/target/jboss-sigar
- [copy] Copying 1 file to /home/jsanda/Development/redhat/rhq/modules/core/plugin-container/target/jboss-sigar
- [unzip] Expanding: /home/jsanda/Development/redhat/rhq/modules/core/plugin-container/target/jboss-sigar/sigar-dist-1.6.5.132.zip into /home/jsanda/Development/redhat/rhq/modules/core/plugin-container/target/jboss-sigar
- [move] Moving 22 files to /home/jsanda/Development/redhat/rhq/modules/core/plugin-container/target/jboss-sigar
-[INFO] Executed tasks
-[INFO] [compiler:testCompile {execution: default-testCompile}]
-[INFO] Not compiling test sources
-[WARNING] DEPRECATED [tasks]: Use target instead
-[INFO] [antrun:run {execution: process-test-classes}]
-[WARNING] Parameter tasks is deprecated, use target instead
-[INFO] Executing tasks
-
-main:
-[INFO] Executed tasks
-[INFO] [surefire:test {execution: default-test}]
-[INFO] Tests are skipped.
-[INFO] [jar:jar {execution: default-jar}]
-[INFO] Building jar: /home/jsanda/Development/redhat/rhq/modules/core/plugin-container/target/rhq-core-plugin-container-4.1.0-SNAPSHOT.jar
-[INFO] [jar:jar {execution: default}]
-[INFO] [jar:test-jar {execution: default}]
-[INFO] Skipping packaging of the test-jar
-[INFO] [install:install {execution: default-install}]
-[INFO] Installing /home/jsanda/Development/redhat/rhq/modules/core/plugin-container/target/rhq-core-plugin-container-4.1.0-SNAPSHOT.jar to /home/jsanda/.m2/repository/org/rhq/rhq-core-plugin-container/4.1.0-SNAPSHOT/rhq-core-plugin-container-4.1.0-SNAPSHOT.jar
-[INFO] ------------------------------------------------------------------------
-[INFO] BUILD SUCCESSFUL
-[INFO] ------------------------------------------------------------------------
-[INFO] Total time: 7 seconds
-[INFO] Finished at: Tue Sep 13 16:43:45 EDT 2011
-[INFO] Final Memory: 59M/481M
-[INFO] ------------------------------------------------------------------------
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/sync/DriftSyncManager.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/sync/DriftSyncManager.java
new file mode 100644
index 0000000..efb27cc
--- /dev/null
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/sync/DriftSyncManager.java
@@ -0,0 +1,121 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2011 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.pc.drift.sync;
+
+import java.io.File;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.rhq.core.clientapi.server.drift.DriftServerService;
+import org.rhq.core.domain.drift.DriftConfiguration;
+import org.rhq.core.domain.drift.DriftConfigurationComparator;
+import org.rhq.core.pc.drift.DriftManager;
+import org.rhq.core.pc.inventory.InventoryManager;
+
+import static org.rhq.core.domain.drift.DriftConfigurationComparator.CompareMode.BOTH_BASE_INFO_AND_DIRECTORY_SPECIFICATIONS;
+
+public class DriftSyncManager {
+ private final Log log = LogFactory.getLog(DriftSyncManager.class);
+
+ private DriftServerService driftServer;
+
+ private DriftManager driftMgr;
+
+ private InventoryManager inventoryMgr;
+
+ private File dataDir;
+
+ public void setDriftServer(DriftServerService driftServer) {
+ this.driftServer = driftServer;
+ }
+
+ public void setDriftManager(DriftManager driftManager) {
+ driftMgr = driftManager;
+ }
+
+ public void setInventoryManager(InventoryManager inventoryManager) {
+ inventoryMgr = inventoryManager;
+ }
+
+ public void setDataDirectory(File dataDirectory) {
+ dataDir = dataDirectory;
+ }
+
+ public void syncConfigsWithServer(Set<Integer> resourceIds) {
+ log.info("Starting server sync for drift configurations...");
+ long startTime = System.currentTimeMillis();
+
+ Map<Integer, List<DriftConfiguration>> configs = driftServer.getDriftConfigurations(resourceIds);
+ DriftConfigurationComparator comparator = new DriftConfigurationComparator(
+ BOTH_BASE_INFO_AND_DIRECTORY_SPECIFICATIONS);
+ DriftSynchronizerFactory synchronizerFactory = new DriftSynchronizerFactory();
+ DriftSynchronizer synchronizer;
+
+ if (isStartUpSync()) {
+ synchronizer = synchronizerFactory.getStartUpSynchronizer(inventoryMgr, dataDir);
+ } else {
+ synchronizer = synchronizerFactory.getRuntimeSynchronizer(driftMgr);
+ }
+
+ int totalDeleted = 0;
+ int totalAdded = 0;
+
+ for (Integer resourceId : configs.keySet()) {
+ Set<DriftConfiguration> resourceConfigsOnServer = new TreeSet<DriftConfiguration>(comparator);
+ resourceConfigsOnServer.addAll(configs.get(resourceId));
+
+ List<DriftConfiguration> deletedConfigs = synchronizer.getDeletedConfigurations(resourceId,
+ resourceConfigsOnServer);
+ totalDeleted += deletedConfigs.size();
+ synchronizer.purgeFromLocalInventory(resourceId, deletedConfigs);
+
+ List<DriftConfiguration> addedConfigs = synchronizer.getAddedConfigurations(resourceId,
+ resourceConfigsOnServer);
+ totalAdded += addedConfigs.size();
+ synchronizer.addToLocalInventory(resourceId, addedConfigs);
+ }
+
+ long endTime = System.currentTimeMillis();
+ if (log.isInfoEnabled()) {
+ log.info("Finished server sync for drift configurations. " + totalAdded + " added and " + totalDeleted +
+ " deleted in " + (endTime - startTime) + " ms");
+ }
+ }
+
+ /**
+ * This method determines whether or not this is a sync being done at start up (or
+ * more precisely during PC initialization). It does by checking to see if
+ * DriftManager is initialized. The only time DriftManager should not be initialized
+ * is during PC initialization which happens at start up or at runtime when the PC is
+ * rebooted.
+ *
+ * @return true if this is a sync being performed at start up or plugin container
+ * initialization.
+ */
+ private boolean isStartUpSync() {
+ return driftMgr == null || !driftMgr.isInitialized();
+ }
+
+}
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/sync/DriftSynchronizer.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/sync/DriftSynchronizer.java
new file mode 100644
index 0000000..79ac3ad
--- /dev/null
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/sync/DriftSynchronizer.java
@@ -0,0 +1,38 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2011 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.pc.drift.sync;
+
+import java.util.List;
+import java.util.Set;
+
+import org.rhq.core.domain.drift.DriftConfiguration;
+
+public interface DriftSynchronizer {
+
+ List<DriftConfiguration> getDeletedConfigurations(int resourceId,
+ Set<DriftConfiguration> configurationsFromServer);
+
+
+ void purgeFromLocalInventory(int resourceId, List<DriftConfiguration> configurations);
+
+ List<DriftConfiguration> getAddedConfigurations(int resourceId, Set<DriftConfiguration> configurationsFromServer);
+
+ void addToLocalInventory(int resourceId, List<DriftConfiguration> configurations);
+}
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/sync/DriftSynchronizerFactory.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/sync/DriftSynchronizerFactory.java
new file mode 100644
index 0000000..5da9d49
--- /dev/null
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/sync/DriftSynchronizerFactory.java
@@ -0,0 +1,37 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2011 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.pc.drift.sync;
+
+import java.io.File;
+
+import org.rhq.core.pc.drift.DriftManager;
+import org.rhq.core.pc.inventory.InventoryManager;
+
+public class DriftSynchronizerFactory {
+
+ public DriftSynchronizer getStartUpSynchronizer(InventoryManager inventoryManager, File dataDir) {
+ return new StartupSynchronizer(inventoryManager, dataDir);
+ }
+
+ public DriftSynchronizer getRuntimeSynchronizer(DriftManager driftManager) {
+ return new RuntimeSynchronizer(driftManager);
+ }
+
+}
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/sync/RuntimeSynchronizer.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/sync/RuntimeSynchronizer.java
new file mode 100644
index 0000000..e7b4aa0
--- /dev/null
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/sync/RuntimeSynchronizer.java
@@ -0,0 +1,123 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2011 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.pc.drift.sync;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.rhq.core.domain.drift.DriftConfiguration;
+import org.rhq.core.domain.drift.DriftConfigurationComparator;
+import org.rhq.core.pc.drift.DriftDetectionSchedule;
+import org.rhq.core.pc.drift.DriftManager;
+import org.rhq.core.pc.drift.ScheduleQueue;
+
+import static org.rhq.core.domain.drift.DriftConfigurationComparator.CompareMode.BOTH_BASE_INFO_AND_DIRECTORY_SPECIFICATIONS;
+
+class RuntimeSynchronizer implements DriftSynchronizer {
+ private final Log log = LogFactory.getLog(RuntimeSynchronizer.class);
+
+ private DriftManager driftMgr;
+
+ public RuntimeSynchronizer(DriftManager driftManager) {
+ driftMgr = driftManager;
+ }
+
+ @Override
+ public List<DriftConfiguration> getDeletedConfigurations(int resourceId,
+ Set<DriftConfiguration> configurationsFromServer) {
+ log.debug("Checking for drift configurations that need to be deleted for resource id " + resourceId);
+ List<DriftConfiguration> deleted = new LinkedList<DriftConfiguration>();
+ ScheduleQueue queue = driftMgr.getSchedulesQueue();
+
+ for (DriftDetectionSchedule schedule : getSchedulesForResource(resourceId, queue.toArray())) {
+ if (!configurationsFromServer.contains(schedule.getDriftConfiguration())) {
+ if (log.isDebugEnabled()) {
+ log.debug("Detected stale drift configuration that needs to be purged - " +
+ toString(resourceId, schedule.getDriftConfiguration()));
+ }
+ deleted.add(schedule.getDriftConfiguration());
+ }
+ }
+ return deleted;
+ }
+
+ @Override
+ public void purgeFromLocalInventory(int resourceId, List<DriftConfiguration> configurations) {
+ log.debug("Preparing to unschedule drift detection and purge from local inventory drift configurations " +
+ "that have been deleted on the server for resource id " + resourceId);
+
+ for (DriftConfiguration c : configurations) {
+ driftMgr.unscheduleDriftDetection(resourceId, c);
+ }
+ }
+
+ @Override
+ public List<DriftConfiguration> getAddedConfigurations(int resourceId,
+ Set<DriftConfiguration> configurationsFromServer) {
+ log.debug("Checking for drift configurations that need to be added for resource id " + resourceId);
+
+ ScheduleQueue queue = driftMgr.getSchedulesQueue();
+ DriftConfigurationComparator comparator = new DriftConfigurationComparator(
+ BOTH_BASE_INFO_AND_DIRECTORY_SPECIFICATIONS);
+ List<DriftConfiguration> added = new LinkedList<DriftConfiguration>();
+
+ for (DriftConfiguration c : configurationsFromServer) {
+ if (!queue.contains(resourceId, c, comparator)) {
+ if (log.isDebugEnabled()) {
+ log.debug("Detected new drift configuration that needs to be added to local inventory - " +
+ toString(resourceId, c));
+ }
+ added.add(c);
+ }
+ }
+ return added;
+ }
+
+ @Override
+ public void addToLocalInventory(int resourceId, List<DriftConfiguration> configurations) {
+ log.debug("Adding drift configurations to local inventory and creating drift detection schedules for " +
+ "resource id " + resourceId);
+
+ for (DriftConfiguration c : configurations) {
+ if (log.isDebugEnabled()) {
+ log.debug("Adding " + toString(resourceId, c) + " to local inventory");
+ }
+ driftMgr.scheduleDriftDetection(resourceId, c);
+ }
+ }
+
+ private String toString(int rid, DriftConfiguration c) {
+ return "DriftConfiguration[id: " + c.getId() + ", name: " + c.getName() + ", resourceId: " + rid + "]";
+ }
+
+ private List<DriftDetectionSchedule> getSchedulesForResource(int resourceId, DriftDetectionSchedule[] schedules) {
+ List<DriftDetectionSchedule> resourceSchedules = new LinkedList<DriftDetectionSchedule>();
+ for (DriftDetectionSchedule s : schedules) {
+ if (s.getResourceId() == resourceId) {
+ resourceSchedules.add(s);
+ }
+ }
+ return resourceSchedules;
+ }
+}
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/sync/StartupSynchronizer.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/sync/StartupSynchronizer.java
new file mode 100644
index 0000000..4309bf8
--- /dev/null
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/sync/StartupSynchronizer.java
@@ -0,0 +1,127 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2011 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.pc.drift.sync;
+
+import java.io.File;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.rhq.core.domain.drift.DriftConfiguration;
+import org.rhq.core.pc.inventory.InventoryManager;
+import org.rhq.core.pc.inventory.ResourceContainer;
+
+import static org.rhq.core.util.file.FileUtil.purge;
+
+class StartupSynchronizer implements DriftSynchronizer {
+ private final Log log = LogFactory.getLog(StartupSynchronizer.class);
+
+ private InventoryManager inventoryMgr;
+
+ private File snapshotsDir;
+
+ public StartupSynchronizer(InventoryManager inventoryManager, File dataDirectory) {
+ inventoryMgr = inventoryManager;
+ snapshotsDir = new File(dataDirectory, "changesets");
+ }
+
+ @Override
+ public List<DriftConfiguration> getDeletedConfigurations(int resourceId,
+ Set<DriftConfiguration> configurationsFromServer) {
+ log.debug("Checking for drift configurations that need to be deleted for resource id " + resourceId);
+ List<DriftConfiguration> deleted = new LinkedList<DriftConfiguration>();
+ ResourceContainer container = inventoryMgr.getResourceContainer(resourceId);
+
+ for (DriftConfiguration c : container.getDriftConfigurations()) {
+ if (!configurationsFromServer.contains(c)) {
+ if (log.isDebugEnabled()) {
+ log.debug("Detected stale drift configuration that needs to be purged - " +
+ toString(resourceId, c));
+ }
+ deleted.add(c);
+ }
+ }
+
+ return deleted;
+ }
+
+ @Override
+ public void purgeFromLocalInventory(int resourceId, List<DriftConfiguration> configurations) {
+ log.debug("Preparing to purge from local inventory drift configurations that have been deleted on the server "
+ + "for resource id " + resourceId);
+ ResourceContainer container = inventoryMgr.getResourceContainer(resourceId);
+ File resourceSnapshotsDir = new File(snapshotsDir, Integer.toString(resourceId));
+
+ for (DriftConfiguration c : configurations) {
+ if (log.isDebugEnabled()) {
+ log.debug("Purging " + toString(resourceId, c) + " from local inventory");
+ }
+ container.removeDriftConfiguration(c);
+ File snapshotDir = new File(resourceSnapshotsDir, c.getName());
+ if (snapshotDir.exists()) {
+ if (log.isDebugEnabled()) {
+ log.debug("Puring snapshot directory " + snapshotDir.getPath());
+ }
+ purge(snapshotDir, true);
+ }
+ }
+ }
+
+ @Override
+ public List<DriftConfiguration> getAddedConfigurations(int resourceId,
+ Set<DriftConfiguration> configurationsFromServer) {
+ log.debug("Checking for drift configurations that need to be added for resource id " + resourceId);
+
+ ResourceContainer container = inventoryMgr.getResourceContainer(resourceId);
+ List<DriftConfiguration> added = new LinkedList<DriftConfiguration>();
+
+
+ for (DriftConfiguration c : configurationsFromServer) {
+ if (!container.containsDriftConfiguration(c)) {
+ if (log.isDebugEnabled()) {
+ log.debug("Detected new drift configuration that needs to be added to local inventory - " +
+ toString(resourceId, c));
+ }
+ added.add(c);
+ }
+ }
+ return added;
+ }
+
+ @Override
+ public void addToLocalInventory(int resourceId, List<DriftConfiguration> configurations) {
+ log.debug("Adding drift configurations to local inventory for resource id " + resourceId);
+ ResourceContainer container = inventoryMgr.getResourceContainer(resourceId);
+
+ for (DriftConfiguration c : configurations) {
+ if (log.isDebugEnabled()) {
+ log.debug("Adding " + toString(resourceId, c) + " to local inventory");
+ }
+ container.addDriftConfiguration(c);
+ }
+ }
+
+ private String toString(int rid, DriftConfiguration c) {
+ return "DriftConfiguration[id: " + c.getId() + ", name: " + c.getName() + ", resourceId: " + rid + "]";
+ }
+}
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java
index a4f292f..5d03d0c 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java
@@ -22,9 +22,6 @@
*/
package org.rhq.core.pc.inventory;
-import static org.rhq.core.domain.drift.DriftConfigurationComparator.CompareMode.BOTH_BASE_INFO_AND_DIRECTORY_SPECIFICATIONS;
-import static org.rhq.core.util.file.FileUtil.purge;
-
import java.io.File;
import java.net.URL;
import java.util.ArrayList;
@@ -39,7 +36,6 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
-import java.util.TreeSet;
import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
@@ -69,8 +65,6 @@ import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.discovery.AvailabilityReport;
import org.rhq.core.domain.discovery.MergeResourceResponse;
import org.rhq.core.domain.discovery.ResourceSyncInfo;
-import org.rhq.core.domain.drift.DriftConfiguration;
-import org.rhq.core.domain.drift.DriftConfigurationComparator;
import org.rhq.core.domain.measurement.Availability;
import org.rhq.core.domain.measurement.AvailabilityType;
import org.rhq.core.domain.measurement.ResourceMeasurementScheduleRequest;
@@ -91,9 +85,7 @@ import org.rhq.core.pc.agent.AgentRegistrar;
import org.rhq.core.pc.agent.AgentService;
import org.rhq.core.pc.availability.AvailabilityCollectorThreadPool;
import org.rhq.core.pc.content.ContentContextImpl;
-import org.rhq.core.pc.drift.DriftDetectionSchedule;
-import org.rhq.core.pc.drift.DriftManager;
-import org.rhq.core.pc.drift.ScheduleQueue;
+import org.rhq.core.pc.drift.sync.DriftSyncManager;
import org.rhq.core.pc.event.EventContextImpl;
import org.rhq.core.pc.inventory.ResourceContainer.ResourceComponentState;
import org.rhq.core.pc.operation.OperationContextImpl;
@@ -2042,9 +2034,9 @@ public class InventoryManager extends AgentService implements ContainerService,
resources.push(child);
}
}
- Map<Integer, List<DriftConfiguration>> configs = configuration.getServerServices().getDriftServerService()
- .getDriftConfigurations(resourceIds);
- installDriftConfigurations(configs);
+
+ DriftSyncManager driftSyncMgr = createDriftSyncManager();
+ driftSyncMgr.syncConfigsWithServer(resourceIds);
}
private boolean supportsDriftManagement(Resource r) {
@@ -2090,9 +2082,8 @@ public class InventoryManager extends AgentService implements ContainerService,
}
}
- Map<Integer, List<DriftConfiguration>> driftConfigs = configuration.getServerServices().getDriftServerService()
- .getDriftConfigurations(committedResourceIds);
- installDriftConfigurations(driftConfigs);
+ DriftSyncManager driftSyncMgr = createDriftSyncManager();
+ driftSyncMgr.syncConfigsWithServer(committedResourceIds);
}
private void postProcessNewlyCommittedResources(Set<Resource> resources) {
@@ -2133,108 +2124,13 @@ public class InventoryManager extends AgentService implements ContainerService,
}
}
- private void installDriftConfigurations(Map<Integer, List<DriftConfiguration>> configsFromServer) {
- log.info("Syncing drift configurations from server with local inventory...");
- DriftManager driftMgr = PluginContainer.getInstance().getDriftManager();
- if (driftMgr != null && driftMgr.isInitialized()) {
- DriftConfigurationComparator comparator = new DriftConfigurationComparator(
- BOTH_BASE_INFO_AND_DIRECTORY_SPECIFICATIONS);
- ScheduleQueue queue = driftMgr.getSchedulesQueue();
-
- // First check for drift configurations that have been deleted
- log.info("Checking for drift configurations that have been deleted on the server");
- for (Integer resourceId : configsFromServer.keySet()) {
- Set<DriftConfiguration> configsFromServerSet = new TreeSet<DriftConfiguration>(comparator);
- configsFromServerSet.addAll(configsFromServer.get(resourceId));
-
- List<DriftConfiguration> deleted = new ArrayList<DriftConfiguration>();
-
- for (DriftDetectionSchedule schedule : getSchedulesForResource(resourceId, queue.toArray())) {
- if (!configsFromServerSet.contains(schedule.getDriftConfiguration())) {
- if (log.isDebugEnabled()) {
- log.debug("Detected stale drift configuration. Preparing to unschedule " + schedule);
- }
- deleted.add(schedule.getDriftConfiguration());
- }
- }
- for (DriftConfiguration c : deleted) {
- driftMgr.unscheduleDriftDetection(resourceId, c);
- }
- }
-
- // add new drift configurations received from the server
- log.info("Checking for new drift configurations");
- for (Integer resourceId : configsFromServer.keySet()) {
- for (DriftConfiguration c : configsFromServer.get(resourceId)) {
- if (!queue.contains(resourceId, c, comparator)) {
- if (log.isDebugEnabled()) {
- log.debug("Detected new drift configuration. Creating new schedule for "
- + "DriftConfiguration[name: " + c.getName() + ", resourceId: " + resourceId + "]");
- }
- driftMgr.scheduleDriftDetection(resourceId, c);
- }
- }
- }
- } else {
- log.info("DriftManager is not available. Drift configurations will be persisted but detection will not "
- + "be scheduled.");
-
- // First check for drift configurations that have been deleted
- log.debug("Checking for stale drift configurations that need to be purged from inventory");
- File changeSetsDir = new File(configuration.getDataDirectory(), "changesets");
- for (Integer resourceId : configsFromServer.keySet()) {
- File resourceDir = new File(changeSetsDir, resourceId.toString());
- ResourceContainer container = getResourceContainer(resourceId);
- Set<DriftConfiguration> resourceConfigs = new TreeSet<DriftConfiguration>(
- new DriftConfigurationComparator(BOTH_BASE_INFO_AND_DIRECTORY_SPECIFICATIONS));
- resourceConfigs.addAll(configsFromServer.get(resourceId));
-
- List<DriftConfiguration> deleted = new ArrayList<DriftConfiguration>();
-
- for (DriftConfiguration c : container.getDriftConfigurations()) {
- if (!resourceConfigs.contains(c)) {
- if (log.isDebugEnabled()) {
- log.debug("Detected stale drift configuration. Preparing to delete DriftConfiguration["
- + "name: " + c.getName() + ", resourceId: " + resourceId + "]");
- }
- deleted.add(c);
- }
- }
-
- for (DriftConfiguration c : deleted) {
- container.removeDriftConfiguration(c);
- File changeSetDir = new File(resourceDir, c.getName());
- if (changeSetDir.exists()) {
- log.debug("Purging " + changeSetDir.getPath());
- purge(changeSetDir, true);
- }
- }
- }
-
- // Now add any any drift configurations received from the server. These
- // could be new or updated configurations.
- log.debug("Checking for new drift configurations");
- for (Integer resourceId : configsFromServer.keySet()) {
- ResourceContainer container = getResourceContainer(resourceId);
- for (DriftConfiguration c : configsFromServer.get(resourceId)) {
- if (log.isDebugEnabled()) {
- log.debug("Adding DriftConfiguration[name: " + c.getName() + ", resourceId: " + resourceId
- + "]");
- }
- container.addDriftConfiguration(c);
- }
- }
- }
- }
-
- private List<DriftDetectionSchedule> getSchedulesForResource(int resourceId, DriftDetectionSchedule[] schedules) {
- List<DriftDetectionSchedule> resourceSchedules = new LinkedList<DriftDetectionSchedule>();
- for (DriftDetectionSchedule s : schedules) {
- if (s.getResourceId() == resourceId) {
- resourceSchedules.add(s);
- }
- }
- return resourceSchedules;
+ private DriftSyncManager createDriftSyncManager() {
+ DriftSyncManager mgr = new DriftSyncManager();
+ mgr.setDriftServer(configuration.getServerServices().getDriftServerService());
+ mgr.setDataDirectory(configuration.getDataDirectory());
+ mgr.setDriftManager(PluginContainer.getInstance().getDriftManager());
+ mgr.setInventoryManager(this);
+ return mgr;
}
/**
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/ResourceContainer.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/ResourceContainer.java
index f0722ed..791857b 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/ResourceContainer.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/ResourceContainer.java
@@ -251,6 +251,12 @@ public class ResourceContainer implements Serializable {
}
}
+ public boolean containsDriftConfiguration(DriftConfiguration c) {
+ synchronized (this) {
+ return driftConfigurations.containsKey(c.getName());
+ }
+ }
+
public void addDriftConfiguration(DriftConfiguration c) {
synchronized (this) {
driftConfigurations.put(c.getName(), c);
12 years, 9 months
[rhq] modules/enterprise
by Simeon Pinder
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/util/SerialUtility.java | 2
modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/startup/ExternalizableStrategyCommandListener.java | 2
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/agentclient/impl/AgentClientImpl.java | 2
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerBean.java | 4
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleServerServiceImpl.java | 4
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/remote/RemoteSafeInvocationHandler.java | 2
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/remote/RemoteWsInvocationHandler.java | 2
modules/enterprise/server/safe-invoker/src/main/java/org/rhq/enterprise/server/safeinvoker/EJB3SafeEndpointInvoker.java | 58 +
modules/enterprise/server/safe-invoker/src/main/java/org/rhq/enterprise/server/safeinvoker/EJB3SafeEndpointInvokerDeploymentAspect.java | 59 +
modules/enterprise/server/safe-invoker/src/main/java/org/rhq/enterprise/server/safeinvoker/HibernateDetachUtility.java | 569 ++++++++++
modules/enterprise/server/safe-invoker/src/main/java/org/rhq/enterprise/server/util/EJB3SafeEndpointInvoker.java | 58 -
modules/enterprise/server/safe-invoker/src/main/java/org/rhq/enterprise/server/util/EJB3SafeEndpointInvokerDeploymentAspect.java | 59 -
modules/enterprise/server/safe-invoker/src/main/java/org/rhq/enterprise/server/util/HibernateDetachUtility.java | 569 ----------
modules/enterprise/server/safe-invoker/src/test/java/org/rhq/enterprise/server/safeinvoker/HibernateDetachUtilityTest.java | 142 ++
modules/enterprise/server/safe-invoker/src/test/java/org/rhq/enterprise/server/util/HibernateDetachUtilityTest.java | 141 --
15 files changed, 837 insertions(+), 836 deletions(-)
New commits:
commit 4763164025895abfa107599527cbe00e3faaa5e2
Author: Simeon Pinder <spinder(a)redhat.com>
Date: Thu Sep 15 16:18:47 2011 -0400
BZ 735403 : repackaging to avoid signed jar issues causing ClassNotFound errors.
i)moved three classes ii)updated classes and tests to use the new package.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/util/SerialUtility.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/util/SerialUtility.java
index 8e1499b..3b3bc90 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/util/SerialUtility.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/util/SerialUtility.java
@@ -25,7 +25,7 @@ import java.io.ObjectOutputStream;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.rhq.enterprise.server.util.HibernateDetachUtility;
+import org.rhq.enterprise.server.safeinvoker.HibernateDetachUtility;
/**
* @author Greg Hinkle
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/startup/ExternalizableStrategyCommandListener.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/startup/ExternalizableStrategyCommandListener.java
index a845c39..7ca48b2 100644
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/startup/ExternalizableStrategyCommandListener.java
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/startup/ExternalizableStrategyCommandListener.java
@@ -23,7 +23,7 @@ import org.rhq.enterprise.communications.command.Command;
import org.rhq.enterprise.communications.command.CommandResponse;
import org.rhq.enterprise.communications.command.client.CommandPreprocessor;
import org.rhq.enterprise.communications.command.server.CommandListener;
-import org.rhq.enterprise.server.util.HibernateDetachUtility;
+import org.rhq.enterprise.server.safeinvoker.HibernateDetachUtility;
/**
* This is a listener for commands coming into the {@link ServiceContainer}'s {@link CommandPreprocessor} and will
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/agentclient/impl/AgentClientImpl.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/agentclient/impl/AgentClientImpl.java
index d1956d5..76d9c3e 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/agentclient/impl/AgentClientImpl.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/agentclient/impl/AgentClientImpl.java
@@ -36,7 +36,7 @@ import org.rhq.enterprise.communications.command.client.ClientCommandSender;
import org.rhq.enterprise.communications.command.client.ClientRemotePojoFactory;
import org.rhq.enterprise.communications.command.client.SendCallback;
import org.rhq.enterprise.server.agentclient.AgentClient;
-import org.rhq.enterprise.server.util.HibernateDetachUtility;
+import org.rhq.enterprise.server.safeinvoker.HibernateDetachUtility;
/**
* Provides the mechanism by which you obtain remote interface proxies to a particular agent. Using those remote
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerBean.java
index 139efe4..ee3a1ba 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerBean.java
@@ -101,10 +101,10 @@ import org.rhq.enterprise.server.core.AgentManagerLocal;
import org.rhq.enterprise.server.plugin.pc.bundle.BundleServerPluginManager;
import org.rhq.enterprise.server.resource.ResourceTypeManagerLocal;
import org.rhq.enterprise.server.resource.group.ResourceGroupManagerLocal;
+import org.rhq.enterprise.server.safeinvoker.HibernateDetachUtility;
+import org.rhq.enterprise.server.safeinvoker.HibernateDetachUtility.SerializationType;
import org.rhq.enterprise.server.util.CriteriaQueryGenerator;
import org.rhq.enterprise.server.util.CriteriaQueryRunner;
-import org.rhq.enterprise.server.util.HibernateDetachUtility;
-import org.rhq.enterprise.server.util.HibernateDetachUtility.SerializationType;
/**
* Manages the creation and usage of bundles.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleServerServiceImpl.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleServerServiceImpl.java
index 1fc6e1a..65a1209 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleServerServiceImpl.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleServerServiceImpl.java
@@ -36,9 +36,9 @@ import org.rhq.core.domain.criteria.PackageVersionCriteria;
import org.rhq.core.util.exception.WrappedRemotingException;
import org.rhq.enterprise.server.content.ContentManagerLocal;
import org.rhq.enterprise.server.content.ContentSourceManagerLocal;
-import org.rhq.enterprise.server.util.HibernateDetachUtility;
+import org.rhq.enterprise.server.safeinvoker.HibernateDetachUtility;
+import org.rhq.enterprise.server.safeinvoker.HibernateDetachUtility.SerializationType;
import org.rhq.enterprise.server.util.LookupUtil;
-import org.rhq.enterprise.server.util.HibernateDetachUtility.SerializationType;
/**
* Server-side implementation of the <code>BundleServerService</code>. This implmentation simply forwards
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/remote/RemoteSafeInvocationHandler.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/remote/RemoteSafeInvocationHandler.java
index 70ab414..d11cc03 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/remote/RemoteSafeInvocationHandler.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/remote/RemoteSafeInvocationHandler.java
@@ -37,7 +37,7 @@ import org.jboss.remoting.invocation.NameBasedInvocation;
import org.rhq.core.server.ExternalizableStrategy;
import org.rhq.core.util.exception.WrappedRemotingException;
-import org.rhq.enterprise.server.util.HibernateDetachUtility;
+import org.rhq.enterprise.server.safeinvoker.HibernateDetachUtility;
/**
* Handle remote invocations. Note that we perform only invocations defined in the remote interfaces.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/remote/RemoteWsInvocationHandler.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/remote/RemoteWsInvocationHandler.java
index c681bbc..22cbddb 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/remote/RemoteWsInvocationHandler.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/remote/RemoteWsInvocationHandler.java
@@ -28,7 +28,7 @@ import org.jboss.remoting.callback.InvokerCallbackHandler;
import org.jboss.remoting.invocation.NameBasedInvocation;
import org.rhq.core.server.ExternalizableStrategy;
-import org.rhq.enterprise.server.util.HibernateDetachUtility;
+import org.rhq.enterprise.server.safeinvoker.HibernateDetachUtility;
public class RemoteWsInvocationHandler implements ServerInvocationHandler {
diff --git a/modules/enterprise/server/safe-invoker/src/main/java/org/rhq/enterprise/server/safeinvoker/EJB3SafeEndpointInvoker.java b/modules/enterprise/server/safe-invoker/src/main/java/org/rhq/enterprise/server/safeinvoker/EJB3SafeEndpointInvoker.java
new file mode 100644
index 0000000..b236f5f
--- /dev/null
+++ b/modules/enterprise/server/safe-invoker/src/main/java/org/rhq/enterprise/server/safeinvoker/EJB3SafeEndpointInvoker.java
@@ -0,0 +1,58 @@
+/*
+ * 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.enterprise.server.safeinvoker;
+
+import java.lang.reflect.Method;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.jboss.ws.core.EndpointInvocation;
+import org.jboss.ws.core.server.ServiceEndpointInvoker;
+import org.jboss.wsf.spi.invocation.InvocationContext;
+
+/**
+ * This invoker will take an uninitialized relationships or references from EJB3 pojo's and null them out so that we can
+ * pass them as normal objects to the webservice binding layer. (Avoiding LazyInitializationExceptions)
+ *
+ * @author Greg Hinkle
+ */
+public class EJB3SafeEndpointInvoker extends ServiceEndpointInvoker {
+ private static final Log LOG = LogFactory.getLog(EJB3SafeEndpointInvoker.class);
+
+ @Override
+ public void invoke(InvocationContext invocationContext) throws Exception {
+ super.invoke(invocationContext);
+ EndpointInvocation inv = invocationContext.getAttachment(EndpointInvocation.class);
+ Object value = inv.getReturnValue();
+ if (value != null) {
+ try {
+ Method m = value.getClass().getMethod("getReturn");
+ if (m != null) {
+ HibernateDetachUtility.nullOutUninitializedFields(value,
+ HibernateDetachUtility.SerializationType.JAXB);
+ }
+
+ inv.setReturnValue(value);
+ } catch (NoSuchMethodException nsme) {
+ // Expected for void return types
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/safe-invoker/src/main/java/org/rhq/enterprise/server/safeinvoker/EJB3SafeEndpointInvokerDeploymentAspect.java b/modules/enterprise/server/safe-invoker/src/main/java/org/rhq/enterprise/server/safeinvoker/EJB3SafeEndpointInvokerDeploymentAspect.java
new file mode 100644
index 0000000..9dd0264
--- /dev/null
+++ b/modules/enterprise/server/safe-invoker/src/main/java/org/rhq/enterprise/server/safeinvoker/EJB3SafeEndpointInvokerDeploymentAspect.java
@@ -0,0 +1,59 @@
+/*
+ * 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.enterprise.server.safeinvoker;
+
+import java.util.Iterator;
+
+import org.jboss.ws.core.server.ServiceEndpointInvoker;
+import org.jboss.ws.core.server.ServiceEndpointInvokerEJB21;
+import org.jboss.wsf.spi.deployment.Deployment;
+import org.jboss.wsf.spi.deployment.DeploymentAspect;
+import org.jboss.wsf.spi.deployment.Endpoint;
+
+/**
+ * This class installs the EJB3SafeEndpointInvoker into the deployment aspect for the endpoint.
+ *
+ * @author Greg Hinkle
+ */
+public class EJB3SafeEndpointInvokerDeploymentAspect extends DeploymentAspect {
+ @Override
+ public void start(Deployment dep) {
+ Iterator i$ = dep.getService().getEndpoints().iterator();
+ do {
+ if (!i$.hasNext()) {
+ break;
+ }
+
+ Endpoint ep = (Endpoint) i$.next();
+ ServiceEndpointInvoker epInvoker = ep.getAttachment(ServiceEndpointInvoker.class);
+ if (epInvoker == null) {
+ org.jboss.wsf.spi.deployment.Deployment.DeploymentType depType = ep.getService().getDeployment()
+ .getType();
+ if (depType == org.jboss.wsf.spi.deployment.Deployment.DeploymentType.JAXRPC_EJB21) {
+ epInvoker = new ServiceEndpointInvokerEJB21();
+ } else {
+ epInvoker = new EJB3SafeEndpointInvoker();
+ }
+
+ ep.addAttachment(org.jboss.ws.core.server.ServiceEndpointInvoker.class, epInvoker);
+ epInvoker.init(ep);
+ }
+ } while (true);
+ }
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/safe-invoker/src/main/java/org/rhq/enterprise/server/safeinvoker/HibernateDetachUtility.java b/modules/enterprise/server/safe-invoker/src/main/java/org/rhq/enterprise/server/safeinvoker/HibernateDetachUtility.java
new file mode 100644
index 0000000..23f73ee
--- /dev/null
+++ b/modules/enterprise/server/safe-invoker/src/main/java/org/rhq/enterprise/server/safeinvoker/HibernateDetachUtility.java
@@ -0,0 +1,569 @@
+/*
+ * 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.enterprise.server.safeinvoker;
+
+import java.beans.BeanInfo;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+import java.util.Set;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlTransient;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.hibernate.Hibernate;
+import org.hibernate.proxy.HibernateProxy;
+
+/**
+ * This is a single static utility that is used to process any object just prior to sending it over the wire
+ * to remote clients (like GWT clients or remote web service clients).
+ *
+ * Essentially this utility scrubs the object of all Hibernate proxies, cleaning it such that it
+ * can be serialized over the wire successfully.
+ *
+ * @author Greg Hinkle
+ * @author Jay Shaughnessy
+ * @author John Mazzitelli
+ */
+@SuppressWarnings("unchecked")
+public class HibernateDetachUtility {
+
+ private static final Log LOG = LogFactory.getLog(HibernateDetachUtility.class);
+
+ public static enum SerializationType {
+ SERIALIZATION, JAXB
+ }
+
+ /*
+ * This is the type of object that will be used to generate identity
+ * hashcodes for objects that are being scanned during the detach.
+ * During production runtime, the hashCodeGenerator will use the
+ * java.lang.System mechanism, but since this is package scoped,
+ * tests can override this since. (See BZ 732089).
+ */
+ static interface HashCodeGenerator {
+ Integer getHashCode(Object value);
+ }
+
+ static class SystemHashCodeGenerator implements HashCodeGenerator {
+ @Override
+ public Integer getHashCode(Object value) {
+ return System.identityHashCode(value);
+ }
+ }
+
+ static HashCodeGenerator hashCodeGenerator = new SystemHashCodeGenerator();
+
+ // be able to configure the deepest recursion this utility will be allowed to go (see BZ 702109 that precipitated this need)
+ private static final String DEPTH_ALLOWED_SYSPROP = "rhq.server.hibernate-detach-utility.depth-allowed";
+ private static final String THROW_EXCEPTION_ON_DEPTH_LIMIT_SYSPROP = "rhq.server.hibernate-detach-utility.throw-exception-on-depth-limit";
+ private static final int depthAllowed;
+ private static final boolean throwExceptionOnDepthLimit;
+ static {
+ int value;
+ try {
+ String str = System.getProperty(DEPTH_ALLOWED_SYSPROP, "100");
+ value = Integer.parseInt(str);
+ } catch (Throwable t) {
+ value = 100;
+ }
+ depthAllowed = value;
+
+ boolean booleanValue;
+ try {
+ String str = System.getProperty(THROW_EXCEPTION_ON_DEPTH_LIMIT_SYSPROP, "true");
+ booleanValue = Boolean.parseBoolean(str);
+ } catch (Throwable t) {
+ booleanValue = true;
+ }
+ throwExceptionOnDepthLimit = booleanValue;
+ }
+
+ public static void nullOutUninitializedFields(Object value, SerializationType serializationType) throws Exception {
+ long start = System.currentTimeMillis();
+ Map<Integer, Object> checkedObjectMap = new HashMap<Integer, Object>();
+ Map<Integer, List<Object>> checkedObjectCollisionMap = new HashMap<Integer, List<Object>>();
+ nullOutUninitializedFields(value, checkedObjectMap, checkedObjectCollisionMap, 0, serializationType);
+ long duration = System.currentTimeMillis() - start;
+ if (duration > 1000) {
+ LOG.info("Detached [" + checkedObjectMap.size() + "] objects in [" + duration + "]ms");
+ } else {
+ LOG.debug("Detached [" + checkedObjectMap.size() + "] objects in [" + duration + "]ms");
+ }
+ // help the garbage collector be clearing these before we leave
+ checkedObjectMap.clear();
+ checkedObjectCollisionMap.clear();
+ }
+
+ /**
+ * @param value the object needing to be detached/scrubbed.
+ * @param checkedObjectMap This maps identityHashCodes to Objects we've already detached. In that way we can
+ * quickly determine if we've already done the work for the incoming value and avoid taversing it again. This
+ * works well almost all of the time, but it is possible that two different objects can have the same identity hash
+ * (conflicts are always possible with a hash). In that case we utilize the checkedObjectCollisionMap (see below).
+ * @param checkedObjectCollisionMap checkedObjectMap maps the identityhash to the *first* object with that hash. In
+ * most cases there will only be mapping for one hash, but it is possible to encounter the same hash for multiple
+ * objects, especially on 32bit or IBM JVMs. It is important to know if an object has already been detached
+ * because if it is somehow self-referencing, we have to stop the recursion. This map holds the 2nd..Nth mapping
+ * for a single hash and is used to ensure we never try to detach an object already processed.
+ * @param depth used to stop infinite recursion, defaults to a depth we don't expectto see, but it is configurable.
+ * @param serializationType
+ * @throws Exception if a problem occurs
+ * @throws IllegalStateException if the recursion depth limit is reached
+ */
+ private static void nullOutUninitializedFields(Object value, Map<Integer, Object> checkedObjectMap,
+ Map<Integer, List<Object>> checkedObjectCollisionMap, int depth, SerializationType serializationType)
+ throws Exception {
+ if (depth > depthAllowed) {
+ String warningMessage = "Recursed too deep [" + depth + " > " + depthAllowed
+ + "], will not attempt to detach object of type ["
+ + ((value != null) ? value.getClass().getName() : "N/A")
+ + "]. This may cause serialization errors later. "
+ + "You can try to work around this by setting the system property [" + DEPTH_ALLOWED_SYSPROP
+ + "] to a value higher than [" + depth + "] or you can set the system property ["
+ + THROW_EXCEPTION_ON_DEPTH_LIMIT_SYSPROP + "] to 'false'";
+ LOG.warn(warningMessage);
+ if (throwExceptionOnDepthLimit) {
+ throw new IllegalStateException(warningMessage);
+ }
+ return;
+ }
+
+ if (null == value) {
+ return;
+ }
+
+ // System.identityHashCode is a hash code, and therefore not guaranteed to be unique. And we've seen this
+ // be the case. So, we use it to try and avoid duplicating work, but handle the case when two objects may
+ // have an identity crisis.
+ Integer valueIdentity = hashCodeGenerator.getHashCode(value);
+ Object checkedObject = checkedObjectMap.get(valueIdentity);
+
+ if (null == checkedObject) {
+ // if we have not yet encountered an object with this hash, store it in our map and start scrubbing
+ checkedObjectMap.put(valueIdentity, value);
+
+ } else if (value == checkedObject) {
+ // if we have scrubbed this already, no more work to be done
+ return;
+
+ } else {
+ // we have a situation where multiple objects have the same identity hashcode, work with our
+ // collision map to decide whether it needs to be scrubbed and add if necessary.
+ // Note that this code block is infrequently hit, it is by design that we've pushed the extra
+ // work, map, etc, involved for this infrequent case into its own block. The standard cases must
+ // be as fast and lean as possible.
+
+ boolean alreadyDetached = false;
+ List<Object> collisionObjects = checkedObjectCollisionMap.get(valueIdentity);
+
+ if (null == collisionObjects) {
+ // if this is the 2nd occurrence for this hash, create a new map entry
+ collisionObjects = new ArrayList<Object>(1);
+ checkedObjectCollisionMap.put(valueIdentity, collisionObjects);
+
+ } else {
+ // if we have scrubbed this already, no more work to be done
+ for (Object collisionObject : collisionObjects) {
+ if (value == collisionObject) {
+ alreadyDetached = true;
+ break;
+ }
+ }
+ }
+
+ if (LOG.isDebugEnabled()) {
+ StringBuilder message = new StringBuilder("\n\tIDENTITY HASHCODE COLLISION [hash=");
+ message.append(valueIdentity);
+ message.append(", alreadyDetached=");
+ message.append(alreadyDetached);
+ message.append("]");
+ message.append("\n\tCurrent : ");
+ message.append(value.getClass().getName());
+ message.append("\n\t ");
+ message.append(value);
+ message.append("\n\tPrevious : ");
+ message.append(checkedObject.getClass().getName());
+ message.append("\n\t ");
+ message.append(checkedObject);
+ for (Object collisionObject : collisionObjects) {
+ message.append("\n\tPrevious : ");
+ message.append(collisionObject.getClass().getName());
+ message.append("\n\t ");
+ message.append(collisionObject);
+ }
+
+ LOG.debug(message);
+ }
+
+ // now that we've done our logging, if already detached we're done. Otherwise add to the list of collision
+ // objects for this hash, and start scrubbing
+ if (alreadyDetached) {
+ return;
+ }
+
+ collisionObjects.add(value);
+ }
+
+ // Perform the detaching
+ if (value instanceof Object[]) {
+ Object[] objArray = (Object[]) value;
+ for (int i = 0; i < objArray.length; i++) {
+ Object listEntry = objArray[i];
+ Object replaceEntry = replaceObject(listEntry);
+ if (replaceEntry != null) {
+ objArray[i] = replaceEntry;
+ }
+ nullOutUninitializedFields(objArray[i], checkedObjectMap, checkedObjectCollisionMap, depth + 1,
+ serializationType);
+ }
+ } else if (value instanceof List) {
+ // Null out any entries in initialized collections
+ ListIterator i = ((List) value).listIterator();
+ while (i.hasNext()) {
+ Object val = i.next();
+ Object replace = replaceObject(val);
+ if (replace != null) {
+ val = replace;
+ i.set(replace);
+ }
+ nullOutUninitializedFields(val, checkedObjectMap, checkedObjectCollisionMap, depth + 1,
+ serializationType);
+ }
+
+ } else if (value instanceof Collection) {
+ Collection collection = (Collection) value;
+ Collection itemsToBeReplaced = new ArrayList();
+ Collection replacementItems = new ArrayList();
+ for (Object item : collection) {
+ Object replacementItem = replaceObject(item);
+ if (replacementItem != null) {
+ itemsToBeReplaced.add(item);
+ replacementItems.add(replacementItem);
+ item = replacementItem;
+ }
+ nullOutUninitializedFields(item, checkedObjectMap, checkedObjectCollisionMap, depth + 1,
+ serializationType);
+ }
+ collection.removeAll(itemsToBeReplaced);
+ collection.addAll(replacementItems); // watch out! if this collection is a Set, HashMap$MapSet doesn't support addAll. See BZ 688000
+ } else if (value instanceof Map) {
+ Map originalMap = (Map) value;
+ HashMap<Object, Object> replaceMap = new HashMap<Object, Object>();
+ for (Iterator i = originalMap.keySet().iterator(); i.hasNext();) {
+ // get original key and value - these might be hibernate proxies
+ Object originalKey = i.next();
+ Object originalKeyValue = originalMap.get(originalKey);
+
+ // replace with non-hibernate classes, if appropriate (will be null otherwise)
+ Object replaceKey = replaceObject(originalKey);
+ Object replaceValue = replaceObject(originalKeyValue);
+
+ // if either original key or original value was a hibernate proxy object, we have to
+ // remove it from the original map, and remember the replacement objects for later
+ if (replaceKey != null || replaceValue != null) {
+ Object newKey = (replaceKey != null) ? replaceKey : originalKey;
+ Object newValue = (replaceValue != null) ? replaceValue : originalKeyValue;
+ replaceMap.put(newKey, newValue);
+ i.remove();
+ }
+ }
+
+ // all hibernate proxies have been removed, we need to replace them with their
+ // non-proxy object representations that we got from replaceObject() calls
+ originalMap.putAll(replaceMap);
+
+ // now go through each item in the map and null out their internal fields
+ for (Object key : originalMap.keySet()) {
+ nullOutUninitializedFields(originalMap.get(key), checkedObjectMap, checkedObjectCollisionMap,
+ depth + 1, serializationType);
+ nullOutUninitializedFields(key, checkedObjectMap, checkedObjectCollisionMap, depth + 1,
+ serializationType);
+ }
+ } else if (value instanceof Enum) {
+ // don't need to detach enums, treat them as special objects
+ return;
+ }
+
+ if (serializationType == SerializationType.JAXB) {
+ XmlAccessorType at = value.getClass().getAnnotation(XmlAccessorType.class);
+ if (at != null && at.value() == XmlAccessType.FIELD) {
+ nullOutFieldsByFieldAccess(value, checkedObjectMap, checkedObjectCollisionMap, depth, serializationType);
+ } else {
+ nullOutFieldsByAccessors(value, checkedObjectMap, checkedObjectCollisionMap, depth, serializationType);
+ }
+ } else if (serializationType == SerializationType.SERIALIZATION) {
+ nullOutFieldsByFieldAccess(value, checkedObjectMap, checkedObjectCollisionMap, depth, serializationType);
+ }
+
+ }
+
+ private static void nullOutFieldsByFieldAccess(Object object, Map<Integer, Object> checkedObjects,
+ Map<Integer, List<Object>> checkedObjectCollisionMap, int depth, SerializationType serializationType)
+ throws Exception {
+
+ Class tmpClass = object.getClass();
+ List<Field> fieldsToClean = new ArrayList<Field>();
+ while (tmpClass != null && tmpClass != Object.class) {
+ Field[] declaredFields = tmpClass.getDeclaredFields();
+ for (Field declaredField : declaredFields) {
+ // do not process static final or transient fields since they won't be serialized anyway
+ int modifiers = declaredField.getModifiers();
+ if (!((Modifier.isFinal(modifiers) && Modifier.isStatic(modifiers)) || Modifier.isTransient(modifiers))) {
+ fieldsToClean.add(declaredField);
+ }
+ }
+ tmpClass = tmpClass.getSuperclass();
+ }
+
+ nullOutFieldsByFieldAccess(object, fieldsToClean, checkedObjects, checkedObjectCollisionMap, depth,
+ serializationType);
+ }
+
+ private static void nullOutFieldsByFieldAccess(Object object, List<Field> classFields,
+ Map<Integer, Object> checkedObjects, Map<Integer, List<Object>> checkedObjectCollisionMap, int depth,
+ SerializationType serializationType) throws Exception {
+
+ boolean accessModifierFlag = false;
+ for (Field field : classFields) {
+ accessModifierFlag = false;
+ if (!field.isAccessible()) {
+ field.setAccessible(true);
+ accessModifierFlag = true;
+ }
+
+ Object fieldValue = field.get(object);
+
+ if (fieldValue instanceof HibernateProxy) {
+
+ Object replacement = null;
+ String assistClassName = fieldValue.getClass().getName();
+ if (assistClassName.contains("javassist") || assistClassName.contains("EnhancerByCGLIB")) {
+
+ Class assistClass = fieldValue.getClass();
+ try {
+ Method m = assistClass.getMethod("writeReplace");
+ replacement = m.invoke(fieldValue);
+
+ String assistNameDelimiter = assistClassName.contains("javassist") ? "_$$_" : "$$";
+
+ assistClassName = assistClassName.substring(0, assistClassName.indexOf(assistNameDelimiter));
+ if (!replacement.getClass().getName().contains("hibernate")) {
+ nullOutUninitializedFields(replacement, checkedObjects, checkedObjectCollisionMap,
+ depth + 1, serializationType);
+
+ field.set(object, replacement);
+ } else {
+ replacement = null;
+ }
+ } catch (Exception e) {
+ LOG.error("Unable to write replace object " + fieldValue.getClass(), e);
+ }
+ }
+
+ if (replacement == null) {
+
+ String className = ((HibernateProxy) fieldValue).getHibernateLazyInitializer().getEntityName();
+
+ //see if there is a context classloader we should use instead of the current one.
+ ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
+
+ Class clazz = contextClassLoader == null ? Class.forName(className) : Class.forName(className,
+ true, contextClassLoader);
+ Class[] constArgs = { Integer.class };
+ Constructor construct = null;
+
+ try {
+ construct = clazz.getConstructor(constArgs);
+ replacement = construct.newInstance((Integer) ((HibernateProxy) fieldValue)
+ .getHibernateLazyInitializer().getIdentifier());
+ field.set(object, replacement);
+ } catch (NoSuchMethodException nsme) {
+
+ try {
+ Field idField = clazz.getDeclaredField("id");
+ Constructor ct = clazz.getDeclaredConstructor();
+ ct.setAccessible(true);
+ replacement = ct.newInstance();
+ if (!idField.isAccessible()) {
+ idField.setAccessible(true);
+ }
+ idField.set(replacement, (Integer) ((HibernateProxy) fieldValue)
+ .getHibernateLazyInitializer().getIdentifier());
+ } catch (Exception e) {
+ e.printStackTrace();
+ LOG.error("No id constructor and unable to set field id for base bean " + className, e);
+ }
+
+ field.set(object, replacement);
+ }
+ }
+
+ } else {
+ if (fieldValue instanceof org.hibernate.collection.PersistentCollection) {
+ // Replace hibernate specific collection types
+
+ if (!((org.hibernate.collection.PersistentCollection) fieldValue).wasInitialized()) {
+ field.set(object, null);
+ } else {
+
+ Object replacement = null;
+ boolean needToNullOutFields = true; // needed for BZ 688000
+ if (fieldValue instanceof Map) {
+ replacement = new HashMap((Map) fieldValue);
+ } else if (fieldValue instanceof List) {
+ replacement = new ArrayList((List) fieldValue);
+ } else if (fieldValue instanceof Set) {
+ ArrayList l = new ArrayList((Set) fieldValue); // cannot recurse Sets, see BZ 688000
+ nullOutUninitializedFields(l, checkedObjects, checkedObjectCollisionMap, depth + 1,
+ serializationType);
+ replacement = new HashSet(l); // convert it back to a Set since that's the type of the real collection, see BZ 688000
+ needToNullOutFields = false;
+ } else if (fieldValue instanceof Collection) {
+ replacement = new ArrayList((Collection) fieldValue);
+ }
+ setField(object, field.getName(), replacement);
+
+ if (needToNullOutFields) {
+ nullOutUninitializedFields(replacement, checkedObjects, checkedObjectCollisionMap,
+ depth + 1, serializationType);
+ }
+ }
+
+ } else {
+ if (fieldValue != null
+ && (fieldValue.getClass().getName().contains("org.rhq") || fieldValue instanceof Collection
+ || fieldValue instanceof Object[] || fieldValue instanceof Map))
+ nullOutUninitializedFields((fieldValue), checkedObjects, checkedObjectCollisionMap, depth + 1,
+ serializationType);
+ }
+ }
+ if (accessModifierFlag) {
+ field.setAccessible(false);
+ }
+ }
+
+ }
+
+ private static Object replaceObject(Object object) {
+ Object replacement = null;
+
+ if (object instanceof HibernateProxy) {
+ if (object.getClass().getName().contains("javassist")) {
+ Class assistClass = object.getClass();
+ try {
+ Method m = assistClass.getMethod("writeReplace");
+ replacement = m.invoke(object);
+
+ } catch (Exception e) {
+ LOG.error("Unable to write replace object " + object.getClass(), e);
+ }
+ }
+ }
+ return replacement;
+ }
+
+ private static void nullOutFieldsByAccessors(Object value, Map<Integer, Object> checkedObjects,
+ Map<Integer, List<Object>> checkedObjectCollisionMap, int depth, SerializationType serializationType)
+ throws Exception {
+ // Null out any collections that aren't loaded
+ BeanInfo bi = Introspector.getBeanInfo(value.getClass(), Object.class);
+
+ PropertyDescriptor[] pds = bi.getPropertyDescriptors();
+ for (PropertyDescriptor pd : pds) {
+ Object propertyValue = null;
+ try {
+ propertyValue = pd.getReadMethod().invoke(value);
+ } catch (Throwable lie) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Couldn't load: " + pd.getName() + " off of " + value.getClass().getSimpleName(), lie);
+ }
+ }
+
+ if (!Hibernate.isInitialized(propertyValue)) {
+ try {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Nulling out: " + pd.getName() + " off of " + value.getClass().getSimpleName());
+ }
+
+ Method writeMethod = pd.getWriteMethod();
+ if ((writeMethod != null) && (writeMethod.getAnnotation(XmlTransient.class) == null)) {
+ pd.getWriteMethod().invoke(value, new Object[] { null });
+ } else {
+ nullOutField(value, pd.getName());
+ }
+ } catch (Exception lie) {
+ LOG.debug("Couldn't null out: " + pd.getName() + " off of " + value.getClass().getSimpleName()
+ + " trying field access", lie);
+ nullOutField(value, pd.getName());
+ }
+ } else {
+ if ((propertyValue instanceof Collection)
+ || ((propertyValue != null) && propertyValue.getClass().getName().startsWith("org.rhq.core.domain"))) {
+ nullOutUninitializedFields(propertyValue, checkedObjects, checkedObjectCollisionMap, depth + 1,
+ serializationType);
+ }
+ }
+ }
+ }
+
+ private static void setField(Object object, String fieldName, Object newValue) {
+ try {
+ Field f = object.getClass().getDeclaredField(fieldName);
+ if (f != null) {
+ // try to set the field this way
+ f.setAccessible(true);
+ f.set(object, newValue);
+ }
+ } catch (NoSuchFieldException e) {
+ // ignore this
+ } catch (IllegalAccessException e) {
+ // ignore this
+ }
+ }
+
+ private static void nullOutField(Object value, String fieldName) {
+ try {
+ Field f = value.getClass().getDeclaredField(fieldName);
+ if (f != null) {
+ // try to set the field this way
+ f.setAccessible(true);
+ f.set(value, null);
+ }
+ } catch (NoSuchFieldException e) {
+ // ignore this
+ } catch (IllegalAccessException e) {
+ // ignore this
+ }
+ }
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/safe-invoker/src/main/java/org/rhq/enterprise/server/util/EJB3SafeEndpointInvoker.java b/modules/enterprise/server/safe-invoker/src/main/java/org/rhq/enterprise/server/util/EJB3SafeEndpointInvoker.java
deleted file mode 100644
index f605df1..0000000
--- a/modules/enterprise/server/safe-invoker/src/main/java/org/rhq/enterprise/server/util/EJB3SafeEndpointInvoker.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * 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.enterprise.server.util;
-
-import java.lang.reflect.Method;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import org.jboss.ws.core.EndpointInvocation;
-import org.jboss.ws.core.server.ServiceEndpointInvoker;
-import org.jboss.wsf.spi.invocation.InvocationContext;
-
-/**
- * This invoker will take an uninitialized relationships or references from EJB3 pojo's and null them out so that we can
- * pass them as normal objects to the webservice binding layer. (Avoiding LazyInitializationExceptions)
- *
- * @author Greg Hinkle
- */
-public class EJB3SafeEndpointInvoker extends ServiceEndpointInvoker {
- private static final Log LOG = LogFactory.getLog(EJB3SafeEndpointInvoker.class);
-
- @Override
- public void invoke(InvocationContext invocationContext) throws Exception {
- super.invoke(invocationContext);
- EndpointInvocation inv = invocationContext.getAttachment(EndpointInvocation.class);
- Object value = inv.getReturnValue();
- if (value != null) {
- try {
- Method m = value.getClass().getMethod("getReturn");
- if (m != null) {
- HibernateDetachUtility.nullOutUninitializedFields(value,
- HibernateDetachUtility.SerializationType.JAXB);
- }
-
- inv.setReturnValue(value);
- } catch (NoSuchMethodException nsme) {
- // Expected for void return types
- }
- }
- }
-}
\ No newline at end of file
diff --git a/modules/enterprise/server/safe-invoker/src/main/java/org/rhq/enterprise/server/util/EJB3SafeEndpointInvokerDeploymentAspect.java b/modules/enterprise/server/safe-invoker/src/main/java/org/rhq/enterprise/server/util/EJB3SafeEndpointInvokerDeploymentAspect.java
deleted file mode 100644
index 9d90417..0000000
--- a/modules/enterprise/server/safe-invoker/src/main/java/org/rhq/enterprise/server/util/EJB3SafeEndpointInvokerDeploymentAspect.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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.enterprise.server.util;
-
-import java.util.Iterator;
-
-import org.jboss.ws.core.server.ServiceEndpointInvoker;
-import org.jboss.ws.core.server.ServiceEndpointInvokerEJB21;
-import org.jboss.wsf.spi.deployment.Deployment;
-import org.jboss.wsf.spi.deployment.DeploymentAspect;
-import org.jboss.wsf.spi.deployment.Endpoint;
-
-/**
- * This class installs the EJB3SafeEndpointInvoker into the deployment aspect for the endpoint.
- *
- * @author Greg Hinkle
- */
-public class EJB3SafeEndpointInvokerDeploymentAspect extends DeploymentAspect {
- @Override
- public void start(Deployment dep) {
- Iterator i$ = dep.getService().getEndpoints().iterator();
- do {
- if (!i$.hasNext()) {
- break;
- }
-
- Endpoint ep = (Endpoint) i$.next();
- ServiceEndpointInvoker epInvoker = ep.getAttachment(ServiceEndpointInvoker.class);
- if (epInvoker == null) {
- org.jboss.wsf.spi.deployment.Deployment.DeploymentType depType = ep.getService().getDeployment()
- .getType();
- if (depType == org.jboss.wsf.spi.deployment.Deployment.DeploymentType.JAXRPC_EJB21) {
- epInvoker = new ServiceEndpointInvokerEJB21();
- } else {
- epInvoker = new EJB3SafeEndpointInvoker();
- }
-
- ep.addAttachment(org.jboss.ws.core.server.ServiceEndpointInvoker.class, epInvoker);
- epInvoker.init(ep);
- }
- } while (true);
- }
-}
\ No newline at end of file
diff --git a/modules/enterprise/server/safe-invoker/src/main/java/org/rhq/enterprise/server/util/HibernateDetachUtility.java b/modules/enterprise/server/safe-invoker/src/main/java/org/rhq/enterprise/server/util/HibernateDetachUtility.java
deleted file mode 100644
index 51b78ee..0000000
--- a/modules/enterprise/server/safe-invoker/src/main/java/org/rhq/enterprise/server/util/HibernateDetachUtility.java
+++ /dev/null
@@ -1,569 +0,0 @@
-/*
- * 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.enterprise.server.util;
-
-import java.beans.BeanInfo;
-import java.beans.Introspector;
-import java.beans.PropertyDescriptor;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.Map;
-import java.util.Set;
-
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlTransient;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.hibernate.Hibernate;
-import org.hibernate.proxy.HibernateProxy;
-
-/**
- * This is a single static utility that is used to process any object just prior to sending it over the wire
- * to remote clients (like GWT clients or remote web service clients).
- *
- * Essentially this utility scrubs the object of all Hibernate proxies, cleaning it such that it
- * can be serialized over the wire successfully.
- *
- * @author Greg Hinkle
- * @author Jay Shaughnessy
- * @author John Mazzitelli
- */
-@SuppressWarnings("unchecked")
-public class HibernateDetachUtility {
-
- private static final Log LOG = LogFactory.getLog(HibernateDetachUtility.class);
-
- public static enum SerializationType {
- SERIALIZATION, JAXB
- }
-
- /*
- * This is the type of object that will be used to generate identity
- * hashcodes for objects that are being scanned during the detach.
- * During production runtime, the hashCodeGenerator will use the
- * java.lang.System mechanism, but since this is package scoped,
- * tests can override this since. (See BZ 732089).
- */
- static interface HashCodeGenerator {
- Integer getHashCode(Object value);
- }
-
- static class SystemHashCodeGenerator implements HashCodeGenerator {
- @Override
- public Integer getHashCode(Object value) {
- return System.identityHashCode(value);
- }
- }
-
- static HashCodeGenerator hashCodeGenerator = new SystemHashCodeGenerator();
-
- // be able to configure the deepest recursion this utility will be allowed to go (see BZ 702109 that precipitated this need)
- private static final String DEPTH_ALLOWED_SYSPROP = "rhq.server.hibernate-detach-utility.depth-allowed";
- private static final String THROW_EXCEPTION_ON_DEPTH_LIMIT_SYSPROP = "rhq.server.hibernate-detach-utility.throw-exception-on-depth-limit";
- private static final int depthAllowed;
- private static final boolean throwExceptionOnDepthLimit;
- static {
- int value;
- try {
- String str = System.getProperty(DEPTH_ALLOWED_SYSPROP, "100");
- value = Integer.parseInt(str);
- } catch (Throwable t) {
- value = 100;
- }
- depthAllowed = value;
-
- boolean booleanValue;
- try {
- String str = System.getProperty(THROW_EXCEPTION_ON_DEPTH_LIMIT_SYSPROP, "true");
- booleanValue = Boolean.parseBoolean(str);
- } catch (Throwable t) {
- booleanValue = true;
- }
- throwExceptionOnDepthLimit = booleanValue;
- }
-
- public static void nullOutUninitializedFields(Object value, SerializationType serializationType) throws Exception {
- long start = System.currentTimeMillis();
- Map<Integer, Object> checkedObjectMap = new HashMap<Integer, Object>();
- Map<Integer, List<Object>> checkedObjectCollisionMap = new HashMap<Integer, List<Object>>();
- nullOutUninitializedFields(value, checkedObjectMap, checkedObjectCollisionMap, 0, serializationType);
- long duration = System.currentTimeMillis() - start;
- if (duration > 1000) {
- LOG.info("Detached [" + checkedObjectMap.size() + "] objects in [" + duration + "]ms");
- } else {
- LOG.debug("Detached [" + checkedObjectMap.size() + "] objects in [" + duration + "]ms");
- }
- // help the garbage collector be clearing these before we leave
- checkedObjectMap.clear();
- checkedObjectCollisionMap.clear();
- }
-
- /**
- * @param value the object needing to be detached/scrubbed.
- * @param checkedObjectMap This maps identityHashCodes to Objects we've already detached. In that way we can
- * quickly determine if we've already done the work for the incoming value and avoid taversing it again. This
- * works well almost all of the time, but it is possible that two different objects can have the same identity hash
- * (conflicts are always possible with a hash). In that case we utilize the checkedObjectCollisionMap (see below).
- * @param checkedObjectCollisionMap checkedObjectMap maps the identityhash to the *first* object with that hash. In
- * most cases there will only be mapping for one hash, but it is possible to encounter the same hash for multiple
- * objects, especially on 32bit or IBM JVMs. It is important to know if an object has already been detached
- * because if it is somehow self-referencing, we have to stop the recursion. This map holds the 2nd..Nth mapping
- * for a single hash and is used to ensure we never try to detach an object already processed.
- * @param depth used to stop infinite recursion, defaults to a depth we don't expectto see, but it is configurable.
- * @param serializationType
- * @throws Exception if a problem occurs
- * @throws IllegalStateException if the recursion depth limit is reached
- */
- private static void nullOutUninitializedFields(Object value, Map<Integer, Object> checkedObjectMap,
- Map<Integer, List<Object>> checkedObjectCollisionMap, int depth, SerializationType serializationType)
- throws Exception {
- if (depth > depthAllowed) {
- String warningMessage = "Recursed too deep [" + depth + " > " + depthAllowed
- + "], will not attempt to detach object of type ["
- + ((value != null) ? value.getClass().getName() : "N/A")
- + "]. This may cause serialization errors later. "
- + "You can try to work around this by setting the system property [" + DEPTH_ALLOWED_SYSPROP
- + "] to a value higher than [" + depth + "] or you can set the system property ["
- + THROW_EXCEPTION_ON_DEPTH_LIMIT_SYSPROP + "] to 'false'";
- LOG.warn(warningMessage);
- if (throwExceptionOnDepthLimit) {
- throw new IllegalStateException(warningMessage);
- }
- return;
- }
-
- if (null == value) {
- return;
- }
-
- // System.identityHashCode is a hash code, and therefore not guaranteed to be unique. And we've seen this
- // be the case. So, we use it to try and avoid duplicating work, but handle the case when two objects may
- // have an identity crisis.
- Integer valueIdentity = hashCodeGenerator.getHashCode(value);
- Object checkedObject = checkedObjectMap.get(valueIdentity);
-
- if (null == checkedObject) {
- // if we have not yet encountered an object with this hash, store it in our map and start scrubbing
- checkedObjectMap.put(valueIdentity, value);
-
- } else if (value == checkedObject) {
- // if we have scrubbed this already, no more work to be done
- return;
-
- } else {
- // we have a situation where multiple objects have the same identity hashcode, work with our
- // collision map to decide whether it needs to be scrubbed and add if necessary.
- // Note that this code block is infrequently hit, it is by design that we've pushed the extra
- // work, map, etc, involved for this infrequent case into its own block. The standard cases must
- // be as fast and lean as possible.
-
- boolean alreadyDetached = false;
- List<Object> collisionObjects = checkedObjectCollisionMap.get(valueIdentity);
-
- if (null == collisionObjects) {
- // if this is the 2nd occurrence for this hash, create a new map entry
- collisionObjects = new ArrayList<Object>(1);
- checkedObjectCollisionMap.put(valueIdentity, collisionObjects);
-
- } else {
- // if we have scrubbed this already, no more work to be done
- for (Object collisionObject : collisionObjects) {
- if (value == collisionObject) {
- alreadyDetached = true;
- break;
- }
- }
- }
-
- if (LOG.isDebugEnabled()) {
- StringBuilder message = new StringBuilder("\n\tIDENTITY HASHCODE COLLISION [hash=");
- message.append(valueIdentity);
- message.append(", alreadyDetached=");
- message.append(alreadyDetached);
- message.append("]");
- message.append("\n\tCurrent : ");
- message.append(value.getClass().getName());
- message.append("\n\t ");
- message.append(value);
- message.append("\n\tPrevious : ");
- message.append(checkedObject.getClass().getName());
- message.append("\n\t ");
- message.append(checkedObject);
- for (Object collisionObject : collisionObjects) {
- message.append("\n\tPrevious : ");
- message.append(collisionObject.getClass().getName());
- message.append("\n\t ");
- message.append(collisionObject);
- }
-
- LOG.debug(message);
- }
-
- // now that we've done our logging, if already detached we're done. Otherwise add to the list of collision
- // objects for this hash, and start scrubbing
- if (alreadyDetached) {
- return;
- }
-
- collisionObjects.add(value);
- }
-
- // Perform the detaching
- if (value instanceof Object[]) {
- Object[] objArray = (Object[]) value;
- for (int i = 0; i < objArray.length; i++) {
- Object listEntry = objArray[i];
- Object replaceEntry = replaceObject(listEntry);
- if (replaceEntry != null) {
- objArray[i] = replaceEntry;
- }
- nullOutUninitializedFields(objArray[i], checkedObjectMap, checkedObjectCollisionMap, depth + 1,
- serializationType);
- }
- } else if (value instanceof List) {
- // Null out any entries in initialized collections
- ListIterator i = ((List) value).listIterator();
- while (i.hasNext()) {
- Object val = i.next();
- Object replace = replaceObject(val);
- if (replace != null) {
- val = replace;
- i.set(replace);
- }
- nullOutUninitializedFields(val, checkedObjectMap, checkedObjectCollisionMap, depth + 1,
- serializationType);
- }
-
- } else if (value instanceof Collection) {
- Collection collection = (Collection) value;
- Collection itemsToBeReplaced = new ArrayList();
- Collection replacementItems = new ArrayList();
- for (Object item : collection) {
- Object replacementItem = replaceObject(item);
- if (replacementItem != null) {
- itemsToBeReplaced.add(item);
- replacementItems.add(replacementItem);
- item = replacementItem;
- }
- nullOutUninitializedFields(item, checkedObjectMap, checkedObjectCollisionMap, depth + 1,
- serializationType);
- }
- collection.removeAll(itemsToBeReplaced);
- collection.addAll(replacementItems); // watch out! if this collection is a Set, HashMap$MapSet doesn't support addAll. See BZ 688000
- } else if (value instanceof Map) {
- Map originalMap = (Map) value;
- HashMap<Object, Object> replaceMap = new HashMap<Object, Object>();
- for (Iterator i = originalMap.keySet().iterator(); i.hasNext();) {
- // get original key and value - these might be hibernate proxies
- Object originalKey = i.next();
- Object originalKeyValue = originalMap.get(originalKey);
-
- // replace with non-hibernate classes, if appropriate (will be null otherwise)
- Object replaceKey = replaceObject(originalKey);
- Object replaceValue = replaceObject(originalKeyValue);
-
- // if either original key or original value was a hibernate proxy object, we have to
- // remove it from the original map, and remember the replacement objects for later
- if (replaceKey != null || replaceValue != null) {
- Object newKey = (replaceKey != null) ? replaceKey : originalKey;
- Object newValue = (replaceValue != null) ? replaceValue : originalKeyValue;
- replaceMap.put(newKey, newValue);
- i.remove();
- }
- }
-
- // all hibernate proxies have been removed, we need to replace them with their
- // non-proxy object representations that we got from replaceObject() calls
- originalMap.putAll(replaceMap);
-
- // now go through each item in the map and null out their internal fields
- for (Object key : originalMap.keySet()) {
- nullOutUninitializedFields(originalMap.get(key), checkedObjectMap, checkedObjectCollisionMap,
- depth + 1, serializationType);
- nullOutUninitializedFields(key, checkedObjectMap, checkedObjectCollisionMap, depth + 1,
- serializationType);
- }
- } else if (value instanceof Enum) {
- // don't need to detach enums, treat them as special objects
- return;
- }
-
- if (serializationType == SerializationType.JAXB) {
- XmlAccessorType at = value.getClass().getAnnotation(XmlAccessorType.class);
- if (at != null && at.value() == XmlAccessType.FIELD) {
- nullOutFieldsByFieldAccess(value, checkedObjectMap, checkedObjectCollisionMap, depth, serializationType);
- } else {
- nullOutFieldsByAccessors(value, checkedObjectMap, checkedObjectCollisionMap, depth, serializationType);
- }
- } else if (serializationType == SerializationType.SERIALIZATION) {
- nullOutFieldsByFieldAccess(value, checkedObjectMap, checkedObjectCollisionMap, depth, serializationType);
- }
-
- }
-
- private static void nullOutFieldsByFieldAccess(Object object, Map<Integer, Object> checkedObjects,
- Map<Integer, List<Object>> checkedObjectCollisionMap, int depth, SerializationType serializationType)
- throws Exception {
-
- Class tmpClass = object.getClass();
- List<Field> fieldsToClean = new ArrayList<Field>();
- while (tmpClass != null && tmpClass != Object.class) {
- Field[] declaredFields = tmpClass.getDeclaredFields();
- for (Field declaredField : declaredFields) {
- // do not process static final or transient fields since they won't be serialized anyway
- int modifiers = declaredField.getModifiers();
- if (!((Modifier.isFinal(modifiers) && Modifier.isStatic(modifiers)) || Modifier.isTransient(modifiers))) {
- fieldsToClean.add(declaredField);
- }
- }
- tmpClass = tmpClass.getSuperclass();
- }
-
- nullOutFieldsByFieldAccess(object, fieldsToClean, checkedObjects, checkedObjectCollisionMap, depth,
- serializationType);
- }
-
- private static void nullOutFieldsByFieldAccess(Object object, List<Field> classFields,
- Map<Integer, Object> checkedObjects, Map<Integer, List<Object>> checkedObjectCollisionMap, int depth,
- SerializationType serializationType) throws Exception {
-
- boolean accessModifierFlag = false;
- for (Field field : classFields) {
- accessModifierFlag = false;
- if (!field.isAccessible()) {
- field.setAccessible(true);
- accessModifierFlag = true;
- }
-
- Object fieldValue = field.get(object);
-
- if (fieldValue instanceof HibernateProxy) {
-
- Object replacement = null;
- String assistClassName = fieldValue.getClass().getName();
- if (assistClassName.contains("javassist") || assistClassName.contains("EnhancerByCGLIB")) {
-
- Class assistClass = fieldValue.getClass();
- try {
- Method m = assistClass.getMethod("writeReplace");
- replacement = m.invoke(fieldValue);
-
- String assistNameDelimiter = assistClassName.contains("javassist") ? "_$$_" : "$$";
-
- assistClassName = assistClassName.substring(0, assistClassName.indexOf(assistNameDelimiter));
- if (!replacement.getClass().getName().contains("hibernate")) {
- nullOutUninitializedFields(replacement, checkedObjects, checkedObjectCollisionMap,
- depth + 1, serializationType);
-
- field.set(object, replacement);
- } else {
- replacement = null;
- }
- } catch (Exception e) {
- LOG.error("Unable to write replace object " + fieldValue.getClass(), e);
- }
- }
-
- if (replacement == null) {
-
- String className = ((HibernateProxy) fieldValue).getHibernateLazyInitializer().getEntityName();
-
- //see if there is a context classloader we should use instead of the current one.
- ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
-
- Class clazz = contextClassLoader == null ? Class.forName(className) : Class.forName(className,
- true, contextClassLoader);
- Class[] constArgs = { Integer.class };
- Constructor construct = null;
-
- try {
- construct = clazz.getConstructor(constArgs);
- replacement = construct.newInstance((Integer) ((HibernateProxy) fieldValue)
- .getHibernateLazyInitializer().getIdentifier());
- field.set(object, replacement);
- } catch (NoSuchMethodException nsme) {
-
- try {
- Field idField = clazz.getDeclaredField("id");
- Constructor ct = clazz.getDeclaredConstructor();
- ct.setAccessible(true);
- replacement = ct.newInstance();
- if (!idField.isAccessible()) {
- idField.setAccessible(true);
- }
- idField.set(replacement, (Integer) ((HibernateProxy) fieldValue)
- .getHibernateLazyInitializer().getIdentifier());
- } catch (Exception e) {
- e.printStackTrace();
- LOG.error("No id constructor and unable to set field id for base bean " + className, e);
- }
-
- field.set(object, replacement);
- }
- }
-
- } else {
- if (fieldValue instanceof org.hibernate.collection.PersistentCollection) {
- // Replace hibernate specific collection types
-
- if (!((org.hibernate.collection.PersistentCollection) fieldValue).wasInitialized()) {
- field.set(object, null);
- } else {
-
- Object replacement = null;
- boolean needToNullOutFields = true; // needed for BZ 688000
- if (fieldValue instanceof Map) {
- replacement = new HashMap((Map) fieldValue);
- } else if (fieldValue instanceof List) {
- replacement = new ArrayList((List) fieldValue);
- } else if (fieldValue instanceof Set) {
- ArrayList l = new ArrayList((Set) fieldValue); // cannot recurse Sets, see BZ 688000
- nullOutUninitializedFields(l, checkedObjects, checkedObjectCollisionMap, depth + 1,
- serializationType);
- replacement = new HashSet(l); // convert it back to a Set since that's the type of the real collection, see BZ 688000
- needToNullOutFields = false;
- } else if (fieldValue instanceof Collection) {
- replacement = new ArrayList((Collection) fieldValue);
- }
- setField(object, field.getName(), replacement);
-
- if (needToNullOutFields) {
- nullOutUninitializedFields(replacement, checkedObjects, checkedObjectCollisionMap,
- depth + 1, serializationType);
- }
- }
-
- } else {
- if (fieldValue != null
- && (fieldValue.getClass().getName().contains("org.rhq") || fieldValue instanceof Collection
- || fieldValue instanceof Object[] || fieldValue instanceof Map))
- nullOutUninitializedFields((fieldValue), checkedObjects, checkedObjectCollisionMap, depth + 1,
- serializationType);
- }
- }
- if (accessModifierFlag) {
- field.setAccessible(false);
- }
- }
-
- }
-
- private static Object replaceObject(Object object) {
- Object replacement = null;
-
- if (object instanceof HibernateProxy) {
- if (object.getClass().getName().contains("javassist")) {
- Class assistClass = object.getClass();
- try {
- Method m = assistClass.getMethod("writeReplace");
- replacement = m.invoke(object);
-
- } catch (Exception e) {
- LOG.error("Unable to write replace object " + object.getClass(), e);
- }
- }
- }
- return replacement;
- }
-
- private static void nullOutFieldsByAccessors(Object value, Map<Integer, Object> checkedObjects,
- Map<Integer, List<Object>> checkedObjectCollisionMap, int depth, SerializationType serializationType)
- throws Exception {
- // Null out any collections that aren't loaded
- BeanInfo bi = Introspector.getBeanInfo(value.getClass(), Object.class);
-
- PropertyDescriptor[] pds = bi.getPropertyDescriptors();
- for (PropertyDescriptor pd : pds) {
- Object propertyValue = null;
- try {
- propertyValue = pd.getReadMethod().invoke(value);
- } catch (Throwable lie) {
- if (LOG.isDebugEnabled()) {
- LOG.debug("Couldn't load: " + pd.getName() + " off of " + value.getClass().getSimpleName(), lie);
- }
- }
-
- if (!Hibernate.isInitialized(propertyValue)) {
- try {
- if (LOG.isDebugEnabled()) {
- LOG.debug("Nulling out: " + pd.getName() + " off of " + value.getClass().getSimpleName());
- }
-
- Method writeMethod = pd.getWriteMethod();
- if ((writeMethod != null) && (writeMethod.getAnnotation(XmlTransient.class) == null)) {
- pd.getWriteMethod().invoke(value, new Object[] { null });
- } else {
- nullOutField(value, pd.getName());
- }
- } catch (Exception lie) {
- LOG.debug("Couldn't null out: " + pd.getName() + " off of " + value.getClass().getSimpleName()
- + " trying field access", lie);
- nullOutField(value, pd.getName());
- }
- } else {
- if ((propertyValue instanceof Collection)
- || ((propertyValue != null) && propertyValue.getClass().getName().startsWith("org.rhq.core.domain"))) {
- nullOutUninitializedFields(propertyValue, checkedObjects, checkedObjectCollisionMap, depth + 1,
- serializationType);
- }
- }
- }
- }
-
- private static void setField(Object object, String fieldName, Object newValue) {
- try {
- Field f = object.getClass().getDeclaredField(fieldName);
- if (f != null) {
- // try to set the field this way
- f.setAccessible(true);
- f.set(object, newValue);
- }
- } catch (NoSuchFieldException e) {
- // ignore this
- } catch (IllegalAccessException e) {
- // ignore this
- }
- }
-
- private static void nullOutField(Object value, String fieldName) {
- try {
- Field f = value.getClass().getDeclaredField(fieldName);
- if (f != null) {
- // try to set the field this way
- f.setAccessible(true);
- f.set(value, null);
- }
- } catch (NoSuchFieldException e) {
- // ignore this
- } catch (IllegalAccessException e) {
- // ignore this
- }
- }
-}
\ No newline at end of file
diff --git a/modules/enterprise/server/safe-invoker/src/test/java/org/rhq/enterprise/server/safeinvoker/HibernateDetachUtilityTest.java b/modules/enterprise/server/safe-invoker/src/test/java/org/rhq/enterprise/server/safeinvoker/HibernateDetachUtilityTest.java
new file mode 100644
index 0000000..08a0201
--- /dev/null
+++ b/modules/enterprise/server/safe-invoker/src/test/java/org/rhq/enterprise/server/safeinvoker/HibernateDetachUtilityTest.java
@@ -0,0 +1,142 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2011 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, version 2, as
+ * published by the Free Software Foundation, and/or the GNU Lesser
+ * General Public License, version 2.1, also as published by the Free
+ * Software Foundation.
+ *
+ * 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 and the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * and the GNU Lesser General Public License along with this program;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.rhq.enterprise.server.safeinvoker;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import org.testng.annotations.Test;
+
+import org.rhq.enterprise.server.safeinvoker.HibernateDetachUtility;
+import org.rhq.enterprise.server.safeinvoker.HibernateDetachUtility.SerializationType;
+
+@Test
+public class HibernateDetachUtilityTest {
+ /**
+ * This tests the rare, but very possible, condition where two objects
+ * have the same identity hashcode (System.identityHashCode(A) == System.identityHashCode(B))
+ * but are not identical objects (A != B). We have seen this as a valid condition
+ * on both SUN and IBM JRE implementations.
+ */
+ public void testIdenticalHashCodesNonIdenticalObjects() throws Exception {
+ class ArrayObject implements Serializable {
+ private static final long serialVersionUID = 1L;
+ long id;
+ Integer[] array;
+ ArrayObject object; // needed for self-referencing
+
+ ArrayObject(long key, ArrayObject obj, Integer... members) {
+ id = key;
+ object = obj;
+ array = members;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("ArrayObject [id=").append(id).append(", object=").append(
+ (object == null) ? "null" : object.id).append(", array=").append(Arrays.toString(array))
+ .append("]");
+ return builder.toString();
+ }
+
+ }
+
+ class DuplicateHashCodeGenerator implements HibernateDetachUtility.HashCodeGenerator {
+ public Integer getHashCode(Object value) {
+ if (value instanceof Integer && ((Integer) value).intValue() >= 2) {
+ return 11111;
+ } else if (value instanceof ArrayObject) {
+ return 22222;
+ } else {
+ return System.identityHashCode(value);
+ }
+ }
+ }
+
+ ArrayObject array1 = new ArrayObject(1, null, 1, 2, 3);
+ ArrayObject array2 = new ArrayObject(2, array1, 2, 3);
+ array1.object = array2; // now 1 references 2 and 2 reference 1, circular dependency
+ ArrayObject array3 = new ArrayObject(3, array2, 3);
+ array3.object = array3;
+ ArrayList<ArrayObject> array = new ArrayList<ArrayObject>(3);
+ array.add(array1);
+ array.add(array2);
+ array.add(array3);
+
+ // SANITY CHECK - make sure our setup is as we expect it to be
+ assert array.get(0).array[0] == Integer.valueOf(1);
+ assert array.get(0).array[1] == Integer.valueOf(2);
+ assert array.get(0).array[2] == Integer.valueOf(3);
+ assert array.get(1).array[0] == Integer.valueOf(2);
+ assert array.get(1).array[1] == Integer.valueOf(3);
+ assert array.get(2).array[0] == Integer.valueOf(3);
+
+ // make sure array1 still references array2 and vice versa
+ assertObjectEquals(array.get(0).object, array.get(1));
+ assertObjectEquals(array.get(1).object, array.get(0));
+
+ // make sure array3 still self-references
+ assertObjectEquals(array.get(2).object, array.get(2));
+
+ // simulate rare condition
+ HibernateDetachUtility.hashCodeGenerator = new DuplicateHashCodeGenerator();
+ HibernateDetachUtility.nullOutUninitializedFields(array, SerializationType.SERIALIZATION);
+ assert array.get(0).array[0] == Integer.valueOf(1);
+ assert array.get(0).array[1] == Integer.valueOf(2);
+ assert array.get(0).array[2] == Integer.valueOf(3);
+ assert array.get(1).array[0] == Integer.valueOf(2);
+ assert array.get(1).array[1] == Integer.valueOf(3);
+ assert array.get(2).array[0] == Integer.valueOf(3);
+
+ // make sure array1 still references array2 and vice versa
+ assertObjectEquals(array.get(0).object, array.get(1));
+ assertObjectEquals(array.get(1).object, array.get(0));
+
+ // make sure array3 still self-references
+ assertObjectEquals(array.get(2).object, array.get(2));
+
+ // put it back the way it was
+ HibernateDetachUtility.hashCodeGenerator = new HibernateDetachUtility.SystemHashCodeGenerator();
+ HibernateDetachUtility.nullOutUninitializedFields(array, SerializationType.SERIALIZATION);
+ assert array.get(0).array[0] == Integer.valueOf(1);
+ assert array.get(0).array[1] == Integer.valueOf(2);
+ assert array.get(0).array[2] == Integer.valueOf(3);
+ assert array.get(1).array[0] == Integer.valueOf(2);
+ assert array.get(1).array[1] == Integer.valueOf(3);
+ assert array.get(2).array[0] == Integer.valueOf(3);
+
+ // make sure array1 still references array2 and vice versa
+ assertObjectEquals(array.get(0).object, array.get(1));
+ assertObjectEquals(array.get(1).object, array.get(0));
+
+ // make sure array3 still self-references
+ assertObjectEquals(array.get(2).object, array.get(2));
+ }
+
+ private void assertObjectEquals(Object o1, Object o2) {
+ assert o1 == o2 : "Object [" + o1 + "] does not equal object [" + o2 + "]";
+ }
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/safe-invoker/src/test/java/org/rhq/enterprise/server/util/HibernateDetachUtilityTest.java b/modules/enterprise/server/safe-invoker/src/test/java/org/rhq/enterprise/server/util/HibernateDetachUtilityTest.java
deleted file mode 100644
index 3df5403..0000000
--- a/modules/enterprise/server/safe-invoker/src/test/java/org/rhq/enterprise/server/util/HibernateDetachUtilityTest.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2011 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, version 2, as
- * published by the Free Software Foundation, and/or the GNU Lesser
- * General Public License, version 2.1, also as published by the Free
- * Software Foundation.
- *
- * 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 and the GNU Lesser General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * and the GNU Lesser General Public License along with this program;
- * if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-package org.rhq.enterprise.server.util;
-
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Arrays;
-
-import org.testng.annotations.Test;
-
-import org.rhq.enterprise.server.util.HibernateDetachUtility.SerializationType;
-
-@Test
-public class HibernateDetachUtilityTest {
- /**
- * This tests the rare, but very possible, condition where two objects
- * have the same identity hashcode (System.identityHashCode(A) == System.identityHashCode(B))
- * but are not identical objects (A != B). We have seen this as a valid condition
- * on both SUN and IBM JRE implementations.
- */
- public void testIdenticalHashCodesNonIdenticalObjects() throws Exception {
- class ArrayObject implements Serializable {
- private static final long serialVersionUID = 1L;
- long id;
- Integer[] array;
- ArrayObject object; // needed for self-referencing
-
- ArrayObject(long key, ArrayObject obj, Integer... members) {
- id = key;
- object = obj;
- array = members;
- }
-
- @Override
- public String toString() {
- StringBuilder builder = new StringBuilder();
- builder.append("ArrayObject [id=").append(id).append(", object=").append(
- (object == null) ? "null" : object.id).append(", array=").append(Arrays.toString(array))
- .append("]");
- return builder.toString();
- }
-
- }
-
- class DuplicateHashCodeGenerator implements HibernateDetachUtility.HashCodeGenerator {
- public Integer getHashCode(Object value) {
- if (value instanceof Integer && ((Integer) value).intValue() >= 2) {
- return 11111;
- } else if (value instanceof ArrayObject) {
- return 22222;
- } else {
- return System.identityHashCode(value);
- }
- }
- }
-
- ArrayObject array1 = new ArrayObject(1, null, 1, 2, 3);
- ArrayObject array2 = new ArrayObject(2, array1, 2, 3);
- array1.object = array2; // now 1 references 2 and 2 reference 1, circular dependency
- ArrayObject array3 = new ArrayObject(3, array2, 3);
- array3.object = array3;
- ArrayList<ArrayObject> array = new ArrayList<ArrayObject>(3);
- array.add(array1);
- array.add(array2);
- array.add(array3);
-
- // SANITY CHECK - make sure our setup is as we expect it to be
- assert array.get(0).array[0] == Integer.valueOf(1);
- assert array.get(0).array[1] == Integer.valueOf(2);
- assert array.get(0).array[2] == Integer.valueOf(3);
- assert array.get(1).array[0] == Integer.valueOf(2);
- assert array.get(1).array[1] == Integer.valueOf(3);
- assert array.get(2).array[0] == Integer.valueOf(3);
-
- // make sure array1 still references array2 and vice versa
- assertObjectEquals(array.get(0).object, array.get(1));
- assertObjectEquals(array.get(1).object, array.get(0));
-
- // make sure array3 still self-references
- assertObjectEquals(array.get(2).object, array.get(2));
-
- // simulate rare condition
- HibernateDetachUtility.hashCodeGenerator = new DuplicateHashCodeGenerator();
- HibernateDetachUtility.nullOutUninitializedFields(array, SerializationType.SERIALIZATION);
- assert array.get(0).array[0] == Integer.valueOf(1);
- assert array.get(0).array[1] == Integer.valueOf(2);
- assert array.get(0).array[2] == Integer.valueOf(3);
- assert array.get(1).array[0] == Integer.valueOf(2);
- assert array.get(1).array[1] == Integer.valueOf(3);
- assert array.get(2).array[0] == Integer.valueOf(3);
-
- // make sure array1 still references array2 and vice versa
- assertObjectEquals(array.get(0).object, array.get(1));
- assertObjectEquals(array.get(1).object, array.get(0));
-
- // make sure array3 still self-references
- assertObjectEquals(array.get(2).object, array.get(2));
-
- // put it back the way it was
- HibernateDetachUtility.hashCodeGenerator = new HibernateDetachUtility.SystemHashCodeGenerator();
- HibernateDetachUtility.nullOutUninitializedFields(array, SerializationType.SERIALIZATION);
- assert array.get(0).array[0] == Integer.valueOf(1);
- assert array.get(0).array[1] == Integer.valueOf(2);
- assert array.get(0).array[2] == Integer.valueOf(3);
- assert array.get(1).array[0] == Integer.valueOf(2);
- assert array.get(1).array[1] == Integer.valueOf(3);
- assert array.get(2).array[0] == Integer.valueOf(3);
-
- // make sure array1 still references array2 and vice versa
- assertObjectEquals(array.get(0).object, array.get(1));
- assertObjectEquals(array.get(1).object, array.get(0));
-
- // make sure array3 still self-references
- assertObjectEquals(array.get(2).object, array.get(2));
- }
-
- private void assertObjectEquals(Object o1, Object o2) {
- assert o1 == o2 : "Object [" + o1 + "] does not equal object [" + o2 + "]";
- }
-}
\ No newline at end of file
12 years, 9 months
[rhq] modules/enterprise
by ips
modules/enterprise/server/container/src/main/bin-resources/bin/rhq-server.sh | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
New commits:
commit c98d6b5d34dce6e97b8875683264cc8c063a9c42
Author: Ian Springer <ian.springer(a)redhat.com>
Date: Thu Sep 15 15:33:36 2011 -0400
add commented lines that can be uncommented to enable JProfiler agent
diff --git a/modules/enterprise/server/container/src/main/bin-resources/bin/rhq-server.sh b/modules/enterprise/server/container/src/main/bin-resources/bin/rhq-server.sh
index b255914..fd88242 100644
--- a/modules/enterprise/server/container/src/main/bin-resources/bin/rhq-server.sh
+++ b/modules/enterprise/server/container/src/main/bin-resources/bin/rhq-server.sh
@@ -54,7 +54,13 @@
# is mainly used to augment the Server's
# default set of options. This can be
# left unset if it is not needed.
-#RHQ_SERVER_ADDITIONAL_JAVA_OPTS=-agentlib:jdwp=transport=dt_socket,address=8787,server=y,suspend=n
+# Enable remote debugging
+#RHQ_SERVER_ADDITIONAL_JAVA_OPTS="-agentlib:jdwp=transport=dt_socket,address=8787,server=y,suspend=n"
+# Enable JProfiler
+#JPROFILER_HOME="/opt/jprofiler6"
+#RHQ_SERVER_ADDITIONAL_JAVA_OPTS="$RHQ_SERVER_ADDITIONAL_JAVA_OPTS -agentlib:jprofilerti=port=8849 -Xbootclasspath/a:$JPROFILER_HOME/bin/agent.jar"
+#export PATH="$PATH:$JPROFILER_HOME/bin"
+#export LD_LIBRARY_PATH="$JPROFILER_HOME/bin/linux-x64"
#
# RHQ_SERVER_CMDLINE_OPTS - If this is defined, these are the command line
# arguments that will be passed to the RHQ Server
12 years, 9 months
[rhq] modules/enterprise
by Simeon Pinder
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/CoreGUI.java | 26 ++++++----
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/AboutModalWindow.java | 1
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/TitleBar.java | 20 +++----
modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html | 2
4 files changed, 28 insertions(+), 21 deletions(-)
New commits:
commit c74567558ed10769eeb0e636c12553f95c9cbb6e
Author: Simeon Pinder <spinder(a)redhat.com>
Date: Thu Sep 15 12:45:36 2011 -0400
BZ 736077: applied patches from bz and one other fix(to disable TitleBar from hardcoding RHQ) to get JON and not RHQ in browser titles.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/CoreGUI.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/CoreGUI.java
index 88801e0..2916bdb 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/CoreGUI.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/CoreGUI.java
@@ -64,6 +64,8 @@ import org.rhq.enterprise.gui.coregui.client.util.message.Message;
import org.rhq.enterprise.gui.coregui.client.util.message.MessageCenter;
import org.rhq.enterprise.gui.coregui.client.util.selenium.SeleniumUtility;
+import java.util.List;
+
/**
* The GWT {@link EntryPoint entry point} to the RHQ GUI.
*
@@ -276,6 +278,7 @@ public class CoreGUI implements EntryPoint, ValueChangeHandler<String>, Event.Na
public void onSuccess(ProductInfo result) {
productInfo = result;
+ Window.setTitle(productInfo.getName());
buildCoreUI();
}
});
@@ -470,22 +473,25 @@ public class CoreGUI implements EntryPoint, ValueChangeHandler<String>, Event.Na
setHeight100();
}
+ // TODO (ips, 09/06/11): i18n the title.
private String getViewPathTitle(ViewPath viewPath) {
- // default title is the path minus any IDs we find. That should give a least some nice default title.
+ // Set the default title to the view path minus any IDs.
StringBuilder viewPathTitle = new StringBuilder();
- for (ViewId viewId : viewPath.getViewPath()) {
- // none of our path elements start with a digit that is NOT an ID; if we see an ID, skip it
- if (!Character.isDigit(viewId.getPath().charAt(0))) {
- if (viewPathTitle.length() > 0) {
+ String productName = (productInfo != null) ? productInfo.getName() : "RHQ";
+ List<ViewId> viewIds = viewPath.getViewPath();
+ if (!viewIds.isEmpty()) {
+ viewPathTitle.append(productName).append(": ");
+ viewPathTitle.append(viewIds.get(0));
+ for (int i = 1, viewPathSize = viewIds.size(); i < viewPathSize; i++) {
+ ViewId viewId = viewIds.get(i);
+ // None of our path elements start with a digit that is NOT an ID, so if we see an ID, skip it.
+ if (!Character.isDigit(viewId.getPath().charAt(0))) {
viewPathTitle.append(" | ");
+ viewPathTitle.append(viewId.getPath());
}
- viewPathTitle.append(viewId.getPath());
}
}
- if (viewPathTitle.length() == 0) {
- viewPathTitle.append("Core Application");
- }
- return "RHQ: " + viewPathTitle.toString();
+ return viewPathTitle.toString();
}
public void initCanvas() {
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/AboutModalWindow.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/AboutModalWindow.java
index b476f66..e219837 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/AboutModalWindow.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/AboutModalWindow.java
@@ -76,6 +76,7 @@ public class AboutModalWindow extends LocatableWindow {
LocatableVLayout contentPane = new LocatableVLayout(extendLocatorId("Content"));
contentPane.setPadding(10);
+ // TODO (ips, 09/06/11): Convert this raw HTML to SmartGWT widgets.
HTMLPane htmlPane = new HTMLPane();
String html = "<span class=\"DisplaySubhead\">\n" + " <a href=\"" + productInfo.getUrl() + "\" title=\""
+ productInfo.getFullName() + " " + productInfo.getUrl() + "\" target=\"_blank\">"
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/TitleBar.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/TitleBar.java
index 3ded730..84c6113 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/TitleBar.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/TitleBar.java
@@ -19,7 +19,6 @@
*/
package org.rhq.enterprise.gui.coregui.client.components;
-import com.google.gwt.user.client.Window;
import com.smartgwt.client.types.VerticalAlignment;
import com.smartgwt.client.widgets.Label;
@@ -91,15 +90,16 @@ public class TitleBar extends LocatableToolStrip {
String contents;
String windowTitle;
- if (title == null) {
- contents = null;
- windowTitle = "RHQ";
- } else {
- contents = "<span class='HeaderLabel'>" + title + "</span>";
- windowTitle = "RHQ: " + title;
- }
- this.label.setContents(contents);
- Window.setTitle(windowTitle);
+ //spinder 9/15/11: Commenting out to let CoreGUI handle all title setting.
+ // if (title == null) {
+ // contents = null;
+ // windowTitle = "RHQ";
+ // } else {
+ // contents = "<span class='HeaderLabel'>" + title + "</span>";
+ // windowTitle = "RHQ: " + title;
+ // }
+ // this.label.setContents(contents);
+ // Window.setTitle(windowTitle);
}
}
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html b/modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html
index 94d9621..21acc5d 100644
--- a/modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html
+++ b/modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html
@@ -13,7 +13,7 @@
<!-- support internationalized characters -->
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
- <title>RHQ Core Application</title>
+ <title>RHQ</title>
<link rel="icon" type="image/png" href="/images/favicon.png" />
<link rel="apple-touch-icon" href="/images/favicon.png" />
12 years, 9 months
[rhq] Branch 'stefan/release_updates' - publish_release.sh release.sh rhq_bash.lib
by snegrea
publish_release.sh | 133 -------------------------------------
release.sh | 189 +++++++++--------------------------------------------
rhq_bash.lib | 134 +++++++++++++++++++++++++++++++++++++
3 files changed, 171 insertions(+), 285 deletions(-)
New commits:
commit a54ba6ff8ddc0fcef5318df1203291221f1e0b3a
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Thu Sep 15 11:44:00 2011 -0500
More refactoring for the publish and release scripts.
diff --git a/publish_release.sh b/publish_release.sh
index 714b7f7..3141102 100755
--- a/publish_release.sh
+++ b/publish_release.sh
@@ -1,5 +1,8 @@
#!/bin/sh
+source `dirname $0`/rhq_bash.lib
+
+
# Functions
abort()
@@ -11,30 +14,6 @@ abort()
exit 1
}
-print_variables()
-{
- for variable in "$@"
- do
- temp_var='eval "echo \$$variable"'
- eval_temp_var=`eval $temp_var`
-
- if [ -z "$eval_temp_var" ]; then
- echo "$variable is NOT defined!"
- else
- echo "$variable=$eval_temp_var"
- fi
- done
-}
-
-print_program_versions()
-{
- for variable in "$@"
- do
- eval $variable
- echo
- done
-}
-
usage()
{
EXE=`basename $0`
@@ -42,112 +21,6 @@ usage()
abort "$@" "Usage: $EXE community|enterprise RELEASE_BRANCH test|production" "Example: $EXE enterprise release-3.0.0 test"
}
-validate_java_6()
-{
- # Make sure JAVA_HOME points to a valid JDK 1.6+ install.
-
- if [ -z "$JAVA_HOME" ]; then
- abort "JAVA_HOME environment variable is not set - JAVA_HOME must point to a JDK (not JRE) 6 install dir."
- fi
-
- if [ ! -d "$JAVA_HOME" ]; then
- abort "JAVA_HOME ($JAVA_HOME) does not exist or is not a directory - JAVA_HOME must point to a JDK (not JRE) 6 install dir."
- fi
-
- echo "Prepending $JAVA_HOME/bin to PATH..."
- PATH="$JAVA_HOME/bin:$PATH"
-
- if ! which java >/dev/null 2>&1; then
- abort "java not found in PATH ($PATH) - JAVA_HOME must point to a JDK (not JRE) 6 install dir."
- fi
-
- if ! which javac >/dev/null 2>&1; then
- abort "javac not found in PATH ($PATH) - JAVA_HOME must point to a JDK (not JRE) 6 install dir."
- fi
-
- if ! javap java.util.Deque >/dev/null 2>&1; then
- abort "java.util.Deque not found - Java version appears to be less than 1.6 - Jave version must be 1.6 or later."
- fi
-}
-
-validate_java_5()
-{
- echo "nothing executed here"
- # spinder 8/30/11: commenting out the JAVA5 support, but leaving logic in place for when we need the same backwards
- # compatibility logic for JD6 vs. JDK7 support.
- # If this is an enterprise release, make sure JAVA5_HOME points to a valid JDK 1.5 install.
- # We need this to validate only Java 5 or earlier APIs are used in all modules, except the CLI, which requires Java 6.
- #
- #if [ "$RELEASE_TYPE" = "enterprise" ]; then
- # if [ -z "$JAVA5_HOME" ]; then
- # abort "JAVA5_HOME environment variable is not set - JAVA5_HOME must point to a JDK (not JRE) 1.5 install dir."
- # fi
- #
- # if [ ! -d "$JAVA5_HOME" ]; then
- # abort "JAVA5_HOME ($JAVA5_HOME) does not exist or is not a directory - JAVA5_HOME must point to a JDK (not JRE) 1.5 install dir."
- # fi
- #
- # if [ ! -x "$JAVA5_HOME/bin/java" ]; then
- # abort "$JAVA5_HOME/bin/java does not exist or is not executable - JAVA5_HOME must point to a JDK (not JRE) 1.5 install dir."
- # fi
- #
- # if [ ! -x "$JAVA5_HOME/bin/javac" ]; then
- # abort "$JAVA5_HOME/bin/javac does not exist or is not executable - JAVA5_HOME must point to a JDK (not JRE) 1.5 install dir."
- # fi
- #
- # if ! "$JAVA5_HOME/bin/javap" java.lang.Enum >/dev/null 2>&1; then
- # abort "java.lang.Enum not found - JAVA5_HOME ($JAVA5_HOME) version appears to be less than 1.5 - version must be 1.5.x."
- # fi
- #
- # if "$JAVA5_HOME/bin/javap" java.util.Deque >/dev/null 2>&1; then
- # abort "java.util.Deque found - JAVA5_HOME ($JAVA5_HOME) version appears to be greater than or equal to 1.6 - version must be 1.5.x."
- # fi
- #fi
-}
-
-validate_maven()
-{
- # Make sure M2_HOME points to a valid Maven 2.1.x or 2.2.x install.
-
- if [ -z "$M2_HOME" ]; then
- abort "M2_HOME environment variable is not set - M2_HOME must point to a Maven, $MINIMUM_MAVEN_VERSION or later, install dir."
- fi
-
- if [ ! -d "$M2_HOME" ]; then
- abort "M2_HOME ($M2_HOME) does not exist or is not a directory - M2_HOME must point to a Maven, $MINIMUM_MAVEN_VERSION or later, install dir."
- fi
-
- echo "Prepending $M2_HOME/bin to PATH..."
- PATH="$M2_HOME/bin:$PATH"
-
- if ! which mvn >/dev/null 2>&1; then
- abort "mvn not found in PATH ($PATH) - M2_HOME must point to a Maven, $MINIMUM_MAVEN_VERSION or later, install dir."
- fi
-
- mvn -version >/dev/null
- [ $? -ne 0 ] && abort "mvn --version failed with exit code $?."
- MAVEN_VERSION=`mvn -version | head -1 | sed 's|[^0-9]*\([^ ]*\).*|\1|'`
- if echo $MAVEN_VERSION | grep -Ev "^(2\.[12]|3\.0)"; then
- abort "Unsupported Maven version - $MAVEN_VERSION. Only Maven 2.1.x, 2.2.x, or 3.0.x is supported. Please update the value of M2_HOME, then try again."
- fi
-}
-
-validate_git()
-{
- # Make sure git 1.6.x or 1.7.x is in the PATH.
-
- if ! which git >/dev/null 2>&1; then
- abort "git not found in PATH ($PATH)."
- fi
-
- git --version >/dev/null
- [ $? -ne 0 ] && abort "git --version failed with exit code $?."
- GIT_VERSION=`git --version | sed 's|[^0-9]*\([^ ]*\).*|\1|'`
- if echo $GIT_VERSION | grep -v "^1.[67]"; then
- abort "Unsupported git version - $GIT_VERSION. Only git 1.6.x or 1.7.x are supported. Please add a directory containing a supported version of git to your PATH, then try again."
- fi
-}
-
validate_arguments()
{
if [ "$#" -ne 3 ]; then
diff --git a/release.sh b/release.sh
index 479bb4d..9ba123e 100755
--- a/release.sh
+++ b/release.sh
@@ -1,18 +1,7 @@
#!/bin/sh
-if [ -n "$RELEASE_DEBUG" ]; then
- echo "Debug output is enabled."
- set -x
-fi
-
-# Constants
-
-PROJECT_NAME="rhq"
-PROJECT_DISPLAY_NAME="RHQ"
-PROJECT_GIT_WEB_URL="http://git.fedorahosted.org/git/?p=rhq/rhq.git"
-TAG_PREFIX="RHQ"
-MINIMUM_MAVEN_VERSION="2.1.0"
+source `dirname $0`/rhq_bash.lib
# Functions
@@ -32,6 +21,21 @@ usage()
}
+if [ -n "$RELEASE_DEBUG" ]; then
+ echo "Debug output is enabled."
+ set -x
+fi
+
+
+# Constants
+
+PROJECT_NAME="rhq"
+PROJECT_DISPLAY_NAME="RHQ"
+PROJECT_GIT_WEB_URL="http://git.fedorahosted.org/git/?p=rhq/rhq.git"
+TAG_PREFIX="RHQ"
+MINIMUM_MAVEN_VERSION="2.1.0"
+
+
# Process command line args.
EXE=`basename $0`
@@ -57,103 +61,15 @@ if [ "$MODE" = "production" ]; then
fi
fi
-
-# Make sure JAVA_HOME points to a valid JDK 1.6+ install.
-
-if [ -z "$JAVA_HOME" ]; then
- abort "JAVA_HOME environment variable is not set - JAVA_HOME must point to a JDK (not JRE) 6 install dir."
-fi
-
-if [ ! -d "$JAVA_HOME" ]; then
- abort "JAVA_HOME ($JAVA_HOME) does not exist or is not a directory - JAVA_HOME must point to a JDK (not JRE) 6 install dir."
-fi
-
-echo "Prepending $JAVA_HOME/bin to PATH..."
-PATH="$JAVA_HOME/bin:$PATH"
-
-if ! which java >/dev/null 2>&1; then
- abort "java not found in PATH ($PATH) - JAVA_HOME must point to a JDK (not JRE) 6 install dir."
-fi
-
-if ! which javac >/dev/null 2>&1; then
- abort "javac not found in PATH ($PATH) - JAVA_HOME must point to a JDK (not JRE) 6 install dir."
-fi
-
-if ! javap java.util.Deque >/dev/null 2>&1; then
- abort "java.util.Deque not found - Java version appears to be less than 1.6 - Jave version must be 1.6 or later."
-fi
-
# TODO: Check that JDK version is < 1.7.
-# spinder 8/30/11: commenting out the JAVA5 support, but leaving logic in place for when we need the same backwards
-# compatibility logic for JD6 vs. JDK7 support.
-# If this is an enterprise release, make sure JAVA5_HOME points to a valid JDK 1.5 install.
-# We need this to validate only Java 5 or earlier APIs are used in all modules, except the CLI, which requires Java 6.
-#
-#if [ "$RELEASE_TYPE" = "enterprise" ]; then
-# if [ -z "$JAVA5_HOME" ]; then
-# abort "JAVA5_HOME environment variable is not set - JAVA5_HOME must point to a JDK (not JRE) 1.5 install dir."
-# fi
-#
-# if [ ! -d "$JAVA5_HOME" ]; then
-# abort "JAVA5_HOME ($JAVA5_HOME) does not exist or is not a directory - JAVA5_HOME must point to a JDK (not JRE) 1.5 install dir."
-# fi
-#
-# if [ ! -x "$JAVA5_HOME/bin/java" ]; then
-# abort "$JAVA5_HOME/bin/java does not exist or is not executable - JAVA5_HOME must point to a JDK (not JRE) 1.5 install dir."
-# fi
-#
-# if [ ! -x "$JAVA5_HOME/bin/javac" ]; then
-# abort "$JAVA5_HOME/bin/javac does not exist or is not executable - JAVA5_HOME must point to a JDK (not JRE) 1.5 install dir."
-# fi
-#
-# if ! "$JAVA5_HOME/bin/javap" java.lang.Enum >/dev/null 2>&1; then
-# abort "java.lang.Enum not found - JAVA5_HOME ($JAVA5_HOME) version appears to be less than 1.5 - version must be 1.5.x."
-# fi
-#
-# if "$JAVA5_HOME/bin/javap" java.util.Deque >/dev/null 2>&1; then
-# abort "java.util.Deque found - JAVA5_HOME ($JAVA5_HOME) version appears to be greater than or equal to 1.6 - version must be 1.5.x."
-# fi
-#fi
-
-
-# Make sure M2_HOME points to a valid Maven 2.1.x or 2.2.x install.
-
-if [ -z "$M2_HOME" ]; then
- abort "M2_HOME environment variable is not set - M2_HOME must point to a Maven, $MINIMUM_MAVEN_VERSION or later, install dir."
-fi
-
-if [ ! -d "$M2_HOME" ]; then
- abort "M2_HOME ($M2_HOME) does not exist or is not a directory - M2_HOME must point to a Maven, $MINIMUM_MAVEN_VERSION or later, install dir."
-fi
+validate_java_6
-echo "Prepending $M2_HOME/bin to PATH..."
-PATH="$M2_HOME/bin:$PATH"
+validate_java_5
-if ! which mvn >/dev/null 2>&1; then
- abort "mvn not found in PATH ($PATH) - M2_HOME must point to a Maven, $MINIMUM_MAVEN_VERSION or later, install dir."
-fi
-
-mvn -version >/dev/null
-[ $? -ne 0 ] && abort "mvn --version failed with exit code $?."
-MAVEN_VERSION=`mvn -version | head -1 | sed 's|[^0-9]*\([^ ]*\).*|\1|'`
-if echo $MAVEN_VERSION | grep -Ev "^(2\.[12]|3\.0)"; then
- abort "Unsupported Maven version - $MAVEN_VERSION. Only Maven 2.1.x, 2.2.x, or 3.0.x is supported. Please update the value of M2_HOME, then try again."
-fi
-
-
-# Make sure git 1.6.x or 1.7.x is in the PATH.
-
-if ! which git >/dev/null 2>&1; then
- abort "git not found in PATH ($PATH)."
-fi
+validate_maven
-git --version >/dev/null
-[ $? -ne 0 ] && abort "git --version failed with exit code $?."
-GIT_VERSION=`git --version | sed 's|[^0-9]*\([^ ]*\).*|\1|'`
-if echo $GIT_VERSION | grep -v "^1.[67]"; then
- abort "Unsupported git version - $GIT_VERSION. Only git 1.6.x or 1.7.x are supported. Please add a directory containing a supported version of git to your PATH, then try again."
-fi
+validate_git
# Set various environment variables.
@@ -194,9 +110,6 @@ fi
if [ -n "$RELEASE_ADDITIONAL_MAVEN_ARGS" ]; then
MAVEN_ARGS="$MAVEN_ARGS $RELEASE_ADDITIONAL_MAVEN_ARGS"
fi
-if [ -z "$MAVEN_LOCAL_REPO_PURGE_INTERVAL_HOURS" ]; then
- MAVEN_LOCAL_REPO_PURGE_INTERVAL_HOURS="6"
-fi
# TODO: We may eventually want to reenable publishing of enterprise artifacts.
#if [ "$MODE" = "production" ] && [ "$RELEASE_TYPE" = "community" ]; then
@@ -220,59 +133,25 @@ export LANG
# Print out a summary of the environment.
-
-echo
echo "========================== Environment Variables =============================="
-echo "JAVA_HOME=$JAVA_HOME"
-[ "$RELEASE_TYPE" = "enterprise" ]
-#[ "$RELEASE_TYPE" = "enterprise" ] && echo "JAVA5_HOME=$JAVA5_HOME"
-echo "M2_HOME=$M2_HOME"
-echo "MAVEN_OPTS=$MAVEN_OPTS"
-echo "PATH=$PATH"
-echo "LANG=$LANG"
+environment_variables=("JAVA_HOME" "M2_HOME" "MAVEN_OPTS" "PATH" "LANG" "RELEASE_TYPE")
+print_variables "${environment_variables[@]}"
+
+
echo "============================= Local Variables ================================="
-echo "WORKING_DIR=$WORKING_DIR"
-echo "PROJECT_NAME=$PROJECT_NAME"
-echo "PROJECT_GIT_URL=$PROJECT_GIT_URL"
-echo "RELEASE_TYPE=$RELEASE_TYPE"
-echo "RELEASE_VERSION=$RELEASE_VERSION"
-echo "DEVELOPMENT_VERSION=$DEVELOPMENT_VERSION"
-echo "RELEASE_BRANCH=$RELEASE_BRANCH"
-echo "RELEASE_TAG=$RELEASE_TAG"
-echo "MODE=$MODE"
-echo "MAVEN_LOCAL_REPO_DIR=$MAVEN_LOCAL_REPO_DIR"
-echo "MAVEN_LOCAL_REPO_PURGE_INTERVAL_HOURS=$MAVEN_LOCAL_REPO_PURGE_INTERVAL_HOURS"
-echo "MAVEN_SETTINGS_FILE=$MAVEN_SETTINGS_FILE"
-echo "MAVEN_ARGS=$MAVEN_ARGS"
-echo "MAVEN_RELEASE_PERFORM_GOAL=$MAVEN_RELEASE_PERFORM_GOAL"
-echo "JBOSS_ORG_USERNAME=$JBOSS_ORG_USERNAME"
-echo "============================= Program Versions ================================"
-git --version
-echo
-java -version
-echo
-mvn --version | head -1
-echo "==============================================================================="
-echo
+local_variables=("WORKING_DIR" "PROJECT_NAME" "PROJECT_GIT_URL" "RELEASE_TYPE" "DEVELOPMENT_VERSION" \
+ "RELEASE_BRANCH" "MODE" "MAVEN_LOCAL_REPO_DIR" \
+ "MAVEN_SETTINGS_FILE" "MAVEN_ARGS" "MAVEN_RELEASE_PERFORM_GOAL" "JBOSS_ORG_USERNAME" \
+ "RELEASE_VERSION" "RELEASE_TAG")
+print_variables "${local_variables[@]}"
-# Clean the Maven local repo if it hasn't been purged recently.
-if [ -f "$MAVEN_LOCAL_REPO_DIR" ]; then
- if [ "$MODE" = "production" ]; then
- echo "Purging MAVEN_LOCAL_REPO_DIR ($MAVEN_LOCAL_REPO_DIR) since this is a production build..."
- #rm -rf "$MAVEN_LOCAL_REPO_DIR"
- else
- echo boo
- #OUTPUT=`find "$MAVEN_LOCAL_REPO_DIR" -maxdepth 0 -mtime $MAVEN_LOCAL_REPO_PURGE_INTERVAL_HOURS`
- #if [ -n "$OUTPUT" ]; then
- # echo "MAVEN_LOCAL_REPO_DIR ($MAVEN_LOCAL_REPO_DIR) has existed for more than $MAVEN_LOCAL_REPO_PURGE_INTERVAL_HOURS hours - purging it for a clean-clean build..."
- # rm -rf "$MAVEN_LOCAL_REPO_DIR"
- #fi
- fi
-
-fi
-mkdir -p "$MAVEN_LOCAL_REPO_DIR"
+echo "============================= Program Versions ================================"
+program_versions=("git --version" "java -version" "mvn --version")
+print_program_versions "${program_versions[@]}"
+
+echo "==============================================================================="
# Create the Maven settings file.
diff --git a/rhq_bash.lib b/rhq_bash.lib
new file mode 100644
index 0000000..19d76da
--- /dev/null
+++ b/rhq_bash.lib
@@ -0,0 +1,134 @@
+
+
+print_variables()
+{
+ for variable in "$@"
+ do
+ temp_var='eval "echo \$$variable"'
+ eval_temp_var=`eval $temp_var`
+
+ if [ -z "$eval_temp_var" ]; then
+ echo "$variable is NOT defined!"
+ else
+ echo "$variable=$eval_temp_var"
+ fi
+ done
+}
+
+
+print_program_versions()
+{
+ for variable in "$@"
+ do
+ eval $variable
+ echo
+ done
+}
+
+
+validate_java_6()
+{
+ # Make sure JAVA_HOME points to a valid JDK 1.6+ install.
+
+ if [ -z "$JAVA_HOME" ]; then
+ abort "JAVA_HOME environment variable is not set - JAVA_HOME must point to a JDK (not JRE) 6 install dir."
+ fi
+
+ if [ ! -d "$JAVA_HOME" ]; then
+ abort "JAVA_HOME ($JAVA_HOME) does not exist or is not a directory - JAVA_HOME must point to a JDK (not JRE) 6 install dir."
+ fi
+
+ echo "Prepending $JAVA_HOME/bin to PATH..."
+ PATH="$JAVA_HOME/bin:$PATH"
+
+ if ! which java >/dev/null 2>&1; then
+ abort "java not found in PATH ($PATH) - JAVA_HOME must point to a JDK (not JRE) 6 install dir."
+ fi
+
+ if ! which javac >/dev/null 2>&1; then
+ abort "javac not found in PATH ($PATH) - JAVA_HOME must point to a JDK (not JRE) 6 install dir."
+ fi
+
+ if ! javap java.util.Deque >/dev/null 2>&1; then
+ abort "java.util.Deque not found - Java version appears to be less than 1.6 - Jave version must be 1.6 or later."
+ fi
+}
+
+validate_java_5()
+{
+ echo "nothing executed here"
+ # spinder 8/30/11: commenting out the JAVA5 support, but leaving logic in place for when we need the same backwards
+ # compatibility logic for JD6 vs. JDK7 support.
+ # If this is an enterprise release, make sure JAVA5_HOME points to a valid JDK 1.5 install.
+ # We need this to validate only Java 5 or earlier APIs are used in all modules, except the CLI, which requires Java 6.
+ #
+ #if [ "$RELEASE_TYPE" = "enterprise" ]; then
+ # if [ -z "$JAVA5_HOME" ]; then
+ # abort "JAVA5_HOME environment variable is not set - JAVA5_HOME must point to a JDK (not JRE) 1.5 install dir."
+ # fi
+ #
+ # if [ ! -d "$JAVA5_HOME" ]; then
+ # abort "JAVA5_HOME ($JAVA5_HOME) does not exist or is not a directory - JAVA5_HOME must point to a JDK (not JRE) 1.5 install dir."
+ # fi
+ #
+ # if [ ! -x "$JAVA5_HOME/bin/java" ]; then
+ # abort "$JAVA5_HOME/bin/java does not exist or is not executable - JAVA5_HOME must point to a JDK (not JRE) 1.5 install dir."
+ # fi
+ #
+ # if [ ! -x "$JAVA5_HOME/bin/javac" ]; then
+ # abort "$JAVA5_HOME/bin/javac does not exist or is not executable - JAVA5_HOME must point to a JDK (not JRE) 1.5 install dir."
+ # fi
+ #
+ # if ! "$JAVA5_HOME/bin/javap" java.lang.Enum >/dev/null 2>&1; then
+ # abort "java.lang.Enum not found - JAVA5_HOME ($JAVA5_HOME) version appears to be less than 1.5 - version must be 1.5.x."
+ # fi
+ #
+ # if "$JAVA5_HOME/bin/javap" java.util.Deque >/dev/null 2>&1; then
+ # abort "java.util.Deque found - JAVA5_HOME ($JAVA5_HOME) version appears to be greater than or equal to 1.6 - version must be 1.5.x."
+ # fi
+ #fi
+}
+
+
+validate_maven()
+{
+ # Make sure M2_HOME points to a valid Maven 2.1.x or 2.2.x install.
+
+ if [ -z "$M2_HOME" ]; then
+ abort "M2_HOME environment variable is not set - M2_HOME must point to a Maven, $MINIMUM_MAVEN_VERSION or later, install dir."
+ fi
+
+ if [ ! -d "$M2_HOME" ]; then
+ abort "M2_HOME ($M2_HOME) does not exist or is not a directory - M2_HOME must point to a Maven, $MINIMUM_MAVEN_VERSION or later, install dir."
+ fi
+
+ echo "Prepending $M2_HOME/bin to PATH..."
+ PATH="$M2_HOME/bin:$PATH"
+
+ if ! which mvn >/dev/null 2>&1; then
+ abort "mvn not found in PATH ($PATH) - M2_HOME must point to a Maven, $MINIMUM_MAVEN_VERSION or later, install dir."
+ fi
+
+ mvn -version >/dev/null
+ [ $? -ne 0 ] && abort "mvn --version failed with exit code $?."
+ MAVEN_VERSION=`mvn -version | head -1 | sed 's|[^0-9]*\([^ ]*\).*|\1|'`
+ if echo $MAVEN_VERSION | grep -Ev "^(2\.[12]|3\.0)"; then
+ abort "Unsupported Maven version - $MAVEN_VERSION. Only Maven 2.1.x, 2.2.x, or 3.0.x is supported. Please update the value of M2_HOME, then try again."
+ fi
+}
+
+validate_git()
+{
+ # Make sure git 1.6.x or 1.7.x is in the PATH.
+
+ if ! which git >/dev/null 2>&1; then
+ abort "git not found in PATH ($PATH)."
+ fi
+
+ git --version >/dev/null
+ [ $? -ne 0 ] && abort "git --version failed with exit code $?."
+ GIT_VERSION=`git --version | sed 's|[^0-9]*\([^ ]*\).*|\1|'`
+ if echo $GIT_VERSION | grep -v "^1.[67]"; then
+ abort "Unsupported git version - $GIT_VERSION. Only git 1.6.x or 1.7.x are supported. Please add a directory containing a supported version of git to your PATH, then try again."
+ fi
+}
12 years, 9 months
[rhq] modules/core modules/enterprise
by mazz
modules/core/domain/src/test/java/org/rhq/core/domain/operation/OperationHistoryTest.java | 2 +-
modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/ResourceGroupTest.java | 2 +-
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/operation/OperationManagerBeanTest.java | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
New commits:
commit 6d50ee623ff7a6279931dd5ad90bc958c86f11fe
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Sep 15 11:56:02 2011 -0400
make the test group names unique from other tests so we can tell what tests created what groups
diff --git a/modules/core/domain/src/test/java/org/rhq/core/domain/operation/OperationHistoryTest.java b/modules/core/domain/src/test/java/org/rhq/core/domain/operation/OperationHistoryTest.java
index df93193..b0fef5c 100644
--- a/modules/core/domain/src/test/java/org/rhq/core/domain/operation/OperationHistoryTest.java
+++ b/modules/core/domain/src/test/java/org/rhq/core/domain/operation/OperationHistoryTest.java
@@ -321,7 +321,7 @@ public class OperationHistoryTest extends AbstractEJB3Test {
resource.setUuid("" + new Random().nextInt());
em.persist(resource);
- ResourceGroup group = new ResourceGroup("testgroup" + System.currentTimeMillis(), resourceType);
+ ResourceGroup group = new ResourceGroup("testgroupOH" + System.currentTimeMillis(), resourceType);
em.persist(group);
group.addExplicitResource(resource);
} catch (Exception e) {
diff --git a/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/ResourceGroupTest.java b/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/ResourceGroupTest.java
index 4ab3f4a..5ff2879 100644
--- a/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/ResourceGroupTest.java
+++ b/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/ResourceGroupTest.java
@@ -78,7 +78,7 @@ public class ResourceGroupTest extends AbstractEJB3Test {
resource.setUuid("" + new Random().nextInt());
em.persist(resource);
- ResourceGroup group = new ResourceGroup("testgroup" + System.currentTimeMillis(), resourceType);
+ ResourceGroup group = new ResourceGroup("testgroupRG" + System.currentTimeMillis(), resourceType);
em.persist(group);
group.addExplicitResource(resource);
} catch (Exception e) {
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/operation/OperationManagerBeanTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/operation/OperationManagerBeanTest.java
index 2f47aa2..f068ead 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/operation/OperationManagerBeanTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/operation/OperationManagerBeanTest.java
@@ -1576,7 +1576,7 @@ public class OperationManagerBeanTest extends AbstractEJB3Test {
resource.setInventoryStatus(InventoryStatus.COMMITTED);
em.persist(resource);
- ResourceGroup group = new ResourceGroup("testgroup" + System.currentTimeMillis(), resourceType);
+ ResourceGroup group = new ResourceGroup("testgroupOMB" + System.currentTimeMillis(), resourceType);
em.persist(group);
group.addExplicitResource(resource);
} catch (Exception e) {
12 years, 9 months
[rhq] Branch 'feature/performance' - modules/enterprise
by Robert Buck
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementScheduleManagerBean.java | 106 ++++++++--
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementScheduleManagerLocal.java | 6
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/NotifyAgentsOfScheduleUpdatesJob.java | 29 ++
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/EnhancedScheduler.java | 2
4 files changed, 124 insertions(+), 19 deletions(-)
New commits:
commit f93ffa9d47045e3026f3297b63ca2473bad36d73
Author: Robert Buck <rbuck(a)redhat.com>
Date: Thu Sep 15 11:03:34 2011 -0400
[BZ 734599] Change notification of schedule updates to agents so it uses quartz, reducing the time to update a metric schedule on a compat group with 1,000 members from 14s to 1.5s.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementScheduleManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementScheduleManagerBean.java
index 0b1c394..abfae0c 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementScheduleManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementScheduleManagerBean.java
@@ -22,12 +22,7 @@ import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
import javax.ejb.EJB;
import javax.ejb.Stateless;
@@ -45,6 +40,7 @@ import org.apache.commons.logging.LogFactory;
import org.jboss.annotation.IgnoreDependency;
+import org.quartz.*;
import org.rhq.core.db.DatabaseType;
import org.rhq.core.db.DatabaseTypeFactory;
import org.rhq.core.db.H2DatabaseType;
@@ -580,7 +576,7 @@ public class MeasurementScheduleManagerBean implements MeasurementScheduleManage
query.setParameter("interval", collectionInterval);
int affectedRows = query.executeUpdate();
- notifyAgentsOfScheduleUpdates(context, measurementScheduleSubQuery);
+ dispatchScheduleUpdatesToAgents(context, measurementScheduleSubQuery);
return affectedRows;
}
@@ -597,7 +593,7 @@ public class MeasurementScheduleManagerBean implements MeasurementScheduleManage
Query query = entityManager.createQuery(updateQuery);
int affectedRows = query.executeUpdate();
- notifyAgentsOfScheduleUpdates(context, measurementScheduleSubQuery);
+ dispatchScheduleUpdatesToAgents(context, measurementScheduleSubQuery);
return affectedRows;
}
@@ -614,20 +610,93 @@ public class MeasurementScheduleManagerBean implements MeasurementScheduleManage
Query query = entityManager.createQuery(updateQuery);
int affectedRows = query.executeUpdate();
- notifyAgentsOfScheduleUpdates(context, measurementScheduleSubQuery);
+ dispatchScheduleUpdatesToAgents(context, measurementScheduleSubQuery);
return affectedRows;
}
- @SuppressWarnings("unchecked")
- private void notifyAgentsOfScheduleUpdates(EntityContext context, String measurementScheduleSubQuery) {
+ private void dispatchScheduleUpdatesToAgents(EntityContext entityContext, String scheduleSubQuery) {
+ Scheduler scheduler;
+ try {
+ scheduler = LookupUtil.getSchedulerBean();
+
+ final String DEFAULT_AGENT_JOB = "AGENT NOTIFICATION JOB";
+ final String DEFAULT_AGENT_GROUP = "AGENT NOTIFICATION GROUP";
+ final String DEFAULT_AGENT_TRIGGER = "AGENT NOTIFICATION TRIGGER";
+
+ JobDetail jobDetail = new JobDetail(
+ DEFAULT_AGENT_JOB,
+ DEFAULT_AGENT_GROUP,
+ NotifyAgentsOfScheduleUpdatesJob.class);
+
+ SimpleTrigger simpleTrigger = new SimpleTrigger(
+ DEFAULT_AGENT_TRIGGER,
+ DEFAULT_AGENT_GROUP,
+ new Date());
+
+ JobDataMap jobDataMap = simpleTrigger.getJobDataMap();
+ jobDataMap.put("ScheduleSubQuery", scheduleSubQuery);
+ jobDataMap.put("EntityContext.resourceId", Integer.toString(entityContext.getResourceId()));
+ jobDataMap.put("EntityContext.groupId", Integer.toString(entityContext.getGroupId()));
+ jobDataMap.put("EntityContext.parentResourceId", Integer.toString(entityContext.getParentResourceId()));
+ jobDataMap.put("EntityContext.resourceTypeId", Integer.toString(entityContext.getResourceTypeId()));
+
+ if (isJobScheduled(scheduler, DEFAULT_AGENT_JOB, DEFAULT_AGENT_GROUP)) {
+ simpleTrigger.setJobName(DEFAULT_AGENT_JOB);
+ simpleTrigger.setJobGroup(DEFAULT_AGENT_GROUP);
+ if (isTriggerScheduled(scheduler, DEFAULT_AGENT_TRIGGER, DEFAULT_AGENT_GROUP)) {
+ scheduler.rescheduleJob(DEFAULT_AGENT_TRIGGER, DEFAULT_AGENT_GROUP, simpleTrigger);
+ } else {
+ scheduler.scheduleJob(simpleTrigger);
+ }
+ } else {
+ scheduler.scheduleJob(jobDetail, simpleTrigger);
+ }
+ } catch (RuntimeException e) {
+ // lookup wrapper throws runtime exceptions, no distinction between
+ // types, so fallback and do the best we can.
+ notifyAgentsOfScheduleUpdates(entityContext, scheduleSubQuery);
+ } catch (SchedulerException e) {
+ // should never happen, but fallback gracefully...
+ log.error("Failed to schedule agents update notification.", e);
+ notifyAgentsOfScheduleUpdates(entityContext, scheduleSubQuery);
+ }
+ }
+
+ private boolean isTriggerScheduled(Scheduler scheduler, String name, String group) {
+ boolean isScheduled = false;
+ try {
+ Trigger trigger = scheduler.getTrigger(name, group);
+ if (trigger != null) {
+ isScheduled = true;
+ }
+ } catch (SchedulerException se) {
+ log.error("Error getting trigger", se);
+ }
+ return isScheduled;
+ }
+
+ private boolean isJobScheduled(Scheduler scheduler, String name, String group) {
+ boolean isScheduled = false;
+ try {
+ JobDetail jobDetail = scheduler.getJobDetail(name, group);
+ if (jobDetail != null) {
+ isScheduled = true;
+ }
+ } catch (SchedulerException se) {
+ log.error("Error getting job detail", se);
+ }
+ return isScheduled;
+ }
+ @SuppressWarnings("unchecked")
+ public void notifyAgentsOfScheduleUpdates(EntityContext entityContext, String scheduleSubQuery) {
List<Integer> agentIds = new ArrayList<Integer>();
try {
String agentsQueryString = "" //
+ "SELECT DISTINCT ms.resource.agent.id " //
+ " FROM MeasurementSchedule ms " //
- + " WHERE ms.id IN ( " + measurementScheduleSubQuery + " ) ";
+ + " WHERE ms.id IN ( " + scheduleSubQuery + " ) ";
if (log.isDebugEnabled()) {
log.debug("agentsQueryString: " + agentsQueryString);
}
@@ -647,7 +716,7 @@ public class MeasurementScheduleManagerBean implements MeasurementScheduleManage
+ " ms.definition.dataType, " //
+ " ms.definition.rawNumericType " //
+ " FROM MeasurementSchedule ms " //
- + " WHERE ms.id IN ( " + measurementScheduleSubQuery + " ) " //
+ + " WHERE ms.id IN ( " + scheduleSubQuery + " ) " //
+ " AND ms.resource.agent.id = :agentId";
if (log.isDebugEnabled()) {
log.debug("scheduleRequestQueryString: " + scheduleRequestQueryString);
@@ -669,9 +738,9 @@ public class MeasurementScheduleManagerBean implements MeasurementScheduleManage
MeasurementScheduleRequest requestData = new MeasurementScheduleRequest( //
(Integer) nextScheduleDataSet[1], // scheduleId
(String) nextScheduleDataSet[2], // definitionName,
- (Long) nextScheduleDataSet[3], // interval,
- (Boolean) nextScheduleDataSet[4], // enabled,
- (DataType) nextScheduleDataSet[5], // dataType,
+ (Long) nextScheduleDataSet[3], // interval,
+ (Boolean) nextScheduleDataSet[4], // enabled,
+ (DataType) nextScheduleDataSet[5], // dataType,
(NumericType) nextScheduleDataSet[6]); // awNumericType
resourceRequest.addMeasurementScheduleRequest(requestData);
}
@@ -698,7 +767,7 @@ public class MeasurementScheduleManagerBean implements MeasurementScheduleManage
}
if (markResources) {
- markResources(context, nextAgentId);
+ markResources(entityContext, nextAgentId);
}
}
}
@@ -1417,4 +1486,5 @@ public class MeasurementScheduleManagerBean implements MeasurementScheduleManage
// }
// }
-}
\ No newline at end of file
+}
+
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementScheduleManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementScheduleManagerLocal.java
index 9edf221..77ee167 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementScheduleManagerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementScheduleManagerLocal.java
@@ -373,4 +373,10 @@ public interface MeasurementScheduleManagerLocal {
*/
PageList<MeasurementSchedule> findSchedulesByCriteria(Subject subject, MeasurementScheduleCriteria criteria);
+ /**
+ * Notifies all agents of measurement schedule changes.
+ * @param entityContext the context.
+ * @param scheduleSubQuery the subquery indicating which schedules changed
+ */
+ void notifyAgentsOfScheduleUpdates(EntityContext entityContext, String scheduleSubQuery);
}
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/NotifyAgentsOfScheduleUpdatesJob.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/NotifyAgentsOfScheduleUpdatesJob.java
new file mode 100644
index 0000000..d61717a
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/NotifyAgentsOfScheduleUpdatesJob.java
@@ -0,0 +1,29 @@
+package org.rhq.enterprise.server.measurement;
+
+import org.quartz.JobDataMap;
+import org.quartz.JobExecutionContext;
+import org.quartz.JobExecutionException;
+import org.rhq.enterprise.server.scheduler.jobs.AbstractStatefulJob;
+import org.rhq.enterprise.server.util.LookupUtil;
+import org.rhq.core.domain.common.EntityContext;
+
+/**
+ * Job that asynchronously notifies agents of schedule updates.
+ */
+public class NotifyAgentsOfScheduleUpdatesJob extends AbstractStatefulJob {
+ @Override
+ public void executeJobCode(JobExecutionContext context) throws JobExecutionException {
+ MeasurementScheduleManagerLocal scheduleManager = LookupUtil.getMeasurementScheduleManager();
+
+ JobDataMap jobDataMap = context.getMergedJobDataMap();
+ String scheduleSubQuery = (String) jobDataMap.get("ScheduleSubQuery");
+ EntityContext entityContext = new EntityContext(
+ Integer.parseInt((String) jobDataMap.get("EntityContext.resourceId")),
+ Integer.parseInt((String) jobDataMap.get("EntityContext.groupId")),
+ Integer.parseInt((String) jobDataMap.get("EntityContext.parentResourceId")),
+ Integer.parseInt((String) jobDataMap.get("EntityContext.resourceTypeId"))
+ );
+
+ scheduleManager.notifyAgentsOfScheduleUpdates(entityContext, scheduleSubQuery);
+ }
+}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/EnhancedScheduler.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/EnhancedScheduler.java
index 1fc2c71..b10f627 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/EnhancedScheduler.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/EnhancedScheduler.java
@@ -24,7 +24,7 @@ import org.quartz.Scheduler;
import org.quartz.SchedulerException;
/**
- * An enhanced scheduler interface that provides the normal scheduler API with some additional convienence methods.
+ * An enhanced scheduler interface that provides the normal scheduler API with some additional convenience methods.
*
* @author John Mazzitelli
*/
12 years, 9 months