[rhq] Branch 'jsanda/metrics-rhq' - 201 commits - .classpath etc/eclipse-tools etc/m2 etc/rhq-ircBot etc/standalone-pc modules/common modules/core modules/enterprise modules/helpers modules/integration-tests modules/jopr modules/plugins pom.xml

Jay Shaughnessy jshaughn at fedoraproject.org
Wed Aug 8 17:10:25 UTC 2012


 .classpath                                                                                                                                                              |   10 
 etc/eclipse-tools/maven/RHQ                                                                                                                                             |   11 
 etc/m2/settings.xml                                                                                                                                                     |    6 
 etc/m2/smartgwt-war-archetype/pom.xml                                                                                                                                   |    2 
 etc/rhq-ircBot/pom.xml                                                                                                                                                  |   51 
 etc/standalone-pc/README.txt                                                                                                                                            |    3 
 etc/standalone-pc/standalone.bat                                                                                                                                        |    9 
 etc/standalone-pc/standalone.sh                                                                                                                                         |   12 
 modules/common/jboss-as/src/main/java/com/jboss/jbossnetwork/product/jbpm/handlers/ControlActionHandler.java                                                            |    6 
 modules/core/arquillian-integration/archive/pom.xml                                                                                                                     |    6 
 modules/core/arquillian-integration/archive/src/main/java/org/rhq/test/shrinkwrap/RhqAgentPluginArchiveImpl.java                                                        |   28 
 modules/core/arquillian-integration/archive/src/main/java/org/rhq/test/shrinkwrap/RhqAgentPluginDescriptorContainer.java                                                |   16 
 modules/core/arquillian-integration/container/src/main/java/org/rhq/test/arquillian/FakeServerInventory.java                                                            |   95 
 modules/core/client-api/pom.xml                                                                                                                                         |  426 +-
 modules/core/client-api/src/main/java/org/rhq/core/clientapi/agent/configuration/ConfigurationUtility.java                                                              |  244 -
 modules/core/client-api/src/main/java/org/rhq/core/clientapi/server/operation/OperationServerService.java                                                               |   14 
 modules/core/client-api/src/test/java/org/rhq/core/clientapi/agent/configuration/ConfigurationUtilityTest.java                                                          |  322 -
 modules/core/dbutils/pom.xml                                                                                                                                            |    2 
 modules/core/dbutils/src/main/scripts/dbsetup/config-schema.xml                                                                                                         |    2 
 modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml                                                                                                          |   24 
 modules/core/domain/src/main/java/org/rhq/core/domain/alert/AlertCondition.java                                                                                         |    8 
 modules/core/domain/src/main/java/org/rhq/core/domain/alert/AlertConditionLog.java                                                                                      |   22 
 modules/core/domain/src/main/java/org/rhq/core/domain/alert/AlertDefinition.java                                                                                        |   40 
 modules/core/domain/src/main/java/org/rhq/core/domain/configuration/ConfigurationUtility.java                                                                           |  334 +
 modules/core/domain/src/main/java/org/rhq/core/domain/configuration/ObfuscatedPropertySimple.java                                                                       |  163 
 modules/core/domain/src/main/java/org/rhq/core/domain/configuration/PropertySimple.java                                                                                 |    2 
 modules/core/domain/src/main/java/org/rhq/core/domain/configuration/definition/PropertyDefinitionList.java                                                              |   20 
 modules/core/domain/src/main/java/org/rhq/core/domain/drift/DriftConfigurationDefinition.java                                                                           |    4 
 modules/core/domain/src/main/java/org/rhq/core/domain/drift/Filter.java                                                                                                 |    2 
 modules/core/domain/src/main/java/org/rhq/core/domain/measurement/TraitMeasurement.java                                                                                 |    2 
 modules/core/domain/src/main/java/org/rhq/core/domain/measurement/TraitMeasurementDTO.java                                                                              |   10 
 modules/core/domain/src/main/java/org/rhq/core/domain/resource/Agent.java                                                                                               |    5 
 modules/core/domain/src/main/java/org/rhq/core/domain/resource/composite/ResourceIdWithAgentComposite.java                                                              |   48 
 modules/core/domain/src/main/java/org/rhq/core/domain/resource/group/DuplicateExpressionTypeException.java                                                              |   38 
 modules/core/domain/src/main/java/org/rhq/core/domain/resource/group/InvalidExpressionException.java                                                                    |   38 
 modules/core/domain/src/main/java/org/rhq/core/domain/util/collection/ArrayUtils.java                                                                                   |   75 
 modules/core/domain/src/test/java/org/rhq/core/domain/configuration/ConfigurationUtilityTest.java                                                                       |  363 +
 modules/core/domain/src/test/java/org/rhq/core/domain/drift/JPADriftChangeSetTest.java                                                                                  |    9 
 modules/core/native-system/src/main/java/org/rhq/core/system/pquery/ProcessInfoQuery.java                                                                               |    2 
 modules/core/native-system/src/test/java/org/rhq/core/system/pquery/ProcessInfoQueryTest.java                                                                           |   55 
 modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/operation/OperationServicesResultCode.java                                                                 |    2 
 modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/util/ServerStartScriptDiscoveryUtility.java                                                                |   13 
 modules/core/plugin-container-itest/src/test/java/org/rhq/core/pc/inventory/DiscoveryTest.java                                                                          |   68 
 modules/core/plugin-container-itest/src/test/java/org/rhq/core/pc/inventory/testplugin/ManualAddDiscoveryComponent.java                                                 |   34 
 modules/core/plugin-container-itest/src/test/java/org/rhq/core/pc/inventory/testplugin/TestResourceComponent.java                                                       |  103 
 modules/core/plugin-container-itest/src/test/java/org/rhq/core/pc/measurement/LateMeasurementRescheduleTest.java                                                        |  175 
 modules/core/plugin-container-itest/src/test/java/org/rhq/core/pc/measurement/ReadOnlyScheduleSetTest.java                                                              |  111 
 modules/core/plugin-container-itest/src/test/java/org/rhq/plugins/test/SingleResourceDiscoveryComponent.java                                                            |   30 
 modules/core/plugin-container-itest/src/test/java/org/rhq/plugins/test/measurement/BZ821058ResourceComponent.java                                                       |   84 
 modules/core/plugin-container-itest/src/test/java/org/rhq/plugins/test/measurement/BZ834019ResourceComponent.java                                                       |  104 
 modules/core/plugin-container-itest/src/test/resources/arquillian.xml                                                                                                   |   10 
 modules/core/plugin-container-itest/src/test/resources/single-metric-rhq-plugin.xml                                                                                     |   21 
 modules/core/plugin-container-itest/src/test/resources/test-great-grandchild-discovery-plugin.xml                                                                       |   30 
 modules/core/plugin-container-itest/src/test/resources/two-metric-rhq-plugin.xml                                                                                        |   27 
 modules/core/plugin-container/src/main/java/org/rhq/core/pc/PluginContainer.java                                                                                        |   18 
 modules/core/plugin-container/src/main/java/org/rhq/core/pc/StandaloneContainer.java                                                                                    |    2 
 modules/core/plugin-container/src/main/java/org/rhq/core/pc/availability/AvailabilityContextImpl.java                                                                   |    7 
 modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftDetector.java                                                                                    |    5 
 modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftFilesSender.java                                                                                 |   42 
 modules/core/plugin-container/src/main/java/org/rhq/core/pc/event/EventContextImpl.java                                                                                 |    7 
 modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java                                                                             |   23 
 modules/core/plugin-container/src/main/java/org/rhq/core/pc/measurement/MeasurementCollectorRunner.java                                                                 |    5 
 modules/core/plugin-container/src/main/java/org/rhq/core/pc/measurement/MeasurementManager.java                                                                         |   26 
 modules/core/plugin-container/src/main/java/org/rhq/core/pc/operation/OperationInvocation.java                                                                          |    8 
 modules/core/plugin-container/src/main/java/org/rhq/core/pc/operation/OperationServicesAdapter.java                                                                     |   13 
 modules/core/plugin-container/src/main/java/org/rhq/core/pc/plugin/PluginValidator.java                                                                                 |   57 
 modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/FilterFileVisitorTest.java                                                                            |    3 
 modules/core/plugin-container/src/test/java/org/rhq/core/pc/operation/OperationManagerTest.java                                                                         |    7 
 modules/core/plugin-container/src/test/java/org/rhq/core/pc/operation/ParallelOperationsTest.java                                                                       |    7 
 modules/core/plugin-test-util/src/main/java/org/rhq/core/plugin/testutil/AbstractAgentPluginTest.java                                                                   |  139 
 modules/core/plugindoc/src/main/java/org/rhq/core/tool/plugindoc/PluginDocGenerator.java                                                                                |    4 
 modules/core/util/src/test/java/org/apache/maven/artifact/versioning/ComparableVersionTest.java                                                                         |    3 
 modules/enterprise/agent/src/etc/plugin-validator.sh                                                                                                                    |    7 
 modules/enterprise/agent/src/etc/standalone-pc.bat                                                                                                                      |    9 
 modules/enterprise/agent/src/etc/standalone-pc.sh                                                                                                                       |   12 
 modules/enterprise/agent/src/test/java/org/rhq/enterprise/agent/AgentComm2Test.java                                                                                     |  148 
 modules/enterprise/agent/src/test/java/org/rhq/enterprise/agent/AgentComm5Test.java                                                                                     |  112 
 modules/enterprise/agent/src/test/java/org/rhq/enterprise/agent/AgentComm6Test.java                                                                                     |  112 
 modules/enterprise/agent/src/test/java/org/rhq/enterprise/agent/AgentCommTestBase.java                                                                                  |    2 
 modules/enterprise/binding/pom.xml                                                                                                                                      |   28 
 modules/enterprise/binding/src/main/java/org/rhq/bindings/SandboxedScriptEngine.java                                                                                    |  204 
 modules/enterprise/binding/src/main/java/org/rhq/bindings/ScriptEngineFactory.java                                                                                      |  211 -
 modules/enterprise/binding/src/main/java/org/rhq/bindings/StandardBindings.java                                                                                         |   55 
 modules/enterprise/binding/src/main/java/org/rhq/bindings/client/AbstractRhqFacadeProxy.java                                                                            |   53 
 modules/enterprise/binding/src/main/java/org/rhq/bindings/client/ResourceClientProxy.java                                                                               |   59 
 modules/enterprise/binding/src/main/java/org/rhq/bindings/client/RhqFacade.java                                                                                         |  102 
 modules/enterprise/binding/src/main/java/org/rhq/bindings/client/RhqManager.java                                                                                        |  133 
 modules/enterprise/binding/src/main/java/org/rhq/bindings/client/RhqManagers.java                                                                                       |  133 
 modules/enterprise/binding/src/main/java/org/rhq/bindings/engine/JsEngineInitializer.java                                                                               |  104 
 modules/enterprise/binding/src/main/java/org/rhq/bindings/engine/ScriptEngineInitializer.java                                                                           |   82 
 modules/enterprise/binding/src/main/java/org/rhq/bindings/script/BaseRhqSchemeScriptSourceProvider.java                                                                 |   63 
 modules/enterprise/binding/src/main/java/org/rhq/bindings/script/RepoScriptSourceProvider.java                                                                          |  127 
 modules/enterprise/binding/src/main/java/org/rhq/bindings/util/InterfaceSimplifier.java                                                                                 |  524 ++
 modules/enterprise/binding/src/main/java/org/rhq/bindings/util/MultiScriptSourceProvider.java                                                                           |   66 
 modules/enterprise/binding/src/main/java/org/rhq/bindings/util/ScriptAssert.java                                                                                        |   36 
 modules/enterprise/binding/src/main/java/org/rhq/bindings/util/ScriptUtil.java                                                                                          |    5 
 modules/enterprise/binding/src/main/java/org/rhq/bindings/util/SimplifiedClass.java                                                                                     |   38 
 modules/enterprise/binding/src/main/java/org/rhq/bindings/util/SimplifiedMethod.java                                                                                    |   41 
 modules/enterprise/binding/src/main/java/org/rhq/bindings/util/SummaryFilter.java                                                                                       |    8 
 modules/enterprise/binding/src/main/resources/META-INF/services/org.rhq.scripting.ScriptSourceProvider                                                                  |    1 
 modules/enterprise/binding/src/test/java/org/rhq/bindings/FakeRhqFacade.java                                                                                            |  152 
 modules/enterprise/binding/src/test/java/org/rhq/bindings/ScriptEngineTest.java                                                                                         |    6 
 modules/enterprise/binding/src/test/java/org/rhq/bindings/client/AbstractRhqFacadeProxyTest.java                                                                        |  185 
 modules/enterprise/binding/src/test/java/org/rhq/bindings/script/RepoScriptSourceProviderTest.java                                                                      |  160 
 modules/enterprise/binding/src/test/java/org/rhq/bindings/util/InterfaceSimplifierTest.java                                                                             |  351 +
 modules/enterprise/binding/src/test/java/org/rhq/bindings/util/ScriptAssertTest.java                                                                                    |    3 
 modules/enterprise/gui/base-perspective-jar/src/main/java/org/rhq/enterprise/server/perspective/AbstractPerspectiveResourceUIBean.java                                  |    4 
 modules/enterprise/gui/base-perspective-jar/src/main/java/org/rhq/enterprise/server/perspective/PerspectiveClientUIBean.java                                            |    2 
 modules/enterprise/gui/coregui/pom.xml                                                                                                                                  |  754 +--
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/IconEnum.java                                                                        |   13 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/ImageManager.java                                                                    |    7 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/ServerPluginControlView.java                                                   |    3 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/roles/RolesView.java                                                           |   21 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/users/UsersView.java                                                           |   16 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/AbstractAlertDefinitionsView.java                                  |    2 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/CliNotificationSenderForm.java                                     |    5 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ConditionsAlertDefinitionForm.java                                 |   17 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ConditionsEditor.java                                              |   28 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/DampeningAlertDefinitionForm.java                                  |   96 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/EditAlertDefinitionForm.java                                       |    2 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/GeneralPropertiesAlertDefinitionForm.java                          |    6 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/GroupAlertDefinitionsView.java                                     |    5 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/NewConditionEditor.java                                            |   47 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/NewNotificationEditor.java                                         |    4 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/NotificationsAlertDefinitionForm.java                              |   12 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/RecoveryAlertDefinitionForm.java                                   |    8 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ResourceAlertDefinitionsView.java                                  |    4 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ResourceOperationNotificationSenderForm.java                       |   11 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/SingleAlertDefinitionView.java                                     |   19 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/TemplateAlertDefinitionsView.java                                  |    4 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/BundleSelector.java                                                           |    3 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/create/BundleTypeDropDownSelectItem.java                                      |    4 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/deploy/GetDeploymentConfigStep.java                                           |   12 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/deploy/SelectBundleVersionStep.java                                           |    3 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/carousel/Carousel.java                                                    |   49 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/ConfigurationEditor.java                                    |  496 +-
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/GroupConfigurationEditor.java                               |    5 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/form/EnhancedSearchBarItem.java                                           |   62 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/form/ImgButtonItem.java                                                   |   67 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/form/SearchBarItem.java                                                   |   62 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/form/SortedSelectItem.java                                                |   96 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/table/Table.java                                                          |  136 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/DashboardsView.java                                                        |    3 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/inventory/groups/graph/ResourceGroupGraphPortlet.java             |    3 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/resource/ResourceMetricsPortlet.java                              |    8 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/wizard/DriftAddDefinitionWizardInfoStep.java                                   |    3 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/wizard/DriftPinTemplateWizardInfoStep.java                                     |    5 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/AlertDefinitionGWTService.java                                                   |    4 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/AlertTemplateGWTService.java                                                     |    4 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/MeasurementDataGWTService.java                                                   |    2 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/ResourceGroupGWTService.java                                                     |    7 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractMeasurementDataTraitDataSource.java                         |   14 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractMeasurementDataTraitListDetailView.java                     |    2 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractMeasurementDataTraitListView.java                           |   43 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/operation/schedule/AbstractOperationScheduleDetailsView.java |   18 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/summary/AbstractActivityView.java                            |   19 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/definitions/GroupDefinitionDataSource.java                          |    7 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/definitions/GroupDefinitionExpressionBuilder.java                   |   34 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/definitions/GroupDefinitionListView.java                            |   21 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/definitions/SingleGroupDefinitionView.java                          |    8 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/configuration/GroupResourceConfigurationEditView.java        |   44 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/monitoring/traits/TraitsView.java                            |  107 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/wizard/GroupCreateStep.java                                         |    1 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/AncestryUtil.java                                                 |    2 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceCompositeSearchView.java                                  |  268 -
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceDatasource.java                                           |   11 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceSearchView.java                                           |   84 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeView.java                                      |  220 -
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/ResourceConfigurationEditView.java           |   25 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MeasurementTableView.java                 |   18 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/traits/TraitsView.java                          |   87 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/discovery/ResourceAutodiscoveryView.java                          |   16 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/factory/ResourceFactoryInfoStep.java                              |    3 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/search/AbstractSearchBar.java                                                        |    3 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/search/FlexSearchBar.java                                                            |   28 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/search/SearchBar.java                                                                |  586 --
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/search/favorites/SavedSearchGrid.java                                                |   11 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/search/suggest/SuggestTextBox_v3.java                                                |   45 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/AbstractSearchStrategy.java                                                |   91 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/BasicSearchStrategy.java                                                   |  250 +
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/EnhancedSearchBar.java                                                     |  279 +
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/FavoritesSearchStrategy.java                                               |  158 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/test/configuration/TestConfigurationFactory.java                                     |    2 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/test/configuration/TestConfigurationView.java                                        |   60 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/test/configuration/TestGroupConfigurationView.java                                   |   40 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/RPCDataSource.java                                                              |   32 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/message/MessageBar.java                                                         |   13 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/AlertDefinitionGWTServiceImpl.java                                               |    4 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/AlertTemplateGWTServiceImpl.java                                                 |    4 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/MeasurementDataGWTServiceImpl.java                                               |    9 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/ResourceGroupGWTServiceImpl.java                                                 |   13 
 modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/MessageConstants.properties                                                     |   10 
 modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties                                                             |   14 
 modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties                                                          |   16 
 modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties                                                          |   17 
 modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties                                                          |   16 
 modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties                                                          |   16 
 modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties                                                          |   21 
 modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties                                                          |   24 
 modules/enterprise/gui/installer-war/pom.xml                                                                                                                            |    6 
 modules/enterprise/gui/installer-war/src/main/java/org/rhq/enterprise/installer/ConfigurationBean.java                                                                  |    7 
 modules/enterprise/gui/installer-war/src/main/resources/InstallerMessages_ko.properties                                                                                 |    8 
 modules/enterprise/gui/installer-war/src/main/resources/InstallerMessages_pt.properties                                                                                 |    2 
 modules/enterprise/gui/installer-war/src/main/resources/InstallerMessages_zh.properties                                                                                 |    1 
 modules/enterprise/gui/installer-war/src/main/webapp/start.jsp                                                                                                          |    5 
 modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/ListPackageHistoryUIBean.java                                                            |    4 
 modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/definition/group/EditGroupDefinitionGeneralPropertiesUIBean.java                                 |    2 
 modules/enterprise/gui/portal-war/src/main/webapp-filtered/WEB-INF/classes/ApplicationResources.properties                                                              |    4 
 modules/enterprise/gui/portal-war/src/main/webapp/rhq/common/menu/menu.xhtml                                                                                            |    2 
 modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/advisoryInfo-plain.xhtml                                                                                  |    3 
 modules/enterprise/gui/rest-war/src/main/java/org/rhq/enterprise/rest/HeaderDumperFilter.java                                                                           |   61 
 modules/enterprise/gui/rest-war/src/main/java/org/rhq/enterprise/rest/JsonPFilter.java                                                                                  |  256 +
 modules/enterprise/gui/rest-war/src/main/webapp/WEB-INF/web.xml                                                                                                         |   47 
 modules/enterprise/gui/rest-war/src/main/webapp/index.html                                                                                                              |    2 
 modules/enterprise/pom.xml                                                                                                                                              |    2 
 modules/enterprise/remoting/cli/pom.xml                                                                                                                                 |   13 
 modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java                                                                                 |  104 
 modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/InteractiveJavascriptCompletor.java                                                             |  602 --
 modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/HelpCommand.java                                                                       |   15 
 modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/LoginCommand.java                                                                      |    4 
 modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/ScriptCommand.java                                                                     |   77 
 modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/script/FileSystemScriptSourceProvider.java                                                      |   72 
 modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/script/SamplesScriptSourceProvider.java                                                         |   67 
 modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/utility/CLIMetadataProvider.java                                                                |   93 
 modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/utility/ChangeRegisteringPrintWriter.java                                                       |  233 +
 modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/utility/CodeCompletionCompletorWrapper.java                                                     |   48 
 modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/utility/DummyCodeCompletion.java                                                                |   50 
 modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/utility/ReflectionUtility.java                                                                  |   27 
 modules/enterprise/remoting/cli/src/main/resources/META-INF/services/org.rhq.scripting.ScriptSourceProvider                                                             |    2 
 modules/enterprise/remoting/cli/src/main/scripts/rhq-client.build.xml                                                                                                   |    3 
 modules/enterprise/remoting/cli/src/test/java/org/rhq/enterprise/client/commands/ScriptCommandTest.java                                                                 |   98 
 modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RemoteClient.java                                                                     |  325 -
 modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RemoteClientProxy.java                                                                |   47 
 modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RhqDownloadsScriptSourceProvider.java                                                 |   89 
 modules/enterprise/remoting/client-api/src/main/resources/META-INF/services/org.rhq.scripting.ScriptSourceProvider                                                      |    1 
 modules/enterprise/scripting/api/pom.xml                                                                                                                                |  173 
 modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/CodeCompletion.java                                                                                    |   70 
 modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/MetadataProvider.java                                                                                  |   84 
 modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptEngineInitializer.java                                                                           |  104 
 modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptEngineProvider.java                                                                              |   68 
 modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptSourceProvider.java                                                                              |   44 
 modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptSourceProviderFactory.java                                                                       |   61 
 modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/util/SandboxedScriptEngine.java                                                                        |  224 +
 modules/enterprise/scripting/javascript/pom.xml                                                                                                                         |  228 +
 modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JavascriptCompletor.java                                                             |  586 ++
 modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineInitializer.java                                                             |  163 
 modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineProvider.java                                                                |   53 
 modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/ExternalScriptable.java                                                       |  496 ++
 modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/JSAdapter.java                                                                |  361 +
 modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/RhinoCompiledScript.java                                                      |   91 
 modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/RhinoScriptEngine.java                                                        |  724 +++
 modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/RhinoScriptEngineFactory.java                                                 |  219 +
 modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/util/ExtendedScriptException.java                                             |   76 
 modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/util/InterfaceImplementor.java                                                |   94 
 modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/util/ScriptEngineFactoryBase.java                                             |   62 
 modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/util/ScriptSourceToModuleSourceProviderAdapter.java                                  |   75 
 modules/enterprise/scripting/javascript/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory                                                           |    1 
 modules/enterprise/scripting/javascript/src/main/resources/META-INF/services/org.rhq.scripting.ScriptEngineProvider                                                     |    1 
 modules/enterprise/scripting/javascript/src/test/java/org/rhq/scripting/javascript/EngineTest.java                                                                      |  124 
 modules/enterprise/scripting/javascript/src/test/java/org/rhq/scripting/javascript/InitializerTest.java                                                                 |  190 
 modules/enterprise/scripting/javascript/src/test/resources/allow-all.policy                                                                                             |    3 
 modules/enterprise/scripting/javascript/src/test/resources/test-module1.js                                                                                              |    7 
 modules/enterprise/scripting/javascript/src/test/resources/test-module2.js                                                                                              |    7 
 modules/enterprise/scripting/pom.xml                                                                                                                                    |   33 
 modules/enterprise/scripting/python/pom.xml                                                                                                                             |  216 +
 modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonScriptEngineFactory.java                                                               |   41 
 modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonScriptEngineInitializer.java                                                           |  132 
 modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonScriptEngineProvider.java                                                              |   54 
 modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonSourceProvider.java                                                                    |  136 
 modules/enterprise/scripting/python/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory                                                               |    1 
 modules/enterprise/scripting/python/src/main/resources/META-INF/services/org.rhq.scripting.ScriptEngineProvider                                                         |    1 
 modules/enterprise/scripting/python/src/test/java/org/rhq/scripting/python/PythonScriptEngineInitializerTest.java                                                       |  178 
 modules/enterprise/scripting/python/src/test/resources/allow-all.policy                                                                                                 |    3 
 modules/enterprise/server/client-api/pom.xml                                                                                                                            |   10 
 modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClient.java                                                                           |  457 --
 modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClientProxy.java                                                                      |   13 
 modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/RhqDownloadsScriptSourceProvider.java                                                      |   80 
 modules/enterprise/server/client-api/src/main/resources/META-INF/services/org.rhq.scripting.ScriptSourceProvider                                                        |    1 
 modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/test/LocalClientTest.java                                                                  |   55 
 modules/enterprise/server/container/src/main/bin-resources/bin/rhq-server.sh                                                                                            |    8 
 modules/enterprise/server/container/src/main/bin-resources/bin/wrapper/rhq-server-wrapper.conf                                                                          |    3 
 modules/enterprise/server/container/src/main/downloadable-resources/connectors/README.txt                                                                               |    2 
 modules/enterprise/server/container/src/main/resources/etc/RHQ-mib.txt                                                                                                  |    4 
 modules/enterprise/server/ear/pom.xml                                                                                                                                   |    6 
 modules/enterprise/server/itests/pom.xml                                                                                                                                |    7 
 modules/enterprise/server/itests/src/test/java/org/rhq/enterprise/client/security/test/JndiAccessTest.java                                                              |    3 
 modules/enterprise/server/jar/pom.xml                                                                                                                                   | 2096 +++++-----
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertConditionLogManagerBean.java                                                           |    3 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertConditionManagerBean.java                                                              |    9 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertConditionManagerLocal.java                                                             |    2 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerBean.java                                                             |    8 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerLocal.java                                                            |   13 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertTemplateManagerBean.java                                                               |    6 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/GroupAlertDefinitionManagerBean.java                                                        |    6 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/GroupAlertDefinitionManagerLocal.java                                                       |   12 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/i18n/AlertI18NResourceKeys.java                                                             |   13 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/FailoverListManagerBean.java                                                                |   34 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/ServerBucket.java                                                                           |    5 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StatusManagerBean.java                                                                      |   29 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentManagerLocal.java                                                                  |    2 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentManagerRemote.java                                                                 |    1 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/RepoManagerBean.java                                                                      |   37 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/RepoManagerLocal.java                                                                     |    3 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/RepoManagerRemote.java                                                                    |   14 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/CoreServerServiceImpl.java                                                                   |   26 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/AgentPluginScanner.java                                                               |   68 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/PluginDeploymentScanner.java                                                          |   16 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerBean.java                                                       |   67 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerLocal.java                                                      |   15 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerRemote.java                                                     |    7 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/operation/OperationServerServiceImpl.java                                                         |   43 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java                                                                 |  180 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/GroupDefinitionManagerBean.java                                         |    2 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/GroupDefinitionManagerLocal.java                                        |    2 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/ExpressionEvaluator.java                                      |   83 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/InvalidExpressionException.java                               |   38 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java                                                                        |   36 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerBean.java                                                                        |  217 -
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerLocal.java                                                                       |   61 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerBean.java                                                                        |   75 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerLocal.java                                                                       |   13 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerBean.java                                                                       |   93 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerLocal.java                                                                      |   34 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java                                                                   |  150 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerLocal.java                                                                  |   29 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java                                                                     |   50 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerLocal.java                                                                    |   20 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/StatusHandlerBean.java                                                                       |   28 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/StatusHandlerLocal.java                                                                      |   13 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/UserHandlerBean.java                                                                         |   52 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/UserHandlerLocal.java                                                                        |   17 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/AlertRest.java                                                                        |   17 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/AvailabilityRest.java                                                                 |    9 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/GroupRest.java                                                                        |   27 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/MetricAggregate.java                                                                  |   11 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/OperationDefinitionRest.java                                                          |   15 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/OperationHistoryRest.java                                                             |   36 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/OperationRest.java                                                                    |   10 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/ResourceWithType.java                                                                 |   13 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/SimplePropDef.java                                                                    |   72 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/UserRest.java                                                                         |   12 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/AlertDefinitionLocal.java                                                          |    4 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/ConfigurationHistoryLocal.java                                                     |    4 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/DriftComplianceLocal.java                                                          |    4 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/InventorySummaryLocal.java                                                         |    5 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/PlatformUtilizationLocal.java                                                      |    4 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/RecentAlertLocal.java                                                              |    4 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/RecentDriftLocal.java                                                              |    4 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/RecentOperationsLocal.java                                                         |    4 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/SuspectMetricLocal.java                                                            |    4 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/jobs/DataPurgeJob.java                                                                  |   18 
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/webservices/WebservicesManagerBean.java                                                           |    8 
 modules/enterprise/server/jar/src/main/resources/rest_templates/alert.ftl                                                                                               |   58 
 modules/enterprise/server/jar/src/main/resources/rest_templates/availability.ftl                                                                                        |    6 
 modules/enterprise/server/jar/src/main/resources/rest_templates/genericStringList.ftl                                                                                   |   31 
 modules/enterprise/server/jar/src/main/resources/rest_templates/group.ftl                                                                                               |   19 
 modules/enterprise/server/jar/src/main/resources/rest_templates/listAlerts.ftl                                                                                          |   32 
 modules/enterprise/server/jar/src/main/resources/rest_templates/listAvailability.ftl                                                                                    |   32 
 modules/enterprise/server/jar/src/main/resources/rest_templates/listGroupDefinition.ftl                                                                                 |   10 
 modules/enterprise/server/jar/src/main/resources/rest_templates/listMetricDefinitions.ftl                                                                               |   38 
 modules/enterprise/server/jar/src/main/resources/rest_templates/listMetricSchedule.ftl                                                                                  |    6 
 modules/enterprise/server/jar/src/main/resources/rest_templates/listOperationHistory.ftl                                                                                |   37 
 modules/enterprise/server/jar/src/main/resources/rest_templates/metricData.ftl                                                                                          |   12 
 modules/enterprise/server/jar/src/main/resources/rest_templates/metricDefinition.ftl                                                                                    |   52 
 modules/enterprise/server/jar/src/main/resources/rest_templates/metricSchedule.ftl                                                                                      |   22 
 modules/enterprise/server/jar/src/main/resources/rest_templates/operationHistory.ftl                                                                                    |   56 
 modules/enterprise/server/jar/src/main/resources/rest_templates/resourceWithType.ftl                                                                                    |   11 
 modules/enterprise/server/jar/src/main/xsl/apiout2docbook.xsl                                                                                                           |    3 
 modules/enterprise/server/jar/src/main/xsl/apiout2html.xsl                                                                                                              |    3 
 modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/alert/test/AlertConditionTest.java                                                                |   78 
 modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/alert/test/AlertManagerBeanTest.java                                                              |  177 
 modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/cloud/FailoverListManagerBeanTest.java                                                            |   33 
 modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/measurement/test/MeasurementDataManagerTest.java                                                  |  242 +
 modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/definition/framework/test/ExpressionEvaluatorTest.java                             |  704 +++
 modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/metadata/PluginManagerBeanTest.java                                                      |   22 
 modules/enterprise/server/plugins/alert-cli/src/main/java/org/rhq/enterprise/server/plugins/alertCli/CliSender.java                                                     |   97 
 modules/enterprise/server/plugins/jboss-software/src/main/java/org/rhq/enterprise/server/plugins/jboss/software/JBossSoftwareContentSourceAdapter.java                  |    2 
 modules/enterprise/server/plugins/validate-all-serverplugins/pom.xml                                                                                                    |    2 
 modules/enterprise/server/xml-schemas/pom.xml                                                                                                                           |  448 +-
 modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/ServerPluginDescriptorUtil.java                                                 |    2 
 modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/XmlSchemas.java                                                                 |    2 
 modules/helpers/rest-docs-generator/pom.xml                                                                                                                             |    5 
 modules/helpers/rest-docs-generator/src/main/java/org/rhq/helpers/rest_docs_generator/ClassLevelProcessor.java                                                          |    6 
 modules/integration-tests/mod_cluster-plugin-test/src/test/java/org/rhq/plugins/modcluster/test/ModClusterPluginIntegrationTest.java                                    |    3 
 modules/jopr/tools/jbas5-plugin-descriptor-gen/pom.xml                                                                                                                  |   46 
 modules/jopr/tools/jbas5-plugin-descriptor-gen/src/main/java/org/jboss/jopr/tool/jbas5/PluginDescriptorGenerator.java                                                   |    6 
 modules/plugins/database/pom.xml                                                                                                                                        |    7 
 modules/plugins/database/src/main/java/org/rhq/plugins/database/AbstractDatabaseComponent.java                                                                          |    6 
 modules/plugins/database/src/main/java/org/rhq/plugins/database/CustomTableComponent.java                                                                               |   31 
 modules/plugins/database/src/main/java/org/rhq/plugins/database/CustomTableDiscoveryComponent.java                                                                      |   58 
 modules/plugins/database/src/main/java/org/rhq/plugins/database/CustomTableRowDiscoveryComponent.java                                                                   |   11 
 modules/plugins/database/src/main/java/org/rhq/plugins/database/DatabaseQueryUtility.java                                                                               |   90 
 modules/plugins/database/src/main/resources/META-INF/rhq-plugin.xml                                                                                                     |   59 
 modules/plugins/database/src/test/java/org/rhq/plugins/database/ComponentTest.java                                                                                      |  545 ++
 modules/plugins/database/src/test/java/org/rhq/plugins/database/H2Database.java                                                                                         |   79 
 modules/plugins/database/src/test/java/org/rhq/plugins/database/H2DatabaseDiscovery.java                                                                                |   46 
 modules/plugins/database/src/test/java/org/rhq/plugins/database/PluginTest.java                                                                                         |   52 
 modules/plugins/database/src/test/resources/META-INF/rhq-plugin.xml                                                                                                     |   47 
 modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/ApplicationServerDiscoveryComponent.java                                                              |   15 
 modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/ApplicationServerOperationsDelegate.java                                                              |   77 
 modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/Ejb2BeanComponent.java                                                                                |   15 
 modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/ManagedComponentComponent.java                                                                        |   71 
 modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/helper/JBossProductType.java                                                                          |   14 
 modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/serviceBinding/ManagerComponent.java                                                                  |   10 
 modules/plugins/jboss-as-5/src/main/resources/META-INF/rhq-plugin.xml                                                                                                   |   26 
 modules/plugins/jboss-as-5/src/test/java/org/rhq/plugins/jbossas5/itest/ApplicationServerComponentTest.java                                                             |   28 
 modules/plugins/jboss-as-7/pom.xml                                                                                                                                      |   90 
 modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseComponent.java                                                                            |    2 
 modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ConfigurationWriteDelegate.java                                                               |   16 
 modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ManagedASDiscovery.java                                                                       |   33 
 modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ModuleOptionsComponent.java                                                                   |  867 ++++
 modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ModuleOptionsDiscoveryComponent.java                                                          |  188 
 modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/StandaloneASDiscovery.java                                                                    |    2 
 modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ThreadingComponent.java                                                                       |   61 
 modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/WebservicesComponent.java                                                                     |   55 
 modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml                                                                                                   | 1622 ++++---
 modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/AbstractJBossAS7PluginTest.java                                                         |   17 
 modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/AbstractServerComponentTest.java                                                        |    8 
 modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/domain/SecurityModuleOptionsTest.java                                                   |  675 +++
 modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/DeploymentTest.java                                                          |  151 
 modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/ResourcesStandaloneServerTest.java                                           |  122 
 modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/TemplatedResourcesTest.java                                                  |    5 
 modules/plugins/jmx/src/main/java/org/rhq/plugins/jmx/ObjectNameQueryUtility.java                                                                                       |   75 
 modules/plugins/jmx/src/main/java/org/rhq/plugins/jmx/ParentDefinedJMXServerNamingUtility.java                                                                          |   40 
 modules/plugins/jmx/src/test/java/org/rhq/plugins/jmx/test/ObjectNameQueryUtilityDelegateTest.java                                                                      |  106 
 modules/plugins/jmx/src/test/java/org/rhq/plugins/jmx/test/ObjectNameQueryUtilityTest.java                                                                              |   13 
 modules/plugins/mysql/src/main/java/org/rhq/plugins/mysql/MySqlDatabaseDiscoveryComponent.java                                                                          |    2 
 modules/plugins/mysql/src/main/java/org/rhq/plugins/mysql/MySqlTableDiscoveryComponent.java                                                                             |   11 
 modules/plugins/mysql/src/main/resources/META-INF/rhq-plugin.xml                                                                                                        |    1 
 modules/plugins/mysql/src/test/java/org/rhq/plugins/mysql/ComponentTest.java                                                                                            |  563 ++
 modules/plugins/mysql/src/test/java/org/rhq/plugins/mysql/PluginTest.java                                                                                               |   61 
 modules/plugins/mysql/src/test/resources/log4j.xml                                                                                                                      |   35 
 modules/plugins/noop/pom.xml                                                                                                                                            |  119 
 modules/plugins/noop/src/main/java/org/rhq/plugins/noop/NoopComponent.java                                                                                              |   67 
 modules/plugins/noop/src/main/resources/META-INF/rhq-plugin.xml                                                                                                         |   25 
 modules/plugins/oracle/src/main/java/org/rhq/plugins/oracle/OracleFlashRecoveryAreaComponent.java                                                                       |   83 
 modules/plugins/oracle/src/main/java/org/rhq/plugins/oracle/OracleServerComponent.java                                                                                  |   12 
 modules/plugins/oracle/src/main/java/org/rhq/plugins/oracle/OracleTablespaceComponent.java                                                                              |   83 
 modules/plugins/oracle/src/main/resources/META-INF/rhq-plugin.xml                                                                                                       |   53 
 modules/plugins/perftest/pom.xml                                                                                                                                        |  453 +-
 modules/plugins/platform/src/main/java/org/rhq/plugins/platform/NetworkAdapterComponent.java                                                                            |  203 
 modules/plugins/pom.xml                                                                                                                                                 |    7 
 pom.xml                                                                                                                                                                 |   52 
 443 files changed, 25160 insertions(+), 8623 deletions(-)

New commits:
commit e649c7c40a79cef1959c95d9b0be0765b7352e2b
Merge: 27d7474 1047bbb
Author: Jay Shaughnessy <jshaughn at redhat.com>
Date:   Wed Aug 8 12:02:34 2012 -0400

    Merge branch 'master' into jsanda/metrics-rhq
    
    Conflicts:
    	modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
    	modules/enterprise/agent/src/test/java/org/rhq/enterprise/agent/AgentComm2Test.java
    	modules/enterprise/agent/src/test/java/org/rhq/enterprise/agent/AgentCommTestBase.java
    	modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractMeasurementDataTraitDataSource.java
    	modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/monitoring/traits/TraitsView.java
    	modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/traits/TraitsView.java

diff --cc .classpath
index fd400dc,0516dd7..b9c8a5b
--- a/.classpath
+++ b/.classpath
@@@ -308,7 -311,7 +311,8 @@@
  	<classpathentry exported="true" kind="var" path="M2_REPO/org/jboss/arquillian/container/arquillian-container-spi/1.0.0.Final/arquillian-container-spi-1.0.0.Final.jar"/>
  	<classpathentry exported="true" kind="var" path="M2_REPO/org/jboss/arquillian/container/arquillian-container-test-api/1.0.0.Final/arquillian-container-test-api-1.0.0.Final.jar"/>
  	<classpathentry exported="true" kind="var" path="M2_REPO/org/jboss/arquillian/testng/arquillian-testng-core/1.0.0.Final/arquillian-testng-core-1.0.0.Final.jar"/>
-     <classpathentry exported="true" kind="var" path="M2_REPO/com/wordnik/swagger-annotations_2.9.1/1.1-SNAPSHOT/swagger-annotations_2.9.1-1.1-20120531.064118-1.jar"/>
-     <classpathentry exported="true" kind="var" path="M2_REPO/org/jboss/byteman/byteman/1.2.1/byteman-1.2.1.jar"/>    
+ 	<classpathentry exported="true" kind="var" path="M2_REPO/com/wordnik/swagger-annotations_2.9.1/1.1-SNAPSHOT/swagger-annotations_2.9.1-1.1-20120531.064118-1.jar"/>
+ 	<classpathentry exported="true" kind="var" path="M2_REPO/org/jboss/byteman/byteman/1.2.1/byteman-1.2.1.jar"/>
++	<classpathentry kind="var" path="M2_REPO/joda-time/joda-time/2.1/joda-time-2.1.jar"/>
  	<classpathentry kind="output" path="eclipse-classes"/>
  </classpath>
diff --cc modules/core/arquillian-integration/container/src/main/java/org/rhq/test/arquillian/FakeServerInventory.java
index 0b7b043,b1ac175..1e8a977
--- a/modules/core/arquillian-integration/container/src/main/java/org/rhq/test/arquillian/FakeServerInventory.java
+++ b/modules/core/arquillian-integration/container/src/main/java/org/rhq/test/arquillian/FakeServerInventory.java
@@@ -345,6 -371,73 +371,73 @@@ public class FakeServerInventory 
          };
      }
  
+     // this expects the mock invocation to have two parameters - Set<Integer> resourceIds, Boolean getChildSchedules
+     public synchronized Answer<Set<ResourceMeasurementScheduleRequest>> getLatestSchedulesForResourceIds() {
+         return new Answer<Set<ResourceMeasurementScheduleRequest>>() {
+             @Override
+             @SuppressWarnings("unchecked")
+             public Set<ResourceMeasurementScheduleRequest> answer(InvocationOnMock invocation) throws Throwable {
+                 Object[] args = invocation.getArguments();
+                 Set<Integer> resourceIds = (Set<Integer>) args[0];
+                 Boolean getChildSchedules = (Boolean) args[1];
+ 
+                 Set<Resource> resources = getResources(resourceIds, getChildSchedules);
+                 Set<ResourceMeasurementScheduleRequest> allSchedules = new HashSet<ResourceMeasurementScheduleRequest>();
+                 for (Resource resource : resources) {
+                     ResourceMeasurementScheduleRequest resourceSchedules = getDefaultMeasurementSchedules(resource);
+                     if (resourceSchedules != null) {
+                         allSchedules.add(resourceSchedules);
+                     }
+                 }
+                 return allSchedules;
+             }
+         };
+     }
+ 
+     // this expects the mock invocation to have one parameter - Set<Integer> resourceIds
+     public synchronized Answer<Set<ResourceMeasurementScheduleRequest>> postProcessNewlyCommittedResources() {
+         return new Answer<Set<ResourceMeasurementScheduleRequest>>() {
+             @Override
+             @SuppressWarnings("unchecked")
+             public Set<ResourceMeasurementScheduleRequest> answer(InvocationOnMock invocation) throws Throwable {
+                 Object[] args = invocation.getArguments();
+                 Set<Integer> resourceIds = (Set<Integer>) args[0];
+ 
+                 Set<Resource> resources = getResources(resourceIds, false);
+                 Set<ResourceMeasurementScheduleRequest> allSchedules = new HashSet<ResourceMeasurementScheduleRequest>();
+                 for (Resource resource : resources) {
+                     ResourceMeasurementScheduleRequest resourceSchedules = getDefaultMeasurementSchedules(resource);
+                     if (resourceSchedules != null) {
+                         allSchedules.add(resourceSchedules);
+                     }
+                 }
+                 return allSchedules;
+             }
+         };
+     }
+ 
+     private ResourceMeasurementScheduleRequest getDefaultMeasurementSchedules(Resource resource) {
+         ResourceType rt = resource.getResourceType();
+         Set<MeasurementDefinition> metrics = rt.getMetricDefinitions();
+         if (metrics == null || metrics.isEmpty()) {
+             return null;
+         }
+ 
+         ResourceMeasurementScheduleRequest resourceSchedules = new ResourceMeasurementScheduleRequest(resource.getId());
+         for (MeasurementDefinition metric : metrics) {
+             int id = this.metricScheduleCounter.getAndIncrement();
+             String name = metric.getName();
+             long interval = metric.getDefaultInterval();
+             boolean enabled = metric.isDefaultOn() || metric.getDisplayType() == DisplayType.SUMMARY;
+             DataType dataType = metric.getDataType();
+             NumericType nDataType = metric.getNumericType();
+             MeasurementScheduleRequest schedule = new MeasurementScheduleRequest(id, name, interval, enabled, dataType,
 -                nDataType);
++                nDataType, resource.getId());
+             resourceSchedules.addMeasurementScheduleRequest(schedule);
+         }
+         return resourceSchedules;
+     }
+ 
      public synchronized boolean isFailing() {
          return failing;
      }
diff --cc modules/core/dbutils/pom.xml
index d4b5505,d4b5505..eee04da
--- a/modules/core/dbutils/pom.xml
+++ b/modules/core/dbutils/pom.xml
@@@ -17,7 -17,7 +17,7 @@@
      <description>Database schema setup, upgrade and other utilities</description>
  
      <properties>
--        <db.schema.version>2.122</db.schema.version>
++        <db.schema.version>2.123</db.schema.version>
          <rhq.ds.type-mapping>${rhq.test.ds.type-mapping}</rhq.ds.type-mapping>
          <rhq.ds.server-name>${rhq.test.ds.server-name}</rhq.ds.server-name>
          <rhq.ds.db-name>${rhq.test.ds.db-name}</rhq.ds.db-name>
diff --cc modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
index aa8b573,2cee9f4..13c240d
--- a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
+++ b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
@@@ -4007,14 -4007,11 +4007,22 @@@
                <schema-javaTask className="ContentSourceConfigurationObfuscationUpgradeTask" />
              </schemaSpec>
  
-           <schemaSpec version="2.122">
-             <schema-directSQL>
-               <statement desc="Adding metrics server plugin active plugin system configuration property">
-                 INSERT INTO rhq_system_config (id, property_key, property_value, default_property_value)
-                 VALUES (59, 'ACTIVE_METRICS_PLUGIN', 'metrics-rhq', 'metrics-rhq')
-               </statement>
-             </schema-directSQL>
-           </schemaSpec>
 -             <schemaSpec version="2.122">
 -               <schema-addColumn   table="RHQ_CONFIG_PROP_DEF" column="MIN_ENTRIES" columnType="INTEGER"/>
 -               <schema-addColumn   table="RHQ_CONFIG_PROP_DEF" column="MAX_ENTRIES" columnType="INTEGER"/>
++            <schemaSpec version="2.122">
++              <schema-addColumn   table="RHQ_CONFIG_PROP_DEF" column="MIN_ENTRIES" columnType="INTEGER"/>
++              <schema-addColumn   table="RHQ_CONFIG_PROP_DEF" column="MAX_ENTRIES" columnType="INTEGER"/>
+             </schemaSpec>
+ 
++            <schemaSpec version="2.123">
++              <schema-directSQL>
++                <statement desc="Adding metrics server plugin active plugin system configuration property">
++                  INSERT INTO rhq_system_config (id, property_key, property_value, default_property_value)
++                  VALUES (59, 'ACTIVE_METRICS_PLUGIN', 'metrics-rhq', 'metrics-rhq')
++                </statement>
++              </schema-directSQL>
++            </schemaSpec>
++
++
++
          </dbupgrade>
      </target>
  </project>
diff --cc modules/core/domain/src/main/java/org/rhq/core/domain/measurement/TraitMeasurement.java
index c6e6b6e,0000000..01e5a2f
mode 100644,000000..100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/measurement/TraitMeasurement.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/measurement/TraitMeasurement.java
@@@ -1,46 -1,0 +1,48 @@@
 +/*
 + *
 + *  * RHQ Management Platform
 + *  * Copyright (C) 2005-2012 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.domain.measurement;
 +
 +import java.io.Serializable;
 +
 +/**
 + * @author John Sanda
 + */
 +public interface TraitMeasurement extends Serializable {
 +
 +    long getTimestamp();
 +
 +    String getValue();
 +
 +    void setValue(String value);
 +
++    String getName();
++
 +    int getResourceId();
 +
 +    int getScheduleId();
 +
 +    int getDefinitionId();
 +
 +    DisplayType getDisplayType();
 +
 +    String getDisplayName();
 +}
diff --cc modules/core/domain/src/main/java/org/rhq/core/domain/measurement/TraitMeasurementDTO.java
index 1128512,0000000..e29419e
mode 100644,000000..100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/measurement/TraitMeasurementDTO.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/measurement/TraitMeasurementDTO.java
@@@ -1,109 -1,0 +1,119 @@@
 +/*
 + *
 + *  * RHQ Management Platform
 + *  * Copyright (C) 2005-2012 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.domain.measurement;
 +
 +/**
 + * @author John Sanda
 + */
 +public class TraitMeasurementDTO implements TraitMeasurement{
 +
 +    private static final long serialVersionUID = 1L;
 +
 +    private long timestamp;
 +    private String value;
++    private String name;
 +    private int resourceId;
 +    private int scheduleId;
 +    private int definitionId;
 +    private DisplayType displayType;
 +    private String displayName;
 +
 +    @Override
 +    public long getTimestamp() {
 +        return timestamp;
 +    }
 +
 +    public void setTimestamp(long timestamp) {
 +        this.timestamp = timestamp;
 +    }
 +
 +    @Override
 +    public String getValue() {
 +        return value;
 +    }
 +
 +    @Override
 +    public void setValue(String value) {
 +        this.value = value;
 +    }
 +
 +    @Override
++    public String getName() {
++        return name;
++    }
++
++    public void setName(String name) {
++        this.name = name;
++    }
++
++    @Override
 +    public int getResourceId() {
 +        return resourceId;
 +    }
 +
 +    public void setResourceId(int resourceId) {
 +        this.resourceId = resourceId;
 +    }
 +
 +    @Override
 +    public int getScheduleId() {
 +        return scheduleId;
 +    }
 +
 +    public void setScheduleId(int scheduleId) {
 +        this.scheduleId = scheduleId;
 +    }
 +
 +    @Override
 +    public int getDefinitionId() {
 +        return definitionId;
 +    }
 +
 +    public void setDefinitionId(int definitionId) {
 +        this.definitionId = definitionId;
 +    }
 +
 +    @Override
 +    public DisplayType getDisplayType() {
 +        return displayType;
 +    }
 +
 +    public void setDisplayType(DisplayType displayType) {
 +        this.displayType = displayType;
 +    }
 +
 +    @Override
 +    public String getDisplayName() {
 +        return displayName;
 +    }
 +
 +    public void setDisplayName(String displayName) {
 +        this.displayName = displayName;
 +    }
 +
 +    @Override
 +    public String toString() {
 +        return "TraitMeasurementDTO[timestamp: " + timestamp + ", value: " + value + ", scheduleId: " +
 +            scheduleId + ", resourceId: " + resourceId + ", definitionId: " + definitionId + ", displayName: " +
 +            displayName + ", displayType: " + displayType + "]";
 +    }
 +}
diff --cc modules/core/plugin-container/src/main/java/org/rhq/core/pc/measurement/MeasurementCollectorRunner.java
index 3351ec9,e9303b4..e34041f
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/measurement/MeasurementCollectorRunner.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/measurement/MeasurementCollectorRunner.java
@@@ -23,8 -23,8 +23,9 @@@
  package org.rhq.core.pc.measurement;
  
  import java.util.ArrayDeque;
+ import java.util.Collections;
  import java.util.Date;
 +import java.util.HashSet;
  import java.util.Set;
  import java.util.concurrent.Callable;
  
@@@ -128,10 -128,10 +129,10 @@@ public class MeasurementCollectorRunne
      }
  
      private void getValues(MeasurementFacet measurementComponent, MeasurementReport report,
 -        Set<? extends MeasurementScheduleRequest> requests, Resource resource) {
 +        Set<MeasurementScheduleRequest> requests, Resource resource) {
          try {
              long start = System.currentTimeMillis();
-             measurementComponent.getValues(report, (Set<MeasurementScheduleRequest>) requests);
+             measurementComponent.getValues(report, Collections.unmodifiableSet(requests));
              long duration = (System.currentTimeMillis() - start);
              if (duration > 2000L) {
                  String message = "[PERF] Collection of measurements for [" + resource + "] (component=["
diff --cc modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractMeasurementDataTraitDataSource.java
index 91e5898,e640d1d..bd07085
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractMeasurementDataTraitDataSource.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractMeasurementDataTraitDataSource.java
@@@ -48,13 -50,14 +48,17 @@@ import org.rhq.enterprise.gui.coregui.c
   *
   * @author Ian Springer
   */
 -public abstract class AbstractMeasurementDataTraitDataSource extends
 -    RPCDataSource<MeasurementDataTrait, MeasurementDataTraitCriteria> {
 +public abstract class AbstractMeasurementDataTraitDataSource<T extends TraitMeasurement, GenericTraitMeasurementCriteria>
 +    extends RPCDataSource <T, MeasurementDataTraitCriteria> {
  
+     public static final String FIELD_METRIC_SCHED_ID = "id";
+     public static final String FIELD_METRIC_NAME = "name";
++    public static final String FIELD_METRIC_DISPLAY_NAME = "displayName";
+ 
      private MeasurementDataGWTServiceAsync measurementService = GWTServiceLookup.getMeasurementDataService();
  
 +    protected MetricsGWTServiceAsync metricsService = GWTServiceLookup.getMetricsService();
 +
      protected AbstractMeasurementDataTraitDataSource() {
          setCanMultiSort(true);
          List<DataSourceField> fields = addDataSourceFields();
@@@ -214,11 -181,13 +222,13 @@@
          ListGridRecord record = new ListGridRecord();
  
          record.setAttribute("primaryKey", from.getScheduleId() + ":" + from.getTimestamp());
-         record.setAttribute("id", from.getDefinitionId());
 -        record.setAttribute(FIELD_METRIC_SCHED_ID, from.getSchedule().getDefinition().getId()); // used for detail view
 -        record.setAttribute(MeasurementDataTraitCriteria.SORT_FIELD_TIMESTAMP, new Date(from.getTimestamp()));
 -        record.setAttribute(MeasurementDataTraitCriteria.SORT_FIELD_DISPLAY_NAME, from.getSchedule().getDefinition()
 -            .getDisplayName());
++        record.setAttribute(FIELD_METRIC_SCHED_ID, from.getDefinitionId());
 +        record.setAttribute(MeasurementDataTraitCriteria.SORT_FIELD_TIMESTAMP,
 +            new Date(from.getTimestamp()));
 +        record.setAttribute(MeasurementDataTraitCriteria.SORT_FIELD_DISPLAY_NAME, from.getDisplayName());
          record.setAttribute(MeasurementDataTraitCriteria.SORT_FIELD_VALUE, from.getValue());
 -        record.setAttribute(FIELD_METRIC_NAME, from.getSchedule().getDefinition().getName());
 -        record.setAttribute(MeasurementDataTraitCriteria.FILTER_FIELD_RESOURCE_ID, from.getSchedule().getResource().getId());
++        record.setAttribute(FIELD_METRIC_NAME, from.getName());
++        record.setAttribute(MeasurementDataTraitCriteria.FILTER_FIELD_RESOURCE_ID, from.getResourceId());
  
          return record;
      }
diff --cc modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/monitoring/traits/TraitsView.java
index 634c06f,f7eb900..c479f22
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/monitoring/traits/TraitsView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/monitoring/traits/TraitsView.java
@@@ -27,10 -38,16 +38,17 @@@ import com.smartgwt.client.widgets.grid
  import com.smartgwt.client.widgets.grid.ListGridRecord;
  
  import org.rhq.core.domain.criteria.MeasurementDataTraitCriteria;
 +import org.rhq.core.domain.criteria.TraitMeasurementCriteria;
+ import org.rhq.core.domain.measurement.MeasurementData;
+ import org.rhq.core.domain.util.collection.ArrayUtils;
+ import org.rhq.enterprise.gui.coregui.client.CoreGUI;
  import org.rhq.enterprise.gui.coregui.client.LinkManager;
+ import org.rhq.enterprise.gui.coregui.client.components.table.TableAction;
+ import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
+ import org.rhq.enterprise.gui.coregui.client.inventory.common.AbstractMeasurementDataTraitDataSource;
  import org.rhq.enterprise.gui.coregui.client.inventory.common.AbstractMeasurementDataTraitListView;
  import org.rhq.enterprise.gui.coregui.client.inventory.resource.AncestryUtil;
+ import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableListGrid;
  import org.rhq.enterprise.gui.coregui.client.util.selenium.SeleniumUtility;
  
  /**
diff --cc modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/traits/TraitsView.java
index 52a14aa,ad422b7..0241ea3
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/traits/TraitsView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/traits/TraitsView.java
@@@ -18,11 -18,30 +18,30 @@@
   */
  package org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.traits;
  
+ import java.util.ArrayList;
+ import java.util.Collections;
+ import java.util.Comparator;
+ import java.util.HashMap;
+ import java.util.HashSet;
+ import java.util.List;
+ import java.util.Map;
+ import java.util.Set;
+ 
+ import com.google.gwt.user.client.rpc.AsyncCallback;
  import com.smartgwt.client.data.Criteria;
+ import com.smartgwt.client.types.SelectionStyle;
  import com.smartgwt.client.widgets.Canvas;
+ import com.smartgwt.client.widgets.grid.ListGridField;
+ import com.smartgwt.client.widgets.grid.ListGridRecord;
  
 -import org.rhq.core.domain.criteria.MeasurementDataTraitCriteria;
 +import org.rhq.core.domain.criteria.TraitMeasurementCriteria;
+ import org.rhq.core.domain.measurement.MeasurementData;
+ import org.rhq.enterprise.gui.coregui.client.CoreGUI;
+ import org.rhq.enterprise.gui.coregui.client.components.table.TableAction;
+ import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
+ import org.rhq.enterprise.gui.coregui.client.inventory.common.AbstractMeasurementDataTraitDataSource;
  import org.rhq.enterprise.gui.coregui.client.inventory.common.AbstractMeasurementDataTraitListView;
+ import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableListGrid;
  
  /**
   * The Resource Monitoring>Traits subtab.
@@@ -55,4 -74,71 +74,72 @@@ public class TraitsView extends Abstrac
  
          return criteria;
      }
+     
+     @Override
+     protected TableAction getLiveValueAction() {
+         return new TableAction() {
+             @Override
+             public boolean isEnabled(ListGridRecord[] selection) {
+                 return selection != null && selection.length > 0;
+             }
+ 
+             @Override
+             public void executeAction(ListGridRecord[] selection, Object actionValue) {
+                 if (selection == null || selection.length == 0) {
+                     return;
+                 }
+                 final Map<String, String> scheduleNames = new HashMap<String, String>();
+                 int[] definitionIds = new int[selection.length];
+                 int i = 0;
+                 for (ListGridRecord record : selection) {
+                     Integer defId = record.getAttributeAsInt(AbstractMeasurementDataTraitDataSource.FIELD_METRIC_SCHED_ID);
+                     definitionIds[i++] = defId.intValue();
+                     
 -                    scheduleNames.put(record.getAttribute(AbstractMeasurementDataTraitDataSource.FIELD_METRIC_NAME), record.getAttribute(MeasurementDataTraitCriteria.SORT_FIELD_DISPLAY_NAME));
++                    scheduleNames.put(record.getAttribute(AbstractMeasurementDataTraitDataSource.FIELD_METRIC_NAME),
++                        record.getAttribute(AbstractMeasurementDataTraitDataSource.FIELD_METRIC_DISPLAY_NAME));
+                 }
+ 
+                 // actually go out and ask the agents for the data
+                 GWTServiceLookup.getMeasurementDataService(60000).findLiveData(resourceId,
+                     definitionIds, new AsyncCallback<Set<MeasurementData>>() {
+                         public void onSuccess(Set<MeasurementData> result) {
+                             if (result == null) {
+                                 result = new HashSet<MeasurementData>(0);
+                             }
+                             ArrayList<ListGridRecord> records = new ArrayList<ListGridRecord>(result.size());
+                             for (MeasurementData data : result) {
+                                     ListGridRecord record = new ListGridRecord();
+                                     record.setAttribute("name", scheduleNames.get(data.getName()));
+                                     record.setAttribute("value", data.getValue());
+                                     records.add(record);
+                             }
+                             Collections.sort(records, new Comparator<ListGridRecord>() {
+                                 public int compare(ListGridRecord o1, ListGridRecord o2) {
+                                     return o1.getAttribute("name").compareTo(o2.getAttribute("name"));
+                                 }
+                             });
+                             showLiveData(records);
+                         }
+ 
+                         @Override
+                         public void onFailure(Throwable caught) {
+                             CoreGUI.getErrorHandler().handleError(MSG.view_measureTable_getLive_failure(), caught);
+                         }
+                     });
+             }
+         };
+     }
+ 
+     @Override
+     protected LocatableListGrid decorateLiveDataGrid(List<ListGridRecord> records) {
+         LocatableListGrid liveDataGrid = new LocatableListGrid(extendLocatorId("liveDataListGrid"));
+         liveDataGrid.setShowAllRecords(true);
+         liveDataGrid.setData(records.toArray(new ListGridRecord[records.size()]));
+         liveDataGrid.setSelectionType(SelectionStyle.NONE);
+         ListGridField name = new ListGridField("name", MSG.dataSource_traits_field_trait());
+         ListGridField value = new ListGridField("value", MSG.common_title_value());
+         liveDataGrid.setFields(name, value);
+ 
+         return liveDataGrid;
+     }
  }
diff --cc modules/integration-tests/mod_cluster-plugin-test/src/test/java/org/rhq/plugins/modcluster/test/ModClusterPluginIntegrationTest.java
index e1304c0,e1304c0..65b86ee
--- a/modules/integration-tests/mod_cluster-plugin-test/src/test/java/org/rhq/plugins/modcluster/test/ModClusterPluginIntegrationTest.java
+++ b/modules/integration-tests/mod_cluster-plugin-test/src/test/java/org/rhq/plugins/modcluster/test/ModClusterPluginIntegrationTest.java
@@@ -166,7 -166,7 +166,8 @@@ public class ModClusterPluginIntegratio
          if (resourceComponent instanceof MeasurementFacet) {
              for (MeasurementDefinition def : resource.getResourceType().getMetricDefinitions()) {
                  Set<MeasurementScheduleRequest> metricList = new HashSet<MeasurementScheduleRequest>();
--                metricList.add(new MeasurementScheduleRequest(1, def.getName(), 1000, true, def.getDataType(), null));
++                metricList.add(new MeasurementScheduleRequest(1, def.getName(), 1000, true, def.getDataType(), null,
++                    resource.getId()));
                  MeasurementReport report = new MeasurementReport();
                  ((MeasurementFacet) resourceComponent).getValues(report, metricList);
  


commit 1047bbb5764ced04b78ee2c81dd9fcb3652387ed
Author: Heiko W. Rupp <hwr at redhat.com>
Date:   Tue Aug 7 12:52:19 2012 -0400

    Add Richard Hensman to the list of contributors.

diff --git a/pom.xml b/pom.xml
index 3dcca11..0ae9a07 100644
--- a/pom.xml
+++ b/pom.xml
@@ -735,7 +735,7 @@
                   <exclusion>
                      <scope>test</scope>
                   </exclusion>
-                  <!--<exclusion> 
+                  <!--<exclusion>
                      <scope>provided</scope>
                   </exclusion>-->
                </exclusions>
@@ -1570,6 +1570,10 @@
             <timezone>+1</timezone>
         </contributor>
         <contributor>
+            <name>Richard Hensman</name>
+            <timezone>0</timezone>
+        </contributor>
+        <contributor>
             <name>Rafael Chies</name>
             <timezone>-7</timezone>
             <url>http://blogdorafaelchies.wordpress.com/</url>


commit 2639e50949fe39e77a4c17a650b62bc13d1e1a5f
Author: Heiko W. Rupp <hwr at redhat.com>
Date:   Tue Aug 7 12:21:07 2012 -0400

    BZ 841047 Don't assume a host name of 'master', but get it via api if it is not set. If this does not work, get it via hostname resolution.

diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ManagedASDiscovery.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ManagedASDiscovery.java
index 10889ce..e055cfa 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ManagedASDiscovery.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ManagedASDiscovery.java
@@ -19,6 +19,8 @@
 package org.rhq.modules.plugins.jbossas7;
 
 import java.io.File;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
@@ -64,7 +66,10 @@ public class ManagedASDiscovery implements ResourceDiscoveryComponent<HostContro
 
         parentComponent = discoveryContext.getParentResourceComponent();
         Configuration hcConfig = discoveryContext.getParentResourceContext().getPluginConfiguration();
-        String hostName = hcConfig.getSimpleValue("domainHost", "master"); // TODO good default?
+        String hostName = hcConfig.getSimpleValue("domainHost", null);
+        if (hostName==null) {
+            hostName = getHostName(discoveryContext.getParentResourceComponent().getASConnection());
+        }
         String productTypeString = hcConfig.getSimpleValue("productType", null);
         JBossProductType productType = JBossProductType.valueOf(productTypeString);
 
@@ -129,6 +134,32 @@ public class ManagedASDiscovery implements ResourceDiscoveryComponent<HostContro
         return discoveredResources;
     }
 
+    /**
+     * Let us try to determine the hostname of the parent's controller via api access.
+     * If that does not work, use host name resolution.
+     *
+     * @param asConnection ASConnection to the parent
+     * @return Host name
+     */
+    private String getHostName(ASConnection asConnection) {
+
+        Operation op = new ReadAttribute(new Address(),"local-host-name");
+        String hostname;
+        Result res = asConnection.execute(op);
+        if (res.isSuccess()) {
+            hostname = (String) res.getResult();
+            return hostname;
+        }
+        // Above failed. Now try falling back to host name resolution
+        try {
+            hostname = InetAddress.getLocalHost().getHostName();
+        } catch (UnknownHostException e) {
+            hostname = "master"; // Very last resort
+        }
+
+        return hostname;
+    }
+
     private String resolveSocketBindingGroup(String serverGroup) {
         Address address = new Address("server-group", serverGroup);
         Operation operation = new ReadAttribute(address, "socket-binding-group");


commit 1b21770ce8d938cce33f03b604b31f6fbc078c14
Author: Jay Shaughnessy <jshaughn at redhat.com>
Date:   Tue Aug 7 11:26:27 2012 -0400

    [Bug 846375 - Resource list views should have name field as initial sort and limit ancestry to client side sorting only]
    - Apply default initial sort on Name field for resource list views (using ResourceSearchView)
      - note, updated constructor chaining to be more efficient while adding
        default sort behavior. Removed an unused constructor.
    - Disable server-side sorting on Ancestry since sorting on the encoded
      value is not useful to the end user.  Allow client-side sorting when all
      rows are fetched, this gives the desired alpha sort on the display value.

diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/AncestryUtil.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/AncestryUtil.java
index 0313b46..15e7bc3 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/AncestryUtil.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/AncestryUtil.java
@@ -66,6 +66,8 @@ public abstract class AncestryUtil {
         ancestryField = new ListGridField(AncestryUtil.RESOURCE_ANCESTRY, CoreGUI.getMessages().common_title_ancestry());
         ancestryField.setAlign(Alignment.LEFT);
         ancestryField.setCellAlign(Alignment.LEFT);
+        // sorting on the encoded db value is not useful, limit to client sorting when we have all of the values
+        ancestryField.setCanSortClientOnly(true);
         setupAncestryListGridFieldCellFormatter(ancestryField);
         setupAncestryListGridFieldHover(ancestryField);
         return ancestryField;
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceDatasource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceDatasource.java
index 9bb1dfa..55271c6 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceDatasource.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceDatasource.java
@@ -52,6 +52,7 @@ import org.rhq.core.domain.measurement.AvailabilityType;
 import org.rhq.core.domain.resource.Resource;
 import org.rhq.core.domain.resource.ResourceCategory;
 import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.core.domain.util.PageControl;
 import org.rhq.core.domain.util.PageList;
 import org.rhq.enterprise.gui.coregui.client.CoreGUI;
 import org.rhq.enterprise.gui.coregui.client.ImageManager;
@@ -250,6 +251,11 @@ public class ResourceDatasource extends RPCDataSource<Resource, ResourceCriteria
         Log.debug(" *** ResourceCriteria Search String: " + getFilter(request, "search", String.class));
         criteria.setSearchExpression(getFilter(request, "search", String.class));
 
+        // filter out unsortable fields (i.e. fields sorted client-side only)
+        PageControl pageControl = getPageControl(request);
+        pageControl.removeOrderingField(AncestryUtil.RESOURCE_ANCESTRY);
+        criteria.setPageControl(pageControl);
+
         return criteria;
     }
 
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceSearchView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceSearchView.java
index ed0a1ca..0e59b6d 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceSearchView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceSearchView.java
@@ -18,13 +18,38 @@
  */
 package org.rhq.enterprise.gui.coregui.client.inventory.resource;
 
+import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.AVAILABILITY;
+import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.CATEGORY;
+import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.CTIME;
+import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.DESCRIPTION;
+import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.ITIME;
+import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.KEY;
+import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.LOCATION;
+import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.MODIFIER;
+import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.MTIME;
+import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.NAME;
+import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.PLUGIN;
+import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.TYPE;
+import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.VERSION;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.EnumSet;
+import java.util.List;
+
 import com.google.gwt.user.client.rpc.AsyncCallback;
 import com.smartgwt.client.data.Criteria;
 import com.smartgwt.client.data.Record;
 import com.smartgwt.client.data.SortSpecifier;
+import com.smartgwt.client.types.SortDirection;
 import com.smartgwt.client.widgets.events.DoubleClickEvent;
 import com.smartgwt.client.widgets.events.DoubleClickHandler;
-import com.smartgwt.client.widgets.grid.*;
+import com.smartgwt.client.widgets.grid.CellFormatter;
+import com.smartgwt.client.widgets.grid.HoverCustomizer;
+import com.smartgwt.client.widgets.grid.ListGrid;
+import com.smartgwt.client.widgets.grid.ListGridField;
+import com.smartgwt.client.widgets.grid.ListGridRecord;
+
 import org.rhq.core.domain.authz.Permission;
 import org.rhq.core.domain.criteria.ResourceCriteria;
 import org.rhq.core.domain.measurement.AvailabilityType;
@@ -34,7 +59,15 @@ import org.rhq.core.domain.search.SearchSubsystem;
 import org.rhq.enterprise.gui.coregui.client.CoreGUI;
 import org.rhq.enterprise.gui.coregui.client.LinkManager;
 import org.rhq.enterprise.gui.coregui.client.components.ReportExporter;
-import org.rhq.enterprise.gui.coregui.client.components.table.*;
+import org.rhq.enterprise.gui.coregui.client.components.table.EscapedHtmlCellFormatter;
+import org.rhq.enterprise.gui.coregui.client.components.table.IconField;
+import org.rhq.enterprise.gui.coregui.client.components.table.RecordExtractor;
+import org.rhq.enterprise.gui.coregui.client.components.table.ResourceAuthorizedTableAction;
+import org.rhq.enterprise.gui.coregui.client.components.table.ResourceCategoryCellFormatter;
+import org.rhq.enterprise.gui.coregui.client.components.table.Table;
+import org.rhq.enterprise.gui.coregui.client.components.table.TableAction;
+import org.rhq.enterprise.gui.coregui.client.components.table.TableActionEnablement;
+import org.rhq.enterprise.gui.coregui.client.components.table.TimestampCellFormatter;
 import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
 import org.rhq.enterprise.gui.coregui.client.gwt.ResourceGWTServiceAsync;
 import org.rhq.enterprise.gui.coregui.client.report.DriftComplianceReportResourceSearchView;
@@ -45,15 +78,9 @@ import org.rhq.enterprise.gui.coregui.client.util.message.Message;
 import org.rhq.enterprise.gui.coregui.client.util.message.Message.Severity;
 import org.rhq.enterprise.gui.coregui.client.util.selenium.SeleniumUtility;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.EnumSet;
-import java.util.List;
-
-import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.*;
-
 /**
- * The list view for {@link Resource}s.
+ * The list view for {@link Resource}s. If not specified a default title is assigned.  If not specified the list will
+ * be initially sorted by resource name, ascending. 
  *
  * @author Jay Shaughnessy
  * @author Greg Hinkle
@@ -62,6 +89,8 @@ import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceD
 public class ResourceSearchView extends Table {
 
     private static final String DEFAULT_TITLE = MSG.common_title_resources();
+    private static final SortSpecifier[] DEFAULT_SORT_SPECIFIER = new SortSpecifier[] { new SortSpecifier("name",
+        SortDirection.ASCENDING) };
 
     private List<ResourceSelectListener> selectListeners = new ArrayList<ResourceSelectListener>();
 
@@ -71,23 +100,21 @@ public class ResourceSearchView extends Table {
      * A list of all Resources in the system.
      */
     public ResourceSearchView(String locatorId) {
-        this(locatorId, null);
-    }
-
-    public ResourceSearchView(String locatorId, String title, String[] excludeFields) {
-        this(locatorId, null, title, null, excludeFields);
+        this(locatorId, null, null, null, null, false);
     }
 
     /**
      * A Resource list filtered by a given criteria.
      */
     public ResourceSearchView(String locatorId, Criteria criteria) {
-        this(locatorId, criteria, DEFAULT_TITLE);
+        this(locatorId, criteria, null, null, null, false);
     }
 
+    /**
+     * A Resource list filtered by a given criteria and optionally exportable
+     */
     public ResourceSearchView(String locatorId, Criteria criteria, boolean exportable) {
-        this(locatorId, criteria);
-        this.exportable = exportable;
+        this(locatorId, criteria, null, null, null, exportable);
     }
 
     /**
@@ -96,7 +123,7 @@ public class ResourceSearchView extends Table {
      * @param headerIcons 24x24 icon(s) to be displayed in the header
      */
     public ResourceSearchView(String locatorId, Criteria criteria, String title, String... headerIcons) {
-        this(locatorId, criteria, title, null, null, headerIcons);
+        this(locatorId, criteria, title, null, null, false, headerIcons);
     }
 
     /**
@@ -106,7 +133,22 @@ public class ResourceSearchView extends Table {
      */
     public ResourceSearchView(String locatorId, Criteria criteria, String title, SortSpecifier[] sortSpecifier,
         String[] excludeFields, String... headerIcons) {
-        super(locatorId, title, criteria, sortSpecifier, excludeFields);
+
+        this(locatorId, criteria, title, sortSpecifier, excludeFields, false, headerIcons);
+    }
+
+    /**
+     * A Resource list filtered by a given criteria with the given title and optionally exportable.
+     *
+     * @param headerIcons 24x24 icon(s) to be displayed in the header
+     */
+    public ResourceSearchView(String locatorId, Criteria criteria, String title, SortSpecifier[] sortSpecifier,
+        String[] excludeFields, boolean exportable, String... headerIcons) {
+
+        super(locatorId, (null == title) ? DEFAULT_TITLE : title, criteria,
+            (null == sortSpecifier) ? DEFAULT_SORT_SPECIFIER : sortSpecifier, excludeFields);
+
+        this.exportable = exportable;
 
         for (String headerIcon : headerIcons) {
             addHeaderIcon(headerIcon);
@@ -309,7 +351,7 @@ public class ResourceSearchView extends Table {
     }
 
     private void addExportAction() {
-        addTableAction("Export",  MSG.common_button_reports_export(), new TableAction() {
+        addTableAction("Export", MSG.common_button_reports_export(), new TableAction() {
             @Override
             public boolean isEnabled(ListGridRecord[] selection) {
                 return true;


commit 076ffb39a33d57b6d42c331058f2551b1ebeb7bc
Author: Jay Shaughnessy <jshaughn at redhat.com>
Date:   Tue Aug 7 11:17:11 2012 -0400

    Add new scripting api module to eclipse source path

diff --git a/.classpath b/.classpath
index 443abde..0516dd7 100644
--- a/.classpath
+++ b/.classpath
@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
 	<classpathentry kind="src" path="modules/common/ant-bundle/src/main/java"/>
+	<classpathentry kind="src" path="modules/enterprise/scripting/api/src/main/java"/>
 	<classpathentry kind="src" path="modules/cli-tests/src/main/java"/>
 	<classpathentry kind="src" path="modules/helpers/jeeGen/src/main/java"/>
 	<classpathentry kind="src" path="modules/helpers/bundleGen/src/main/java"/>


commit 00b1ee491e609c660113866e834668d0c1c6f3bc
Author: Simeon Pinder <spinder at fulliautomatix.conchfritter.com>
Date:   Tue Aug 7 11:05:07 2012 -0400

     [BZ 839552] passed in the wrong configuration when overriding behavior for SecurityDomain as7 nodes.

diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ModuleOptionsComponent.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ModuleOptionsComponent.java
index d486542..a4dccd0 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ModuleOptionsComponent.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ModuleOptionsComponent.java
@@ -474,7 +474,7 @@ public class ModuleOptionsComponent extends BaseComponent implements Configurati
     public void updateResourceConfiguration(ConfigurationUpdateReport report) {
         //determine the component
         ResourceType resourceType = context.getResourceType();
-        ConfigurationDefinition configDef = resourceType.getPluginConfigurationDefinition();
+        ConfigurationDefinition configDef = context.getResourceType().getResourceConfigurationDefinition();
         Set<ResourceType> nodeParentTypes = context.getResourceType().getParentResourceTypes();
         ResourceType parentType = (ResourceType) nodeParentTypes.toArray()[0];
         ResourceType grandParentType = (ResourceType) parentType.getParentResourceTypes().toArray()[0];


commit 153be59c5228bfe4e63657da405d30b5bdb6b423
Author: Lukas Krejci <lkrejci at redhat.com>
Date:   Tue Aug 7 15:54:18 2012 +0200

    [BZ 846269] - AS5's shutdown operation doesn't require availability to be up.

diff --git a/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/ApplicationServerOperationsDelegate.java b/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/ApplicationServerOperationsDelegate.java
index 5ac0413..60fa42d 100644
--- a/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/ApplicationServerOperationsDelegate.java
+++ b/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/ApplicationServerOperationsDelegate.java
@@ -54,6 +54,29 @@ import org.rhq.core.system.SystemInfo;
  * @author Jay Shaughnessy
  */
 public class ApplicationServerOperationsDelegate {
+    
+    private static class ExecutionFailedException extends Exception {
+
+        private static final long serialVersionUID = 1L;
+
+        @SuppressWarnings("unused")
+        public ExecutionFailedException() {
+        }
+
+        public ExecutionFailedException(String message, Throwable cause) {
+            super(message, cause);
+        }
+
+        public ExecutionFailedException(String message) {
+            super(message);
+        }
+
+        @SuppressWarnings("unused")
+        public ExecutionFailedException(Throwable cause) {
+            super(cause);
+        }       
+    }
+    
     /**
      * max amount of time to wait for server to show as unavailable after
      * executing stop - in milliseconds
@@ -303,28 +326,30 @@ public class ApplicationServerOperationsDelegate {
      * @return The result of the shutdown operation - is successful
      */
     private OperationResult shutDown() {
-        AvailabilityType avail = this.serverComponent.getAvailability();
-        if (avail == AvailabilityType.DOWN) {
-            OperationResult result = new OperationResult();
-            result.setErrorMessage("The server is already shut down.");
-            return result;
-        }
-
         Configuration pluginConfig = serverComponent.getResourceContext().getPluginConfiguration();
         ApplicationServerShutdownMethod shutdownMethod = Enum.valueOf(ApplicationServerShutdownMethod.class,
             pluginConfig.getSimple(ApplicationServerPluginConfigurationProperties.SHUTDOWN_METHOD_CONFIG_PROP)
                 .getStringValue());
-        String resultMessage = ApplicationServerShutdownMethod.JMX.equals(shutdownMethod) ? shutdownViaJmx()
-            : shutdownViaScript();
-
-        avail = waitForServerToShutdown();
+        String errorMessage = null;
+        String resultMessage = null;
+        try {
+            resultMessage = ApplicationServerShutdownMethod.JMX.equals(shutdownMethod) ? shutdownViaJmx()
+                : shutdownViaScript();
+        } catch (ExecutionFailedException e) {
+            errorMessage = e.getMessage();
+        }
+        
+        AvailabilityType avail = waitForServerToShutdown();
         OperationResult result;
         if (avail == AvailabilityType.UP) {
             result = new OperationResult();
             result.setErrorMessage("The server failed to shut down.");
         } else {
-            return new OperationResult(resultMessage);
+            result = new OperationResult();
+            result.setSimpleResult(resultMessage);
+            result.setErrorMessage(errorMessage);
         }
+        
         return result;
     }
 
@@ -333,7 +358,7 @@ public class ApplicationServerOperationsDelegate {
      *
      * @return success message if no errors are encountered
      */
-    private String shutdownViaScript() {
+    private String shutdownViaScript() throws ExecutionFailedException {
         File shutdownScriptFile = getShutdownScriptPath();
         validateScriptFile(shutdownScriptFile,
             ApplicationServerPluginConfigurationProperties.SHUTDOWN_SCRIPT_CONFIG_PROP);
@@ -378,8 +403,8 @@ public class ApplicationServerOperationsDelegate {
         logExecutionResults(results);
 
         if (results.getError() != null) {
-            throw new RuntimeException("Error executing shutdown script while stopping AS instance. Exit code ["
-                + results.getExitCode() + "]", results.getError());
+            throw new ExecutionFailedException("Error executing shutdown script while stopping AS instance. Exit code ["
+                + results.getExitCode() + "]: " + results.getError().getMessage(), results.getError());
         }
 
         return "The server has been shut down.";
@@ -397,7 +422,7 @@ public class ApplicationServerOperationsDelegate {
      *
      * @return success message if no errors are encountered
      */
-    private String shutdownViaJmx() {
+    private String shutdownViaJmx() throws ExecutionFailedException {
         Configuration pluginConfig = serverComponent.getResourceContext().getPluginConfiguration();
         String mbeanName = pluginConfig.getSimple(
             ApplicationServerPluginConfigurationProperties.SHUTDOWN_MBEAN_CONFIG_PROP).getStringValue();
@@ -406,7 +431,7 @@ public class ApplicationServerOperationsDelegate {
 
         EmsConnection connection = this.serverComponent.getEmsConnection();
         if (connection == null) {
-            throw new RuntimeException("Can not connect to the server");
+            throw new ExecutionFailedException("Can not connect to the server");
         }
         EmsBean bean = connection.getBean(mbeanName);
         EmsOperation operation = bean.getOperation(operationName);
@@ -422,14 +447,18 @@ public class ApplicationServerOperationsDelegate {
          * method, we'd need a clever way for the user to specify parameters
          * anyway.
          */
-        List<EmsParameter> params = operation.getParameters();
-        int count = params.size();
-        if (count == 0)
-            operation.invoke(new Object[0]);
-        else { // overloaded operation
-            operation.invoke(new Object[] { 0 }); // return code of 0
+        try {
+            List<EmsParameter> params = operation.getParameters();
+            int count = params.size();
+            if (count == 0)
+                operation.invoke(new Object[0]);
+            else { // overloaded operation
+                operation.invoke(new Object[] { 0 }); // return code of 0
+            }
+        } catch (RuntimeException e) {
+            throw new ExecutionFailedException("Shutting down the server using JMX failed: " + e.getMessage(), e);
         }
-
+        
         return "The server has been shut down.";
     }
 
diff --git a/modules/plugins/jboss-as-5/src/test/java/org/rhq/plugins/jbossas5/itest/ApplicationServerComponentTest.java b/modules/plugins/jboss-as-5/src/test/java/org/rhq/plugins/jbossas5/itest/ApplicationServerComponentTest.java
index 2bc7f47..6d60b85 100644
--- a/modules/plugins/jboss-as-5/src/test/java/org/rhq/plugins/jbossas5/itest/ApplicationServerComponentTest.java
+++ b/modules/plugins/jboss-as-5/src/test/java/org/rhq/plugins/jbossas5/itest/ApplicationServerComponentTest.java
@@ -24,6 +24,8 @@ package org.rhq.plugins.jbossas5.itest;
 
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
 
 import java.io.File;
 import java.util.Arrays;
@@ -50,6 +52,7 @@ import org.rhq.core.pc.inventory.InventoryManager;
 import org.rhq.core.pc.inventory.ResourceContainer;
 import org.rhq.core.pluginapi.configuration.ListPropertySimpleWrapper;
 import org.rhq.core.pluginapi.configuration.MapPropertySimpleWrapper;
+import org.rhq.core.pluginapi.operation.OperationResult;
 import org.rhq.core.pluginapi.util.FileUtils;
 import org.rhq.core.pluginapi.util.StartScriptConfiguration;
 import org.rhq.core.system.ProcessInfo;
@@ -197,9 +200,32 @@ public class ApplicationServerComponentTest extends AbstractJBossAS5PluginTest {
         avail = getAvailability(getServerResource());
         assertEquals(avail, AvailabilityType.DOWN);
 
+        //change the plugin config to shutdown via JMX
+        Configuration pluginConfig = getServerResource().getPluginConfiguration();
+        pluginConfig.getSimple("shutdownMethod").setValue("JMX");
+        restartServerResourceComponent();
+        
+        //invoke the shutdown operation again and assert that it actually ran and generated some error message.
+        OperationResult operationResult = invokeOperation(getServerResource(), SHUTDOWN_OPERATION_NAME, null);
+        avail = getAvailability(getServerResource());        
+        assertEquals(avail, AvailabilityType.DOWN);
+        assertNotNull(operationResult.getErrorMessage());
+        
+        //ok, now try the same with the script shutdown method
+        pluginConfig = getServerResource().getPluginConfiguration();
+        pluginConfig.getSimple("shutdownMethod").setValue("SCRIPT");
+        restartServerResourceComponent();
+        
+        //invoke the shutdown operation again and assert that it actually ran
+        operationResult = invokeOperation(getServerResource(), SHUTDOWN_OPERATION_NAME, null);
+        avail = getAvailability(getServerResource());        
+        assertEquals(avail, AvailabilityType.DOWN);
+        assertNull(operationResult.getErrorMessage());
+        assertEquals(operationResult.getSimpleResult(), "The server has been shut down.");
+        
         // Before restarting it, add some stuff to the 'startScriptEnv' and 'startScriptArgs' props so we can verify
         // they are used correctly by the Start op.
-        Configuration pluginConfig = getServerResource().getPluginConfiguration();
+        pluginConfig = getServerResource().getPluginConfiguration();
         StartScriptConfiguration startScriptConfig = new StartScriptConfiguration(pluginConfig);
 
         // Add a var to the start script env.


commit 11f741ebd98c10d294e23d5f7174d12b67baea90
Author: Jay Shaughnessy <jshaughn at redhat.com>
Date:   Mon Aug 6 15:08:20 2012 -0400

    [Bug 828428 - org.rhq.enterprise.server.cloud.instance.CacheConsistencyManagerBean ERROR ORA-01795: maximum number of expressions in a list is 1000]
    This time the problem is 1000 or more agents on a server (with status <> 0).
    Batch the updates to avoid the Oracle limitation.

diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StatusManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StatusManagerBean.java
index dfd1990..9658dd1 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StatusManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StatusManagerBean.java
@@ -95,13 +95,28 @@ public class StatusManagerBean implements StatusManagerLocal {
         List<Integer> agentIds = selectQuery.getResultList();
 
         if (agentIds.size() > 0) {
-            /* 
-             * note: not worried about size of the in clause, because the number of
-             * agents per server will be reasonable, say, 50-150
-             */
-            Query updateQuery = entityManager.createNamedQuery(Agent.QUERY_UPDATE_CLEAR_STATUS_BY_IDS);
-            updateQuery.setParameter("agentIds", agentIds);
-            updateQuery.executeUpdate();
+
+            // handle the oracle 1000 member IN clause issue
+            final int ORACLE_BATCH_SIZE = 1000;
+
+            int numAgents = agentIds.size();
+            int batches = (numAgents / ORACLE_BATCH_SIZE) + 1;
+
+            // iterate over the agent ids when we have more than 1000 of them
+            for (int batch = 0; batch < batches; ++batch) {
+                int fromIndex = batch * ORACLE_BATCH_SIZE;
+                int toIndex = fromIndex + ORACLE_BATCH_SIZE;
+                if (toIndex > numAgents) // don't run over the end of the list
+                    toIndex = numAgents;
+                List<Integer> agentIdBatch = agentIds.subList(fromIndex, toIndex);
+
+                if (fromIndex == toIndex)
+                    continue;
+
+                Query updateQuery = entityManager.createNamedQuery(Agent.QUERY_UPDATE_CLEAR_STATUS_BY_IDS);
+                updateQuery.setParameter("agentIds", agentIdBatch);
+                int numUpdated = updateQuery.executeUpdate();
+            }
         }
 
         return agentIds;


commit b1867328cf3186d0c86a44b5296c1fbd1f48f1d8
Author: Richard Hensman <richard at onevisionconsulting.co.uk>
Date:   Thu Jul 19 21:44:44 2012 +0100

    Add support for monitoring Flash Recovery Areas to the Oracle plugin

diff --git a/modules/plugins/oracle/src/main/java/org/rhq/plugins/oracle/OracleFlashRecoveryAreaComponent.java b/modules/plugins/oracle/src/main/java/org/rhq/plugins/oracle/OracleFlashRecoveryAreaComponent.java
new file mode 100644
index 0000000..0446d7f
--- /dev/null
+++ b/modules/plugins/oracle/src/main/java/org/rhq/plugins/oracle/OracleFlashRecoveryAreaComponent.java
@@ -0,0 +1,83 @@
+/*
+ * 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.plugins.oracle;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.rhq.core.domain.measurement.AvailabilityType;
+import org.rhq.core.domain.measurement.MeasurementDataNumeric;
+import org.rhq.core.domain.measurement.MeasurementReport;
+import org.rhq.core.domain.measurement.MeasurementScheduleRequest;
+import org.rhq.core.pluginapi.measurement.MeasurementFacet;
+import org.rhq.core.util.jdbc.JDBCUtil;
+import org.rhq.plugins.database.AbstractDatabaseComponent;
+import org.rhq.plugins.database.DatabaseQueryUtility;
+
+/**
+ * Oracle Flash Recovery Area Component.
+ * 
+ * @author Richard Hensman
+ */
+public class OracleFlashRecoveryAreaComponent extends AbstractDatabaseComponent implements MeasurementFacet {
+
+    private static final String SQL_AVAILABLE = "SELECT COUNT(*) FROM v$recovery_file_dest WHERE name = ?";
+    private static final String SQL_VALUES =
+        "SELECT space_limit spaceLimit, space_used spaceUsed, space_reclaimable spaceReclaimable, number_of_files numberOfFiles, (space_used/space_limit) usedPercent " +
+        "FROM v$recovery_file_dest WHERE name = ?";
+
+
+    private static Log log = LogFactory.getLog(OracleFlashRecoveryAreaComponent.class);
+
+    public AvailabilityType getAvailability() {
+        PreparedStatement statement = null;
+        ResultSet resultSet = null;
+        try {
+            statement = getConnection().prepareStatement(SQL_AVAILABLE);
+            statement.setString(1, this.resourceContext.getResourceKey());
+            resultSet = statement.executeQuery();
+            if (resultSet.next() && (resultSet.getInt(1) == 1)) {
+                return AvailabilityType.UP;
+            }
+        } catch (SQLException e) {
+            log.debug("unable to query", e);
+        } finally {
+            JDBCUtil.safeClose(statement, resultSet);
+        }
+
+        return AvailabilityType.DOWN;
+    }
+
+    public void getValues(MeasurementReport report, Set<MeasurementScheduleRequest> metrics) throws Exception {
+        Map<String, Double> values = DatabaseQueryUtility.getNumericQueryValues(this, SQL_VALUES,
+                this.resourceContext.getResourceKey());
+        for (MeasurementScheduleRequest request : metrics) {
+            Double d = values.get(request.getName().toUpperCase(Locale.US));
+            if (d != null) {
+                report.addData(new MeasurementDataNumeric(request, d));
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/modules/plugins/oracle/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/oracle/src/main/resources/META-INF/rhq-plugin.xml
index 8ef56cb..d8606e1 100644
--- a/modules/plugins/oracle/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/oracle/src/main/resources/META-INF/rhq-plugin.xml
@@ -610,14 +610,31 @@
             <c:simple-property name="description" default="Oracle Tablespace"/>
          </plugin-configuration>
 
-         <!-- Space used in the tablespace (database blocks) -->
          <metric property="usedSpace" displayName="Used Space" description="Space used in the tablespace (database blocks)" displayType="summary"/>
-         <!-- Total size of the tablespace (database blocks) -->
          <metric property="totalSize" displayName="Total Size" description="Total size of the tablespace (database blocks)" displayType="summary"/>
-         <!-- Percentage of the tablespace used -->
          <metric property="usedPercent" displayName="Used Percent" description="Percentage of the tablespace used" displayType="summary" units="percentage"/>
 
       </service>
+      
+      <service name="Oracle Flash Recovery Areas"
+         discovery="org.rhq.plugins.database.CustomTableRowDiscoveryComponent"
+         class="org.rhq.plugins.oracle.OracleFlashRecoveryAreaComponent">
+
+         <plugin-configuration>
+            <c:simple-property name="table" default="V$RECOVERY_FILE_DEST"/>
+            <c:simple-property name="metricQuery" default="SELECT {key} FROM V$RECOVERY_FILE_DEST"/>
+            <c:simple-property name="keyColumn" default="name"/>
+            <c:simple-property name="name" default="{key}"/>
+            <c:simple-property name="description" default="Oracle Flash Recovery Areas"/>
+         </plugin-configuration>
+
+         <metric property="spaceLimit" displayName="Space Limit" description="Flash Recovery Area space limit (database blocks)" displayType="summary"/>
+         <metric property="spaceUsed" displayName="Space Used" description="Space used in the Flash Recovery Area (database blocks)" displayType="summary"/>
+         <metric property="spaceReclaimable" displayName="Space Reclaimable" description="Space reclaimable in the Flash Recovery Area (database blocks)" displayType="summary"/>
+         <metric property="numberOfFiles" displayName="Number Of Files" description="Number of files in the Flash Recovery Area" displayType="summary"/>
+         <metric property="usedPercent" displayName="Used Percent" description="Percentage of the Flash Recovery Area used" displayType="summary" units="percentage"/>
+
+      </service>
 
    </server>
 


commit 9726761caf702f5a53f33ef2d957a84e55953196
Author: Richard Hensman <richard at onevisionconsulting.co.uk>
Date:   Wed Jul 18 15:09:10 2012 +0100

    Add support for monitoring table spaces to the Oracle plugin

diff --git a/modules/plugins/oracle/src/main/java/org/rhq/plugins/oracle/OracleTablespaceComponent.java b/modules/plugins/oracle/src/main/java/org/rhq/plugins/oracle/OracleTablespaceComponent.java
new file mode 100644
index 0000000..e99787b
--- /dev/null
+++ b/modules/plugins/oracle/src/main/java/org/rhq/plugins/oracle/OracleTablespaceComponent.java
@@ -0,0 +1,83 @@
+/*
+ * 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.plugins.oracle;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.rhq.core.domain.measurement.AvailabilityType;
+import org.rhq.core.domain.measurement.MeasurementDataNumeric;
+import org.rhq.core.domain.measurement.MeasurementReport;
+import org.rhq.core.domain.measurement.MeasurementScheduleRequest;
+import org.rhq.core.pluginapi.measurement.MeasurementFacet;
+import org.rhq.core.util.jdbc.JDBCUtil;
+import org.rhq.plugins.database.AbstractDatabaseComponent;
+import org.rhq.plugins.database.DatabaseQueryUtility;
+
+/**
+ * Oracle Tablespace Component.
+ * 
+ * @author Richard Hensman
+ */
+public class OracleTablespaceComponent extends AbstractDatabaseComponent implements MeasurementFacet {
+
+    private static final String SQL_AVAILABLE = "SELECT COUNT(*) FROM dba_tablespaces WHERE tablespace_name = ?";
+    private static final String SQL_VALUES =
+        "SELECT USED_SPACE usedSpace, TABLESPACE_SIZE totalSize, (USED_PERCENT/100) usedPercent " +
+        "FROM dba_tablespace_usage_metrics where tablespace_name = ?";
+
+
+    private static Log log = LogFactory.getLog(OracleTablespaceComponent.class);
+
+    public AvailabilityType getAvailability() {
+        PreparedStatement statement = null;
+        ResultSet resultSet = null;
+        try {
+            statement = getConnection().prepareStatement(SQL_AVAILABLE);
+            statement.setString(1, this.resourceContext.getResourceKey());
+            resultSet = statement.executeQuery();
+            if (resultSet.next() && (resultSet.getInt(1) == 1)) {
+                return AvailabilityType.UP;
+            }
+        } catch (SQLException e) {
+            log.debug("unable to query", e);
+        } finally {
+            JDBCUtil.safeClose(statement, resultSet);
+        }
+
+        return AvailabilityType.DOWN;
+    }
+
+    public void getValues(MeasurementReport report, Set<MeasurementScheduleRequest> metrics) throws Exception {
+        Map<String, Double> values = DatabaseQueryUtility.getNumericQueryValues(this, SQL_VALUES,
+                this.resourceContext.getResourceKey());
+        for (MeasurementScheduleRequest request : metrics) {
+            Double d = values.get(request.getName().toUpperCase(Locale.US));
+            if (d != null) {
+                report.addData(new MeasurementDataNumeric(request, d));
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/modules/plugins/oracle/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/oracle/src/main/resources/META-INF/rhq-plugin.xml
index 00f0284..8ef56cb 100644
--- a/modules/plugins/oracle/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/oracle/src/main/resources/META-INF/rhq-plugin.xml
@@ -593,8 +593,29 @@
             <c:simple-property name="description" default="Oracle User"/>
          </plugin-configuration>
 
-          <metric property="connections" displayName="Total Connections" displayType="summary"/>
-          <metric property="active" displayName="Active Connections" displayType="summary"/>
+         <metric property="connections" displayName="Total Connections" displayType="summary"/>
+         <metric property="active" displayName="Active Connections" displayType="summary"/>
+
+      </service>
+
+      <service name="Oracle Tablespaces"
+         discovery="org.rhq.plugins.database.CustomTableRowDiscoveryComponent"
+         class="org.rhq.plugins.oracle.OracleTablespaceComponent">
+
+         <plugin-configuration>
+            <c:simple-property name="table" default="DBA_TABLESPACES"/>
+            <c:simple-property name="metricQuery" default="SELECT {key} FROM DBA_TABLESPACES"/>
+            <c:simple-property name="keyColumn" default="tablespace_name"/>
+            <c:simple-property name="name" default="{key}"/>
+            <c:simple-property name="description" default="Oracle Tablespace"/>
+         </plugin-configuration>
+
+         <!-- Space used in the tablespace (database blocks) -->
+         <metric property="usedSpace" displayName="Used Space" description="Space used in the tablespace (database blocks)" displayType="summary"/>
+         <!-- Total size of the tablespace (database blocks) -->
+         <metric property="totalSize" displayName="Total Size" description="Total size of the tablespace (database blocks)" displayType="summary"/>
+         <!-- Percentage of the tablespace used -->
+         <metric property="usedPercent" displayName="Used Percent" description="Percentage of the tablespace used" displayType="summary" units="percentage"/>
 
       </service>
 


commit 5b37f7a17ef64863a810a5b92cbf885eca05dda3
Author: John Sanda <jsanda at redhat.com>
Date:   Mon Aug 6 12:38:46 2012 -0400

    [BZ 838861] Handle empty zip file on java 7
    
    Since an exception is not thrown when closing a ZipOutputStream on an
    empty zip file in Java 7, I have added logic to check whether or not the
    zip file has any content. sendChangeSetContentToServer is called only if
    the content file is non-empty. The logging logic has been updated as
    well so that we only log an error message when failing to close the
    output stream only when the content file is non-empty. This keeps the
    logging clean and consistent across Java 6 and 7.

diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftFilesSender.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftFilesSender.java
index 59d3054..266b666 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftFilesSender.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftFilesSender.java
@@ -1,20 +1,25 @@
 package org.rhq.core.pc.drift;
 
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+
 import org.rhq.common.drift.ChangeSetReader;
 import org.rhq.common.drift.FileEntry;
 import org.rhq.common.drift.Headers;
 import org.rhq.core.domain.drift.DriftFile;
 import org.rhq.core.util.stream.StreamUtil;
 
-import java.io.*;
-import java.util.List;
-import java.util.Map;
-import java.util.TreeMap;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipOutputStream;
-
 public class DriftFilesSender implements Runnable {
 
     private Log log = LogFactory.getLog(DriftFilesSender.class);
@@ -52,6 +57,7 @@ public class DriftFilesSender implements Runnable {
     @Override
     public void run() {
         ZipOutputStream stream = null;
+        int numContentFiles = 0;
         try {
             if (log.isInfoEnabled()) {
                 log.info("Preparing to send content to server for " + defToString());
@@ -89,6 +95,7 @@ public class DriftFilesSender implements Runnable {
                         log.debug("Adding " + file.getPath() + " to " + contentFileName);
                     }
                     addFileToContentZipFile(stream, driftFile, file);
+                    ++numContentFiles;
                 }
             } else {
                 Map<String, FileEntry> fileEntries = createSnapshotIndex();
@@ -106,15 +113,18 @@ public class DriftFilesSender implements Runnable {
                             log.debug("Adding " + file.getPath() + " to " + contentFileName);
                         }
                         addFileToContentZipFile(stream, driftFile, file);
+                        ++numContentFiles;
                     }
                 }
             }
 
+            if (numContentFiles > 0) {
+                driftClient.sendChangeSetContentToServer(resourceId, headers.getDriftDefinitionName(), zipFile);
+            }
+
             stream.close();
             stream = null;
 
-            driftClient.sendChangeSetContentToServer(resourceId, headers.getDriftDefinitionName(), zipFile);
-
             if (log.isInfoEnabled()) {
                 long endTime = System.currentTimeMillis();
                 log.info("Finished submitting request to send content to server in " + (endTime - startTime) +
@@ -122,7 +132,19 @@ public class DriftFilesSender implements Runnable {
             }
 
         } catch (IOException e) {
-            log.error("Failed to send drift files.", e);
+            if (numContentFiles > 0) {
+                // Only log an error message if the content zip file is not empty. With
+                // Java 6, closing an empty ZipOutputStream causes an exception which we
+                // can ignore. On Java 7 however, no exception is thrown when closing an
+                // empty ZipOutputStream. This check keeps the error reporting logic
+                // consistent across Java 6 and 7 such that we only log an error message
+                // when we fail to close the output stream when the content zip file is
+                // not empty. See https://bugzilla.redhat.com/show_bug.cgi?id=838681 for
+                // more info.
+                //
+                // jsanda
+                log.error("Failed to send drift files.", e);
+            }
         } finally {
             if (stream != null) {
                 try {


commit 0aeaf8e9f71ea154e2421e67e29269eea33b762c
Author: mtho11 <mikecthompson at gmail.com>
Date:   Fri Aug 3 15:02:56 2012 -0700

    [BZ 826224 Creation of Compatible Group fails with value too long for type character when a description is entered which is longer then 100 characters] Group names limited now to 100 chars to match DB.

diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/wizard/GroupCreateStep.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/wizard/GroupCreateStep.java
index ee49f4e..143c159 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/wizard/GroupCreateStep.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/wizard/GroupCreateStep.java
@@ -75,6 +75,7 @@ public class GroupCreateStep extends AbstractWizardStep {
             TextItem name = new TextItem("name", MSG.common_title_name());
             name.setRequired(true);
             name.setWidth(300);
+            name.setLength(100);
             name.addChangedHandler(new ChangedHandler() {
                 @Override
                 public void onChanged(ChangedEvent changedEvent) {


commit 970715c3f73d18c6ecd3696b8970f6782fea49fa
Author: Mike Thompson <mithomps at redhat.com>
Date:   Fri Aug 3 07:28:36 2012 -0700

    [BZ 841045 advisoryInfo-plain.xhtml is missing parameters on the repo-plain.xhtml link] applied patch from jlivings.

diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/advisoryInfo-plain.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/advisoryInfo-plain.xhtml
index c672d16..7590610 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/advisoryInfo-plain.xhtml
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/advisoryInfo-plain.xhtml
@@ -24,7 +24,10 @@
    <ui:define name="breadcrumbs">
       <h:outputLink value="listContentProviders-plain.xhtml">
          ${msg["contentprovider.list.breadcrumb"]}
+         <f:param name="mode" value="view" />
+         <f:param name="id" value="#{param.id}" />
       </h:outputLink>
+
       &gt;
       <h:outputLink value="repo-plain.xhtml">
          ${msg["repo.list.breadcrumb"]}


commit 63b805d29a7b66593203de5a006770adab06e105
Author: Mike Thompson <mithomps at redhat.com>
Date:   Wed Aug 1 20:00:29 2012 -0700

    [BZ 838665 - Changing selected operation does not clear out parameters sent along with request]

diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/operation/schedule/AbstractOperationScheduleDetailsView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/operation/schedule/AbstractOperationScheduleDetailsView.java
index c52eb30..8b26cb2 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/operation/schedule/AbstractOperationScheduleDetailsView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/operation/schedule/AbstractOperationScheduleDetailsView.java
@@ -193,6 +193,8 @@ public abstract class AbstractOperationScheduleDetailsView extends
         operationNameItem.setShowTitle(true);
         items.add(operationNameItem);
         operationNameItem.addChangedHandler(new ChangedHandler() {
+
+            @Override
             public void onChanged(ChangedEvent event) {
                 handleOperationNameChange();
             }
@@ -423,18 +425,15 @@ public abstract class AbstractOperationScheduleDetailsView extends
     private void refreshOperationParametersItem() {
         String operationName = getSelectedOperationName();
         String value;
+        operationParameters = null; // reset params between dropdown selects
+        // make sure we wipe out anything left by the previous op def
+        for (Canvas child : this.operationParametersConfigurationHolder.getChildren()) {
+            child.destroy();
+        }
         if (operationName == null) {
             value = "<i>" + MSG.view_operationScheduleDetails_fieldDefault_parameters() + "</i>";
-            for (Canvas child : this.operationParametersConfigurationHolder.getChildren()) {
-                child.destroy();
-            }
             this.operationParametersConfigurationHolder.hide();
         } else {
-            // make sure we wipe out anything left by the previous op def
-            for (Canvas child : this.operationParametersConfigurationHolder.getChildren()) {
-                child.destroy();
-            }
-
             final ConfigurationDefinition parametersDefinition = this.operationNameToParametersDefinitionMap
                 .get(operationName);
             if (parametersDefinition == null || parametersDefinition.getPropertyDefinitions().isEmpty()) {


commit 4f60260d2afe019943f23c64cdaf14f1f11c3d53
Author: Heiko W. Rupp <hwr at redhat.com>
Date:   Wed Aug 1 16:34:02 2012 -0400

    BZ 845118 provide delegates for the tow classes that were moved to util/ as other plugins may still rely on the old package structure.

diff --git a/modules/plugins/jmx/src/main/java/org/rhq/plugins/jmx/ObjectNameQueryUtility.java b/modules/plugins/jmx/src/main/java/org/rhq/plugins/jmx/ObjectNameQueryUtility.java
new file mode 100644
index 0000000..bc4b264
--- /dev/null
+++ b/modules/plugins/jmx/src/main/java/org/rhq/plugins/jmx/ObjectNameQueryUtility.java
@@ -0,0 +1,75 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 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.plugins.jmx;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.rhq.core.domain.configuration.Configuration;
+
+/**
+ * Delegate for the old version of the class which got moved to util package
+ * @author Heiko W. Rupp
+ * @deprecated Use the version in the util package
+ */
+public class ObjectNameQueryUtility {
+
+    private org.rhq.plugins.jmx.util.ObjectNameQueryUtility onu;
+
+    public ObjectNameQueryUtility(String objectNameQueryTemplate) {
+        onu = new org.rhq.plugins.jmx.util.ObjectNameQueryUtility(objectNameQueryTemplate);
+    }
+
+    public ObjectNameQueryUtility(String objectNameQueryTemplate, Configuration parentConfiguration) {
+        onu = new org.rhq.plugins.jmx.util.ObjectNameQueryUtility(objectNameQueryTemplate,parentConfiguration);
+    }
+
+    public boolean setMatchedKeyValues(Map<String, String> keyProperties) {
+        return onu.setMatchedKeyValues(keyProperties);
+    }
+
+    public String formatMessage(String message) {
+        return onu.formatMessage(message);
+    }
+
+    public void resetVariables() {
+        onu.resetVariables();
+    }
+
+    public String getQueryTemplate() {
+        return onu.getQueryTemplate();
+    }
+
+    public Map<String, String> getVariableProperties() {
+        return onu.getVariableProperties();
+    }
+
+    public Map<String, String> getVariableValues() {
+        return onu.getVariableValues();
+    }
+
+    public String getTranslatedQuery() {
+        return onu.getTranslatedQuery();
+    }
+
+    public boolean isContainsExtraKeyProperties(Set<String> strings) {
+        return onu.isContainsExtraKeyProperties(strings);
+    }
+}
diff --git a/modules/plugins/jmx/src/main/java/org/rhq/plugins/jmx/ParentDefinedJMXServerNamingUtility.java b/modules/plugins/jmx/src/main/java/org/rhq/plugins/jmx/ParentDefinedJMXServerNamingUtility.java
new file mode 100644
index 0000000..fccb0ab
--- /dev/null
+++ b/modules/plugins/jmx/src/main/java/org/rhq/plugins/jmx/ParentDefinedJMXServerNamingUtility.java
@@ -0,0 +1,40 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 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.plugins.jmx;
+
+import org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext;
+
+/**
+ * Delegate for the original version of this
+ * class that got moved to util/
+ * @deprecated Use the version of the class in the util Package
+ * @see org.rhq.plugins.jmx.util.ParentDefinedJMXServerNamingUtility
+ * @author Heiko W. Rupp
+ */
+ at Deprecated
+public class ParentDefinedJMXServerNamingUtility {
+    public static final String PROPERTY_CHILD_JMX_SERVER_NAME = "childJmxServerName";
+
+    /** @deprecated use the version in util package instead */
+    @Deprecated
+    public static String getJVMName(ResourceDiscoveryContext<?> context) {
+        return org.rhq.plugins.jmx.util.ParentDefinedJMXServerNamingUtility.getJVMName(context);
+    }
+}
diff --git a/modules/plugins/jmx/src/test/java/org/rhq/plugins/jmx/test/ObjectNameQueryUtilityDelegateTest.java b/modules/plugins/jmx/src/test/java/org/rhq/plugins/jmx/test/ObjectNameQueryUtilityDelegateTest.java
new file mode 100644
index 0000000..58d11a1
--- /dev/null
+++ b/modules/plugins/jmx/src/test/java/org/rhq/plugins/jmx/test/ObjectNameQueryUtilityDelegateTest.java
@@ -0,0 +1,106 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 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.plugins.jmx.test;
+
+import java.util.Collections;
+
+import javax.management.MalformedObjectNameException;
+import javax.management.ObjectName;
+
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.PropertySimple;
+import org.rhq.plugins.jmx.ObjectNameQueryUtility;
+
+/**
+ * This test explicitly tests the delegate for the ObjectNameQueryUtility.
+ * The Utility itself got moved into the util package. To be backward compatible,
+ * we need to have a delegate
+ */
+public class ObjectNameQueryUtilityDelegateTest {
+    @Test
+    public void testObjectNameQueryUtility() throws MalformedObjectNameException {
+        ObjectNameQueryUtility onqu = null;
+        onqu = new ObjectNameQueryUtility("java.lang:type=MemoryPool,name=Code Cache");
+        assert onqu.getQueryTemplate().equals("java.lang:type=MemoryPool,name=Code Cache");
+
+        onqu = new ObjectNameQueryUtility("java.lang:type=MemoryPool,name=%name%");
+        assert onqu.getTranslatedQuery().equals("java.lang:type=MemoryPool,*");
+        assert onqu.getVariableProperties().size() == 1;
+        assert onqu.getVariableProperties().get("name").equals("name");
+
+        onqu = new ObjectNameQueryUtility("java.lang:type=Threading");
+
+        onqu = new ObjectNameQueryUtility("java.lang:type=%foo%");
+        assert onqu.getTranslatedQuery().equals("java.lang:*");
+        assert onqu.getVariableProperties().size() == 1;
+        assert onqu.getVariableProperties().get("type").equals("foo");
+
+        onqu = new ObjectNameQueryUtility("jboss.esb.*:service=Queue,name=%name%");
+        assert onqu.getTranslatedQuery().equals("jboss.esb.*:service=Queue,*");
+        assert onqu.getVariableProperties().size() == 1;
+        assert onqu.getVariableProperties().get("name").equals("name");
+        ObjectName testON = new ObjectName(
+            "jboss.esb.quickstart.destination:service=Queue,name=quickstart_helloworld_Request_gw");
+        onqu.setMatchedKeyValues(testON.getKeyPropertyList());
+        String formulatedMessageTemplate = "Name of queue: {name}";
+        assert onqu.formatMessage(formulatedMessageTemplate).equals("Name of queue: quickstart_helloworld_Request_gw");
+
+        onqu = new ObjectNameQueryUtility("java.lang:type=%MyType%,name=%MyName%,app=%MyApp%,foo=%MyFoo%");
+        assert onqu.getTranslatedQuery().equals("java.lang:*");
+        assert onqu.getVariableProperties().size() == 4;
+        testON = new ObjectName("java.lang:type=A,name=B,app=C,foo=D");
+        onqu.setMatchedKeyValues(testON.getKeyPropertyList());
+        formulatedMessageTemplate = "Type: {MyType}, Name: {MyName}, App: {MyApp}, Foo: {MyFoo}";
+        assert onqu.formatMessage(formulatedMessageTemplate).equals("Type: A, Name: B, App: C, Foo: D");
+
+        Configuration c = new Configuration();
+        c.put(new PropertySimple("e", "foo"));
+        c.put(new PropertySimple("g", "bar"));
+        onqu = new ObjectNameQueryUtility("a:b=c,d={e},f={g}", c);
+        System.out.println("Template: " + onqu.getQueryTemplate());
+        assert onqu.getQueryTemplate().equals("a:b=c,d=foo,f=bar");
+
+        // Test some very long replacement tokens inspired by BZ 828596
+        onqu = new ObjectNameQueryUtility("*:type=HttpMetricInspector,name=%name%");
+        assert onqu.getQueryTemplate().equals("*:type=HttpMetricInspector,name=%name%");
+        assert onqu.getVariableProperties().size() == 1;
+        assert onqu.getVariableProperties().get("name").equals("name");
+        testON = new ObjectName("FooBarABCDEFGHIJKLMNOPQRSTUVWXYZ:type=HttpMetricInspector,name=ABCDEFGHIJKLMNOPQRSTUVWXYZöABCDEFGHIJKLMNOPQRSTUVWXYZ");
+        onqu.setMatchedKeyValues(testON.getKeyPropertyList());
+        formulatedMessageTemplate = "Http metrics for endpoint {name}";
+        String res = onqu.formatMessage(formulatedMessageTemplate);
+        assert res.equals("Http metrics for endpoint ABCDEFGHIJKLMNOPQRSTUVWXYZöABCDEFGHIJKLMNOPQRSTUVWXYZ") : res;
+
+
+    }
+
+    @Test
+    public void testObjectNameQueryUtilityFiltering() throws MalformedObjectNameException {
+        ObjectNameQueryUtility onqu = null;
+
+        onqu = new ObjectNameQueryUtility("java.lang:type=MemoryPool,name=%foo%");
+        assert !onqu.isContainsExtraKeyProperties(Collections.singleton("type"));
+        assert !onqu.isContainsExtraKeyProperties(Collections.singleton("name"));
+        assert onqu.isContainsExtraKeyProperties(Collections.singleton("splat"));
+
+    }
+
+}
\ No newline at end of file


commit a9a655c1b1ff04330ef75e7a7c9456b88bd0ad56
Author: Mike Thompson <mithomps at redhat.com>
Date:   Tue Jul 31 09:07:55 2012 -0700

    [BZ 733487 New SearchBar] Handle null search condition better.

diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/BasicSearchStrategy.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/BasicSearchStrategy.java
index 5409248..f56c81e 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/BasicSearchStrategy.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/BasicSearchStrategy.java
@@ -163,7 +163,7 @@ public class BasicSearchStrategy extends AbstractSearchStrategy {
                     .getValueAsString().length());
         } else {
             Log.debug("Empty Search expression");
-            getTabAwareSearchSuggestions(SearchSubsystem.RESOURCE, "", 0);
+            getTabAwareSearchSuggestions(SearchSubsystem.RESOURCE, null, 0);
         }
     }
 
@@ -175,7 +175,7 @@ public class BasicSearchStrategy extends AbstractSearchStrategy {
     private void getTabAwareSearchSuggestions(final SearchSubsystem searchSubsystem, final String expression,
         int caretPosition) {
 
-        if (expression.equals(lastExpression)) {
+        if (null != expression && expression.equals(lastExpression)) {
             // short-circuit if we dont really need to do a search
             Log.debug("search tab aware Suggestions: ignoring duplicate search for: " + expression);
             return;
@@ -193,7 +193,7 @@ public class BasicSearchStrategy extends AbstractSearchStrategy {
                     ComboBoxItem comboBox = searchBar.getSearchComboboxItem();
 
                     // If the value has already changed assume a subsequent search is what they want
-                    if (!expression.equals(comboBox.getValueAsString())) {
+                    if (null != expression && !expression.equals(comboBox.getValueAsString())) {
                         Log.debug("search tab aware Suggestions: ignoring obsolete results for: " + expression);
                         return;
                     }


commit 412f7ac30c6e395d56f86b3ab434452681d82277
Author: John Mazzitelli <mazz at redhat.com>
Date:   Tue Jul 31 10:19:26 2012 -0400

    fix the versions to mimic the actual version strings in the distros

diff --git a/modules/core/util/src/test/java/org/apache/maven/artifact/versioning/ComparableVersionTest.java b/modules/core/util/src/test/java/org/apache/maven/artifact/versioning/ComparableVersionTest.java
index 2e81763..6a390765 100644
--- a/modules/core/util/src/test/java/org/apache/maven/artifact/versioning/ComparableVersionTest.java
+++ b/modules/core/util/src/test/java/org/apache/maven/artifact/versioning/ComparableVersionTest.java
@@ -39,7 +39,6 @@ public class ComparableVersionTest {
         RHQ_VERSIONS.add("4.4.0.RC1");
         RHQ_VERSIONS.add("4.4.0.RC2");
         RHQ_VERSIONS.add("4.4.0.GA");
-        RHQ_VERSIONS.add("4.4.1.GA");
     }
 
     private static List<String> JON_VERSIONS = new ArrayList<String>();
@@ -52,7 +51,7 @@ public class ComparableVersionTest {
         JON_VERSIONS.add("4.4.0.JON310BETA1");
         JON_VERSIONS.add("4.4.0.JON310CR1");
         JON_VERSIONS.add("4.4.0.JON310GA");
-        JON_VERSIONS.add("4.4.1.JON311GA");
+        JON_VERSIONS.add("4.4.0.JON311GA");
     }
 
     public void testRHQVersions() {


commit b49d9d3dd66056bee9fc58f8a4084f6f62487da4
Author: Mike Thompson <mithomps at redhat.com>
Date:   Mon Jul 30 20:51:25 2012 -0700

    [BZ 733487 New SearchBar] Fixed bug with return key in search bar not properly sending search. Added i18n.

diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/BasicSearchStrategy.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/BasicSearchStrategy.java
index cf40099..5409248 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/BasicSearchStrategy.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/BasicSearchStrategy.java
@@ -138,32 +138,33 @@ public class BasicSearchStrategy extends AbstractSearchStrategy {
     public void searchFocusHandler(FocusEvent event) {
         Log.debug("focus in BasicSearchStrategy");
         String searchExpression = searchBar.getSearchComboboxItem().getValueAsString();
-        if (null != searchExpression && searchExpression.length() > 0) {
-            getTabAwareSearchSuggestions(SearchSubsystem.RESOURCE,
-                searchBar.getSearchComboboxItem().getValueAsString(), searchBar.getSearchComboboxItem()
-                    .getValueAsString().length());
-        } else {
-            getTabAwareSearchSuggestions(SearchSubsystem.RESOURCE, "", 0);
-        }
+        doSearch(searchExpression);
     }
 
+
+
     @Override
     public void searchKeyUpHandler(KeyUpEvent keyUpEvent) {
         Log.debug("Keyup in BasicSearchStrategy: " + keyUpEvent.getKeyName());
         String searchExpression = searchBar.getSearchComboboxItem().getValueAsString();
+        doSearch(searchExpression);
+
+    }
+
+    @Override
+    public void searchReturnKeyHandler(KeyUpEvent keyUpEvent) {
+        doSearch((String)keyUpEvent.getItem().getValue());
+    }
+
+    private void doSearch(String searchExpression) {
         if (null != searchExpression && searchExpression.length() > 0) {
             getTabAwareSearchSuggestions(SearchSubsystem.RESOURCE,
-                searchBar.getSearchComboboxItem().getValueAsString(), searchBar.getSearchComboboxItem()
+                    searchBar.getSearchComboboxItem().getValueAsString(), searchBar.getSearchComboboxItem()
                     .getValueAsString().length());
         } else {
+            Log.debug("Empty Search expression");
             getTabAwareSearchSuggestions(SearchSubsystem.RESOURCE, "", 0);
         }
-
-    }
-
-    @Override
-    public void searchReturnKeyHandler(KeyUpEvent keyUpEvent) {
-        // Do nothing here; standard Table.TableFilter will handle normally
     }
 
     @Override
@@ -171,10 +172,11 @@ public class BasicSearchStrategy extends AbstractSearchStrategy {
         return 25;
     }
 
-    private void getTabAwareSearchSuggestions(SearchSubsystem searchSubsystem, final String expression,
+    private void getTabAwareSearchSuggestions(final SearchSubsystem searchSubsystem, final String expression,
         int caretPosition) {
 
         if (expression.equals(lastExpression)) {
+            // short-circuit if we dont really need to do a search
             Log.debug("search tab aware Suggestions: ignoring duplicate search for: " + expression);
             return;
         }
@@ -182,9 +184,11 @@ public class BasicSearchStrategy extends AbstractSearchStrategy {
 
         final long suggestStart = System.currentTimeMillis();
 
+        Log.debug("Searching for: "+expression);
         searchService.getTabAwareSuggestions(searchSubsystem, expression, caretPosition, null,
             new AsyncCallback<List<SearchSuggestion>>() {
 
+                @Override
                 public void onSuccess(List<SearchSuggestion> results) {
                     ComboBoxItem comboBox = searchBar.getSearchComboboxItem();
 
@@ -235,8 +239,9 @@ public class BasicSearchStrategy extends AbstractSearchStrategy {
                     Log.debug(results.size() + " suggestions searches fetched in: " + suggestFetchTime + "ms");
                 }
 
+                @Override
                 public void onFailure(Throwable caught) {
-                    CoreGUI.getErrorHandler().handleError("Failed to retrieve search suggestion", caught);
+                    CoreGUI.getErrorHandler().handleError(MSG.search_failed_to_retrieve_search_suggestion(), caught);
                 }
 
             });
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/EnhancedSearchBar.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/EnhancedSearchBar.java
index e793f9f..c22ccd8 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/EnhancedSearchBar.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/EnhancedSearchBar.java
@@ -71,10 +71,10 @@ public class EnhancedSearchBar extends ToolStrip {
 
     private final SearchGWTServiceAsync searchService = GWTServiceLookup.getSearchService();
 
-    private static final List IGNORED_KEYS;
+    private static final List<String> IGNORED_KEYS;
 
     static {
-        IGNORED_KEYS = new ArrayList(2);
+        IGNORED_KEYS = new ArrayList<String>(2);
         IGNORED_KEYS.add("Arrow_Down");
         IGNORED_KEYS.add("Arrow_Up");
     }
@@ -253,13 +253,13 @@ public class EnhancedSearchBar extends ToolStrip {
             @Override
             public void onSuccess(Integer newSavedSearchId) {
                 currentSearchId = newSavedSearchId;
-                Message message = new Message("Successfully Saved Search: " + name, Message.Severity.Info);
+                Message message = new Message(MSG.search_successfully_saved_search(name),  Message.Severity.Info);
                 CoreGUI.getMessageCenter().notify(message);
             }
 
             @Override
             public void onFailure(Throwable caught) {
-                Message message = new Message("Failure to Save Search " + name, Message.Severity.Error);
+                Message message = new Message(MSG.search_failed_to_save_search(name), Message.Severity.Error);
                 CoreGUI.getMessageCenter().notify(message);
             }
         });
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/FavoritesSearchStrategy.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/FavoritesSearchStrategy.java
index a04a000..9cdffbd 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/FavoritesSearchStrategy.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/FavoritesSearchStrategy.java
@@ -102,16 +102,18 @@ public class FavoritesSearchStrategy extends AbstractSearchStrategy {
         Subject subject = UserSessionManager.getSessionSubject();
         savedSearchCriteria.addFilterSubjectId(subject.getId());
         savedSearchCriteria.setStrict(true);
-        final long start = System.currentTimeMillis();
+        final long startTime = System.currentTimeMillis();
 
         searchService.findSavedSearchesByCriteria(savedSearchCriteria, new AsyncCallback<List<SavedSearch>>() {
 
+            @Override
             public void onFailure(Throwable caught) {
                 CoreGUI.getErrorHandler().handleError(MSG.search_failed_to_retrieve_saved_search(), caught);
             }
 
+            @Override
             public void onSuccess(List<SavedSearch> result) {
-                long fetchTime = System.currentTimeMillis() - start;
+                long fetchTime = System.currentTimeMillis() - startTime;
                 Log.debug(result.size() + " saved searches fetched in: " + fetchTime + "ms");
 
                 DataSource dataSource = new DataSource();
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
index 2e371d9..a558db1 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
@@ -413,8 +413,11 @@ filter_from_date = From
 filter_to_date = To
 group_tree_groupOfResourceType = Group of [{0}]
 group_tree_partialClusterTooltip = {0} out of {1} group members have a ''{2}'' resource
+search_failed_to_save_search = Failed to Save Search: {0}
 search_failed_to_retrieve_saved_search = Failed to retrieve saved search
+search_failed_to_retrieve_search_suggestion = Failed to retrieve search suggestion
 search_name_your_search = name you search
+search_successfully_saved_search = Successfully Saved Search: {0}
 util_ancestry_parentAncestry = Parent Ancestry for:
 util_errorHandler_nullException = exception was null
 util_monitoringRequestCallback_error_checkServerStatusFailure = Unable to determine login status - check Server status.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
index 275fe4d..b146b3d 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
@@ -432,8 +432,11 @@ filter_from_date = Od
 filter_to_date = Do
 group_tree_groupOfResourceType = Skupina: [{0}]
 group_tree_partialClusterTooltip = {0} z {1} členů skupiny má "{2}" zdroj
+##search_failed_to_save_search = Failed to Save Search: {0}
 ##search_failed_to_retrieve_saved_search = Failed to retrieve saved search
+##search_failed_to_retrieve_search_suggestion = Failed to retrieve search suggestion
 ##search_name_your_search = name you search
+##search_successfully_saved_search = Successfully Saved Search: {0}
 util_ancestry_parentAncestry = Původ rodiče pro:
 util_errorHandler_nullException = výjimka byla null
 util_monitoringRequestCallback_error_checkServerStatusFailure = Nepodařilo se určit stav přihlašování - zkontrolujte stav serveru.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
index ddd07fd..7b9effe 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
@@ -397,8 +397,11 @@ filter_from_date = Von
 filter_to_date = Bis
 ##group_tree_groupOfResourceType = Group of [{0}]
 group_tree_partialClusterTooltip = {0} der {1} Gruppenmitglieder haben eine ''{2}'' Ressource
+##search_failed_to_save_search = Failed to Save Search: {0}
 ##search_failed_to_retrieve_saved_search = Failed to retrieve saved search
+##search_failed_to_retrieve_search_suggestion = Failed to retrieve search suggestion
 ##search_name_your_search = name you search
+##search_successfully_saved_search = Successfully Saved Search: {0}
 util_disambiguationReportDecorator_pluginSuffix = ({0} Plugin)
 util_errorHandler_nullException = Exception war null
 ##util_monitoringRequestCallback_error_checkServerStatusFailure = Unable to determine login status - check Server status.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
index 6eb5212..b7c191e 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
@@ -410,8 +410,11 @@ filter_from_date = 開始
 filter_to_date = 終了
 ##group_tree_groupOfResourceType = Group of [{0}]
 group_tree_partialClusterTooltip = {1} の中の {0} グループメンバーが ''{2}'' リソースを持っています
+##search_failed_to_save_search = Failed to Save Search: {0}
 ##search_failed_to_retrieve_saved_search = Failed to retrieve saved search
+##search_failed_to_retrieve_search_suggestion = Failed to retrieve search suggestion
 ##search_name_your_search = name you search
+##search_successfully_saved_search = Successfully Saved Search: {0}
 util_ancestry_parentAncestry = 親の先祖 :
 util_disambiguationReportDecorator_pluginSuffix = ({0} プラグイン)
 util_errorHandler_nullException = 例外は null でした
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
index 900b847..72b2f34 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
@@ -416,8 +416,11 @@ favorites_resources = Recursos Favoritos
 ##filter_to_date = To
 ##group_tree_groupOfResourceType = Group of [{0}]
 group_tree_partialClusterTooltip = {0} out of {1} group members have a ''{2}'' resource
+##search_failed_to_save_search = Failed to Save Search: {0}
 ##search_failed_to_retrieve_saved_search = Failed to retrieve saved search
+##search_failed_to_retrieve_search_suggestion = Failed to retrieve search suggestion
 ##search_name_your_search = name you search
+##search_successfully_saved_search = Successfully Saved Search: {0}
 util_ancestry_parentAncestry = Ancestral para:
 util_errorHandler_nullException = Exce\u00E7\u00E3o nula
 util_monitoringRequestCallback_error_checkServerStatusFailure = Imposs\u00EDvel verificar o status do login - verifique o status do Servidor.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
index 43abe46..5a44858 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
@@ -403,8 +403,11 @@
 #filter_from_date = From
 #filter_to_date = To
 #group_tree_partialClusterTooltip = {0} out of {1} group members have a ''{2}'' resource
+##search_failed_to_save_search = Failed to Save Search: {0}
 ##search_failed_to_retrieve_saved_search = Failed to retrieve saved search
-##search_name_your_search = name you search
+##search_failed_to_retrieve_search_suggestion = Failed to retrieve search suggestion
+##search_name_your_search = name you searci
+##search_successfully_saved_search = Successfully Saved Search: {0}
 #util_ancestry_parentAncestry = Parent Ancestry for:
 #util_errorHandler_nullException = exception was null
 #util_monitoringRequestCallback_error_checkServerStatusFailure = Unable to determine login status - check Server status.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
index 9f3fd76..6ae9e47 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
@@ -405,8 +405,11 @@ favorites_resources = \u8d44\u6e90\u6536\u85cf\u5939
 ##filter_to_date = To
 ##group_tree_groupOfResourceType = Group of [{0}]
 group_tree_partialClusterTooltip = \u9664\u53bb {1},{0}\u7684\u7ec4\u6210\u5458\u62e5\u6709 \u4e00\u4e2a''{2}''\u8d44\u6e90
+##search_failed_to_save_search = Failed to Save Search: {0}
 ##search_failed_to_retrieve_saved_search = Failed to retrieve saved search
+##search_failed_to_retrieve_search_suggestion = Failed to retrieve search suggestion
 ##search_name_your_search = name you search
+##search_successfully_saved_search = Successfully Saved Search: {0}
 util_ancestry_parentAncestry = Parent Ancestry for:
 util_errorHandler_nullException = \u5f02\u5e38\u662f null
 util_monitoringRequestCallback_error_checkServerStatusFailure = \u65e0\u6cd5\u786e\u5b9a\u767b\u5f55\u72b6\u6001- \u68c0\u67e5\u670d\u52a1\u5668\u72b6\u6001.


commit f4484a83507fa1f45ea18e5862dceb376efeda1c
Author: Lukas Krejci <lkrejci at redhat.com>
Date:   Tue Jul 31 00:24:17 2012 +0200

    [BZ 844495] - Fixing the inconsistency in the string handling introduced by
    Rhino 1.7R4. The new version of Rhino introduced some performance
    optimizations in the script concatenation which confused the script engine,
    which is based on the previous versions of Rhino.

diff --git a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/RhinoScriptEngine.java b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/RhinoScriptEngine.java
index e8069a6..0475ecb 100644
--- a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/RhinoScriptEngine.java
+++ b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/RhinoScriptEngine.java
@@ -78,6 +78,7 @@ import javax.script.SimpleBindings;
 import javax.script.SimpleScriptContext;
 
 import org.mozilla.javascript.Callable;
+import org.mozilla.javascript.ConsString;
 import org.mozilla.javascript.Context;
 import org.mozilla.javascript.ContextFactory;
 import org.mozilla.javascript.Function;
@@ -90,6 +91,7 @@ import org.mozilla.javascript.Scriptable;
 import org.mozilla.javascript.ScriptableObject;
 import org.mozilla.javascript.Synchronizer;
 import org.mozilla.javascript.Undefined;
+import org.mozilla.javascript.WrapFactory;
 import org.mozilla.javascript.Wrapper;
 import org.mozilla.javascript.commonjs.module.RequireBuilder;
 import org.mozilla.javascript.commonjs.module.provider.ModuleSourceProvider;
@@ -123,6 +125,8 @@ import org.rhq.scripting.javascript.engine.util.InterfaceImplementor;
  * Modified to include the "require()" function by default.
  * Modified to tighten the security of the script execution by running it in an
  * AccessControlContext active at the time of the script engine creation.
+ * Modified to allow correct interoperability between Java and javascript string even
+ * if represented by the custom ConsString instance.
  * 
  * @author Lukas Krejci
  */
@@ -167,7 +171,30 @@ public class RhinoScriptEngine  extends AbstractScriptEngine
     //LK - added support for CommonJS modules
     private RequireBuilder requireBuilder;
     
+    //LK - custom wrap factory to overcome the difficulties comparing java strings with ConsString instances
+    //     introduced by Rhino 1.7R4.
+    private static class CustomWrapFactory extends WrapFactory {
+
+        /**
+         * This behaves exactly the same as the super class' method except the fact that
+         * the ConsString is considered "primitive" and is not wrapped in any manner.
+         * <p>
+         * This is then consistent with the rest of Rhino that expects ConsString as a possible
+         * implementation of the string.
+         */
+        @Override
+        public Object wrap(Context cx, Scriptable scope, Object obj, Class<?> staticType) {
+            if (obj instanceof ConsString) {
+                return obj;
+            }
+            
+            return super.wrap(cx, scope, obj, staticType);
+        }
+    }
+    
+
     //LK - make all the scripts run in an access control context
+    //LK - use a custom wrap factory to overcome the ConsString being mishandled when transferring from java to js and back
     static {
         ContextFactory.initGlobal(new ContextFactory() {
             @Override
@@ -193,9 +220,11 @@ public class RhinoScriptEngine  extends AbstractScriptEngine
                 }
             }
                         
+            @Override
             protected Context makeContext() {
                 Context cx = super.makeContext();
                 cx.setOptimizationLevel(-1);
+                cx.setWrapFactory(new CustomWrapFactory());
                 return cx;
             }
 
diff --git a/modules/enterprise/scripting/javascript/src/test/java/org/rhq/scripting/javascript/EngineTest.java b/modules/enterprise/scripting/javascript/src/test/java/org/rhq/scripting/javascript/EngineTest.java
index 7ccde17..6aa9355 100644
--- a/modules/enterprise/scripting/javascript/src/test/java/org/rhq/scripting/javascript/EngineTest.java
+++ b/modules/enterprise/scripting/javascript/src/test/java/org/rhq/scripting/javascript/EngineTest.java
@@ -78,6 +78,32 @@ public class EngineTest {
         assertEquals(captureScriptOutput(script), output, "Unexpected functions found in modules");
     }
 
+    public void stringHandlingConsistent() throws Exception {
+        String script = "var a = \"str\"\n"
+            + "var b = \"str\"\n"
+            + "var test1 = a + b\n"
+            + "var test2 = \"strstr\"\n"
+            + "var test3 = new java.lang.String(\"strstr\")\n";
+        
+        ScriptEngine engine = new ScriptEngineManager().getEngineByName("javascript");
+        
+        engine.eval(script);
+        
+        //now do the tests with the initialized context
+        
+        Object ret = engine.eval("test1 == test2");        
+        assertEquals(ret, Boolean.TRUE, "Unexpected concatenated and javascript string comparison.");        
+        
+        ret = engine.eval("test1 == test3");        
+        assertEquals(ret, Boolean.TRUE, "Unexpected concatenated and java string comparison.");
+        
+        ret = engine.eval("test2 == test3");        
+        assertEquals(ret, Boolean.TRUE, "Unexpected javascript and java string comparison.");
+                
+        ret = engine.eval("java.lang.Integer.parseInt('1' + '2');");
+        assertEquals(ret, 12, "Engine failed to pass a concatenated string as a string parameter.");
+    }
+    
     private ScriptEngine getScriptEngine() {
         ScriptEngineManager manager = new ScriptEngineManager();
         return manager.getEngineByName("rhino-nonjdk");               


commit 264bf23cb169b7c2fe73f1756138914752f4f2ee
Author: Heiko W. Rupp <hwr at redhat.com>
Date:   Mon Jul 30 10:23:35 2012 -0400

    BZ 844217 - Use the correct name for the deployments directory (for bundles).

diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/StandaloneASDiscovery.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/StandaloneASDiscovery.java
index a756dea..9d93300 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/StandaloneASDiscovery.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/StandaloneASDiscovery.java
@@ -87,7 +87,7 @@ public class StandaloneASDiscovery extends BaseProcessDiscovery {
         // Set deployment directory, which only exists for standalone servers
         String baseDir = pluginConfig.getSimpleValue("baseDir");
         if (baseDir != null) {
-            File deployDir = new File(baseDir, "deployment");
+            File deployDir = new File(baseDir, "deployments");
             pluginConfig.put(new PropertySimple("deployDir", deployDir.getPath()));
         }
 


commit c1d8f3211ece139eb08cb3f2ee22747a78f9d821
Author: Heiko W. Rupp <hwr at redhat.com>
Date:   Fri Jul 27 11:24:55 2012 -0400

    Allow to run the plugin validator standalone. If done so, also print warnings and errors to stdout/stderr.

diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/plugin/PluginValidator.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/plugin/PluginValidator.java
index da50213..73da44f 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/plugin/PluginValidator.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/plugin/PluginValidator.java
@@ -54,15 +54,19 @@ import org.rhq.core.pluginapi.plugin.PluginLifecycleListener;
 public class PluginValidator {
     private static final Log LOG = LogFactory.getLog(PluginValidator.class);
     private static final String PLUGIN_DESCRIPTOR_PATH = "META-INF/rhq-plugin.xml";
+    static boolean interactive = false;
 
     /**
      * If no args are passed in, the current thread's classloader will be used to find the plugins to validate.
      * If one or more argument strings are provided, they will be assumed to be paths to the plugin jars to validate
      * (in which case the thread's classloader will be ignored and not searched for plugins).
      *
+     * If one argument is '-i'. Warnings and Errors will also be printed to stdout and stderr, which helps developers
+     * to find issues when they run the Plugin validator as a standalone tool.
+     *
      * The last line this will output will be "!OK!" and exit with an exit code of 0 if everything is OK.
      * The last line this will output will be "!FAILURE!" and exit with an exit code of 1 if one or more plugins failed validation.
-     * 
+     *
      * @param args 0 or more plugin jar file paths
      */
     public static void main(String[] args) {
@@ -72,6 +76,11 @@ public class PluginValidator {
             if (args.length > 0) {
                 finder = new SimplePluginFinder();
                 for (String arg : args) {
+                    if (arg.equals("-i")) {
+                        interactive = true;
+                        continue;
+                    }
+
                     URL jarUrl = new File(arg).toURI().toURL();
                     finder.addUrl(jarUrl);
                     LOG.info("Plugin jar: " + jarUrl);
@@ -109,7 +118,7 @@ public class PluginValidator {
             boolean sizesMatch = (manager.getPlugins().size() == finder.findPlugins().size());
             if (!sizesMatch) {
                 success = false;
-                LOG.error("Only [" + manager.getPlugins().size() + "] out of [" + finder.findPlugins().size()
+                errorLog("Only [" + manager.getPlugins().size() + "] out of [" + finder.findPlugins().size()
                     + "] plugin descriptors are valid.");
             } else {
                 LOG.info("All [" + finder.findPlugins().size() + "] plugin descriptors are valid.");
@@ -147,47 +156,47 @@ public class PluginValidator {
         String componentClass = metadataManager.getComponentClass(resourceType);
         if (componentClass == null) {
             success = false;
-            LOG.error("Missing component class in resource type [" + resourceType.getName() + "] from plugin ["
+            errorLog("Missing component class in resource type [" + resourceType.getName() + "] from plugin ["
                 + resourceType.getPlugin() + "]");
         } else {
             try {
                 Class componentClazz = Class.forName(componentClass, false, pluginEnvironment.getPluginClassLoader());
                 if (!ResourceComponent.class.isAssignableFrom(componentClazz)) {
                     success = false;
-                    LOG.error("Component class [" + componentClass + "] for resource type [" + resourceType.getName()
+                    errorLog("Component class [" + componentClass + "] for resource type [" + resourceType.getName()
                         + "] from plugin [" + resourceType.getPlugin() + "] does not implement "
                         + ResourceComponent.class);
                 }
                 if (!resourceType.getMetricDefinitions().isEmpty()
                     && !MeasurementFacet.class.isAssignableFrom(componentClazz)) {
                     success = false;
-                    LOG.error("Component class [" + componentClass + "] for resource type [" + resourceType.getName()
+                    errorLog("Component class [" + componentClass + "] for resource type [" + resourceType.getName()
                         + "] from plugin [" + resourceType.getPlugin()
                         + "] does not support the measurement collection facet but defines metrics.");
                 }
                 if (!resourceType.getOperationDefinitions().isEmpty()
                     && !OperationFacet.class.isAssignableFrom(componentClazz)) {
                     success = false;
-                    LOG.error("Component class [" + componentClass + "] for resource type [" + resourceType.getName()
+                    errorLog("Component class [" + componentClass + "] for resource type [" + resourceType.getName()
                         + "] from plugin [" + resourceType.getPlugin()
                         + "] does not support the operations facet but defines operations.");
                 }
                 if (resourceType.getBundleType() != null && !BundleFacet.class.isAssignableFrom(componentClazz)) {
                     success = false;
-                    LOG.error("Component class [" + componentClass + "] for resource type [" + resourceType.getName()
+                    errorLog("Component class [" + componentClass + "] for resource type [" + resourceType.getName()
                         + "] from plugin [" + resourceType.getPlugin()
                         + "] does not support the bundle facet but defines a bundle type.");
                 }
                 if (!resourceType.getPackageTypes().isEmpty() && !ContentFacet.class.isAssignableFrom(componentClazz)) {
                     success = false;
-                    LOG.error("Component class [" + componentClass + "] for resource type [" + resourceType.getName()
+                    errorLog("Component class [" + componentClass + "] for resource type [" + resourceType.getName()
                         + "] from plugin [" + resourceType.getPlugin()
                         + "] does not support the content management facet but defines package types.");
                 }
                 if (resourceType.getResourceConfigurationDefinition() != null
                     && !ConfigurationFacet.class.isAssignableFrom(componentClazz)) {
                     success = false;
-                    LOG.error("Component class [" + componentClass + "] for resource type [" + resourceType.getName()
+                    errorLog("Component class [" + componentClass + "] for resource type [" + resourceType.getName()
                         + "] from plugin [" + resourceType.getPlugin()
                         + "] does not support the configuration facet but defines resource configuration.");
                 }
@@ -200,19 +209,19 @@ public class PluginValidator {
                 }
                 if (hasCreatableChild && !CreateChildResourceFacet.class.isAssignableFrom(componentClazz)) {
                     success = false;
-                    LOG.error("Component class [" + componentClass + "] for resource type [" + resourceType.getName()
+                    errorLog("Component class [" + componentClass + "] for resource type [" + resourceType.getName()
                         + "] from plugin [" + resourceType.getPlugin()
                         + "] does not support the child creation facet but has metadata saying it can.");
                 }
                 if (resourceType.isDeletable() && !DeleteResourceFacet.class.isAssignableFrom(componentClazz)) {
                     success = false;
-                    LOG.error("Component class [" + componentClass + "] for resource type [" + resourceType.getName()
+                    errorLog("Component class [" + componentClass + "] for resource type [" + resourceType.getName()
                         + "] from plugin [" + resourceType.getPlugin()
                         + "] does not support delete resource facet but has metadata saying it can delete children.");
                 }
             } catch (Exception e) {
                 success = false;
-                LOG.error("Cannot find component class [" + componentClass + "] for resource type ["
+                errorLog("Cannot find component class [" + componentClass + "] for resource type ["
                     + resourceType.getName() + "] from plugin [" + resourceType.getPlugin() + "].");
             }
         }
@@ -228,18 +237,18 @@ public class PluginValidator {
                 Class discoveryClazz = Class.forName(discoveryClass, false, pluginEnvironment.getPluginClassLoader());
                 if (!ResourceDiscoveryComponent.class.isAssignableFrom(discoveryClazz)) {
                     success = false;
-                    LOG.error("Discovery class [" + discoveryClass + "] for resource type [" + resourceType.getName()
+                    errorLog("Discovery class [" + discoveryClass + "] for resource type [" + resourceType.getName()
                         + "] from plugin [" + resourceType.getPlugin() + "] does not implement "
                         + ResourceDiscoveryComponent.class);
                 }
                 if (resourceType.isSupportsManualAdd() && !ManualAddFacet.class.isAssignableFrom(discoveryClazz)) {
-                    LOG.warn("Discovery class [" + discoveryClass + "] for resource type [" + resourceType.getName()
+                    warnLog("Discovery class [" + discoveryClass + "] for resource type [" + resourceType.getName()
                         + "] from plugin [" + resourceType.getPlugin() + "] does not implement " + ManualAddFacet.class
                         + " - implementing manual-add in discoverResources() is deprecated.");
                 }
             } catch (Exception e) {
                 success = false;
-                LOG.error("Cannot find discovery class [" + discoveryClass + "] for resource type ["
+                errorLog("Cannot find discovery class [" + discoveryClass + "] for resource type ["
                     + resourceType.getName() + "] from plugin [" + resourceType.getPlugin() + "].");
             }
         }
@@ -255,12 +264,12 @@ public class PluginValidator {
                 Class overseerClazz = Class.forName(overseerClass, false, pluginEnvironment.getPluginClassLoader());
                 if (!PluginLifecycleListener.class.isAssignableFrom(overseerClazz)) {
                     success = false;
-                    LOG.error("Plugin Lifecycle Listener class [" + overseerClass + "] for plugin ["
+                    errorLog("Plugin Lifecycle Listener class [" + overseerClass + "] for plugin ["
                         + resourceType.getPlugin() + "] does not implement " + PluginLifecycleListener.class);
                 }
             } catch (Exception e) {
                 success = false;
-                LOG.error("Cannot find Plugin Lifecycle Listener class [" + overseerClass + "] for plugin ["
+                errorLog("Cannot find Plugin Lifecycle Listener class [" + overseerClass + "] for plugin ["
                     + resourceType.getPlugin() + "].");
             }
         }
@@ -279,10 +288,22 @@ public class PluginValidator {
                 pluginFinder.addUrl(jarUrl);
                 LOG.info("Found plugin jar: " + jarUrl);
             } else {
-                LOG.warn("Found a plugin descriptor outside of a jar, skipping: " + descriptorUrl);
+                warnLog("Found a plugin descriptor outside of a jar, skipping: " + descriptorUrl);
             }
         }
 
         return pluginFinder;
     }
+
+    private static void errorLog(String errorMessage) {
+        LOG.error(errorMessage);
+        if (interactive)
+            System.err.println(errorMessage);
+    }
+
+    private static void warnLog(String warningMessage) {
+        LOG.warn(warningMessage);
+        if (interactive)
+            System.out.println(warningMessage);
+    }
 }
\ No newline at end of file
diff --git a/modules/enterprise/agent/src/etc/plugin-validator.sh b/modules/enterprise/agent/src/etc/plugin-validator.sh
new file mode 100755
index 0000000..803ff6c
--- /dev/null
+++ b/modules/enterprise/agent/src/etc/plugin-validator.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+for i in lib/*.jar
+do
+  CP=$CP:$i
+done
+java -cp $CP org.rhq.core.pc.plugin.PluginValidator -i $*


commit 3fd82d43b6e74a1fe9c6a7a4e9c017f4882b725d
Author: Heiko W. Rupp <hwr at redhat.com>
Date:   Wed Jul 25 09:39:09 2012 -0400

    Put the standalone container start scripts directly in the agent distro, to make it easier to use them for developers.

diff --git a/etc/standalone-pc/README.txt b/etc/standalone-pc/README.txt
index b940187..c71fda7 100644
--- a/etc/standalone-pc/README.txt
+++ b/etc/standalone-pc/README.txt
@@ -8,6 +8,9 @@ alternatively copy an existing agent directory
 Copy the standalone.(sh|bat) script to this agent directory in bin/ next to the
 existing rhq-agent.(sh|bat) scripts
 
+AS OF RHQ 4.5 the scripts are already installed as standalone-pc.(sh|bat) in the
+bin/ directory of the agent.
+
 If you have no plugins in the plugin/ directory, then copy at least the rhq-platform-*.jar
 to plugins/ (e.g. from the rhq.ear/rhq-ownloads/rhq-plugins) directory of the server.
 
diff --git a/etc/standalone-pc/standalone.bat b/etc/standalone-pc/standalone.bat
deleted file mode 100644
index c8da8a3..0000000
--- a/etc/standalone-pc/standalone.bat
+++ /dev/null
@@ -1,9 +0,0 @@
- at echo off
-
-rem uncomment below if you want to enable JPDA debugging
-rem set RHQ_AGENT_ADDITIONAL_JAVA_OPTS=-Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,address=9797,server=y,suspend=n
-
-setlocal
-set RHQ_AGENT_MAINCLASS=org.rhq.core.pc.StandaloneContainer
-call rhq-agent.bat %*
-endlocal
diff --git a/etc/standalone-pc/standalone.sh b/etc/standalone-pc/standalone.sh
deleted file mode 100755
index d8ffef6..0000000
--- a/etc/standalone-pc/standalone.sh
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/bin/sh
-
-_DOLLARZERO=`readlink "$0" 2>/dev/null || echo "$0"`
-RHQ_AGENT_BIN_DIR_PATH=`dirname "$_DOLLARZERO"`
-RHQ_AGENT_MAINCLASS=org.rhq.core.pc.StandaloneContainer
-export RHQ_AGENT_MAINCLASS
-
-# uncomment below if you want to enable JPDA debugging
-#RHQ_AGENT_ADDITIONAL_JAVA_OPTS="-Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,address=9797,server=y,suspend=n"
-#export RHQ_AGENT_ADDITIONAL_JAVA_OPTS
-
-$RHQ_AGENT_BIN_DIR_PATH/rhq-agent.sh $*
diff --git a/modules/enterprise/agent/src/etc/standalone-pc.bat b/modules/enterprise/agent/src/etc/standalone-pc.bat
new file mode 100644
index 0000000..c8da8a3
--- /dev/null
+++ b/modules/enterprise/agent/src/etc/standalone-pc.bat
@@ -0,0 +1,9 @@
+ at echo off
+
+rem uncomment below if you want to enable JPDA debugging
+rem set RHQ_AGENT_ADDITIONAL_JAVA_OPTS=-Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,address=9797,server=y,suspend=n
+
+setlocal
+set RHQ_AGENT_MAINCLASS=org.rhq.core.pc.StandaloneContainer
+call rhq-agent.bat %*
+endlocal
diff --git a/modules/enterprise/agent/src/etc/standalone-pc.sh b/modules/enterprise/agent/src/etc/standalone-pc.sh
new file mode 100755
index 0000000..d8ffef6
--- /dev/null
+++ b/modules/enterprise/agent/src/etc/standalone-pc.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+_DOLLARZERO=`readlink "$0" 2>/dev/null || echo "$0"`
+RHQ_AGENT_BIN_DIR_PATH=`dirname "$_DOLLARZERO"`
+RHQ_AGENT_MAINCLASS=org.rhq.core.pc.StandaloneContainer
+export RHQ_AGENT_MAINCLASS
+
+# uncomment below if you want to enable JPDA debugging
+#RHQ_AGENT_ADDITIONAL_JAVA_OPTS="-Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,address=9797,server=y,suspend=n"
+#export RHQ_AGENT_ADDITIONAL_JAVA_OPTS
+
+$RHQ_AGENT_BIN_DIR_PATH/rhq-agent.sh $*


commit 7da515fa212ddf4903984c1b24092523fc4136a0
Author: Heiko W. Rupp <hwr at redhat.com>
Date:   Wed Jul 25 09:23:49 2012 -0400

    Fix a small typo.

diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerLocal.java
index c032481..5ee68f4 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerLocal.java
@@ -58,7 +58,7 @@ public interface AlertHandlerLocal {
     @GZIP
     @GET
     @Path("/")
-    @ApiOperation(value = "List all alerts", multiValueResponse = true, responseClass = "List<AlertRest")
+    @ApiOperation(value = "List all alerts", multiValueResponse = true, responseClass = "List<AlertRest>")
     Response listAlerts(
             @ApiParam(value = "Page number", defaultValue = "0") @QueryParam("page") int page,
             @ApiParam(value = "Limit to priority", allowableValues = "High, Medium, Low, All") @DefaultValue("All") @QueryParam("prio") String prio,


commit 0170a5ac909fd4120fd88f9d01fb039851289261
Author: Simeon Pinder <spinder at redhat.com>
Date:   Sat Jul 21 15:46:03 2012 -0400

     [BZ 840512] Fix for issue with Obfuscated properties affecting CSP credentials.
       - Removed earlier workaround for failed deobfuscation
       - Reimplement Obfuscation without symmetric Hibernate annotations
       - Now PostLoad is only used to deobfuscate for in memory use of Obfuscated properties.

diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/ObfuscatedPropertySimple.java b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/ObfuscatedPropertySimple.java
index 779b795..07b3467 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/ObfuscatedPropertySimple.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/ObfuscatedPropertySimple.java
@@ -26,10 +26,6 @@ import java.io.ObjectOutputStream;
 import javax.persistence.DiscriminatorValue;
 import javax.persistence.Entity;
 import javax.persistence.PostLoad;
-import javax.persistence.PostPersist;
-import javax.persistence.PostUpdate;
-import javax.persistence.PrePersist;
-import javax.persistence.PreUpdate;
 import javax.xml.bind.annotation.XmlAccessType;
 import javax.xml.bind.annotation.XmlAccessorType;
 import javax.xml.bind.annotation.XmlRootElement;
@@ -43,6 +39,9 @@ import org.rhq.core.util.obfuscation.Obfuscator;
  * This is a specialization of {@link PropertySimple} that provides password obfuscation
  * methods.
  *
+ * In memory, the value is always kept in clear text. It is only at persisting or
+ * serialization time that the value is stored in its obfuscated form.
+ * 
  * @author Lukas Krejci
  */
 @DiscriminatorValue("obfuscated")
@@ -51,10 +50,15 @@ import org.rhq.core.util.obfuscation.Obfuscator;
 @XmlRootElement
 public class ObfuscatedPropertySimple extends PropertySimple {
 
+    //note that while there were changes since RHQ 4.4.0.GA (or JON 3.1.0.GA) version of this class
+    //the serialization has NOT changed. The over-the-wire format of this class remained the same.
+    //Hence, serializationVersionUID is still at 1.
     private static final long serialVersionUID = 1L;
 
     private static final Log LOG = LogFactory.getLog(ObfuscatedPropertySimple.class);
     
+    private transient String clearTextValue;
+    
     public ObfuscatedPropertySimple() {
     }
 
@@ -74,6 +78,16 @@ public class ObfuscatedPropertySimple extends PropertySimple {
      */
     protected ObfuscatedPropertySimple(PropertySimple original, boolean keepId) {
         super(original, keepId);
+        setValue(original.getStringValue());
+    }
+
+    /**
+     * @param original
+     * @param keepId
+     */
+    protected ObfuscatedPropertySimple(ObfuscatedPropertySimple original, boolean keepId) {
+        super(original, keepId);
+        this.clearTextValue = original.clearTextValue;
     }
 
     /**
@@ -81,7 +95,8 @@ public class ObfuscatedPropertySimple extends PropertySimple {
      * @param value
      */
     public ObfuscatedPropertySimple(String name, Object value) {
-        super(name, value);
+        super(name, null);
+        setValue(value);
     }
 
     @Override
@@ -89,50 +104,132 @@ public class ObfuscatedPropertySimple extends PropertySimple {
         return new ObfuscatedPropertySimple(this, keepId);
     }
     
+    @PostLoad
+    protected void initClearTextValue() {
+        clearTextValue = deobfuscate(getObfuscatedStringValue());
+    }
+       
     /**
-     * We deobfuscate right after the entity has been loaded from the database or right
-     * after we persist or update the value.
-     * 
-     * Because we change the value before persist or update, we have to swap the value back
-     * as soon as those DB changes are done, so that we only use the raw value in memory.
+     * @return the value as being stored in the database
      */
-    @PostLoad
-    @PostPersist
-    @PostUpdate
-    protected void deobfuscate() {
-        String value = getStringValue();
-        if (value != null) {
-            try {
-                setStringValue(Obfuscator.decode(getStringValue()));
-            } catch (Exception e) {
-                LOG.error("Failed to deobfuscate property value: [" + value + "]", e);
-            }
+    public String getObfuscatedStringValue() {
+        return super.getStringValue();
+    }
+    
+    /**
+     * The value of this property as string. Note that this is always in "clear text". I.e. the value
+     * you get from this method is NOT obfuscated (but it gets stored in the database obfuscated).
+     */
+    @Override
+    public String getStringValue() {
+        return clearTextValue;
+    }
+    
+    /**
+     * Sets the value of this property. You should pass the "clear text" value - the obfuscation of
+     * the value in the database is done for you behind the scenes.
+     */
+    @Override
+    public void setValue(Object value) {
+        //just use the logic in the superclass to set the value
+        super.setValue(value);
+        //and obtain the result
+        this.clearTextValue = super.getStringValue();
+        
+        //now set the underlying value to the obfuscated one
+        super.setValue(obfuscate(clearTextValue));
+        
+        //now we have the clear text string representation of the value in "clearTextValue",
+        //the stringValue in the superclass contains the corresponding obfuscated string.
+    }
+    
+    
+    @Override
+    public Boolean getBooleanValue() {
+        String val = getStringValue();
+        return val == null ? null : Boolean.valueOf(val);
+    }
+
+    @Override
+    public Long getLongValue() {
+        String val = getStringValue();
+        return val == null ? null : Long.valueOf(val);
+    }
+
+    @Override
+    public Integer getIntegerValue() {
+        String val = getStringValue();
+        return val == null ? null : Integer.valueOf(val);
+    }
+
+    @Override
+    public Float getFloatValue() {
+        String val = getStringValue();
+        return val == null ? null : Float.valueOf(val);
+    }
+
+    @Override
+    public Double getDoubleValue() {
+        String val = getStringValue();
+        return val == null ? null : Double.valueOf(val);
+    }
+
+    @Override
+    public boolean isMasked() {
+        return MASKED_VALUE.equals(getStringValue());
+    }
+
+    @Override
+    public void mask() {
+        if (getStringValue() != null) {
+            setValue(MASKED_VALUE);
+        }
+    }
+
+    protected String deobfuscate(String value) {
+        try {
+            return value == null ? null : Obfuscator.decode(value);
+        } catch (NumberFormatException nfe) {//detect unobfuscated properties from before patch
+            //Assuming that this was in incorrect state from BZ840512
+            //logging that we found an unobfuscated value and if it's not part of patch/upgrade contact administrator
+            LOG.error("Failed to deobfuscate property value: [" + value + "]. If this is not part of a patch/upgrade "
+                + "then you should contact System Administrator to have the property details reset.");
+            //Returning plain value to prevent Content Source load failure. On save should be correctly obfuscated
+            return value;
+        } catch (Exception e) {
+            LOG.error("Failed to deobfuscate property value: [" + value + "]", e);
+            throw new IllegalArgumentException("Failed to deobfuscate property value: [" + value + "]", e);
         }
     }
     
     /**
      * Obfuscate the value right before it gets pushed down to the database.
      */
-    @PrePersist
-    @PreUpdate
-    protected void obfuscate() {
-        String value = getStringValue();
-        if (value != null) {
-            try {
-                setStringValue(Obfuscator.encode(value));
-            } catch (Exception e) {
-                LOG.error("Failed to obfuscate property value: [" + value + "]", e);
-            }
+    protected String obfuscate(String value) {
+        try {
+            return value == null ? null : Obfuscator.encode(value);
+        } catch (Exception e) {
+            LOG.error("Failed to obfuscate property value: [" + value + "]", e);
+            throw new IllegalArgumentException("Failed to obfuscate property value: [" + value + "]", e);
         }
     }
     
+    /**
+     * Overriden to not leak the unobfuscated value in the toString() method, output of which
+     * might end up in logs, etc.
+     */
+    @Override
+    protected void appendToStringInternals(StringBuilder str) {
+        str.append(", obfuscated-value=").append(getObfuscatedStringValue());
+        str.append(", override=").append(getOverride());
+    };
+
     private void writeObject(ObjectOutputStream str) throws IOException {
-        obfuscate();
         str.defaultWriteObject();        
     }
     
     private void readObject(ObjectInputStream str) throws IOException, ClassNotFoundException {
         str.defaultReadObject();
-        deobfuscate();
+        initClearTextValue();
     }
 }
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/PropertySimple.java b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/PropertySimple.java
index 8edc331..dd7aebd 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/PropertySimple.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/PropertySimple.java
@@ -55,7 +55,7 @@ public class PropertySimple extends Property implements Serializable {
      * clients from being able to view the current value of PASSWORD properties. The value is made obscure enough to
      * make the chances of it being the same as the property's unmasked value next to nil.
      */
-    private static final String MASKED_VALUE = "_._._[MaSKeD]_._._";
+    public static final String MASKED_VALUE = "_._._[MaSKeD]_._._";
 
     @Column(name = "string_value", length = MAX_VALUE_LENGTH)
     private String stringValue;
diff --git a/modules/enterprise/server/plugins/jboss-software/src/main/java/org/rhq/enterprise/server/plugins/jboss/software/JBossSoftwareContentSourceAdapter.java b/modules/enterprise/server/plugins/jboss-software/src/main/java/org/rhq/enterprise/server/plugins/jboss/software/JBossSoftwareContentSourceAdapter.java
index 4b3516a..4061980 100644
--- a/modules/enterprise/server/plugins/jboss-software/src/main/java/org/rhq/enterprise/server/plugins/jboss/software/JBossSoftwareContentSourceAdapter.java
+++ b/modules/enterprise/server/plugins/jboss-software/src/main/java/org/rhq/enterprise/server/plugins/jboss/software/JBossSoftwareContentSourceAdapter.java
@@ -21,6 +21,8 @@ package org.rhq.enterprise.server.plugins.jboss.software;
 import java.io.InputStream;
 import java.net.URI;
 import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 
 import churchillobjects.rss4j.RssDocument;
@@ -38,7 +40,6 @@ import org.apache.commons.logging.LogFactory;
 
 import org.rhq.core.domain.configuration.Configuration;
 import org.rhq.core.domain.configuration.PropertySimple;
-import org.rhq.core.util.obfuscation.Obfuscator;
 import org.rhq.enterprise.server.plugin.pc.content.ContentProvider;
 import org.rhq.enterprise.server.plugin.pc.content.ContentProviderPackageDetails;
 import org.rhq.enterprise.server.plugin.pc.content.PackageSource;
@@ -221,16 +222,6 @@ public class JBossSoftwareContentSourceAdapter implements ContentProvider, Packa
 
             int status = client.executeMethod(method);
 
-            //BZ840512: check for issue deobfuscating the password:
-            if (status == 401 || status == 403) {
-                password = Obfuscator.decode(password);//in case de/unobfuscation failed.
-                UsernamePasswordCredentials upc = new UsernamePasswordCredentials(username, password);
-                client.getState().setCredentials("users", method.getHostConfiguration().getHost(), upc);
-                log.warn("You have either input bad Content Source credentials or"
-                    + " there is a problem retrieving obfuscated passwords. Retrying...");
-                status = client.executeMethod(method);
-            }
-
             //Check to see if redirection has occurred
             String currentUrl = method.getURI().getURI();
             //if redirection has occurred, reconnect with correct address.


commit 4f7c64deab774aee682daa5c37352509ed0422ac
Author: Heiko W. Rupp <hwr at redhat.com>
Date:   Fri Jul 20 11:31:48 2012 -0400

    BZ  839080 - accept pid files that also contain whitespace or line endings (\n \r )

diff --git a/modules/core/native-system/src/main/java/org/rhq/core/system/pquery/ProcessInfoQuery.java b/modules/core/native-system/src/main/java/org/rhq/core/system/pquery/ProcessInfoQuery.java
index 82486ca..1e9eeb3 100644
--- a/modules/core/native-system/src/main/java/org/rhq/core/system/pquery/ProcessInfoQuery.java
+++ b/modules/core/native-system/src/main/java/org/rhq/core/system/pquery/ProcessInfoQuery.java
@@ -470,6 +470,6 @@ public class ProcessInfoQuery {
             contents = "";
         }
 
-        return contents;
+        return contents.trim();
     }
 }
\ No newline at end of file
diff --git a/modules/core/native-system/src/test/java/org/rhq/core/system/pquery/ProcessInfoQueryTest.java b/modules/core/native-system/src/test/java/org/rhq/core/system/pquery/ProcessInfoQueryTest.java
index bc8d77d..466983a 100644
--- a/modules/core/native-system/src/test/java/org/rhq/core/system/pquery/ProcessInfoQueryTest.java
+++ b/modules/core/native-system/src/test/java/org/rhq/core/system/pquery/ProcessInfoQueryTest.java
@@ -291,6 +291,61 @@ public class ProcessInfoQueryTest {
     }
 
     /**
+     * Test PID files.
+     *
+     * @throws Exception
+     */
+    public void testPIQLPidfileNL() throws Exception {
+        File pidfile = File.createTempFile("test", ".pid");
+        try {
+            FileOutputStream fos = new FileOutputStream(pidfile);
+            fos.write("3\n".getBytes());
+            fos.flush();
+            fos.close();
+
+            results = query.query("process|pidfile|match=" + pidfile.getCanonicalPath());
+            assert results.size() == 1 : results;
+            assertPidExists(3, results, "pidfile had pid #3 in it and should have matched pid 3");
+
+            results = query.query("process|pidfile|nomatch=" + pidfile.getCanonicalPath());
+            assert results.size() == (query.getProcesses().size() - 1) : "should match all but pid 3:" + results;
+            assertPidDoesNotExist(3, results, "pidfile had pid #3 in it so .ne should not have matched pid 3");
+
+            results = query.query("process|pidfile|match|parent=" + pidfile.getCanonicalPath());
+            assert results.size() == 2 : "there are two child procs of parent process found in pidfile:" + results;
+            assertPidExists(4, results, "");
+            assertPidExists(5, results, "");
+        } finally {
+            pidfile.delete();
+        }
+    }
+
+    public void testPIQLPidfileNLLF() throws Exception {
+        File pidfile = File.createTempFile("test", ".pid");
+        try {
+            FileOutputStream fos = new FileOutputStream(pidfile);
+            fos.write("3\r\n".getBytes());
+            fos.flush();
+            fos.close();
+
+            results = query.query("process|pidfile|match=" + pidfile.getCanonicalPath());
+            assert results.size() == 1 : results;
+            assertPidExists(3, results, "pidfile had pid #3 in it and should have matched pid 3");
+
+            results = query.query("process|pidfile|nomatch=" + pidfile.getCanonicalPath());
+            assert results.size() == (query.getProcesses().size() - 1) : "should match all but pid 3:" + results;
+            assertPidDoesNotExist(3, results, "pidfile had pid #3 in it so .ne should not have matched pid 3");
+
+            results = query.query("process|pidfile|match|parent=" + pidfile.getCanonicalPath());
+            assert results.size() == 2 : "there are two child procs of parent process found in pidfile:" + results;
+            assertPidExists(4, results, "");
+            assertPidExists(5, results, "");
+        } finally {
+            pidfile.delete();
+        }
+    }
+
+    /**
      * Test regular expressions.
      */
     public void testPIQLProcessNameRegularExpression() {


commit c5d2853bba213e53a2e50b1e67394f32b1f43fc1
Author: Heiko W. Rupp <hwr at redhat.com>
Date:   Wed Jul 18 16:00:02 2012 -0400

    Explicitly remove availability entries, as there is no cascade delete from resource to availability.

diff --git a/modules/core/domain/src/test/java/org/rhq/core/domain/drift/JPADriftChangeSetTest.java b/modules/core/domain/src/test/java/org/rhq/core/domain/drift/JPADriftChangeSetTest.java
index b2eddb3..d6bf7c1 100644
--- a/modules/core/domain/src/test/java/org/rhq/core/domain/drift/JPADriftChangeSetTest.java
+++ b/modules/core/domain/src/test/java/org/rhq/core/domain/drift/JPADriftChangeSetTest.java
@@ -1,6 +1,6 @@
 /*
  * RHQ Management Platform
- * Copyright (C) 2011 Red Hat, Inc.
+ * Copyright (C) 2011-2012 Red Hat, Inc.
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
@@ -34,11 +34,11 @@ import org.testng.annotations.Test;
 
 import org.rhq.core.domain.configuration.Configuration;
 import org.rhq.core.domain.drift.DriftConfigurationDefinition.DriftHandlingMode;
+import org.rhq.core.domain.measurement.Availability;
 import org.rhq.core.domain.resource.Resource;
 import org.rhq.core.domain.resource.ResourceType;
 import org.rhq.core.domain.shared.ResourceBuilder;
 import org.rhq.core.domain.shared.ResourceTypeBuilder;
-import org.rhq.core.domain.test.AbstractEJB3Test;
 import org.rhq.test.TransactionCallback;
 
 public class JPADriftChangeSetTest extends DriftDataAccessTest {
@@ -79,6 +79,11 @@ public class JPADriftChangeSetTest extends DriftDataAccessTest {
     private void purgeDB() {
         EntityManager em = getEntityManager();
 
+        List<Availability> avails = (List<Availability>) em.createQuery("SELECT a FROM Availability a").getResultList();
+        for (Availability a : avails) {
+            em.remove(a);
+        }
+
         List<Resource> resources = (List<Resource>) em.createQuery("from Resource where resourceType.name = :name")
             .setParameter("name", RESOURCE_TYPE_NAME).getResultList();
         for (Resource resource : resources) {


commit 82777d7d70ec46338aaa1b662099b0dcb653c67d
Author: Heiko W. Rupp <hwr at redhat.com>
Date:   Wed Jul 18 15:44:03 2012 -0400

    Test very long tokens.

diff --git a/modules/plugins/jmx/src/test/java/org/rhq/plugins/jmx/test/ObjectNameQueryUtilityTest.java b/modules/plugins/jmx/src/test/java/org/rhq/plugins/jmx/test/ObjectNameQueryUtilityTest.java
index a7e9f77..93bd5b8 100644
--- a/modules/plugins/jmx/src/test/java/org/rhq/plugins/jmx/test/ObjectNameQueryUtilityTest.java
+++ b/modules/plugins/jmx/src/test/java/org/rhq/plugins/jmx/test/ObjectNameQueryUtilityTest.java
@@ -76,6 +76,19 @@ public class ObjectNameQueryUtilityTest {
         onqu = new ObjectNameQueryUtility("a:b=c,d={e},f={g}", c);
         System.out.println("Template: " + onqu.getQueryTemplate());
         assert onqu.getQueryTemplate().equals("a:b=c,d=foo,f=bar");
+
+        // Test some very long replacement tokens inspired by BZ 828596
+        onqu = new ObjectNameQueryUtility("*:type=HttpMetricInspector,name=%name%");
+        assert onqu.getQueryTemplate().equals("*:type=HttpMetricInspector,name=%name%");
+        assert onqu.getVariableProperties().size() == 1;
+        assert onqu.getVariableProperties().get("name").equals("name");
+        testON = new ObjectName("FooBarABCDEFGHIJKLMNOPQRSTUVWXYZ:type=HttpMetricInspector,name=ABCDEFGHIJKLMNOPQRSTUVWXYZöABCDEFGHIJKLMNOPQRSTUVWXYZ");
+        onqu.setMatchedKeyValues(testON.getKeyPropertyList());
+        formulatedMessageTemplate = "Http metrics for endpoint {name}";
+        String res = onqu.formatMessage(formulatedMessageTemplate);
+        assert res.equals("Http metrics for endpoint ABCDEFGHIJKLMNOPQRSTUVWXYZöABCDEFGHIJKLMNOPQRSTUVWXYZ") : res;
+
+
     }
 
     @Test


commit d554ac2d56373ecf1e692e5c356f9e7c22a0a6e5
Author: Jirka Kremser <jkremser at redhat.com>
Date:   Wed Jul 18 14:42:52 2012 +0200

    adding a plugin for creating the dependency graph among maven modules when running mvn site:site

diff --git a/pom.xml b/pom.xml
index 8e99665..3dcca11 100644
--- a/pom.xml
+++ b/pom.xml
@@ -721,6 +721,26 @@
             <artifactId>animal-sniffer-maven-plugin</artifactId>
             <version>${animal.sniffer.version}</version>
          </plugin>
+      	 <plugin>
+            <groupId>com.googlecode.maven-overview-plugin</groupId>
+            <artifactId>maven-overview-plugin</artifactId>
+            <version>RELEASE</version>
+            <configuration>
+               <width>4096</width>
+               <height>4096</height>
+               <maxDepth>0</maxDepth>
+               <suppressedScopes>provided, test</suppressedScopes>
+               <includes>${rhq.groupId}</includes>
+               <exclusions>
+                  <exclusion>
+                     <scope>test</scope>
+                  </exclusion>
+                  <!--<exclusion> 
+                     <scope>provided</scope>
+                  </exclusion>-->
+               </exclusions>
+            </configuration>
+         </plugin>
        </plugins>
      </pluginManagement>
 
@@ -1294,6 +1314,11 @@
 
     <reporting>
         <plugins>
+            <plugin>
+                <groupId>com.googlecode.maven-overview-plugin</groupId>
+                <artifactId>maven-overview-plugin</artifactId>
+            </plugin>
+
 <!--
             <plugin>
                 <artifactId>maven-javadoc-plugin</artifactId>
@@ -1438,6 +1463,12 @@
             <timezone>+1</timezone>
         </developer>
         <developer>
+            <name>Jirka Kremser</name>
+            <email>jkremser at redhat.com</email>
+            <timezone>+1</timezone>
+            <url>http://serviceasaservice.wordpress.com/</url>
+        </developer>
+        <developer>
             <name>Joseph Marques</name>
             <url>http://josephmarques.wordpress.com/</url>
             <timezone>-5</timezone>


commit 1704544f28ee4781e5b8a18cb93c3622e74e551b
Author: Mike Thompson <mithomps at redhat.com>
Date:   Tue Jul 17 11:25:42 2012 -0700

    [BZ 815305] Min/max constraints. Fix db-upgrade.xml to addColumn instead of alterColumn and change column names to MIN_ENTRIES from MIN and MAX_ENTRIES from MAX so that we dont have any conflicts with other databases.

diff --git a/modules/core/dbutils/src/main/scripts/dbsetup/config-schema.xml b/modules/core/dbutils/src/main/scripts/dbsetup/config-schema.xml
index 7e189d9..d5d937e 100644
--- a/modules/core/dbutils/src/main/scripts/dbsetup/config-schema.xml
+++ b/modules/core/dbutils/src/main/scripts/dbsetup/config-schema.xml
@@ -27,8 +27,8 @@
         <column name="NAME" type="VARCHAR2" required="false" size="255"/>
         <column name="DISPLAY_NAME" type="VARCHAR2" required="false" size="100"/>
         <column name="DESCRIPTION" type="VARCHAR2" required="false" size="1000"/>
-        <column name="MIN" type="INTEGER" required="false"  />
-        <column name="MAX" type="INTEGER" required="false"  />
+        <column name="MIN_ENTRIES" type="INTEGER" required="false"  />
+        <column name="MAX_ENTRIES" type="INTEGER" required="false"  />
         <column name="DEFAULT_VALUE" type="VARCHAR2" required="false" size="2000"/>
         <column name="REQUIRED" type="BOOLEAN" required="false"/>
         <column name="READONLY" type="BOOLEAN" required="false"/>
diff --git a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
index 2aafb72..2cee9f4 100644
--- a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
+++ b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
@@ -4008,8 +4008,8 @@
             </schemaSpec>
 
              <schemaSpec version="2.122">
-               <schema-alterColumn   table="RHQ_CONFIG_PROP_DEF" column="MIN" columnType="INTEGER"/>
-               <schema-alterColumn   table="RHQ_CONFIG_PROP_DEF" column="MAX" columnType="INTEGER"/>
+               <schema-addColumn   table="RHQ_CONFIG_PROP_DEF" column="MIN_ENTRIES" columnType="INTEGER"/>
+               <schema-addColumn   table="RHQ_CONFIG_PROP_DEF" column="MAX_ENTRIES" columnType="INTEGER"/>
             </schemaSpec>
 
         </dbupgrade>
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/definition/PropertyDefinitionList.java b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/definition/PropertyDefinitionList.java
index a3b11a6..adf1f34 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/definition/PropertyDefinitionList.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/definition/PropertyDefinitionList.java
@@ -25,6 +25,7 @@ package org.rhq.core.domain.configuration.definition;
 import java.lang.Integer;
 
 import javax.persistence.CascadeType;
+import javax.persistence.Column;
 import javax.persistence.DiscriminatorValue;
 import javax.persistence.Entity;
 import javax.persistence.JoinColumn;
@@ -49,8 +50,10 @@ import org.jetbrains.annotations.NotNull;
 public class PropertyDefinitionList extends PropertyDefinition {
     private static final long serialVersionUID = 1L;
 
+    @Column(name = "MIN_ENTRIES")
     private int min = 0;
 
+    @Column(name = "MAX_ENTRIES")
     private int max = Integer.MAX_VALUE;
 
     @JoinColumn(name = "parent_list_definition_id")


commit 04b9e55a116c31d5da3d919e213bb29a33e37f4b
Author: Jay Shaughnessy <jshaughn at redhat.com>
Date:   Tue Jul 17 13:41:13 2012 -0400

    [Bug 839256 - FailoverListManagerBeanTest fail on OpenJDK 1.7]
    The fixes that helped java7 hurt java6, so for java6's sake, relax the
    unit test balancing validation a tick more.

diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/cloud/FailoverListManagerBeanTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/cloud/FailoverListManagerBeanTest.java
index 1c59b16..ac07e18 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/cloud/FailoverListManagerBeanTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/cloud/FailoverListManagerBeanTest.java
@@ -242,8 +242,13 @@ public class FailoverListManagerBeanTest extends AbstractEJB3Test {
                 int ceil = (int) Math.ceil(div);
                 int floor = (int) Math.floor(div);
                 // as we get deeper be more lenient. We haven't come up with any sort of genius algorithm, it's
-                // just ok, if it balances well for the primary through tertiary levels that's pretty good.
-                if (level > 3) {
+                // just ok, if it balances well for the primary and secondary that's good.  Allow a skew of 1 for
+                // level 3-5 and a skew of 2 for levels past that
+                if (level > 2) {
+                    ++ceil;
+                    --floor;
+                }
+                if (level > 5) {
                     ++ceil;
                     --floor;
                 }


commit 58a4d6fb96fde3310ca27de7b344ff89c2c684aa
Author: Mike Thompson <mithomps at redhat.com>
Date:   Mon Jul 16 16:47:23 2012 -0700

    Fix imports to follow RHQ eclipse standards.

diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/definition/PropertyDefinitionList.java b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/definition/PropertyDefinitionList.java
index 92c8df6..a3b11a6 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/definition/PropertyDefinitionList.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/definition/PropertyDefinitionList.java
@@ -22,6 +22,8 @@
  */
 package org.rhq.core.domain.configuration.definition;
 
+import java.lang.Integer;
+
 import javax.persistence.CascadeType;
 import javax.persistence.DiscriminatorValue;
 import javax.persistence.Entity;
@@ -33,7 +35,6 @@ import javax.xml.bind.annotation.XmlSeeAlso;
 
 import org.jetbrains.annotations.NotNull;
 
-import java.lang.Integer;
 
 /**
  * The definition of a list of properties where each member of the list has the same definition. The definition of the
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/carousel/Carousel.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/carousel/Carousel.java
index 31e58e6..d82d2ee 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/carousel/Carousel.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/carousel/Carousel.java
@@ -25,11 +25,19 @@ import com.smartgwt.client.types.SelectionStyle;
 import com.smartgwt.client.types.VerticalAlignment;
 import com.smartgwt.client.util.BooleanCallback;
 import com.smartgwt.client.util.SC;
-import com.smartgwt.client.widgets.*;
+import com.smartgwt.client.widgets.Canvas;
+import com.smartgwt.client.widgets.HTMLFlow;
+import com.smartgwt.client.widgets.IButton;
+import com.smartgwt.client.widgets.Img;
+import com.smartgwt.client.widgets.Label;
 import com.smartgwt.client.widgets.events.ClickEvent;
 import com.smartgwt.client.widgets.events.ClickHandler;
 import com.smartgwt.client.widgets.events.DoubleClickHandler;
-import com.smartgwt.client.widgets.form.fields.*;
+import com.smartgwt.client.widgets.form.fields.FormItem;
+import com.smartgwt.client.widgets.form.fields.HiddenItem;
+import com.smartgwt.client.widgets.form.fields.SelectItem;
+import com.smartgwt.client.widgets.form.fields.SpinnerItem;
+import com.smartgwt.client.widgets.form.fields.TextItem;
 import com.smartgwt.client.widgets.form.fields.events.ChangedEvent;
 import com.smartgwt.client.widgets.form.fields.events.ChangedHandler;
 import com.smartgwt.client.widgets.form.fields.events.KeyPressEvent;
@@ -44,9 +52,23 @@ import org.rhq.enterprise.gui.coregui.client.CoreGUI;
 import org.rhq.enterprise.gui.coregui.client.RefreshableView;
 import org.rhq.enterprise.gui.coregui.client.components.buttons.BackButton;
 import org.rhq.enterprise.gui.coregui.client.components.form.EnhancedSearchBarItem;
-import org.rhq.enterprise.gui.coregui.client.util.selenium.*;
-
-import java.util.*;
+import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableDynamicForm;
+import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableHLayout;
+import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableIButton;
+import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableIMenuButton;
+import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableMenu;
+import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableToolStrip;
+import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableVLayout;
+import org.rhq.enterprise.gui.coregui.client.util.selenium.SeleniumUtility;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
 
 /**
  * Similar to (i.e. originally a copy of) Table but instead of encapsulating a ListGrid, it manages a list of 
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceDatasource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceDatasource.java
index b2084df..9bb1dfa 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceDatasource.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceDatasource.java
@@ -18,6 +18,24 @@
  */
 package org.rhq.enterprise.gui.coregui.client.inventory.resource;
 
+import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.AVAILABILITY;
+import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.CATEGORY;
+import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.CTIME;
+import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.DESCRIPTION;
+import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.ITIME;
+import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.KEY;
+import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.LOCATION;
+import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.MODIFIER;
+import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.MTIME;
+import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.NAME;
+import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.PLUGIN;
+import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.TYPE;
+import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.VERSION;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+
 import com.google.gwt.user.client.rpc.AsyncCallback;
 import com.smartgwt.client.data.DSRequest;
 import com.smartgwt.client.data.DSResponse;
@@ -28,6 +46,7 @@ import com.smartgwt.client.data.fields.DataSourceIntegerField;
 import com.smartgwt.client.data.fields.DataSourceTextField;
 import com.smartgwt.client.rpc.RPCResponse;
 import com.smartgwt.client.widgets.grid.ListGridRecord;
+
 import org.rhq.core.domain.criteria.ResourceCriteria;
 import org.rhq.core.domain.measurement.AvailabilityType;
 import org.rhq.core.domain.resource.Resource;
@@ -44,12 +63,6 @@ import org.rhq.enterprise.gui.coregui.client.util.Log;
 import org.rhq.enterprise.gui.coregui.client.util.RPCDataSource;
 import org.rhq.enterprise.gui.coregui.client.util.message.Message;
 
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-
-import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.*;
-
 /**
  * @author Greg Hinkle
  */
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/RPCDataSource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/RPCDataSource.java
index 4a1a06f..2f0ad01 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/RPCDataSource.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/RPCDataSource.java
@@ -18,8 +18,25 @@
  */
 package org.rhq.enterprise.gui.coregui.client.util;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
 import com.google.gwt.core.client.JavaScriptObject;
-import com.smartgwt.client.data.*;
+import com.smartgwt.client.data.Criteria;
+import com.smartgwt.client.data.DSRequest;
+import com.smartgwt.client.data.DSResponse;
+import com.smartgwt.client.data.DataSource;
+import com.smartgwt.client.data.DataSourceField;
+import com.smartgwt.client.data.Record;
+import com.smartgwt.client.data.SortSpecifier;
 import com.smartgwt.client.data.fields.DataSourceIntegerField;
 import com.smartgwt.client.data.fields.DataSourceTextField;
 import com.smartgwt.client.rpc.RPCResponse;
@@ -30,6 +47,7 @@ import com.smartgwt.client.util.JSOHelper;
 import com.smartgwt.client.widgets.form.validator.IntegerRangeValidator;
 import com.smartgwt.client.widgets.form.validator.LengthRangeValidator;
 import com.smartgwt.client.widgets.grid.ListGridRecord;
+
 import org.rhq.core.domain.alert.AlertPriority;
 import org.rhq.core.domain.criteria.BaseCriteria;
 import org.rhq.core.domain.drift.DriftCategory;
@@ -47,8 +65,6 @@ import org.rhq.enterprise.gui.coregui.client.util.message.Message;
 import org.rhq.enterprise.gui.coregui.client.util.rpc.DataSourceResponseStatistics;
 import org.rhq.enterprise.gui.coregui.client.util.selenium.SeleniumUtility;
 
-import java.util.*;
-
 /**
  * Base GWT-RPC oriented DataSource class.
  * 
@@ -594,7 +610,7 @@ public abstract class RPCDataSource<T, C extends BaseCriteria> extends DataSourc
         Map<String, Object> criteriaMap = criteria.getValues();
 
         for (Map.Entry<String, Object> nextEntry : criteriaMap.entrySet()) {
-            Log.debug("Request Criteria: "+nextEntry.getKey() + ":" + nextEntry.getValue());
+            Log.debug("Request Criteria: " + nextEntry.getKey() + ":" + nextEntry.getValue());
         }
     }
 
@@ -628,13 +644,12 @@ public abstract class RPCDataSource<T, C extends BaseCriteria> extends DataSourc
         }
 
         //if (Log.isDebugEnabled() && result != null) {
-            Log.debug("Filter: " + paramName + "=[" + result + "]");
+        Log.debug("Filter: " + paramName + "=[" + result + "]");
         //}
 
         return result;
     }
 
-
     protected static DataSourceTextField createTextField(String name, String title, Integer minLength,
         Integer maxLength, Boolean required) {
         DataSourceTextField textField = new DataSourceTextField(name, title);


commit 0fe3c6d7b0f6c6845bfc4ef59c767fc6ad8715c0
Author: Mike Thompson <mithomps at redhat.com>
Date:   Mon Jul 16 14:55:06 2012 -0700

    [BZ 815305] Min/max constraints. This second part of the fix addresses the database schema change and upgrade to schema 2.122.

diff --git a/modules/core/dbutils/pom.xml b/modules/core/dbutils/pom.xml
index 3947b19..d4b5505 100644
--- a/modules/core/dbutils/pom.xml
+++ b/modules/core/dbutils/pom.xml
@@ -17,7 +17,7 @@
     <description>Database schema setup, upgrade and other utilities</description>
 
     <properties>
-        <db.schema.version>2.121</db.schema.version>
+        <db.schema.version>2.122</db.schema.version>
         <rhq.ds.type-mapping>${rhq.test.ds.type-mapping}</rhq.ds.type-mapping>
         <rhq.ds.server-name>${rhq.test.ds.server-name}</rhq.ds.server-name>
         <rhq.ds.db-name>${rhq.test.ds.db-name}</rhq.ds.db-name>
diff --git a/modules/core/dbutils/src/main/scripts/dbsetup/config-schema.xml b/modules/core/dbutils/src/main/scripts/dbsetup/config-schema.xml
index 07f101d..7e189d9 100644
--- a/modules/core/dbutils/src/main/scripts/dbsetup/config-schema.xml
+++ b/modules/core/dbutils/src/main/scripts/dbsetup/config-schema.xml
@@ -27,6 +27,8 @@
         <column name="NAME" type="VARCHAR2" required="false" size="255"/>
         <column name="DISPLAY_NAME" type="VARCHAR2" required="false" size="100"/>
         <column name="DESCRIPTION" type="VARCHAR2" required="false" size="1000"/>
+        <column name="MIN" type="INTEGER" required="false"  />
+        <column name="MAX" type="INTEGER" required="false"  />
         <column name="DEFAULT_VALUE" type="VARCHAR2" required="false" size="2000"/>
         <column name="REQUIRED" type="BOOLEAN" required="false"/>
         <column name="READONLY" type="BOOLEAN" required="false"/>
diff --git a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
index 312da82..2aafb72 100644
--- a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
+++ b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
@@ -4006,6 +4006,12 @@
             <schemaSpec version="2.121">
               <schema-javaTask className="ContentSourceConfigurationObfuscationUpgradeTask" />
             </schemaSpec>
+
+             <schemaSpec version="2.122">
+               <schema-alterColumn   table="RHQ_CONFIG_PROP_DEF" column="MIN" columnType="INTEGER"/>
+               <schema-alterColumn   table="RHQ_CONFIG_PROP_DEF" column="MAX" columnType="INTEGER"/>
+            </schemaSpec>
+
         </dbupgrade>
     </target>
 </project>
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/definition/PropertyDefinitionList.java b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/definition/PropertyDefinitionList.java
index 1b1f248..92c8df6 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/definition/PropertyDefinitionList.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/definition/PropertyDefinitionList.java
@@ -48,10 +48,8 @@ import java.lang.Integer;
 public class PropertyDefinitionList extends PropertyDefinition {
     private static final long serialVersionUID = 1L;
 
-    @Transient
     private int min = 0;
 
-    @Transient
     private int max = Integer.MAX_VALUE;
 
     @JoinColumn(name = "parent_list_definition_id")


commit be31334f300fda868fddc5a88d7525e7f333828e
Author: Mike Thompson <mithomps at redhat.com>
Date:   Fri Jul 13 10:06:10 2012 -0700

    [BZ 733487 - Search bar saved searches menu ignores clicks] Replace existing GWT search bar with new smartgwt search bar.

diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/IconEnum.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/IconEnum.java
index 987dca6..e586406 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/IconEnum.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/IconEnum.java
@@ -88,6 +88,16 @@ public enum IconEnum {
     BUNDLE_REVERT("subsystems/bundle/BundleAction_Revert_16.png", "subsystems/bundle/BundleAction_Revert_24.png"),
 
     /////////////////////////////
+    // Search
+    /////////////////////////////
+    STAR_OFF("search/star1.png"),
+    STAR_ACTIVE("search/star2.png"),
+    STAR_ON("search/star3.png"),
+    ARROW_WHITE("search/menu_arrow.png"),
+    ARROW_GRAY("search/menu_arrow_down.png"),
+    TRASH("search/trash.png"),
+
+    /////////////////////////////
     //  Administration Tab
     /////////////////////////////
     ADMIN("global/Admin_16.png", "global/Admin_24.png"),
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/carousel/Carousel.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/carousel/Carousel.java
index a89e1e2..31e58e6 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/carousel/Carousel.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/carousel/Carousel.java
@@ -18,15 +18,6 @@
  */
 package org.rhq.enterprise.gui.coregui.client.components.carousel;
 
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Date;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
 import com.google.gwt.event.dom.client.KeyCodes;
 import com.smartgwt.client.data.Criteria;
 import com.smartgwt.client.types.Overflow;
@@ -34,19 +25,11 @@ import com.smartgwt.client.types.SelectionStyle;
 import com.smartgwt.client.types.VerticalAlignment;
 import com.smartgwt.client.util.BooleanCallback;
 import com.smartgwt.client.util.SC;
-import com.smartgwt.client.widgets.Canvas;
-import com.smartgwt.client.widgets.HTMLFlow;
-import com.smartgwt.client.widgets.IButton;
-import com.smartgwt.client.widgets.Img;
-import com.smartgwt.client.widgets.Label;
+import com.smartgwt.client.widgets.*;
 import com.smartgwt.client.widgets.events.ClickEvent;
 import com.smartgwt.client.widgets.events.ClickHandler;
 import com.smartgwt.client.widgets.events.DoubleClickHandler;
-import com.smartgwt.client.widgets.form.fields.FormItem;
-import com.smartgwt.client.widgets.form.fields.HiddenItem;
-import com.smartgwt.client.widgets.form.fields.SelectItem;
-import com.smartgwt.client.widgets.form.fields.SpinnerItem;
-import com.smartgwt.client.widgets.form.fields.TextItem;
+import com.smartgwt.client.widgets.form.fields.*;
 import com.smartgwt.client.widgets.form.fields.events.ChangedEvent;
 import com.smartgwt.client.widgets.form.fields.events.ChangedHandler;
 import com.smartgwt.client.widgets.form.fields.events.KeyPressEvent;
@@ -56,20 +39,14 @@ import com.smartgwt.client.widgets.layout.LayoutSpacer;
 import com.smartgwt.client.widgets.menu.IMenuButton;
 import com.smartgwt.client.widgets.menu.MenuItem;
 import com.smartgwt.client.widgets.menu.events.MenuItemClickEvent;
-
 import org.rhq.core.domain.search.SearchSubsystem;
 import org.rhq.enterprise.gui.coregui.client.CoreGUI;
 import org.rhq.enterprise.gui.coregui.client.RefreshableView;
 import org.rhq.enterprise.gui.coregui.client.components.buttons.BackButton;
-import org.rhq.enterprise.gui.coregui.client.components.form.SearchBarItem;
-import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableDynamicForm;
-import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableHLayout;
-import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableIButton;
-import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableIMenuButton;
-import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableMenu;
-import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableToolStrip;
-import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableVLayout;
-import org.rhq.enterprise.gui.coregui.client.util.selenium.SeleniumUtility;
+import org.rhq.enterprise.gui.coregui.client.components.form.EnhancedSearchBarItem;
+import org.rhq.enterprise.gui.coregui.client.util.selenium.*;
+
+import java.util.*;
 
 /**
  * Similar to (i.e. originally a copy of) Table but instead of encapsulating a ListGrid, it manages a list of 
@@ -193,8 +170,7 @@ public abstract class Carousel extends LocatableHLayout implements RefreshableVi
 
         } else {
             if (!this.hideSearchBar) {
-                final SearchBarItem searchFilter = new SearchBarItem("search", MSG.common_button_search(),
-                    getSearchSubsystem(), getInitialSearchBarSearchText());
+                final EnhancedSearchBarItem searchFilter = new EnhancedSearchBarItem("search",  getSearchSubsystem(), getInitialSearchBarSearchText());
                 setFilterFormItems(searchFilter);
             }
         }
@@ -877,7 +853,7 @@ public abstract class Carousel extends LocatableHLayout implements RefreshableVi
         com.google.gwt.event.dom.client.KeyPressHandler {
 
         private Carousel carousel;
-        private SearchBarItem searchBarItem;
+        private EnhancedSearchBarItem searchBarItem;
         private HiddenItem hiddenItem;
 
         public CarouselFilter(Carousel carousel) {
@@ -898,13 +874,13 @@ public abstract class Carousel extends LocatableHLayout implements RefreshableVi
                     nextFormItem.addKeyPressHandler(this);
                 } else if (nextFormItem instanceof SelectItem) {
                     nextFormItem.addChangedHandler(this);
-                } else if (nextFormItem instanceof SearchBarItem) {
-                    searchBarItem = (SearchBarItem) nextFormItem;
-                    searchBarItem.getSearchBar().addKeyPressHandler(this);
+                } else if (nextFormItem instanceof EnhancedSearchBarItem) {
+                    //searchBarItem = (SearchBarItem) nextFormItem;
+                    //searchBarItem.getSearchBar().addKeyPressHandler(this);
                     String name = searchBarItem.getName();
                     searchBarItem.setName(name + "_hidden");
                     hiddenItem = new HiddenItem(name);
-                    hiddenItem.setValue(searchBarItem.getSearchBar().getValue());
+                    //hiddenItem.setValue(searchBarItem.getSearchBar().getValue());
                 }
             }
 
@@ -943,7 +919,7 @@ public abstract class Carousel extends LocatableHLayout implements RefreshableVi
                 return;
             }
             // TODO: figure out why this event is being sent twice
-            hiddenItem.setValue(searchBarItem.getSearchBar().getValue());
+            //hiddenItem.setValue(searchBarItem.getSearchBar().getValue());
             fetchFilteredCarouselData();
         }
     }
@@ -1103,7 +1079,7 @@ public abstract class Carousel extends LocatableHLayout implements RefreshableVi
          * Execute the action with the currently selected record(s) as the target(s).
          *
          * @param selection the currently selected record(s)
-         * @param actionValue a value optionally supplied by the action (for example, a menuItem action's selection) 
+         * @param actionValue a value optionally supplied by the action (for example, a menuItem action's selection)
          */
         void executeAction(Object actionValue); //TODO add arg
     }
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/form/EnhancedSearchBarItem.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/form/EnhancedSearchBarItem.java
new file mode 100644
index 0000000..bb0a453b
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/form/EnhancedSearchBarItem.java
@@ -0,0 +1,62 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 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.gui.coregui.client.components.form;
+
+import com.smartgwt.client.types.VerticalAlignment;
+import com.smartgwt.client.widgets.Canvas;
+import com.smartgwt.client.widgets.form.fields.CanvasItem;
+import org.rhq.core.domain.search.SearchSubsystem;
+import org.rhq.enterprise.gui.coregui.client.searchbar.EnhancedSearchBar;
+
+/**
+ * Wrap the SearchBar component in CanvasItem so it can be put into a DynamicForm.
+ * @author Mike Thompson
+ */
+public class EnhancedSearchBarItem extends CanvasItem {
+    private Canvas canvas = new Canvas();
+    private EnhancedSearchBar searchBar;
+
+    public EnhancedSearchBarItem(String name, SearchSubsystem subsystem, String initialSearchText) {
+        super(name, null);
+        setShowTitle(false);
+
+        searchBar = new EnhancedSearchBar(subsystem, initialSearchText);
+
+        searchBar.setHeight("30px");
+        searchBar.setWidth100();
+        canvas.addChild(searchBar);
+        canvas.setWidth100();
+
+        setCanvas(canvas);
+        setHeight(30);
+        setWidth("100%");
+        setTitleVAlign(VerticalAlignment.TOP);
+    }
+
+    @Override
+    public Canvas getCanvas() {
+        return canvas;
+    }
+
+    public EnhancedSearchBar getSearchBar() {
+        return searchBar;
+    }
+
+
+}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/form/ImgButtonItem.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/form/ImgButtonItem.java
new file mode 100644
index 0000000..48f9314
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/form/ImgButtonItem.java
@@ -0,0 +1,67 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 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.gui.coregui.client.components.form;
+
+import com.smartgwt.client.types.VerticalAlignment;
+import com.smartgwt.client.widgets.Canvas;
+import com.smartgwt.client.widgets.ImgButton;
+import com.smartgwt.client.widgets.form.fields.CanvasItem;
+
+/**
+ * Image Button Item is a convenience class to use ImgButton in a DynamicForm.
+ *
+ * @author Mike Thompson
+ */
+public class ImgButtonItem extends CanvasItem{
+
+    private Canvas canvas = new Canvas();
+    private ImgButton imageButton;
+
+    public ImgButtonItem(){
+        construct(null);
+    }
+
+    public ImgButtonItem(String imagePath) {
+        construct(imagePath);
+    }
+
+    private void construct(String imagePath) {
+        imageButton = new ImgButton();
+
+        if(null != imagePath){
+           imageButton.setIcon(imagePath);
+        }
+        imageButton.setHeight("30px");
+        canvas.addChild(imageButton);
+        setShowTitle(false);
+
+        setCanvas(canvas);
+        setHeight(30);
+        setTitleVAlign(VerticalAlignment.TOP);
+    }
+
+    @Override
+    public Canvas getCanvas() {
+        return canvas;
+    }
+
+    public ImgButton getImageButton() {
+        return imageButton;
+    }
+}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/form/SearchBarItem.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/form/SearchBarItem.java
deleted file mode 100644
index a0a5689..0000000
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/form/SearchBarItem.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2010 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.gui.coregui.client.components.form;
-
-import com.smartgwt.client.types.VerticalAlignment;
-import com.smartgwt.client.widgets.Canvas;
-import com.smartgwt.client.widgets.form.fields.CanvasItem;
-
-import org.rhq.core.domain.search.SearchSubsystem;
-import org.rhq.enterprise.gui.coregui.client.search.FlexSearchBar;
-
-/**
- * @author Joseph Marques
- */
-public class SearchBarItem extends CanvasItem {
-
-    private Canvas canvas = new Canvas();
-    private FlexSearchBar searchBar;
-
-    public SearchBarItem(String name, String title, SearchSubsystem subsystem) {
-        this(name, title, subsystem, null);
-    }
-
-    public SearchBarItem(String name, String title, SearchSubsystem subsystem, String initialSearchText) {
-        super(name, title);
-
-        searchBar = new FlexSearchBar(subsystem, initialSearchText);
-
-        searchBar.setHeight("30px");
-        canvas.addChild(searchBar);
-
-        setCanvas(canvas);
-        setHeight(30);
-        setTitleVAlign(VerticalAlignment.TOP);
-    }
-
-    @Override
-    public Canvas getCanvas() {
-        return canvas;
-    }
-
-    public FlexSearchBar getSearchBar() {
-        return searchBar;
-    }
-
-}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/table/Table.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/table/Table.java
index 27692b8..2eea340 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/table/Table.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/table/Table.java
@@ -26,7 +26,6 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
-import com.google.gwt.event.dom.client.KeyCodes;
 import com.google.gwt.user.client.Timer;
 import com.smartgwt.client.data.Criteria;
 import com.smartgwt.client.data.DSCallback;
@@ -50,6 +49,7 @@ import com.smartgwt.client.widgets.events.ClickEvent;
 import com.smartgwt.client.widgets.events.ClickHandler;
 import com.smartgwt.client.widgets.events.DoubleClickEvent;
 import com.smartgwt.client.widgets.events.DoubleClickHandler;
+import com.smartgwt.client.widgets.form.fields.ComboBoxItem;
 import com.smartgwt.client.widgets.form.fields.FormItem;
 import com.smartgwt.client.widgets.form.fields.HiddenItem;
 import com.smartgwt.client.widgets.form.fields.SelectItem;
@@ -76,7 +76,7 @@ import org.rhq.enterprise.gui.coregui.client.InitializableView;
 import org.rhq.enterprise.gui.coregui.client.RefreshableView;
 import org.rhq.enterprise.gui.coregui.client.components.TitleBar;
 import org.rhq.enterprise.gui.coregui.client.components.form.DateFilterItem;
-import org.rhq.enterprise.gui.coregui.client.components.form.SearchBarItem;
+import org.rhq.enterprise.gui.coregui.client.components.form.EnhancedSearchBarItem;
 import org.rhq.enterprise.gui.coregui.client.util.CriteriaUtility;
 import org.rhq.enterprise.gui.coregui.client.util.Log;
 import org.rhq.enterprise.gui.coregui.client.util.RPCDataSource;
@@ -286,7 +286,7 @@ public class Table<DS extends RPCDataSource> extends LocatableHLayout implements
      * </pre>
      * This is called from onInit() and guarantees grid not null.
      * 
-     * @param ListGrid grid
+     * @param grid
      */
     protected void configureListGrid(ListGrid grid) {
         listGrid.setWidth100();
@@ -310,8 +310,8 @@ public class Table<DS extends RPCDataSource> extends LocatableHLayout implements
             configureTableFilters();
         } else {
             if (!this.hideSearchBar) {
-                final SearchBarItem searchFilter = new SearchBarItem("search", MSG.common_button_search(),
-                    getSearchSubsystem(), getInitialSearchBarSearchText());
+                final EnhancedSearchBarItem searchFilter = new EnhancedSearchBarItem("search", getSearchSubsystem(),
+                    getInitialSearchBarSearchText());
                 setFilterFormItems(searchFilter);
             }
         }
@@ -771,10 +771,7 @@ public class Table<DS extends RPCDataSource> extends LocatableHLayout implements
         final ListGrid listGrid = getListGrid();
 
         Criteria criteria = getCurrentCriteria();
-        if (Log.isDebugEnabled()) {
-            Log.debug(getClass().getName() + ".refresh() using criteria [" + CriteriaUtility.toString(criteria)
-                + "]...");
-        }
+        Log.debug(getClass().getName() + ".refresh() using criteria [" + CriteriaUtility.toString(criteria) + "]...");
         listGrid.setCriteria(criteria);
 
         if (resetPaging) {
@@ -1150,11 +1147,10 @@ public class Table<DS extends RPCDataSource> extends LocatableHLayout implements
      *
      * @author Joseph Marques 
      */
-    private static class TableFilter extends LocatableDynamicForm implements KeyPressHandler, ChangedHandler,
-        com.google.gwt.event.dom.client.KeyPressHandler {
+    private static class TableFilter extends LocatableDynamicForm implements KeyPressHandler, ChangedHandler {
 
         private Table<?> table;
-        private SearchBarItem searchBarItem;
+        private EnhancedSearchBarItem searchBarItem;
         private HiddenItem hiddenItem;
 
         public TableFilter(Table<?> table) {
@@ -1175,22 +1171,29 @@ public class Table<DS extends RPCDataSource> extends LocatableHLayout implements
                     nextFormItem.addChangedHandler(this);
                 } else if (nextFormItem instanceof DateFilterItem) {
                     nextFormItem.addChangedHandler(this);
-                } else if (nextFormItem instanceof SearchBarItem) {
-                    searchBarItem = (SearchBarItem) nextFormItem;
-                    searchBarItem.getSearchBar().addKeyPressHandler(this);
+                } else if (nextFormItem instanceof EnhancedSearchBarItem) {
+                    searchBarItem = (EnhancedSearchBarItem) nextFormItem;
+                    searchBarItem.getSearchBar().getSearchComboboxItem().addKeyPressHandler(this);
                     String name = searchBarItem.getName();
+                    // postfix the name of the item so it is not processed by the filters and that the
+                    // hidden item is used instead.
                     searchBarItem.setName(name + "_hidden");
                     hiddenItem = new HiddenItem(name);
-                    hiddenItem.setValue(searchBarItem.getSearchBar().getValue());
+                    hiddenItem.setValue(searchBarItem.getSearchBar().getSearchComboboxItem().getValueAsString());
                 }
             }
 
             if (hiddenItem != null) {
+                Log.debug("Found hidden items");
+                // Add the hidden item if it exists
                 FormItem[] tmpItems = new FormItem[items.length + 1];
                 System.arraycopy(items, 0, tmpItems, 0, items.length);
                 tmpItems[items.length] = hiddenItem;
                 items = tmpItems;
             }
+            for (FormItem item : items) {
+                Log.debug(" ********     Form Items sent: " + item.getName() + ": " + item.getValue());
+            }
 
             super.setItems(items);
         }
@@ -1203,7 +1206,22 @@ public class Table<DS extends RPCDataSource> extends LocatableHLayout implements
         public void onKeyPress(KeyPressEvent event) {
             if (event.getKeyName().equals("Enter")) {
                 Log.debug("Table.TableFilter Pressed Enter key");
-                fetchFilteredTableData();
+
+                if (null != searchBarItem) {
+                    ComboBoxItem comboBoxItem = searchBarItem.getSearchBar().getSearchComboboxItem();
+                    String searchBarValue = comboBoxItem.getValueAsString();
+                    String hiddenValue = (String) hiddenItem.getValue();
+                    Log.debug("Table.TableFilter searchBarValue :" + searchBarValue + ", hiddenValue" + hiddenValue);
+
+                    // Only send a fetch request if the user actually changed the search expression.
+                    if (!equals(searchBarValue, hiddenValue)) {
+                        hiddenItem.setValue(searchBarValue);
+                        Log.debug("Table.TableFilter fetchFilteredTableData");
+                        fetchFilteredTableData();
+                    }
+                } else {
+                    fetchFilteredTableData();
+                }
             }
         }
 
@@ -1216,25 +1234,6 @@ public class Table<DS extends RPCDataSource> extends LocatableHLayout implements
             return super.getFields().length != 0;
         }
 
-        @Override
-        public void onKeyPress(com.google.gwt.event.dom.client.KeyPressEvent event) {
-            if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) {
-                // TODO (ips, 10/14/11): Figure out why this event is being sent twice. However, this is not urgent,
-                //                       since the if check below will prevent the 2nd event from triggering a redundant
-                //                       fetch request.
-                Log.debug("Table.TableFilter Pressed Enter key2");
-                String searchBarValue = searchBarItem.getSearchBar().getValue();
-                String hiddenValue = (String) hiddenItem.getValue();
-                Log.debug("Table.TableFilter searchBarValue :" + searchBarValue + ", hiddenValue" + hiddenValue);
-                // Only send a fetch request if the user actually changed the search expression.
-                if (!equals(searchBarValue, hiddenValue)) {
-                    hiddenItem.setValue(searchBarValue);
-                    Log.debug("Table.TableFilter fetchFilteredTableData");
-                    fetchFilteredTableData();
-                }
-            }
-        }
-
         private static boolean equals(String string1, String string2) {
             if (string1 == null) {
                 return (string2 == null);
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceDatasource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceDatasource.java
index 1b34b6d..b2084df 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceDatasource.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceDatasource.java
@@ -18,24 +18,6 @@
  */
 package org.rhq.enterprise.gui.coregui.client.inventory.resource;
 
-import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.AVAILABILITY;
-import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.CATEGORY;
-import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.CTIME;
-import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.DESCRIPTION;
-import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.ITIME;
-import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.KEY;
-import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.LOCATION;
-import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.MODIFIER;
-import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.MTIME;
-import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.NAME;
-import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.PLUGIN;
-import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.TYPE;
-import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.VERSION;
-
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-
 import com.google.gwt.user.client.rpc.AsyncCallback;
 import com.smartgwt.client.data.DSRequest;
 import com.smartgwt.client.data.DSResponse;
@@ -46,7 +28,6 @@ import com.smartgwt.client.data.fields.DataSourceIntegerField;
 import com.smartgwt.client.data.fields.DataSourceTextField;
 import com.smartgwt.client.rpc.RPCResponse;
 import com.smartgwt.client.widgets.grid.ListGridRecord;
-
 import org.rhq.core.domain.criteria.ResourceCriteria;
 import org.rhq.core.domain.measurement.AvailabilityType;
 import org.rhq.core.domain.resource.Resource;
@@ -59,9 +40,16 @@ import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
 import org.rhq.enterprise.gui.coregui.client.gwt.ResourceGWTServiceAsync;
 import org.rhq.enterprise.gui.coregui.client.inventory.resource.type.ResourceTypeRepository;
 import org.rhq.enterprise.gui.coregui.client.inventory.resource.type.ResourceTypeRepository.TypesLoadedCallback;
+import org.rhq.enterprise.gui.coregui.client.util.Log;
 import org.rhq.enterprise.gui.coregui.client.util.RPCDataSource;
 import org.rhq.enterprise.gui.coregui.client.util.message.Message;
 
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+
+import static org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDataSourceField.*;
+
 /**
  * @author Greg Hinkle
  */
@@ -230,7 +218,7 @@ public class ResourceDatasource extends RPCDataSource<Resource, ResourceCriteria
     protected ResourceCriteria getFetchCriteria(final DSRequest request) {
         ResourceCriteria criteria = new ResourceCriteria();
 
-        //printRequestCriteria(request);
+        printRequestCriteria(request);
         criteria.addFilterId(getFilter(request, "id", Integer.class));
         criteria.addFilterParentResourceId(getFilter(request, "parentId", Integer.class));
         criteria.addFilterCurrentAvailability(getFilter(request, AVAILABILITY.propertyName(), AvailabilityType.class));
@@ -245,6 +233,8 @@ public class ResourceDatasource extends RPCDataSource<Resource, ResourceCriteria
         criteria.addFilterTagName(getFilter(request, "tagName", String.class));
         criteria.addFilterVersion(getFilter(request, "version", String.class));
         criteria.addFilterParentResourceCategory(getFilter(request, FILTER_PARENT_CATEGORY, ResourceCategory.class));
+        //@todo: Remove me when finished debugging search expression
+        Log.debug(" *** ResourceCriteria Search String: " + getFilter(request, "search", String.class));
         criteria.setSearchExpression(getFilter(request, "search", String.class));
 
         return criteria;
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/ResourceConfigurationEditView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/ResourceConfigurationEditView.java
index 52e3c69..4e87eb0 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/ResourceConfigurationEditView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/ResourceConfigurationEditView.java
@@ -47,7 +47,6 @@ import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.ResourceD
 import org.rhq.enterprise.gui.coregui.client.inventory.resource.type.ResourceTypeRepository;
 import org.rhq.enterprise.gui.coregui.client.inventory.resource.type.ResourceTypeRepository.MetadataType;
 import org.rhq.enterprise.gui.coregui.client.inventory.resource.type.ResourceTypeRepository.TypeLoadedCallback;
-import org.rhq.enterprise.gui.coregui.client.util.Log;
 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.LocatableIButton;
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/search/AbstractSearchBar.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/search/AbstractSearchBar.java
index 7758c4a..d26913a 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/search/AbstractSearchBar.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/search/AbstractSearchBar.java
@@ -19,14 +19,13 @@
 package org.rhq.enterprise.gui.coregui.client.search;
 
 import com.google.gwt.user.client.ui.Composite;
-
 import org.rhq.core.domain.search.SearchSubsystem;
 
 /**
  * Abstract class for SearchBar, so that a separate implementation can be written alongside the original. 
- * 
  * @author Joseph Marques
  */
+ at Deprecated
 public abstract class AbstractSearchBar extends Composite {
 
     public abstract SearchSubsystem getSearchSubsystem();
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/search/FlexSearchBar.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/search/FlexSearchBar.java
index cb39479..4875c92 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/search/FlexSearchBar.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/search/FlexSearchBar.java
@@ -18,32 +18,11 @@
  */
 package org.rhq.enterprise.gui.coregui.client.search;
 
-import java.util.List;
-
-import java.util.logging.Logger;
-import com.google.gwt.event.dom.client.BlurEvent;
-import com.google.gwt.event.dom.client.BlurHandler;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.event.dom.client.FocusEvent;
-import com.google.gwt.event.dom.client.FocusHandler;
-import com.google.gwt.event.dom.client.KeyCodes;
-import com.google.gwt.event.dom.client.KeyPressEvent;
-import com.google.gwt.event.dom.client.KeyPressHandler;
-import com.google.gwt.event.dom.client.MouseOutEvent;
-import com.google.gwt.event.dom.client.MouseOutHandler;
-import com.google.gwt.event.dom.client.MouseOverEvent;
-import com.google.gwt.event.dom.client.MouseOverHandler;
+import com.google.gwt.event.dom.client.*;
 import com.google.gwt.event.logical.shared.CloseEvent;
 import com.google.gwt.event.logical.shared.CloseHandler;
 import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwt.user.client.ui.HorizontalPanel;
-import com.google.gwt.user.client.ui.Image;
-import com.google.gwt.user.client.ui.Label;
-import com.google.gwt.user.client.ui.Panel;
-import com.google.gwt.user.client.ui.PopupPanel;
-import com.google.gwt.user.client.ui.TextBox;
-
+import com.google.gwt.user.client.ui.*;
 import org.rhq.core.domain.auth.Subject;
 import org.rhq.core.domain.criteria.SavedSearchCriteria;
 import org.rhq.core.domain.search.SavedSearch;
@@ -59,9 +38,12 @@ import org.rhq.enterprise.gui.coregui.client.util.Log;
 import org.rhq.enterprise.gui.coregui.client.util.message.Message;
 import org.rhq.enterprise.gui.coregui.client.util.message.Message.Severity;
 
+import java.util.List;
+
 /**
  * @author Joseph Marques
  */
+ at Deprecated
 public class FlexSearchBar extends AbstractSearchBar {
 
     private static final Messages MSG = CoreGUI.getMessages();
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/search/SearchBar.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/search/SearchBar.java
deleted file mode 100644
index c4dc6eb..0000000
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/search/SearchBar.java
+++ /dev/null
@@ -1,586 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2010 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.gui.coregui.client.search;
-
-import java.util.List;
-
-import com.google.gwt.event.dom.client.BlurEvent;
-import com.google.gwt.event.dom.client.BlurHandler;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.event.dom.client.FocusEvent;
-import com.google.gwt.event.dom.client.FocusHandler;
-import com.google.gwt.event.dom.client.KeyCodes;
-import com.google.gwt.event.dom.client.KeyPressEvent;
-import com.google.gwt.event.dom.client.KeyPressHandler;
-import com.google.gwt.event.dom.client.MouseOutEvent;
-import com.google.gwt.event.dom.client.MouseOutHandler;
-import com.google.gwt.event.dom.client.MouseOverEvent;
-import com.google.gwt.event.dom.client.MouseOverHandler;
-import com.google.gwt.event.logical.shared.CloseEvent;
-import com.google.gwt.event.logical.shared.CloseHandler;
-import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.Element;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwt.user.client.ui.Image;
-import com.google.gwt.user.client.ui.Label;
-import com.google.gwt.user.client.ui.PopupPanel;
-import com.google.gwt.user.client.ui.RootPanel;
-import com.google.gwt.user.client.ui.TextBox;
-
-import org.rhq.core.domain.auth.Subject;
-import org.rhq.core.domain.criteria.SavedSearchCriteria;
-import org.rhq.core.domain.search.SavedSearch;
-import org.rhq.core.domain.search.SearchSubsystem;
-import org.rhq.enterprise.gui.coregui.client.CoreGUI;
-import org.rhq.enterprise.gui.coregui.client.Messages;
-import org.rhq.enterprise.gui.coregui.client.UserSessionManager;
-import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
-import org.rhq.enterprise.gui.coregui.client.search.favorites.SavedSearchGrid;
-import org.rhq.enterprise.gui.coregui.client.search.favorites.SavedSearchGrid.SavedSearchSelectionHandler;
-import org.rhq.enterprise.gui.coregui.client.search.suggest.SuggestTextBox_v3;
-import org.rhq.enterprise.gui.coregui.client.util.Log;
-import org.rhq.enterprise.gui.coregui.client.util.message.Message;
-import org.rhq.enterprise.gui.coregui.client.util.message.Message.Severity;
-
-/**
- * @author Joseph Marques
- */
-public class SearchBar extends AbstractSearchBar {
-
-    private static final Messages MSG = CoreGUI.getMessages();
-
-    public static final String DEFAULT_PATTERN_NAME = MSG.view_searchBar_defaultPattern();
-
-    private static final String IMAGE_DIR = "/coregui/images/search/";
-
-    private static final String STAR_OFF_URL = IMAGE_DIR + "star1.png";
-    private static final String STAR_ACTIVE_URL = IMAGE_DIR + "star2.png";
-    private static final String STAR_ON_URL = IMAGE_DIR + "star3.png";
-
-    private static final String ARROW_WHITE_URL = IMAGE_DIR + "menu_arrow.png";
-    private static final String ARROW_GRAY_URL = IMAGE_DIR + "menu_arrow_down.png";
-
-    public static final String TRASH = IMAGE_DIR + "trash.png";
-
-    private final TextBox patternField = new TextBox();
-    private final SuggestTextBox_v3 autoCompletePatternField = new SuggestTextBox_v3(this, patternField);
-    private final TextBox patternNameField = new TextBox();
-    private final Label patternNameLabel = new Label();
-
-    private final Image starImage = new Image(STAR_OFF_URL);
-    private final Image arrowImage = new Image(ARROW_WHITE_URL);
-
-    private final PopupPanel savedSearchesPanel = new PopupPanel(true);
-    private SavedSearchGrid savedSearchesGrid;
-
-    private Integer currentSearchId = 0;
-    private long lastNameFieldBlurTime = 0;
-
-    private SearchSubsystem searchSubsystem;
-    private String defaultSearchText;
-    private String defaultSavedSearchPatternId;
-    private String selectedTab;
-
-    private Element searchButton;
-
-    private AsyncCallback<Void> blackHoleCallback = new AsyncCallback<Void>() {
-        @Override
-        public void onFailure(Throwable caught) {
-            // old search bar can't access CoreGUI.getErrorHandler(), silently ignore the error
-        }
-
-        @Override
-        public void onSuccess(Void result) {
-            // old search bar can't access CoreGUI.getMessageCenter(), silently continue with success path
-        }
-    };
-
-    public static boolean existsOnPage() {
-        return getSearchBarElement() != null;
-    }
-
-    private static Element getSearchBarElement() {
-        return DOM.getElementById("searchBar");
-    }
-
-    public void loadAdditionalDataFromDivAttributes() {
-        Element searchBarElement = getSearchBarElement();
-
-        String searchButtonId = searchBarElement.getAttribute("searchButtonId");
-        searchButton = DOM.getElementById(searchButtonId);
-
-        // Don't know what this originally was going to be used for, but if you notice,
-        // after all the if-stmts are evaluated true, the only piece of code to be invoked
-        // (prepareSearchExecution()) has been commented out. So this is a no-op. In addition
-        // the second if-stmt (getEventTarget().equals(searchButton) doesn't look correct and
-        // may not ever evaluate to true anyway. Commenting this out, in case something like this
-        // is needed in the future, but we'll havee to probably fix that if-stmt first.
-
-        //        Event.addNativePreviewHandler(new NativePreviewHandler() {
-        //            public void onPreviewNativeEvent(NativePreviewEvent event) {
-        //                if (event.getNativeEvent() != null && event.getNativeEvent().getEventTarget() != null) {
-        //                    if (event.getNativeEvent().getEventTarget().equals(searchButton)
-        //                        && event.getTypeInt() == Event.ONMOUSEDOWN) {
-        //                        //prepareSearchExecution();
-        //                    }
-        //                }
-        //            }
-        //        });
-
-        String searchSubsystem = searchBarElement.getAttribute("searchSubsystem");
-        setSearchSubsystem(SearchSubsystem.valueOf(searchSubsystem.toUpperCase()));
-
-        String defaultSearchText = searchBarElement.getAttribute("defaultSearchText");
-        setDefaultSearchText(defaultSearchText);
-
-        String defaultSavedSearchPatternId = searchBarElement.getAttribute("defaultSavedSearchPatternId");
-        setDefaultSavedSearchPatternId(defaultSavedSearchPatternId);
-
-        String tab = searchBarElement.getAttribute("subtab");
-        if (tab != null) {
-            tab = tab.trim().toLowerCase();
-            if (tab.equals("") || tab.equals("all")) {
-                tab = null;
-            }
-        }
-        this.selectedTab = tab;
-    }
-
-    public SearchBar() {
-        Log.info("Loading SearchBar...");
-
-        // in the future, will be instantiated directly from a higher-level widget
-        if (existsOnPage()) {
-            loadAdditionalDataFromDivAttributes();
-        }
-
-        RootPanel.get("patternFieldContainer").add(autoCompletePatternField);
-        RootPanel.get("patternNameFieldContainer").add(patternNameField);
-        RootPanel.get("patternNameLabelContainer").add(patternNameLabel);
-        RootPanel.get("starImageContainer").add(starImage);
-        RootPanel.get("arrowImageContainer").add(arrowImage);
-        RootPanel.get("savedSearchesContainer").add(savedSearchesPanel);
-
-        setupAutoCompletingPatternField();
-        setupPatternNameField();
-        setupPatternNameLabel();
-        setupStarImage();
-        setupArrowImage();
-        setupSavedSearches();
-
-        // 
-        if (defaultSearchText != null) {
-            this.autoCompletePatternField.setText(defaultSearchText);
-            click(searchButton); // execute the search with this default search expression
-        } else if (defaultSavedSearchPatternId != null) {
-            try {
-                Integer savedSearchId = Integer.valueOf(defaultSavedSearchPatternId);
-                activateSavedSearch(savedSearchId);
-            } catch (Exception e) {
-                this.autoCompletePatternField.setText(MSG
-                    .view_searchBar_savedSearch_failFind(defaultSavedSearchPatternId));
-                click(searchButton); // execute the search, which will help to further highlight the error
-            }
-        }
-
-        // presume the enclosing page logic loads results without a button click
-    }
-
-    public void setSearchSubsystem(SearchSubsystem searchSubsystem) {
-        this.searchSubsystem = searchSubsystem;
-        savedSearchesGrid = new SavedSearchGrid(searchSubsystem);
-    }
-
-    public SearchSubsystem getSearchSubsystem() {
-        return searchSubsystem;
-    }
-
-    public void setDefaultSearchText(String defaultSearchText) {
-        if (defaultSearchText == null || defaultSearchText.trim().equals("")) {
-            return; // do nothing
-        }
-
-        this.defaultSearchText = defaultSearchText;
-    }
-
-    public String getDefaultSearchText() {
-        return defaultSearchText;
-    }
-
-    public void setDefaultSavedSearchPatternId(String defaultSavedSearchPatternId) {
-        if (defaultSavedSearchPatternId == null || defaultSavedSearchPatternId.trim().equals("")) {
-            return; // do nothing
-        }
-
-        this.defaultSavedSearchPatternId = defaultSavedSearchPatternId;
-    }
-
-    public String getSelectedTab() {
-        return selectedTab;
-    }
-
-    public String getDefaultSavedSearchPatternId() {
-        return defaultSavedSearchPatternId;
-    }
-
-    private void setupAutoCompletingPatternField() {
-        autoCompletePatternField.getElement().setId("patternField");
-        autoCompletePatternField.setStyleName("patternField");
-
-        AutoCompletePatternFieldEventHandler handler = new AutoCompletePatternFieldEventHandler();
-        autoCompletePatternField.getTextBox().addFocusHandler(handler);
-        autoCompletePatternField.getTextBox().addBlurHandler(handler);
-        autoCompletePatternField.addKeyPressHandler(handler);
-    }
-
-    private void setupPatternNameField() {
-        patternNameField.setStyleName("patternNameField");
-        patternNameField.setVisible(false);
-
-        PatternNameFieldEventHandler handler = new PatternNameFieldEventHandler();
-        patternNameField.addKeyPressHandler(handler);
-        patternNameField.addClickHandler(handler);
-        patternNameField.addBlurHandler(handler);
-    }
-
-    private void setupPatternNameLabel() {
-        patternNameLabel.setStyleName("patternNameLabel");
-        patternNameLabel.setVisible(false);
-
-        PatternNameLabelEventHandler handler = new PatternNameLabelEventHandler();
-        patternNameLabel.addClickHandler(handler);
-    }
-
-    private void setupStarImage() {
-        StarImageEventHandler handler = new StarImageEventHandler();
-        starImage.addClickHandler(handler);
-        starImage.addMouseOverHandler(handler);
-        starImage.addMouseOutHandler(handler);
-    }
-
-    private void setupArrowImage() {
-        ArrowImageEventHandler handler = new ArrowImageEventHandler();
-        arrowImage.addClickHandler(handler);
-    }
-
-    private void setupSavedSearches() {
-        savedSearchesPanel.add(savedSearchesGrid);
-        savedSearchesPanel.setStyleName("savedSearchesPanel");
-        savedSearchesGrid.addStyleName("savedSearchesPanel");
-
-        // panel position will be re-calculated on down-arrow click
-        savedSearchesPanel.show();
-        savedSearchesPanel.hide();
-
-        SavedSearchesEventHandler handler = new SavedSearchesEventHandler();
-        savedSearchesPanel.addCloseHandler(handler);
-        savedSearchesGrid.setSavedSearchSelectionHandler(handler);
-    }
-
-    private void turnNameFieldIntoLabel() {
-        String name = patternNameField.getText();
-
-        if (name.equalsIgnoreCase(DEFAULT_PATTERN_NAME)) {
-            name = "";
-        }
-
-        arrowImage.setVisible(true);
-        patternNameField.setVisible(false);
-
-        if (name.equals("")) {
-            GWTServiceLookup.getSearchService().deleteSavedSearch(currentSearchId, blackHoleCallback);
-            currentSearchId = 0;
-            starImage.setUrl(STAR_OFF_URL);
-        } else {
-            // NOTE: currently do not support updated a saved search pattern
-            if (currentSearchId == 0) {
-                String pattern = autoCompletePatternField.getText();
-                createSavedSearch(name, pattern);
-            } else {
-                updateSavedSearchName(currentSearchId, name);
-            }
-            patternNameLabel.setText(elipse(name));
-            patternNameLabel.setVisible(true);
-            starImage.setUrl(STAR_ON_URL);
-        }
-    }
-
-    private void turnNameLabelIntoField() {
-        patternNameField.setText(patternNameLabel.getText());
-        patternNameField.setVisible(true);
-        patternNameLabel.setVisible(false);
-        patternNameField.setFocus(true);
-    }
-
-    private String elipse(String data) {
-        if (data.length() > 14) {
-            return data.substring(0, 14) + "...";
-        }
-        return data;
-    }
-
-    private void createSavedSearch(final String name, final String pattern) {
-        Subject subject = UserSessionManager.getSessionSubject();
-        SavedSearch newSavedSearch = new SavedSearch(searchSubsystem, name, pattern, subject);
-        GWTServiceLookup.getSearchService().createSavedSearch(newSavedSearch, new AsyncCallback<Integer>() {
-            @Override
-            public void onSuccess(Integer newSavedSearchId) {
-                currentSearchId = newSavedSearchId;
-            }
-
-            @Override
-            public void onFailure(Throwable caught) {
-            }
-        });
-    }
-
-    private void updateSavedSearchName(final int savedSearchId, final String newName) {
-        GWTServiceLookup.getSearchService().updateSavedSearchName(savedSearchId, newName, new AsyncCallback<Boolean>() {
-            @Override
-            public void onSuccess(Boolean hadUpdates) {
-                // no message bar to send update message to if hadUpdates
-            }
-
-            @Override
-            public void onFailure(Throwable caught) {
-            }
-        });
-    }
-
-    /*
-     * Event Handlers
-     */
-    class AutoCompletePatternFieldEventHandler implements KeyPressHandler, FocusHandler, BlurHandler {
-        public void onKeyPress(KeyPressEvent event) {
-            // hide pattern field/label, turn off star
-            if (event.getCharCode() == KeyCodes.KEY_ENTER) {
-                return;
-            }
-
-            patternNameLabel.setText("");
-            patternNameLabel.setVisible(false);
-            patternNameField.setValue("", true);
-            patternNameField.setVisible(false);
-            currentSearchId = 0;
-            starImage.setUrl(STAR_OFF_URL);
-
-            if (event.getCharCode() == KeyCodes.KEY_ESCAPE) {
-                autoCompletePatternField.hideSuggestionList();
-                event.preventDefault();
-                event.stopPropagation();
-            }
-        }
-
-        public void onFocus(FocusEvent event) {
-            autoCompletePatternField.showSuggestionList();
-            savedSearchesPanel.hide();
-        }
-
-        public void onBlur(BlurEvent event) {
-            savedSearchesPanel.hide();
-        }
-    }
-
-    class PatternNameFieldEventHandler implements KeyPressHandler, ClickHandler, BlurHandler {
-        public void onKeyPress(KeyPressEvent event) {
-            //if (event.getCharCode() == KeyCodes.KEY_ENTER) {
-            if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) {
-                Log.debug("ENTER key press on pattern name field");
-                turnNameFieldIntoLabel();
-            }
-        }
-
-        public void onClick(ClickEvent event) {
-            if (patternNameField.getText().equals(DEFAULT_PATTERN_NAME)) {
-                patternNameField.setValue("", false);
-            }
-        }
-
-        public void onBlur(BlurEvent event) {
-            Log.debug("onblur event on pattern name field");
-            lastNameFieldBlurTime = System.currentTimeMillis();
-            turnNameFieldIntoLabel();
-        }
-    }
-
-    class PatternNameLabelEventHandler implements ClickHandler {
-        public void onClick(ClickEvent event) {
-            turnNameLabelIntoField();
-        }
-    }
-
-    class StarImageEventHandler implements ClickHandler, MouseOverHandler, MouseOutHandler {
-        public void onClick(ClickEvent event) {
-            Log.debug("onClick for StarImage");
-            lastNameFieldBlurTime = System.currentTimeMillis();
-            long diff = System.currentTimeMillis() - lastNameFieldBlurTime;
-            if (Math.abs(diff) < 750) {
-                /*
-                 * This event propagation is annoying.  If the threshold is set too low, then both
-                 * the name field blur event and this star image click event fire...but the blur
-                 * event fires first, which turns the star white.  Then a click on a white star
-                 * triggers edit mode, re-enabling the name field.  However, setting the threshold
-                 * too high will prevent the click event from being handled when the user naturally
-                 * wants to click on the star in rapid succession within the threshold time frame.
-                 * It is hoped that 750ms will strike a nice balance, and that most users will never
-                 * experienced any oddities from this trade-off.
-                 */
-                return;
-            }
-
-            if (starImage.getUrl().endsWith(STAR_ACTIVE_URL)) {
-                patternNameField.setText(DEFAULT_PATTERN_NAME);
-                patternNameField.setVisible(true);
-                patternNameField.selectAll();
-                patternNameField.setFocus(true);
-                patternNameLabel.setVisible(false);
-            } else if (starImage.getUrl().endsWith(STAR_ON_URL)) {
-                starImage.setUrl(STAR_ACTIVE_URL);
-                patternNameField.setVisible(false);
-                patternNameLabel.setVisible(false);
-                GWTServiceLookup.getSearchService().deleteSavedSearch(currentSearchId, blackHoleCallback);
-            }
-        }
-
-        public void onMouseOver(MouseOverEvent event) {
-            if (starImage.getUrl().endsWith(STAR_OFF_URL)) {
-                starImage.setUrl(STAR_ACTIVE_URL);
-
-            }
-        }
-
-        public void onMouseOut(MouseOutEvent event) {
-            if (starImage.getUrl().endsWith(STAR_ACTIVE_URL) && !patternNameField.isVisible()) {
-                starImage.setUrl(STAR_OFF_URL);
-            }
-        }
-    }
-
-    class ArrowImageEventHandler implements ClickHandler {
-        public void onClick(ClickEvent event) {
-            Log.debug("onClick for ArrowImage");
-            savedSearchesGrid.updateModel(new AsyncCallback<List<SavedSearch>>() {
-                @Override
-                public void onFailure(Throwable caught) {
-                    // nothing needs to be done
-                }
-
-                @Override
-                public void onSuccess(List<SavedSearch> updatedGridData) {
-                    int left = autoCompletePatternField.getAbsoluteLeft();
-                    int top = autoCompletePatternField.getAbsoluteTop() + autoCompletePatternField.getOffsetHeight();
-                    savedSearchesPanel.setPopupPosition(left, top + 5);
-                    savedSearchesPanel.show();
-                    arrowImage.setUrl(ARROW_GRAY_URL);
-                }
-            });
-        }
-    }
-
-    class SavedSearchesEventHandler implements CloseHandler<PopupPanel>, SavedSearchSelectionHandler {
-        public void onClose(CloseEvent<PopupPanel> event) {
-            arrowImage.setUrl(ARROW_WHITE_URL);
-        }
-
-        public void handleSelection(final int rowIndex, final int columnIndex, final SavedSearch savedSearch) {
-            Log.debug("SavedSearchesEventHandler.handleSelection(" + rowIndex + "," + columnIndex + "," + savedSearch
-                + ")");
-            if (columnIndex == 1) {
-                GWTServiceLookup.getSearchService().deleteSavedSearch(savedSearch.getId(), new AsyncCallback<Void>() {
-                    @Override
-                    public void onFailure(Throwable caught) {
-                    }
-
-                    @Override
-                    public void onSuccess(Void result) {
-                        if (currentSearchId == savedSearch.getId()) {
-                            currentSearchId = 0;
-                            patternNameField.setValue("", true);
-                            patternNameField.setVisible(false);
-                            patternNameLabel.setText("");
-                            patternNameLabel.setVisible(false);
-                            autoCompletePatternField.setFocus(true);
-                            starImage.setUrl(STAR_OFF_URL);
-                            savedSearchesPanel.hide();
-                        }
-
-                        // is user deleting the one and only element in the list?
-                        if (savedSearchesGrid.size() == 1) {
-                            savedSearchesPanel.hide();
-                        }
-                        savedSearchesGrid.removeRow(rowIndex);
-                    }
-                });
-            } else {
-                activateSavedSearch(savedSearch); // activating the saved search also clicks the button
-            }
-        }
-    }
-
-    private static native void click(Element button)
-    /*-{
-        button.click();
-    }-*/;
-
-    public void activateSavedSearch(Integer savedSearchId) {
-        activeSavedSearchByIdOrName(savedSearchId, null);
-    }
-
-    public void activateSavedSearch(String savedSearchName) {
-        activeSavedSearchByIdOrName(null, savedSearchName);
-    }
-
-    private void activeSavedSearchByIdOrName(Integer savedSearchId, String savedSearchName) {
-        Subject subject = UserSessionManager.getSessionSubject();
-        SavedSearchCriteria criteria = new SavedSearchCriteria();
-        criteria.addFilterSubjectId(subject.getId());
-        criteria.addFilterId(savedSearchId); // null OK
-        criteria.addFilterName(savedSearchName); // null OK
-
-        GWTServiceLookup.getSearchService().findSavedSearchesByCriteria(criteria,
-            new AsyncCallback<List<SavedSearch>>() {
-                @Override
-                public void onFailure(Throwable caught) {
-                    CoreGUI.getErrorHandler().handleError("Failure to select saved search", caught);
-                }
-
-                @Override
-                public void onSuccess(List<SavedSearch> results) {
-                    if (results.size() != 1) {
-                        CoreGUI.getMessageCenter().notify(new Message("Error selecting saved search", Severity.Error));
-                    } else {
-                        SavedSearch savedSearch = results.get(0);
-                        activateSavedSearch(savedSearch);
-                    }
-                }
-            });
-    }
-
-    public void activateSavedSearch(SavedSearch savedSearch) {
-        currentSearchId = savedSearch.getId();
-        autoCompletePatternField.setValue(savedSearch.getPattern(), true);
-        patternNameField.setValue(savedSearch.getName(), true);
-        Log.debug("search results change: [" + savedSearch.getName() + "," + savedSearch.getPattern() + "]");
-        turnNameFieldIntoLabel();
-        savedSearchesPanel.hide();
-        click(searchButton);
-    }
-
-}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/search/favorites/SavedSearchGrid.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/search/favorites/SavedSearchGrid.java
index 8965900..3845a27 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/search/favorites/SavedSearchGrid.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/search/favorites/SavedSearchGrid.java
@@ -18,15 +18,11 @@
  */
 package org.rhq.enterprise.gui.coregui.client.search.favorites;
 
-import java.util.ArrayList;
-import java.util.List;
-
 import com.google.gwt.user.client.DOM;
 import com.google.gwt.user.client.Element;
 import com.google.gwt.user.client.Event;
 import com.google.gwt.user.client.rpc.AsyncCallback;
 import com.google.gwt.user.client.ui.Grid;
-
 import org.rhq.core.domain.auth.Subject;
 import org.rhq.core.domain.criteria.SavedSearchCriteria;
 import org.rhq.core.domain.search.SavedSearch;
@@ -35,11 +31,14 @@ import org.rhq.core.domain.util.PageOrdering;
 import org.rhq.enterprise.gui.coregui.client.CoreGUI;
 import org.rhq.enterprise.gui.coregui.client.UserSessionManager;
 import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
-import org.rhq.enterprise.gui.coregui.client.search.SearchBar;
+
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * @author Joseph Marques
  */
+ at Deprecated
 public class SavedSearchGrid extends Grid {
 
     private SavedSearchSelectionHandler patternSelectionHandler;
@@ -130,7 +129,7 @@ public class SavedSearchGrid extends Grid {
 
     protected void onRowOver(Element row) {
         Element actionCell = DOM.getChild(row, 1);
-        DOM.setStyleAttribute(actionCell, "backgroundImage", "url(" + SearchBar.TRASH + ")");
+        //DOM.setStyleAttribute(actionCell, "backgroundImage", "url(" + SearchBar.TRASH + ")");
         DOM.setStyleAttribute(actionCell, "backgroundRepeat", "no-repeat");
         DOM.setStyleAttribute(actionCell, "backgroundPosition", "center");
         DOM.setStyleAttribute(actionCell, "width", "24px");
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/search/suggest/SuggestTextBox_v3.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/search/suggest/SuggestTextBox_v3.java
index 8030b2b..c4b91c5 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/search/suggest/SuggestTextBox_v3.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/search/suggest/SuggestTextBox_v3.java
@@ -18,47 +18,17 @@
  */
 package org.rhq.enterprise.gui.coregui.client.search.suggest;
 
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-
-import com.google.gwt.event.dom.client.BlurHandler;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.event.dom.client.FocusHandler;
-import com.google.gwt.event.dom.client.HandlesAllKeyEvents;
-import com.google.gwt.event.dom.client.HasAllFocusHandlers;
-import com.google.gwt.event.dom.client.KeyCodes;
-import com.google.gwt.event.dom.client.KeyDownEvent;
-import com.google.gwt.event.dom.client.KeyDownHandler;
-import com.google.gwt.event.dom.client.KeyPressEvent;
-import com.google.gwt.event.dom.client.KeyPressHandler;
-import com.google.gwt.event.dom.client.KeyUpEvent;
-import com.google.gwt.event.dom.client.KeyUpHandler;
-import com.google.gwt.event.logical.shared.HasSelectionHandlers;
-import com.google.gwt.event.logical.shared.SelectionEvent;
-import com.google.gwt.event.logical.shared.SelectionHandler;
-import com.google.gwt.event.logical.shared.ValueChangeEvent;
-import com.google.gwt.event.logical.shared.ValueChangeHandler;
+import com.google.gwt.event.dom.client.*;
+import com.google.gwt.event.logical.shared.*;
 import com.google.gwt.event.shared.HandlerRegistration;
 import com.google.gwt.user.client.Command;
 import com.google.gwt.user.client.DOM;
 import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.HasText;
-import com.google.gwt.user.client.ui.HasValue;
-import com.google.gwt.user.client.ui.MenuBar;
-import com.google.gwt.user.client.ui.MenuItem;
-import com.google.gwt.user.client.ui.PopupPanel;
-import com.google.gwt.user.client.ui.SuggestOracle;
+import com.google.gwt.user.client.ui.*;
 import com.google.gwt.user.client.ui.SuggestOracle.Callback;
 import com.google.gwt.user.client.ui.SuggestOracle.Request;
 import com.google.gwt.user.client.ui.SuggestOracle.Response;
 import com.google.gwt.user.client.ui.SuggestOracle.Suggestion;
-import com.google.gwt.user.client.ui.TextBox;
-import com.google.gwt.user.client.ui.TextBoxBase;
-
 import org.rhq.core.domain.search.SearchSuggestion;
 import org.rhq.core.domain.search.SearchSuggestion.Kind;
 import org.rhq.enterprise.gui.coregui.client.CoreGUI;
@@ -68,7 +38,14 @@ import org.rhq.enterprise.gui.coregui.client.gwt.SearchGWTServiceAsync;
 import org.rhq.enterprise.gui.coregui.client.search.AbstractSearchBar;
 import org.rhq.enterprise.gui.coregui.client.util.Log;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+ at Deprecated
 public class SuggestTextBox_v3 extends Composite implements HasText, HasAllFocusHandlers, HasValue<String>,
+
     HasSelectionHandlers<Suggestion> {
 
     private static final Messages MSG = CoreGUI.getMessages();
@@ -648,6 +625,7 @@ public class SuggestTextBox_v3 extends Composite implements HasText, HasAllFocus
         }
     }
 
+    @Deprecated
     class SearchSuggestOracle extends SuggestOracle {
         private SearchGWTServiceAsync searchService = GWTServiceLookup.getSearchService();
 
@@ -738,6 +716,7 @@ public class SuggestTextBox_v3 extends Composite implements HasText, HasAllFocus
         }
     }
 
+    @Deprecated
     class SearchSuggestionRequest extends SuggestOracle.Request {
         private int cursorPosition;
 
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/AbstractSearchStrategy.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/AbstractSearchStrategy.java
new file mode 100644
index 0000000..bfd0bd7
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/AbstractSearchStrategy.java
@@ -0,0 +1,91 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 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.gui.coregui.client.searchbar;
+
+import com.smartgwt.client.widgets.form.fields.events.FocusEvent;
+import com.smartgwt.client.widgets.form.fields.events.KeyUpEvent;
+import com.smartgwt.client.widgets.grid.CellFormatter;
+import com.smartgwt.client.widgets.grid.events.RecordClickHandler;
+
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.enterprise.gui.coregui.client.CoreGUI;
+import org.rhq.enterprise.gui.coregui.client.Messages;
+import org.rhq.enterprise.gui.coregui.client.UserSessionManager;
+import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
+import org.rhq.enterprise.gui.coregui.client.gwt.SearchGWTServiceAsync;
+
+
+/**
+ * AbstractSearchStrategy defines common search strategy behaviors the subclasses must implement.
+ * Also, houses common functionality such as user auth and searching the domain.
+ *
+ * @author Mike Thompson
+ */
+public abstract  class AbstractSearchStrategy implements RecordClickHandler, CellFormatter
+{
+    protected static final Messages MSG = CoreGUI.getMessages();
+    public static final String ATTR_ID = "id";
+    public static final String ATTR_KIND = "kind"; // not for saved search
+    public static final String ATTR_NAME = "name";
+    public static final String ATTR_DESCRIPTION = "description";
+    public static final String ATTR_RESULT_COUNT = "resultCount";
+    public static final String ATTR_PATTERN = "pattern";
+    public static final String ATTR_VALUE = "value";
+
+    protected final SearchGWTServiceAsync searchService =  GWTServiceLookup.getSearchService();
+
+    final Subject subject;
+    protected final EnhancedSearchBar searchBar;
+
+    public AbstractSearchStrategy(EnhancedSearchBar searchBar){
+        this.searchBar = searchBar;
+        subject = UserSessionManager.getSessionSubject();
+    }
+
+    /**
+     * Handle the key press event in the search bar. Must be overridden in subclass.
+     * @param keyUpEvent
+     */
+    public abstract void searchKeyUpHandler(KeyUpEvent keyUpEvent);
+
+    /**
+     * Handle the focus event in the search bar. Must be overridden in subclass.
+     * @param focusEvent
+     */
+    public abstract void searchFocusHandler(FocusEvent focusEvent);
+
+    /**
+     * Search results can have different heights (i.e. 1 row or 2 rows). Must be overridden
+     * in subclass.
+     * @return height in pixels
+     */
+    public abstract int getCellHeight();
+
+
+    /**
+     * When return key is pressed in the search bar do I want to do any further
+     * customization. Optionally, overridden by subclass.
+     * @param keyUpEvent
+     */
+    public void searchReturnKeyHandler(KeyUpEvent keyUpEvent){
+        // do nothing by default
+    }
+
+
+}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/BasicSearchStrategy.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/BasicSearchStrategy.java
new file mode 100644
index 0000000..cf40099
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/BasicSearchStrategy.java
@@ -0,0 +1,245 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 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.gui.coregui.client.searchbar;
+
+import java.util.List;
+
+import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.smartgwt.client.data.DataSource;
+import com.smartgwt.client.data.fields.DataSourceTextField;
+import com.smartgwt.client.widgets.form.fields.ComboBoxItem;
+import com.smartgwt.client.widgets.form.fields.events.FocusEvent;
+import com.smartgwt.client.widgets.form.fields.events.KeyUpEvent;
+import com.smartgwt.client.widgets.grid.ListGridRecord;
+import com.smartgwt.client.widgets.grid.events.RecordClickEvent;
+
+import org.rhq.core.domain.criteria.SavedSearchCriteria;
+import org.rhq.core.domain.search.SavedSearch;
+import org.rhq.core.domain.search.SearchSubsystem;
+import org.rhq.core.domain.search.SearchSuggestion;
+import org.rhq.enterprise.gui.coregui.client.CoreGUI;
+import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
+import org.rhq.enterprise.gui.coregui.client.util.Log;
+import org.rhq.enterprise.gui.coregui.client.util.message.Message;
+
+/**
+ * This is the general search strategy implementation used for most searches.
+ * These strategy classes operate by providing the standard functionality
+ * needed by searches as defined by the super class {@link AbstractSearchStrategy}
+ * This strategy works in conjunction with the {@link FavoritesSearchStrategy} for
+ * saved searches.
+ * @author Mike Thompson
+ */
+public class BasicSearchStrategy extends AbstractSearchStrategy {
+
+    private String lastExpression;
+
+    public BasicSearchStrategy(EnhancedSearchBar searchBar) {
+        super(searchBar);
+    }
+
+    @Override
+    public String format(Object value, ListGridRecord record, int rowNum, int colNum) {
+
+        Log.debug("Using BasicSearch Formatter");
+
+        String name = record.getAttribute(ATTR_NAME);
+        String kind = record.getAttribute(ATTR_KIND);
+
+        String style = "font-variant: small-caps; font-weight: bold; font-size: 11px; float: left; margin-left: 2px; width: 50px;";
+        StringBuilder sb = new StringBuilder();
+        sb.append("<div style='height:30px;width:400px;float:left;white-space:nowrap;overflow:hidden;' >");
+        String color = (kind.equals(SearchSuggestion.Kind.GlobalSavedSearch.getDisplayName()) || kind
+            .equals(SearchSuggestion.Kind.UserSavedSearch.getDisplayName())) ? "color:green;" : "color:grey";
+        sb.append("<span style='" + style + color + "' >");
+        sb.append(kind);
+        sb.append("</span>");
+        sb.append("<span style='" + style + "' >");
+        sb.append(name);
+        sb.append("</span>");
+        sb.append("</div>");
+
+        return sb.toString();
+    }
+
+    /**
+     * Executed when this field is clicked on.  Note that if {@link
+     * com.smartgwt.client.widgets.grid.ListGrid#addRecordClickHandler ListGrid.recordClick} is also defined, it will be fired
+     * for fields that define a recordClick handler if the field-level handler returns true. Call {@link com.smartgwt.client.widgets.grid.events.RecordClickEvent#cancel()} from within {@link com.smartgwt.client.widgets.grid.events.RecordClickHandler#onRecordClick} to prevent the
+     * grid-level handler from firing.
+     *
+     * @param event the event
+     */
+    @Override
+    public void onRecordClick(RecordClickEvent event) {
+        Log.debug("BasicSearchStrategy click");
+        String kind = event.getRecord().getAttribute(ATTR_KIND);
+        if (kind.equals("SAVED") || kind.equals("GLOBAL")) {
+            searchBar.switchToSavedSearchMode();
+            String savedSearchName = event.getRecord().getAttribute(ATTR_VALUE);
+            searchBar.getSaveSearchTextItem().setValue(savedSearchName);
+            assignSavedSearchExpression(savedSearchName, searchBar.getSearchComboboxItem());
+        } else {
+
+            String clickedExpression = event.getRecord().getAttribute(ATTR_NAME);
+            searchBar.getSearchComboboxItem().setValue(clickedExpression);
+            if (null != clickedExpression && clickedExpression.length() > 0) {
+                getTabAwareSearchSuggestions(SearchSubsystem.RESOURCE, clickedExpression, clickedExpression.length());
+            }
+        }
+    }
+
+    private void assignSavedSearchExpression(final String savedSearchName, final ComboBoxItem searchComboBoxItem) {
+        SavedSearchCriteria criteria = new SavedSearchCriteria();
+        criteria.addFilterSubjectId(subject.getId());
+        criteria.addFilterName(savedSearchName); // null OK
+        criteria.setStrict(true);
+
+        GWTServiceLookup.getSearchService().findSavedSearchesByCriteria(criteria,
+            new AsyncCallback<List<SavedSearch>>() {
+                @Override
+                public void onFailure(Throwable caught) {
+                    CoreGUI.getErrorHandler().handleError(MSG.view_searchBar_savedSearch_failFind(savedSearchName),
+                        caught);
+                }
+
+                @Override
+                public void onSuccess(List<SavedSearch> results) {
+                    if (results.size() == 0) {
+                        CoreGUI.getMessageCenter().notify(
+                            new Message(MSG.view_searchBar_savedSearch_failFind(savedSearchName),
+                                Message.Severity.Error));
+                    } else {
+                        SavedSearch savedSearch = results.get(0);
+                        searchComboBoxItem.setValue(savedSearch.getPattern());
+                    }
+                }
+            });
+
+    }
+
+    @Override
+    public void searchFocusHandler(FocusEvent event) {
+        Log.debug("focus in BasicSearchStrategy");
+        String searchExpression = searchBar.getSearchComboboxItem().getValueAsString();
+        if (null != searchExpression && searchExpression.length() > 0) {
+            getTabAwareSearchSuggestions(SearchSubsystem.RESOURCE,
+                searchBar.getSearchComboboxItem().getValueAsString(), searchBar.getSearchComboboxItem()
+                    .getValueAsString().length());
+        } else {
+            getTabAwareSearchSuggestions(SearchSubsystem.RESOURCE, "", 0);
+        }
+    }
+
+    @Override
+    public void searchKeyUpHandler(KeyUpEvent keyUpEvent) {
+        Log.debug("Keyup in BasicSearchStrategy: " + keyUpEvent.getKeyName());
+        String searchExpression = searchBar.getSearchComboboxItem().getValueAsString();
+        if (null != searchExpression && searchExpression.length() > 0) {
+            getTabAwareSearchSuggestions(SearchSubsystem.RESOURCE,
+                searchBar.getSearchComboboxItem().getValueAsString(), searchBar.getSearchComboboxItem()
+                    .getValueAsString().length());
+        } else {
+            getTabAwareSearchSuggestions(SearchSubsystem.RESOURCE, "", 0);
+        }
+
+    }
+
+    @Override
+    public void searchReturnKeyHandler(KeyUpEvent keyUpEvent) {
+        // Do nothing here; standard Table.TableFilter will handle normally
+    }
+
+    @Override
+    public int getCellHeight() {
+        return 25;
+    }
+
+    private void getTabAwareSearchSuggestions(SearchSubsystem searchSubsystem, final String expression,
+        int caretPosition) {
+
+        if (expression.equals(lastExpression)) {
+            Log.debug("search tab aware Suggestions: ignoring duplicate search for: " + expression);
+            return;
+        }
+        lastExpression = expression;
+
+        final long suggestStart = System.currentTimeMillis();
+
+        searchService.getTabAwareSuggestions(searchSubsystem, expression, caretPosition, null,
+            new AsyncCallback<List<SearchSuggestion>>() {
+
+                public void onSuccess(List<SearchSuggestion> results) {
+                    ComboBoxItem comboBox = searchBar.getSearchComboboxItem();
+
+                    // If the value has already changed assume a subsequent search is what they want
+                    if (!expression.equals(comboBox.getValueAsString())) {
+                        Log.debug("search tab aware Suggestions: ignoring obsolete results for: " + expression);
+                        return;
+                    }
+
+                    DataSource ds = comboBox.getOptionDataSource();
+
+                    if (null == ds) {
+                        ds = new DataSource();
+                        ds.setClientOnly(true);
+                        DataSourceTextField idField = new DataSourceTextField(ATTR_ID, "Id");
+                        idField.setPrimaryKey(true);
+                        DataSourceTextField valueField = new DataSourceTextField(ATTR_VALUE, "Value");
+                        DataSourceTextField kindField = new DataSourceTextField(ATTR_KIND, "Kind");
+                        DataSourceTextField nameField = new DataSourceTextField(ATTR_NAME, "Name");
+                        ds.setFields(idField, valueField, kindField, nameField);
+
+                        comboBox.setOptionDataSource(ds);
+
+                    } else {
+                        ds.invalidateCache();
+                    }
+
+                    for (SearchSuggestion searchSuggestion : results) {
+                        Log.debug("search tab aware Suggestions: " + searchSuggestion.getKind() + ", "
+                            + searchSuggestion.getValue() + ", " + searchSuggestion.getLabel());
+                        ListGridRecord record = new ListGridRecord();
+                        record.setAttribute(ATTR_ID, searchSuggestion.getValue());
+                        if (null != searchSuggestion.getKind()) {
+                            record.setAttribute(ATTR_KIND, searchSuggestion.getKind().getDisplayName());
+                        }
+                        record.setAttribute(ATTR_NAME, searchSuggestion.getLabel());
+                        record.setAttribute(ATTR_VALUE, searchSuggestion.getValue());
+                        ds.addData(record);
+                    }
+
+                    try {
+                        comboBox.fetchData();
+                    } catch (Exception e) {
+                        Log.debug("Caught exception on fetchData: " + e);
+                    }
+
+                    long suggestFetchTime = System.currentTimeMillis() - suggestStart;
+                    Log.debug(results.size() + " suggestions searches fetched in: " + suggestFetchTime + "ms");
+                }
+
+                public void onFailure(Throwable caught) {
+                    CoreGUI.getErrorHandler().handleError("Failed to retrieve search suggestion", caught);
+                }
+
+            });
+    }
+
+}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/EnhancedSearchBar.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/EnhancedSearchBar.java
new file mode 100644
index 0000000..e793f9f
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/EnhancedSearchBar.java
@@ -0,0 +1,279 @@
+/*
+ * 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.gui.coregui.client.searchbar;
+
+import java.util.ArrayList;
+import java.util.EnumMap;
+import java.util.List;
+
+import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.smartgwt.client.types.TextMatchStyle;
+import com.smartgwt.client.widgets.events.ClickEvent;
+import com.smartgwt.client.widgets.events.ClickHandler;
+import com.smartgwt.client.widgets.form.fields.ComboBoxItem;
+import com.smartgwt.client.widgets.form.fields.TextItem;
+import com.smartgwt.client.widgets.form.fields.events.FocusEvent;
+import com.smartgwt.client.widgets.form.fields.events.FocusHandler;
+import com.smartgwt.client.widgets.form.fields.events.KeyUpEvent;
+import com.smartgwt.client.widgets.form.fields.events.KeyUpHandler;
+import com.smartgwt.client.widgets.grid.ListGrid;
+import com.smartgwt.client.widgets.toolbar.ToolStrip;
+import com.smartgwt.client.widgets.toolbar.ToolStripButton;
+
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.search.SavedSearch;
+import org.rhq.core.domain.search.SearchSubsystem;
+import org.rhq.enterprise.gui.coregui.client.CoreGUI;
+import org.rhq.enterprise.gui.coregui.client.IconEnum;
+import org.rhq.enterprise.gui.coregui.client.Messages;
+import org.rhq.enterprise.gui.coregui.client.UserSessionManager;
+import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
+import org.rhq.enterprise.gui.coregui.client.gwt.SearchGWTServiceAsync;
+import org.rhq.enterprise.gui.coregui.client.util.Log;
+import org.rhq.enterprise.gui.coregui.client.util.message.Message;
+
+/**
+ * The class defines the UI component of the search bar.
+ * Behavior related to the retrieving/saving of searches is delegated to the Search Strategies.
+ * The enumMaps confine us to just setting the search modes and the modes determine the strategies.
+ * This is a little safer than typical strategy pattern where we can set any strategy regardless of the
+ * search mode (in this case, the search mode and strategies can get out of sync). In fact,
+ * there is no setter for the search strategy, as you cant set it is setup by the enumMap only.
+ *
+ * @author  Mike Thompson
+ */
+public class EnhancedSearchBar extends ToolStrip {
+    private static final Messages MSG = CoreGUI.getMessages();
+    private SearchSubsystem searchSubsystem;
+    private Integer currentSearchId = 0;
+    private ToolStripButton saveSearchButton;
+    private ComboBoxItem searchComboboxItem;
+    private ListGrid pickListGrid;
+    private TextItem saveSearchTextItem;
+    private final FavoritesSearchStrategy favoritesSearchStrategy;
+    private final BasicSearchStrategy basicSearchStrategy;
+
+    private final SearchGWTServiceAsync searchService = GWTServiceLookup.getSearchService();
+
+    private static final List IGNORED_KEYS;
+
+    static {
+        IGNORED_KEYS = new ArrayList(2);
+        IGNORED_KEYS.add("Arrow_Down");
+        IGNORED_KEYS.add("Arrow_Up");
+    }
+
+    enum SearchMode {
+        BASIC_SEARCH_MODE, SAVED_SEARCH_MODE
+    }
+
+    private SearchMode searchMode = SearchMode.BASIC_SEARCH_MODE;
+
+    /**
+     * The enumMap will act as a simple state machine defining the mappings of search strategy behavior and
+     * eliminating any if logic.
+     */
+    private EnumMap<SearchMode, AbstractSearchStrategy> searchStrategies = new EnumMap<SearchMode, AbstractSearchStrategy>(
+        SearchMode.class);
+
+    public EnhancedSearchBar(SearchSubsystem searchSubsystem) {
+        this(searchSubsystem, null);
+    }
+
+    public EnhancedSearchBar(SearchSubsystem searchSubsystem, String initialSearchText) {
+        if (null == searchSubsystem) {
+            this.searchSubsystem = SearchSubsystem.RESOURCE; // default to resource
+        } else {
+            this.searchSubsystem = searchSubsystem;
+        }
+        setAutoHeight();
+        setWidth100();
+        addSpacer(40);
+
+        searchComboboxItem = new ComboBoxItem("search", MSG.common_button_search());
+        // now that we have searchComboBoxItem setup dependent objects
+        favoritesSearchStrategy = new FavoritesSearchStrategy(this);
+        basicSearchStrategy = new BasicSearchStrategy(this);
+        // now we can fill our enumMap
+        searchStrategies.put(SearchMode.BASIC_SEARCH_MODE, basicSearchStrategy);
+        searchStrategies.put(SearchMode.SAVED_SEARCH_MODE, favoritesSearchStrategy);
+
+        searchComboboxItem.setWidth(670);
+        searchComboboxItem.setBrowserSpellCheck(false);
+        //we manually fetch each time we update the picklist values. That makes the delay setting meaningless.
+        searchComboboxItem.setAutoFetchData(false);
+        searchComboboxItem.setFetchDelay(300); // I'm not sure if this has an affect with no autoFetch
+
+        pickListGrid = new ListGrid();
+        configureCommonHandlers();
+
+        searchComboboxItem.setTextMatchStyle(TextMatchStyle.SUBSTRING);
+        searchComboboxItem.setShowPickListOnKeypress(true);
+        searchComboboxItem.setRedrawOnChange(true);
+        // this changes it to autocomplete field from combobox
+        searchComboboxItem.setShowPickerIcon(true);
+        searchComboboxItem.addKeyUpHandler(new KeyUpHandler() {
+            @Override
+            public void onKeyUp(KeyUpEvent keyUpEvent) {
+                Log.debug("onKeyUp search Mode: " + searchMode);
+
+                if (IGNORED_KEYS.contains(keyUpEvent.getKeyName())) {
+                    return;
+                }
+
+                if (keyUpEvent.getKeyName().equals("Enter")) {
+                    getSearchStrategy().searchReturnKeyHandler(keyUpEvent);
+                    searchComboboxItem.focusInItem();
+                } else {
+                    getSearchStrategy().searchKeyUpHandler(keyUpEvent);
+                }
+            }
+        });
+
+        searchComboboxItem.addFocusHandler(new FocusHandler() {
+            @Override
+            public void onFocus(FocusEvent event) {
+                Log.debug("onFocus search Mode: " + searchMode);
+
+                getSearchStrategy().searchFocusHandler(event);
+            }
+        });
+
+        searchComboboxItem.setPickListProperties(pickListGrid);
+        addFormItem(searchComboboxItem);
+
+        saveSearchButton = new ToolStripButton();
+        saveSearchButton.setIcon(IconEnum.STAR_OFF.getIcon16x16Path());
+        saveSearchButton.addClickHandler(new ClickHandler() {
+            @Override
+            public void onClick(ClickEvent event) {
+                toggleFavoriteSearch();
+            }
+        });
+        addButton(saveSearchButton);
+
+        saveSearchTextItem = new TextItem("savedSearchName");
+        saveSearchTextItem.setShowTitle(false);
+        saveSearchTextItem.setWidth(150);
+        addFormItem(saveSearchTextItem);
+        saveSearchTextItem.hide();
+
+        saveSearchTextItem.addKeyUpHandler(new KeyUpHandler() {
+            @Override
+            public void onKeyUp(KeyUpEvent keyUpEvent) {
+                if (keyUpEvent.getKeyName().equals("Enter")) {
+                    saveFavoriteSearch();
+                }
+            }
+        });
+
+        // set the default search provider
+        switchToBasicSearchMode();
+
+        this.draw();
+    }
+
+    private void saveFavoriteSearch() {
+        Log.debug("Saving Favorite Search: " + saveSearchTextItem.getValueAsString());
+        createSavedSearch(saveSearchTextItem.getValueAsString(), searchComboboxItem.getValueAsString());
+        toggleFavoriteSearch();
+    }
+
+    public SearchMode getSearchMode() {
+        return searchMode;
+    }
+
+    public void setSearchMode(SearchMode searchMode) {
+        this.searchMode = searchMode;
+    }
+
+    /**
+     * This is the one method where the searchMode state is allowed to change.
+     */
+    public void toggleFavoriteSearch() {
+        if (getSearchMode().equals(SearchMode.SAVED_SEARCH_MODE)) {
+            switchToBasicSearchMode();
+        } else {
+            switchToSavedSearchMode();
+        }
+
+        Log.debug("toggleFavorites searchMode set to: " + searchMode);
+        configureCommonHandlers();
+
+    }
+
+    public void switchToBasicSearchMode() {
+        setSearchMode(SearchMode.BASIC_SEARCH_MODE);
+        saveSearchButton.setIcon(IconEnum.STAR_OFF.getIcon16x16Path());
+        saveSearchTextItem.hide();
+        configureCommonHandlers();
+    }
+
+    public void switchToSavedSearchMode() {
+        setSearchMode(SearchMode.SAVED_SEARCH_MODE);
+        saveSearchButton.setIcon(IconEnum.STAR_ON.getIcon16x16Path());
+        saveSearchTextItem.show();
+        saveSearchTextItem.setValue(MSG.search_name_your_search());
+        saveSearchTextItem.setSelectOnFocus(true);
+        saveSearchTextItem.selectValue();
+        configureCommonHandlers();
+    }
+
+    private void configureCommonHandlers() {
+        pickListGrid.setCellHeight(getSearchStrategy().getCellHeight());
+        pickListGrid.addRecordClickHandler(getSearchStrategy());
+        pickListGrid.setCellFormatter(getSearchStrategy());
+        pickListGrid.redraw();
+    }
+
+    public String getValue() {
+        return searchComboboxItem.getValueAsString();
+    }
+
+    private void createSavedSearch(final String name, final String pattern) {
+        Subject subject = UserSessionManager.getSessionSubject();
+        SavedSearch newSavedSearch = new SavedSearch(searchSubsystem, name, pattern, subject);
+        searchService.createSavedSearch(newSavedSearch, new AsyncCallback<Integer>() {
+            @Override
+            public void onSuccess(Integer newSavedSearchId) {
+                currentSearchId = newSavedSearchId;
+                Message message = new Message("Successfully Saved Search: " + name, Message.Severity.Info);
+                CoreGUI.getMessageCenter().notify(message);
+            }
+
+            @Override
+            public void onFailure(Throwable caught) {
+                Message message = new Message("Failure to Save Search " + name, Message.Severity.Error);
+                CoreGUI.getMessageCenter().notify(message);
+            }
+        });
+    }
+
+    public AbstractSearchStrategy getSearchStrategy() {
+        return searchStrategies.get(searchMode);
+    }
+
+    public ComboBoxItem getSearchComboboxItem() {
+        return searchComboboxItem;
+    }
+
+    public TextItem getSaveSearchTextItem() {
+        return saveSearchTextItem;
+    }
+}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/FavoritesSearchStrategy.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/FavoritesSearchStrategy.java
new file mode 100644
index 0000000..a04a000
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/searchbar/FavoritesSearchStrategy.java
@@ -0,0 +1,156 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 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.gui.coregui.client.searchbar;
+
+import java.util.List;
+
+import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.smartgwt.client.data.DataSource;
+import com.smartgwt.client.data.fields.DataSourceIntegerField;
+import com.smartgwt.client.data.fields.DataSourceTextField;
+import com.smartgwt.client.widgets.form.fields.events.FocusEvent;
+import com.smartgwt.client.widgets.form.fields.events.KeyUpEvent;
+import com.smartgwt.client.widgets.grid.ListGridRecord;
+import com.smartgwt.client.widgets.grid.events.RecordClickEvent;
+
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.criteria.SavedSearchCriteria;
+import org.rhq.core.domain.search.SavedSearch;
+import org.rhq.enterprise.gui.coregui.client.CoreGUI;
+import org.rhq.enterprise.gui.coregui.client.UserSessionManager;
+import org.rhq.enterprise.gui.coregui.client.util.Log;
+
+/**
+ * Search Strategy for the Favorite Saved Searches.
+ * If you wish to save your searches for later use this search strategy
+ * will facilitate favorite searches.
+ *
+ * @author Mike Thompson
+ */
+public class FavoritesSearchStrategy extends AbstractSearchStrategy {
+
+    public FavoritesSearchStrategy(EnhancedSearchBar searchBar){
+        super(searchBar);
+    }
+
+    @Override
+    public String format(Object value, ListGridRecord record, int rowNum, int colNum) {
+
+        Log.debug("Using Favorites Formatter");
+
+        String name = record.getAttribute(ATTR_NAME);
+        Integer resultCount = record.getAttributeAsInt(ATTR_RESULT_COUNT);
+        String pattern = record.getAttribute(ATTR_PATTERN);
+
+        String resultAsString = (resultCount != null) ? "("+String.valueOf(resultCount)+")" : "";
+        final String styleStr = "font-family:arial;font-size:11px;white-space:nowrap;overflow:hidden;";
+        String formatString = "<table>" +
+                "<tr><td ><span style='" + styleStr + "width:170px;color:green;float:left'>" + name + "</span></td>" +
+                "<td align='right'><span style='" + styleStr + "width:50px;float:right;font-weight:bold'>" + resultAsString+ "</span></td></tr>" +
+                "<tr><td colSpan=2><span style='" + styleStr + "width:220px;float:left'>" + pattern + "</span></td></tr></table>";
+
+        return formatString;
+    }
+
+
+    /**
+     * Executed when this field is clicked on.  Note that if {@link
+     * com.smartgwt.client.widgets.grid.ListGrid#addRecordClickHandler ListGrid.recordClick} is also defined, it will be fired
+     * for fields that define a recordClick handler if the field-level handler returns true. Call {@link com.smartgwt.client.widgets.grid.events.RecordClickEvent#cancel()} from within {@link com.smartgwt.client.widgets.grid.events.RecordClickHandler#onRecordClick} to prevent the
+     * grid-level handler from firing.
+     *
+     * @param event the event
+     */
+    @Override
+    public void onRecordClick(RecordClickEvent event) {
+        // do nothing here; just here if we need to do something
+        searchBar.getSaveSearchTextItem().setValue(event.getRecord().getAttribute(ATTR_NAME));
+        searchBar.getSearchComboboxItem().setValue(event.getRecord().getAttribute(ATTR_PATTERN));
+
+    }
+
+    @Override
+    public void searchKeyUpHandler(KeyUpEvent keyUpEvent) {
+        populateSearchComboboxSavedSearchesWithAutoComplete();
+    }
+
+
+    @Override
+    public void searchFocusHandler(FocusEvent focusEvent) {
+        // nothing currently
+    }
+
+    private void populateSearchComboboxSavedSearchesWithAutoComplete(){
+
+        SavedSearchCriteria savedSearchCriteria = new SavedSearchCriteria();
+        Subject subject = UserSessionManager.getSessionSubject();
+        savedSearchCriteria.addFilterSubjectId(subject.getId());
+        savedSearchCriteria.setStrict(true);
+        final long start = System.currentTimeMillis();
+
+        searchService.findSavedSearchesByCriteria(savedSearchCriteria, new AsyncCallback<List<SavedSearch>>() {
+
+            public void onFailure(Throwable caught) {
+                CoreGUI.getErrorHandler().handleError(MSG.search_failed_to_retrieve_saved_search(), caught);
+            }
+
+            public void onSuccess(List<SavedSearch> result) {
+                long fetchTime = System.currentTimeMillis() - start;
+                Log.debug(result.size() + " saved searches fetched in: " + fetchTime + "ms");
+
+                DataSource dataSource = new DataSource();
+                dataSource.setClientOnly(true);
+                DataSourceTextField valueField = new DataSourceTextField(ATTR_ID, "Id");
+                valueField.setPrimaryKey(true);
+                DataSourceTextField kindField = new DataSourceTextField(ATTR_KIND, "Kind");
+                DataSourceTextField nameField = new DataSourceTextField(ATTR_NAME, "Name");
+                DataSourceTextField patternField = new DataSourceTextField(ATTR_PATTERN, "Pattern");
+                DataSourceTextField descriptionField = new DataSourceTextField(ATTR_DESCRIPTION, "Description");
+                DataSourceIntegerField recordCount = new DataSourceIntegerField(ATTR_RESULT_COUNT, "Result Count");
+                dataSource.setFields(valueField, kindField,nameField,patternField,descriptionField,recordCount);
+
+                for (SavedSearch savedSearch : result) {
+                    Log.debug("savedSearch: " + savedSearch.getName());
+                    ListGridRecord record = new ListGridRecord();
+                    record.setAttribute(ATTR_ID, savedSearch.getId());
+                    record.setAttribute(ATTR_KIND, "Saved");
+                    record.setAttribute(ATTR_NAME, savedSearch.getName());
+                    record.setAttribute(ATTR_DESCRIPTION, savedSearch.getDescription());
+                    record.setAttribute(ATTR_PATTERN, savedSearch.getPattern());
+                    if (savedSearch.getResultCount() != null)
+                        record.setAttribute(ATTR_RESULT_COUNT, savedSearch.getResultCount());
+                    dataSource.addData(record);
+                }
+
+                searchBar.getSearchComboboxItem().setOptionDataSource(dataSource);
+            }
+        });
+    }
+
+    @Override
+    public int getCellHeight() {
+        return 35;
+    }
+
+    @Override
+    public void searchReturnKeyHandler(KeyUpEvent keyUpEvent) {
+        // do nothing
+        Log.debug("return key in SavedSearchProvider");
+    }
+}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/RPCDataSource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/RPCDataSource.java
index b7944a4..4a1a06f 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/RPCDataSource.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/RPCDataSource.java
@@ -19,7 +19,6 @@
 package org.rhq.enterprise.gui.coregui.client.util;
 
 import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.user.client.Window;
 import com.smartgwt.client.data.*;
 import com.smartgwt.client.data.fields.DataSourceIntegerField;
 import com.smartgwt.client.data.fields.DataSourceTextField;
@@ -595,7 +594,7 @@ public abstract class RPCDataSource<T, C extends BaseCriteria> extends DataSourc
         Map<String, Object> criteriaMap = criteria.getValues();
 
         for (Map.Entry<String, Object> nextEntry : criteriaMap.entrySet()) {
-            Window.alert(nextEntry.getKey() + ":" + nextEntry.getValue());
+            Log.debug("Request Criteria: "+nextEntry.getKey() + ":" + nextEntry.getValue());
         }
     }
 
@@ -628,9 +627,9 @@ public abstract class RPCDataSource<T, C extends BaseCriteria> extends DataSourc
             }
         }
 
-        if (Log.isDebugEnabled() && result != null) {
+        //if (Log.isDebugEnabled() && result != null) {
             Log.debug("Filter: " + paramName + "=[" + result + "]");
-        }
+        //}
 
         return result;
     }
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
index 56766cd..2e371d9 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
@@ -413,6 +413,8 @@ filter_from_date = From
 filter_to_date = To
 group_tree_groupOfResourceType = Group of [{0}]
 group_tree_partialClusterTooltip = {0} out of {1} group members have a ''{2}'' resource
+search_failed_to_retrieve_saved_search = Failed to retrieve saved search
+search_name_your_search = name you search
 util_ancestry_parentAncestry = Parent Ancestry for:
 util_errorHandler_nullException = exception was null
 util_monitoringRequestCallback_error_checkServerStatusFailure = Unable to determine login status - check Server status.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
index f7d4ef7..275fe4d 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
@@ -432,6 +432,8 @@ filter_from_date = Od
 filter_to_date = Do
 group_tree_groupOfResourceType = Skupina: [{0}]
 group_tree_partialClusterTooltip = {0} z {1} členů skupiny má "{2}" zdroj
+##search_failed_to_retrieve_saved_search = Failed to retrieve saved search
+##search_name_your_search = name you search
 util_ancestry_parentAncestry = Původ rodiče pro:
 util_errorHandler_nullException = výjimka byla null
 util_monitoringRequestCallback_error_checkServerStatusFailure = Nepodařilo se určit stav přihlašování - zkontrolujte stav serveru.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
index a40cb2f..ddd07fd 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
@@ -397,6 +397,8 @@ filter_from_date = Von
 filter_to_date = Bis
 ##group_tree_groupOfResourceType = Group of [{0}]
 group_tree_partialClusterTooltip = {0} der {1} Gruppenmitglieder haben eine ''{2}'' Ressource
+##search_failed_to_retrieve_saved_search = Failed to retrieve saved search
+##search_name_your_search = name you search
 util_disambiguationReportDecorator_pluginSuffix = ({0} Plugin)
 util_errorHandler_nullException = Exception war null
 ##util_monitoringRequestCallback_error_checkServerStatusFailure = Unable to determine login status - check Server status.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
index e135c0d..6eb5212 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
@@ -410,6 +410,8 @@ filter_from_date = 開始
 filter_to_date = 終了
 ##group_tree_groupOfResourceType = Group of [{0}]
 group_tree_partialClusterTooltip = {1} の中の {0} グループメンバーが ''{2}'' リソースを持っています
+##search_failed_to_retrieve_saved_search = Failed to retrieve saved search
+##search_name_your_search = name you search
 util_ancestry_parentAncestry = 親の先祖 :
 util_disambiguationReportDecorator_pluginSuffix = ({0} プラグイン)
 util_errorHandler_nullException = 例外は null でした
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
index 843d5d2..900b847 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
@@ -416,6 +416,8 @@ favorites_resources = Recursos Favoritos
 ##filter_to_date = To
 ##group_tree_groupOfResourceType = Group of [{0}]
 group_tree_partialClusterTooltip = {0} out of {1} group members have a ''{2}'' resource
+##search_failed_to_retrieve_saved_search = Failed to retrieve saved search
+##search_name_your_search = name you search
 util_ancestry_parentAncestry = Ancestral para:
 util_errorHandler_nullException = Exce\u00E7\u00E3o nula
 util_monitoringRequestCallback_error_checkServerStatusFailure = Imposs\u00EDvel verificar o status do login - verifique o status do Servidor.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
index 512e087..43abe46 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
@@ -403,6 +403,8 @@
 #filter_from_date = From
 #filter_to_date = To
 #group_tree_partialClusterTooltip = {0} out of {1} group members have a ''{2}'' resource
+##search_failed_to_retrieve_saved_search = Failed to retrieve saved search
+##search_name_your_search = name you search
 #util_ancestry_parentAncestry = Parent Ancestry for:
 #util_errorHandler_nullException = exception was null
 #util_monitoringRequestCallback_error_checkServerStatusFailure = Unable to determine login status - check Server status.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
index 269ed1c..9f3fd76 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
@@ -405,6 +405,8 @@ favorites_resources = \u8d44\u6e90\u6536\u85cf\u5939
 ##filter_to_date = To
 ##group_tree_groupOfResourceType = Group of [{0}]
 group_tree_partialClusterTooltip = \u9664\u53bb {1},{0}\u7684\u7ec4\u6210\u5458\u62e5\u6709 \u4e00\u4e2a''{2}''\u8d44\u6e90
+##search_failed_to_retrieve_saved_search = Failed to retrieve saved search
+##search_name_your_search = name you search
 util_ancestry_parentAncestry = Parent Ancestry for:
 util_errorHandler_nullException = \u5f02\u5e38\u662f null
 util_monitoringRequestCallback_error_checkServerStatusFailure = \u65e0\u6cd5\u786e\u5b9a\u767b\u5f55\u72b6\u6001- \u68c0\u67e5\u670d\u52a1\u5668\u72b6\u6001.


commit 39e949017892c6845a026c8f86d6618796108b87
Author: Simeon Pinder <spinder at redhat.com>
Date:   Mon Jul 16 15:44:28 2012 -0400

     [BZ 840512] workaround bug in persistence container.

diff --git a/modules/enterprise/server/plugins/jboss-software/src/main/java/org/rhq/enterprise/server/plugins/jboss/software/JBossSoftwareContentSourceAdapter.java b/modules/enterprise/server/plugins/jboss-software/src/main/java/org/rhq/enterprise/server/plugins/jboss/software/JBossSoftwareContentSourceAdapter.java
index 2758e2b..4b3516a 100644
--- a/modules/enterprise/server/plugins/jboss-software/src/main/java/org/rhq/enterprise/server/plugins/jboss/software/JBossSoftwareContentSourceAdapter.java
+++ b/modules/enterprise/server/plugins/jboss-software/src/main/java/org/rhq/enterprise/server/plugins/jboss/software/JBossSoftwareContentSourceAdapter.java
@@ -38,6 +38,7 @@ import org.apache.commons.logging.LogFactory;
 
 import org.rhq.core.domain.configuration.Configuration;
 import org.rhq.core.domain.configuration.PropertySimple;
+import org.rhq.core.util.obfuscation.Obfuscator;
 import org.rhq.enterprise.server.plugin.pc.content.ContentProvider;
 import org.rhq.enterprise.server.plugin.pc.content.ContentProviderPackageDetails;
 import org.rhq.enterprise.server.plugin.pc.content.PackageSource;
@@ -220,6 +221,16 @@ public class JBossSoftwareContentSourceAdapter implements ContentProvider, Packa
 
             int status = client.executeMethod(method);
 
+            //BZ840512: check for issue deobfuscating the password:
+            if (status == 401 || status == 403) {
+                password = Obfuscator.decode(password);//in case de/unobfuscation failed.
+                UsernamePasswordCredentials upc = new UsernamePasswordCredentials(username, password);
+                client.getState().setCredentials("users", method.getHostConfiguration().getHost(), upc);
+                log.warn("You have either input bad Content Source credentials or"
+                    + " there is a problem retrieving obfuscated passwords. Retrying...");
+                status = client.executeMethod(method);
+            }
+
             //Check to see if redirection has occurred
             String currentUrl = method.getURI().getURI();
             //if redirection has occurred, reconnect with correct address.


commit b98e5f305e20dfc04baa38036c6b4e1e377052f8
Author: Jay Shaughnessy <jshaughn at redhat.com>
Date:   Mon Jul 16 16:09:28 2012 -0400

    [Bug 839256 - FailoverListManagerBeanTest fail on OpenJDK 1.7]
    Tweak algorithm for better distribution and also relax test verification to
    allow for minor imbalance at deeper levels of failover.

diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/FailoverListManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/FailoverListManagerBean.java
index f38d1ae..97ba097 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/FailoverListManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/FailoverListManagerBean.java
@@ -44,8 +44,8 @@ import org.rhq.core.domain.cloud.PartitionEvent;
 import org.rhq.core.domain.cloud.PartitionEventDetails;
 import org.rhq.core.domain.cloud.Server;
 import org.rhq.core.domain.cloud.composite.FailoverListComposite;
-import org.rhq.core.domain.cloud.composite.FailoverListDetailsComposite;
 import org.rhq.core.domain.cloud.composite.FailoverListComposite.ServerEntry;
+import org.rhq.core.domain.cloud.composite.FailoverListDetailsComposite;
 import org.rhq.core.domain.resource.Agent;
 import org.rhq.enterprise.server.RHQConstants;
 import org.rhq.enterprise.server.core.AgentManagerLocal;
@@ -210,27 +210,27 @@ public class FailoverListManagerBean implements FailoverListManagerLocal {
             agentServerListMap.put(next, new ArrayList<ServerBucket>(servers.size()));
         }
 
-        // assign server lists level by level: primary, then secondary, the tertiary, etc        
+        // assign server lists level by level: primary, then secondary, then tertiary, etc        
         for (int level = 0; (level < servers.size()); ++level) {
 
             // Initialize the bucket loads for the next round
             initBuckets(buckets, existingLoads, level);
 
-            // assign a server for this level to each agent, balancing as we go
-            for (Agent next : agents) {
+            // assign a server for this level to each agent, balancing as we go            
 
+            // keep track of the how many agents have been assignd on this pass
+            int agentsAssigned = 0;
+            // introduce more list disparity by changing the bucket iteration direction on each level  
+            int rotate = (((level % 2) == 0) ? -1 : 1);
+
+            for (Agent next : agents) {
                 List<ServerBucket> serverList = agentServerListMap.get(next);
 
                 // When assigning primary (i.e. level 0), supply the current primary as the preferred server.
-                // This should reduce connection churn by letting most agents stay put (but affects balancing, we'll deal with
-                // that below)
+                // This should reduce connection churn by letting most agents stay put (but affects balancing, we'll 
+                // deal with that below)
                 ServerBucket bestBucket = null;
 
-                // Rotate the list (makes the last entry the first entry) on each iteration. This
-                // enhances bucket distribution amongst the levels and ensures that we don't starve
-                // buckets at the end of the list.
-                Collections.rotate(buckets, 1);
-
                 if ((0 == level) && (null != next.getServer())) {
                     bestBucket = ServerBucket.getBestBucket(buckets, serverList, next.getAffinityGroup(), next
                         .getServer().getName());
@@ -238,6 +238,18 @@ public class FailoverListManagerBean implements FailoverListManagerLocal {
                     bestBucket = ServerBucket.getBestBucket(buckets, serverList, next.getAffinityGroup(), null);
                 }
 
+                // Rotate the list on each iteration. This enhances bucket distribution amongst the levels and ensures
+                // that we don't starve buckets at the end of the list.  Also, we alternate the rotation direction on
+                // each level which seems to help.
+                Collections.rotate(buckets, rotate);
+
+                // Reverse the buckets completely each time we have assigned an agent to each server.  This avoids
+                // duplicating failover lists completely by not repeating the same server sequence over and over on the
+                // same level.
+                if ((++agentsAssigned % buckets.size() == 0)) {
+                    Collections.reverse(buckets);
+                }
+
                 if (null == bestBucket) {
                     // this should never happen but let's defensively check and log
                     log.error("Unexpected Condition! null bucket in getForAllAgents()");
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/ServerBucket.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/ServerBucket.java
index 931c1d0..b98aaf0 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/ServerBucket.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/ServerBucket.java
@@ -43,6 +43,11 @@ public class ServerBucket {
         assignedAgents = new ArrayList<Agent>();
     }
 
+    @Override
+    public String toString() {
+        return serverEntry.toString();
+    }
+
     static ServerBucket getBestBucket(List<ServerBucket> buckets, List<ServerBucket> usedBuckets,
         AffinityGroup affinityGroup, String preferredServerName) {
         ServerBucket result = null;
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/cloud/FailoverListManagerBeanTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/cloud/FailoverListManagerBeanTest.java
index 29e9e58..1c59b16 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/cloud/FailoverListManagerBeanTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/cloud/FailoverListManagerBeanTest.java
@@ -225,11 +225,15 @@ public class FailoverListManagerBeanTest extends AbstractEJB3Test {
         validateBasic(result, numServers, numAgents);
 
         // validate balance level by level
-        for (int i = 0; (i < numServers); ++i) {
+        for (int level = 0; (level < numServers); ++level) {
             Map<String, Integer> distributionMap = new HashMap<String, Integer>(numServers);
             for (Agent agent : result.keySet()) {
                 FailoverListComposite flc = result.get(agent);
-                FailoverListComposite.ServerEntry server = flc.get(i);
+                // for debugging
+                //if (i == 1) {
+                //    System.out.println(agent + " : " + flc);
+                //}
+                FailoverListComposite.ServerEntry server = flc.get(level);
                 Integer count = distributionMap.get(server.address);
                 distributionMap.put(server.address, (null == count) ? 1 : ++count);
             }
@@ -237,8 +241,16 @@ public class FailoverListManagerBeanTest extends AbstractEJB3Test {
                 double div = (double) numAgents / (double) numServers;
                 int ceil = (int) Math.ceil(div);
                 int floor = (int) Math.floor(div);
-                assert agentsOnServer <= ceil;
-                assert agentsOnServer >= floor;
+                // as we get deeper be more lenient. We haven't come up with any sort of genius algorithm, it's
+                // just ok, if it balances well for the primary through tertiary levels that's pretty good.
+                if (level > 3) {
+                    ++ceil;
+                    --floor;
+                }
+                assert agentsOnServer <= ceil : "AgentsOnServer [" + agentsOnServer + "] > ceiling [" + ceil
+                    + "] (level " + level + ")";
+                assert agentsOnServer >= floor : "AgentsOnServer [" + agentsOnServer + "] < floor [" + floor
+                    + "] (level " + level + ")";
             }
         }
 
@@ -261,7 +273,8 @@ public class FailoverListManagerBeanTest extends AbstractEJB3Test {
                 Integer agentId = Integer.valueOf(agent.getAddress());
                 Integer serverId = Integer.valueOf(server.address);
                 if ((level < numAffinityServers) && (agentId < numAffinityAgents))
-                    assert (serverId < numAffinityServers);
+                    assert (serverId < numAffinityServers) : "serverId [" + serverId + "] >= numAffinityServers ["
+                        + numAffinityServers + "]";
                 Integer count = distributionMap.get(serverId);
                 distributionMap.put(serverId, (null == count) ? 1 : ++count);
             }
@@ -275,8 +288,8 @@ public class FailoverListManagerBeanTest extends AbstractEJB3Test {
                     }
                     int ceil = (int) Math.ceil(div);
                     int floor = (int) Math.floor(div);
-                    assert agentsOnServer <= ceil;
-                    assert agentsOnServer >= floor;
+                    assert agentsOnServer <= ceil : "AgentsOnServer [" + agentsOnServer + "] > ceiling [" + ceil + "]";
+                    assert agentsOnServer >= floor : "AgentsOnServer [" + agentsOnServer + "] < floor [" + floor + "]";
                 }
             }
         }
@@ -585,5 +598,4 @@ public class FailoverListManagerBeanTest extends AbstractEJB3Test {
         assert serverLists.get(0).equals(serverLists.get(2));
         assert serverLists.get(1).equals(serverLists.get(2));
     }
-
 }
\ No newline at end of file


commit 06f1af5e7ec0dbdc2dcfbd4dc1fd40b5831ac89e
Author: Jirka Kremser <jkremser at redhat.com>
Date:   Mon Jul 16 21:01:24 2012 +0200

    [BZ 839720] tests

diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/measurement/test/MeasurementDataManagerTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/measurement/test/MeasurementDataManagerTest.java
index 424145a..a6abea9 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/measurement/test/MeasurementDataManagerTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/measurement/test/MeasurementDataManagerTest.java
@@ -18,10 +18,19 @@
  */
 package org.rhq.enterprise.server.measurement.test;
 
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
 import java.util.Date;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Random;
+import java.util.Set;
 
 import javax.persistence.EntityManager;
 import javax.persistence.Query;
@@ -30,10 +39,14 @@ import org.testng.annotations.AfterMethod;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
+import org.rhq.core.clientapi.agent.measurement.MeasurementAgentService;
 import org.rhq.core.domain.auth.Subject;
 import org.rhq.core.domain.measurement.DataType;
 import org.rhq.core.domain.measurement.DisplayType;
 import org.rhq.core.domain.measurement.MeasurementCategory;
+import org.rhq.core.domain.measurement.MeasurementData;
+import org.rhq.core.domain.measurement.MeasurementDataPK;
+import org.rhq.core.domain.measurement.MeasurementDataTrait;
 import org.rhq.core.domain.measurement.MeasurementDefinition;
 import org.rhq.core.domain.measurement.MeasurementReport;
 import org.rhq.core.domain.measurement.MeasurementSchedule;
@@ -46,11 +59,13 @@ import org.rhq.core.domain.resource.Agent;
 import org.rhq.core.domain.resource.Resource;
 import org.rhq.core.domain.resource.ResourceCategory;
 import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.core.domain.resource.group.ResourceGroup;
 import org.rhq.core.domain.util.PageControl;
 import org.rhq.core.domain.util.PageList;
 import org.rhq.enterprise.server.measurement.CallTimeDataManagerLocal;
 import org.rhq.enterprise.server.measurement.MeasurementDataManagerLocal;
 import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.test.TestServerCommunicationsService;
 import org.rhq.enterprise.server.util.LookupUtil;
 import org.rhq.enterprise.server.util.ResourceTreeHelper;
 
@@ -68,10 +83,12 @@ public class MeasurementDataManagerTest extends AbstractEJB3Test {
     private Subject overlord;
 
     private Resource resource1, resource2;
-    private MeasurementDefinition definitionCt1;
-    private MeasurementDefinition definitionCt2;
+    private ResourceGroup group;
+    private MeasurementDefinition definitionCt1, definitionCt2, definitionCt3;
+    private MeasurementSchedule schedule1, schedule2, schedule3;
     private ResourceType theResourceType;
     private Agent theAgent;
+    private Set<MeasurementData> expectedResult1, expectedResult2, expectedResult3;
 
     @BeforeMethod
     public void beforeMethod() {
@@ -79,6 +96,7 @@ public class MeasurementDataManagerTest extends AbstractEJB3Test {
             this.measurementDataManager = LookupUtil.getMeasurementDataManager();
             this.callTimeDataManager = LookupUtil.getCallTimeDataManager();
             this.overlord = LookupUtil.getSubjectManager().getOverlord();
+
         } catch (Throwable t) {
             // Catch RuntimeExceptions and Errors and dump their stack trace, because Surefire will completely swallow them
             // and throw a cryptic NPE (see http://jira.codehaus.org/browse/SUREFIRE-157)!
@@ -95,6 +113,7 @@ public class MeasurementDataManagerTest extends AbstractEJB3Test {
             callTimeDataManager.purgeCallTimeData(new Date());
 
             EntityManager em = beginTx();
+
             // delete keys
             List<Integer> resourceIds = new ArrayList<Integer>();
             resourceIds.add(resource1.getId());
@@ -119,10 +138,20 @@ public class MeasurementDataManagerTest extends AbstractEJB3Test {
             em.remove(definitionCt1);
             definitionCt2 = em.merge(definitionCt2);
             em.remove(definitionCt2);
+            if (definitionCt3 != null) {
+                definitionCt3 = em.merge(definitionCt3);
+                em.remove(definitionCt3);
+            }
 
             theResourceType = em.merge(theResourceType);
             em.remove(theResourceType);
 
+            // delete group (if exist)
+            if (group != null) {
+                group = em.merge(group);
+                em.remove(group);
+            }
+
             theAgent = em.merge(theAgent);
             em.remove(theAgent);
 
@@ -141,16 +170,6 @@ public class MeasurementDataManagerTest extends AbstractEJB3Test {
 
             setupResources(em);
 
-            MeasurementSchedule schedule1 = new MeasurementSchedule(definitionCt1, resource1);
-            em.persist(schedule1);
-            definitionCt1.addSchedule(schedule1);
-            resource1.addSchedule(schedule1);
-
-            MeasurementSchedule schedule2 = new MeasurementSchedule(definitionCt1, resource2);
-            em.persist(schedule2);
-            definitionCt1.addSchedule(schedule2);
-            resource2.addSchedule(schedule2);
-
             em.flush();
             long now = System.currentTimeMillis();
 
@@ -200,16 +219,6 @@ public class MeasurementDataManagerTest extends AbstractEJB3Test {
 
             setupResources(em);
 
-            MeasurementSchedule schedule1 = new MeasurementSchedule(definitionCt1, resource1);
-            em.persist(schedule1);
-            definitionCt1.addSchedule(schedule1);
-            resource1.addSchedule(schedule1);
-
-            MeasurementSchedule schedule2 = new MeasurementSchedule(definitionCt2, resource1);
-            em.persist(schedule2);
-            definitionCt1.addSchedule(schedule2);
-            resource2.addSchedule(schedule2);
-
             em.flush();
             long now = System.currentTimeMillis();
 
@@ -282,6 +291,195 @@ public class MeasurementDataManagerTest extends AbstractEJB3Test {
         resource2.setUuid("" + new Random().nextInt());
         resource2.setAgent(theAgent);
         em.persist(resource2);
+
+        schedule1 = new MeasurementSchedule(definitionCt1, resource1);
+        em.persist(schedule1);
+        definitionCt1.addSchedule(schedule1);
+        resource1.addSchedule(schedule1);
+
+        schedule2 = new MeasurementSchedule(definitionCt2, resource1);
+        em.persist(schedule2);
+        definitionCt1.addSchedule(schedule2);
+        resource2.addSchedule(schedule2);
+    }
+
+    /**
+     * Just set up the group of two resources plus measurement definitions
+     *
+     * @param  em The EntityManager to use
+     *
+     */
+    private void setupGroupOfResources(EntityManager em) {
+        theAgent = new Agent("testagent", "localhost", 1234, "", "randomToken");
+        em.persist(theAgent);
+
+        theResourceType = new ResourceType("test-plat", "test-plugin", ResourceCategory.PLATFORM, null);
+        em.persist(theResourceType);
+
+        definitionCt1 = new MeasurementDefinition("CT-Def1", MeasurementCategory.PERFORMANCE,
+            MeasurementUnits.MILLISECONDS, DataType.CALLTIME, true, 60000, DisplayType.SUMMARY);
+        definitionCt1.setResourceType(theResourceType);
+        em.persist(definitionCt1);
+
+        definitionCt2 = new MeasurementDefinition("CT-Def2", MeasurementCategory.PERFORMANCE,
+            MeasurementUnits.MILLISECONDS, DataType.CALLTIME, true, 60000, DisplayType.SUMMARY);
+        definitionCt2.setResourceType(theResourceType);
+        em.persist(definitionCt2);
+
+        definitionCt3 = new MeasurementDefinition("CT-Def3", MeasurementCategory.PERFORMANCE,
+            MeasurementUnits.MILLISECONDS, DataType.CALLTIME, true, 60000, DisplayType.SUMMARY);
+        definitionCt3.setResourceType(theResourceType);
+        em.persist(definitionCt3);
+
+        resource1 = new Resource("test-platform-key1", "test-platform-name", theResourceType);
+        resource1.setUuid("" + new Random().nextInt());
+        resource1.setAgent(theAgent);
+        em.persist(resource1);
+
+        resource2 = new Resource("test-platform-key2", "test-platform-name", theResourceType);
+        resource2.setUuid("" + new Random().nextInt());
+        resource2.setAgent(theAgent);
+        em.persist(resource2);
+
+        schedule1 = new MeasurementSchedule(definitionCt1, resource1);
+        em.persist(schedule1);
+        definitionCt1.addSchedule(schedule1);
+        resource1.addSchedule(schedule1);
+
+        schedule2 = new MeasurementSchedule(definitionCt2, resource2);
+        em.persist(schedule2);
+        definitionCt2.addSchedule(schedule2);
+        resource2.addSchedule(schedule2);
+
+        schedule3 = new MeasurementSchedule(definitionCt3, resource2);
+        em.persist(schedule3);
+        definitionCt3.addSchedule(schedule3);
+        resource2.addSchedule(schedule3);
+
+        group = new ResourceGroup("test-group", theResourceType);
+        em.persist(group);
+
+        // prepare return values and expected values
+        long time1 = System.currentTimeMillis();
+        long time2 = time1 + 1;
+        long time3 = time2 + 1;
+        String name1 = "a";
+        String name2 = "b";
+        String name3 = "c";
+        String value1 = "test-value1";
+        String value2 = "test-value2";
+        String value3 = "test-value3";
+
+        // method findLiveDataForGroup adds prefix with resource id which is part of equals
+        MeasurementData expectedData1 = makeMeasurement(time1, schedule1.getId(), value1, name1);
+        expectedData1.setName(resource1.getId() + ":" + name1);
+        MeasurementData expectedData2 = makeMeasurement(time2, schedule2.getId(), value2, name2);
+        expectedData2.setName(resource2.getId() + ":" + name2);
+        MeasurementData expectedData3 = makeMeasurement(time3, schedule3.getId(), value3, name3);
+        expectedData3.setName(resource2.getId() + ":" + name3);
+
+        expectedResult1 = new HashSet<MeasurementData>(1);
+        expectedResult1.add(expectedData1);
+        expectedResult2 = new HashSet<MeasurementData>(2);
+        expectedResult2.add(expectedData2);
+        expectedResult2.add(expectedData3);
+        expectedResult3 = new HashSet<MeasurementData>(3);
+        expectedResult3.addAll(expectedResult1);
+        expectedResult3.addAll(expectedResult2);
+
+        // mock the MeasurementAgentService
+        MeasurementAgentService mockedMeasurementService = mock(MeasurementAgentService.class);
+        when(mockedMeasurementService.getRealTimeMeasurementValue(eq(resource1.getId()), any(Set.class))).thenReturn(
+            new HashSet<MeasurementData>(Arrays.asList(makeMeasurement(time1, schedule1.getId(), value1, name1))));
+        when(mockedMeasurementService.getRealTimeMeasurementValue(eq(resource2.getId()), any(Set.class))).thenReturn(
+            new HashSet<MeasurementData>(Arrays.asList(makeMeasurement(time2, schedule2.getId(), value2, name2),
+                makeMeasurement(time3, schedule3.getId(), value3, name3))));
+        TestServerCommunicationsService agentServiceContainer = prepareForTestAgents();
+        agentServiceContainer.measurementService = mockedMeasurementService;
+    }
+
+    @Test
+    public void testFindLiveDataForGroup1() throws Exception {
+        // prepare DB
+        EntityManager em = beginTx();
+        setupGroupOfResources(em);
+        commitAndClose(em);
+        try {
+            Set<MeasurementData> actualResult = measurementDataManager.findLiveDataForGroup(overlord, group.getId(),
+                new int[] { resource1.getId() }, new int[] { definitionCt1.getId() });
+
+            Set<MeasurementData> actualResultWithNewHashCodes = new HashSet<MeasurementData>(actualResult);
+            assertEquals(expectedResult1, actualResultWithNewHashCodes);
+
+            actualResult = measurementDataManager.findLiveDataForGroup(overlord, group.getId(),
+                new int[] { resource2.getId() }, new int[] { definitionCt2.getId(), definitionCt3.getId() });
+            actualResultWithNewHashCodes = new HashSet<MeasurementData>(actualResult);
+            assertEquals(expectedResult2, actualResultWithNewHashCodes);
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            fail();
+            throw e;
+        }
+    }
+
+    @Test
+    public void testFindLiveDataForGroup2() throws Exception {
+        // prepare DB
+        EntityManager em = beginTx();
+        setupGroupOfResources(em);
+        commitAndClose(em);
+        try {
+            Set<MeasurementData> actualResult = measurementDataManager.findLiveDataForGroup(overlord, group.getId(),
+                new int[] { resource1.getId(), resource2.getId() },
+                new int[] { definitionCt1.getId(), definitionCt2.getId(), definitionCt3.getId() });
+            Set<MeasurementData> actualResultWithNewHashCodes = new HashSet<MeasurementData>(actualResult);
+            assertEquals(expectedResult3, actualResultWithNewHashCodes);
+        } catch (Exception e) {
+            e.printStackTrace();
+            fail();
+            throw e;
+        }
+    }
+
+    @Test
+    public void testFindLiveDataForGroup3() throws Exception {
+        // prepare DB
+        EntityManager em = beginTx();
+        setupGroupOfResources(em);
+        commitAndClose(em);
+        try {
+
+            Set<MeasurementData> actualResult = measurementDataManager.findLiveDataForGroup(overlord, group.getId(),
+                null, new int[] { definitionCt1.getId() });
+            assertEquals(Collections.emptySet(), actualResult);
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            fail();
+            throw e;
+        }
+    }
+
+    @Test
+    public void testFindLiveDataForGroup4() throws Exception {
+        // prepare DB
+        EntityManager em = beginTx();
+        setupGroupOfResources(em);
+        commitAndClose(em);
+        try {
+            measurementDataManager.findLiveDataForGroup(null, group.getId(), new int[] { resource1.getId() },
+                new int[] { definitionCt1.getId() });
+            fail();
+        } catch (Exception e) {
+            // ok, it was expected
+        }
+    }
+
+    private MeasurementData makeMeasurement(long time, int scheduleId, String value, String name) {
+        MeasurementData measurement = new MeasurementDataTrait(new MeasurementDataPK(time, scheduleId), value);
+        measurement.setName(name);
+        return measurement;
     }
 
     private EntityManager beginTx() throws Exception {


commit 2d6b3d400552fb087acb21feb856f082f446ae5e
Author: Jirka Kremser <jkremser at redhat.com>
Date:   Mon Jul 16 12:08:58 2012 +0200

    [BZ 808175] typo

diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerLocal.java
index a285a7f..1878a8f 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerLocal.java
@@ -181,7 +181,7 @@ public interface MeasurementDataManagerLocal {
      *
      * @return MeasurementData for this Schedule
      */
-    Set<MeasurementData> findLiveDataForGroup(Subject subject, int groupId, int[] resourceId, int[] definitionIds);
+    Set<MeasurementData> findLiveDataForGroup(Subject subject, int groupId, int[] resourceIds, int[] definitionIds);
 
     /**
      * Returns a list of numeric data point lists for the given compatible group - one per specified measurement
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerRemote.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerRemote.java
index d3163ec..b452adf 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerRemote.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerRemote.java
@@ -76,7 +76,7 @@ public interface MeasurementDataManagerRemote {
     Set<MeasurementData> findLiveDataForGroup(//
         @WebParam(name = "subject") Subject subject, //
         @WebParam(name = "groupId") int groupId,//
-        @WebParam(name = "resourceId") int[] resourceId, //
+        @WebParam(name = "resourceId") int[] resourceIds, //
         @WebParam(name = "definitionIds") int[] definitionIds);
 
     @WebMethod


commit edb9cf72684d5f5cccc9cf5c0c0f068f17042ea3
Author: Jay Shaughnessy <jshaughn at redhat.com>
Date:   Fri Jul 13 14:49:53 2012 -0400

    Add some null/empty string protection, even though the string really should
    never be empty.

diff --git a/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/util/ServerStartScriptDiscoveryUtility.java b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/util/ServerStartScriptDiscoveryUtility.java
index df8ac21..4476173 100644
--- a/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/util/ServerStartScriptDiscoveryUtility.java
+++ b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/util/ServerStartScriptDiscoveryUtility.java
@@ -290,12 +290,21 @@ public class ServerStartScriptDiscoveryUtility {
         }
 
         int startScriptIndex;
-        // Advance past any shell (e.g. /bin/sh or cmd.exe) options.
+        // Advance past any shell (e.g. /bin/sh or cmd.exe) options or empty args
         for (startScriptIndex = 1; (startScriptIndex < serverParentProcessCommandLine.length); ++startScriptIndex) {
-            if (serverParentProcessCommandLine[startScriptIndex].charAt(0) != OPTION_PREFIX) {
+            // the arg should not be null or empty, but we've seen empty args from Sigar...            
+            String arg = serverParentProcessCommandLine[startScriptIndex];
+
+            if (arg != null && !arg.isEmpty() && arg.charAt(0) != OPTION_PREFIX) {
                 break;
             }
         }
+
+        // for whatever unanticipated reason, we advanced past all of the args
+        if (startScriptIndex == serverParentProcessCommandLine.length) {
+            return null;
+        }
+
         String possibleStartScript = serverParentProcessCommandLine[startScriptIndex];
         return (isScript(possibleStartScript)) ? startScriptIndex : null;
     }


commit 6e4d8cd596e81674ec3eacc625be9f3eb3d04f2a
Author: Lukas Krejci <lkrejci at redhat.com>
Date:   Fri Jul 13 16:56:55 2012 +0200

    Making the package scanning of the python language support configurable
    through additional RHQ-specific system variables.
    Update the RHQ server startup scripts to configure the python's package
    scanning so that it properly discovers domain jar and its packages and
    classes. This is then used to pre-import domain classes into the script
    context for the alert scripts.

diff --git a/modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonScriptEngineInitializer.java b/modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonScriptEngineInitializer.java
index e868204..3a030f4 100644
--- a/modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonScriptEngineInitializer.java
+++ b/modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonScriptEngineInitializer.java
@@ -51,8 +51,8 @@ public class PythonScriptEngineInitializer implements ScriptEngineInitializer {
 
     static {
         Properties props = new Properties();
-        props.put("python.packages.paths", "java.class.path,sun.boot.class.path");
-        props.put("python.packages.directories", "java.ext.dirs");
+        props.put("python.packages.paths", "rhq.python.additional.classpath,java.class.path,sun.boot.class.path");
+        props.put("python.packages.directories", "rhq.python.additional.package.dirs,java.ext.dirs");
         props.put("python.cachedir.skip", false);
         PythonInterpreter.initialize(System.getProperties(), props, null);
     }
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 1a38161..f481201 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
@@ -284,6 +284,12 @@ if $JAVA -version 2>&1 | grep "IBM J9" >/dev/null 2>&1; then
    fi
 fi
 
+#-----------------------------------------------------------------------
+# Setup the Python package scanning in case we have Python scripting available
+#-----------------------------------------------------------------------
+JYTHON_CACHE_DIR="$RHQ_SERVER_HOME/jbossas/server/default/data/jython.cachedir"
+PYTHON_ADDITIONAL_CLASSPATH="$RHQ_SERVER_HOME/jbossas/server/default/deploy/rhq.ear/rhq-core-domain-ejb3.jar/./"
+
 # ----------------------------------------------------------------------
 # Prepare the VM command line options to be passed in
 # ----------------------------------------------------------------------
@@ -293,7 +299,7 @@ if [ -z "$RHQ_SERVER_JAVA_OPTS" ]; then
 fi
 # Add the JVM opts that we always want to specify, whether or not the user set RHQ_SERVER_JAVA_OPTS.
 # Note that the double equals for the policy file specification IS INTENTIONAL
-RHQ_SERVER_JAVA_OPTS="-Dapp.name=rhq-server $RHQ_SERVER_JAVA_OPTS -Djava.awt.headless=true -Djboss.platform.mbeanserver -Dsun.lang.ClassLoader.allowArraySyntax=true -Djava.util.logging.config.file=$RHQ_SERVER_HOME/jbossas/server/default/conf/logging.properties -Djava.security.manager -Djava.security.policy==$RHQ_SERVER_HOME/bin/rhq-server.security-policy"
+RHQ_SERVER_JAVA_OPTS="-Dapp.name=rhq-server $RHQ_SERVER_JAVA_OPTS -Djava.awt.headless=true -Djboss.platform.mbeanserver -Dsun.lang.ClassLoader.allowArraySyntax=true -Djava.util.logging.config.file=$RHQ_SERVER_HOME/jbossas/server/default/conf/logging.properties -Djava.security.manager -Djava.security.policy==$RHQ_SERVER_HOME/bin/rhq-server.security-policy -Dpython.cachedir=$JYTHON_CACHE_DIR -Drhq.python.additional.classpath=$PYTHON_ADDITIONAL_CLASSPATH"
 
 debug_msg "RHQ_SERVER_JAVA_OPTS: $RHQ_SERVER_JAVA_OPTS"
 debug_msg "RHQ_SERVER_ADDITIONAL_JAVA_OPTS: $RHQ_SERVER_ADDITIONAL_JAVA_OPTS"
diff --git a/modules/enterprise/server/container/src/main/bin-resources/bin/wrapper/rhq-server-wrapper.conf b/modules/enterprise/server/container/src/main/bin-resources/bin/wrapper/rhq-server-wrapper.conf
index b4f178b..cf30c5a 100644
--- a/modules/enterprise/server/container/src/main/bin-resources/bin/wrapper/rhq-server-wrapper.conf
+++ b/modules/enterprise/server/container/src/main/bin-resources/bin/wrapper/rhq-server-wrapper.conf
@@ -71,6 +71,9 @@ wrapper.java.additional.11=-Dsun.lang.ClassLoader.allowArraySyntax=true
 wrapper.java.additional.12=-Djava.security.manager
 # the double equals for the policy file specification IS INTENTIONAL
 wrapper.java.additional.13="-Djava.security.policy==%RHQ_SERVER_HOME%/bin/rhq-server.security-policy"
+#Setup up a cache dir for jython in case python script support was available in the server
+wrapper.java.additional.14="-Dpython.cachedir=%RHQ_SERVER_HOME%/jbossas/server/default/data/jython.cachedir"
+wrapper.java.additional.15="-Drhq.python.additional.classpath=%RHQ_SERVER_HOME%/jbossas/server/default/deploy/rhq.ear/rhq-core-domain-ejb3.jar/./"
 
 # We want to make sure the Server starts in the JBossAS bin directory
 wrapper.working.dir=%RHQ_SERVER_HOME%/jbossas/bin


commit 33db4718581ca09afc259a8e73310ce65a573025
Author: Lukas Krejci <lkrejci at redhat.com>
Date:   Fri Jul 13 16:54:14 2012 +0200

    [BZ 839780] - The scriptengine providers now can tell the file extension of
    the scripts they support. The alert-cli plugin then picks the correct
    script engine implementation for a script based on its file name extension.

diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/ScriptEngineFactory.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/ScriptEngineFactory.java
index 9887958..6bba114 100644
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/ScriptEngineFactory.java
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/ScriptEngineFactory.java
@@ -114,6 +114,25 @@ public class ScriptEngineFactory {
         return new HashSet<String>(KNOWN_PROVIDERS.keySet());       
     }
     
+    public static String getLanguageByScriptFileExtension(String fileExtension) {
+        for (ScriptEngineProvider p : KNOWN_PROVIDERS.values()) {
+            if (fileExtension.equals(p.getScriptFileExtension())) {
+                return p.getSupportedLanguage();
+            }
+        }
+
+        return null;
+    }
+
+    public static String getFileExtensionForLanguage(String language) {
+        ScriptEngineProvider provider = KNOWN_PROVIDERS.get(language);
+        if (provider == null) {
+            return null;
+        }
+
+        return provider.getScriptFileExtension();
+    }
+
     /**
      * Initializes the script engine for given language.
      * 
diff --git a/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptEngineProvider.java b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptEngineProvider.java
index 067ed90..f5b619e 100644
--- a/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptEngineProvider.java
+++ b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptEngineProvider.java
@@ -47,6 +47,12 @@ public interface ScriptEngineProvider {
     String getSupportedLanguage();
 
     /**
+     * @return the file extension of files written in the language supported by this provider.
+     * The returned string is the extension without the leading dot.
+     */
+    String getScriptFileExtension();
+
+    /**
      * @return an implementation of {@link ScriptEngineInitializer} that can instantiate
      * and initialize a script engine for the supported language for use with RHQ. 
      */
diff --git a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineProvider.java b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineProvider.java
index 02d54eb..63c5023 100644
--- a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineProvider.java
+++ b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineProvider.java
@@ -36,6 +36,11 @@ public class JsEngineProvider implements ScriptEngineProvider {
     }
 
     @Override
+    public String getScriptFileExtension() {
+        return "js";
+    }
+
+    @Override
     public ScriptEngineInitializer getInitializer() {
         return new JsEngineInitializer();
     }
diff --git a/modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonScriptEngineProvider.java b/modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonScriptEngineProvider.java
index c0bfcac..2d71f85 100644
--- a/modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonScriptEngineProvider.java
+++ b/modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonScriptEngineProvider.java
@@ -36,6 +36,11 @@ public class PythonScriptEngineProvider implements ScriptEngineProvider {
     }
 
     @Override
+    public String getScriptFileExtension() {
+        return "py";
+    }
+
+    @Override
     public ScriptEngineInitializer getInitializer() {
         return new PythonScriptEngineInitializer();
     }
diff --git a/modules/enterprise/server/plugins/alert-cli/src/main/java/org/rhq/enterprise/server/plugins/alertCli/CliSender.java b/modules/enterprise/server/plugins/alert-cli/src/main/java/org/rhq/enterprise/server/plugins/alertCli/CliSender.java
index 0bca2fa..5eb9360 100644
--- a/modules/enterprise/server/plugins/alert-cli/src/main/java/org/rhq/enterprise/server/plugins/alertCli/CliSender.java
+++ b/modules/enterprise/server/plugins/alert-cli/src/main/java/org/rhq/enterprise/server/plugins/alertCli/CliSender.java
@@ -30,8 +30,11 @@ import java.io.PipedOutputStream;
 import java.io.PrintWriter;
 import java.nio.charset.Charset;
 import java.util.ArrayDeque;
+import java.util.ArrayList;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Queue;
 
 import javax.script.ScriptEngine;
@@ -71,8 +74,6 @@ import org.rhq.scripting.ScriptSourceProviderFactory;
  */
 public class CliSender extends AlertSender<CliComponent> {
 
-    private static final String ENGINE_NAME = "javascript";
-
     private static final int MAX_RESULT_SIZE = 4000;
 
     public static final String PROP_PACKAGE_ID = "packageId";
@@ -91,7 +92,7 @@ public class CliSender extends AlertSender<CliComponent> {
     //no more than 10 concurrently running CLI notifications..
     //is that enough?
     private static final int MAX_SCRIPT_ENGINES = 10;
-    private static Queue<ScriptEngine> SCRIPT_ENGINES = new ArrayDeque<ScriptEngine>(MAX_SCRIPT_ENGINES);
+    private static Map<String, Queue<ScriptEngine>> SCRIPT_ENGINES = new HashMap<String, Queue<ScriptEngine>>();
     private static int ENGINES_IN_USE = 0;
 
     /**
@@ -108,12 +109,18 @@ public class CliSender extends AlertSender<CliComponent> {
         public Throwable throwable;
     }
 
+    private static class BitsAndFileExtension {
+        InputStream packageBits;
+        String scriptFileExtension;
+    }
+
     public SenderResult send(Alert alert) {
         SenderResult result = new SenderResult();
         BufferedReader reader = null;
         ScriptEngine engine = null;
         Subject subjectWithSession = null;
         final SessionManager sessionManager = SessionManager.getInstance();
+        String language = null;
 
         try {
             final Config config = getConfig();
@@ -127,9 +134,25 @@ public class CliSender extends AlertSender<CliComponent> {
             ByteArrayOutputStream scriptOutputStream = new ByteArrayOutputStream();
             PrintWriter scriptOut = new PrintWriter(scriptOutputStream);
 
-            engine = getScriptEngine(alert, scriptOut, config);
+            BitsAndFileExtension packageData = getPackageBits(config.packageId, config.repoId);
+
+            InputStream packageBits = packageData.packageBits;
+            String scriptFileExtension = packageData.scriptFileExtension;
+            language = ScriptEngineFactory.getLanguageByScriptFileExtension(scriptFileExtension);
+
+            if (language == null) {
+                ArrayList<String> supportedExtensions = new ArrayList<String>();
+                for (String lang : ScriptEngineFactory.getSupportedLanguages()) {
+                    supportedExtensions.add(ScriptEngineFactory.getFileExtensionForLanguage(lang));
+                }
+
+                throw new IllegalArgumentException(
+                    "Could not determine the script engine to use based on the script file extension '"
+                        + scriptFileExtension + "'. Only the following extensions are currently supported: "
+                        + supportedExtensions);
+            }
 
-            InputStream packageBits = getPackageBits(config.packageId, config.repoId);
+            engine = getScriptEngine(alert, scriptOut, config, language);
 
             reader = new BufferedReader(new InputStreamReader(packageBits));
 
@@ -166,7 +189,7 @@ public class CliSender extends AlertSender<CliComponent> {
                     exceptionHolder.scriptException);
 
                 //make things pretty for the UI
-                ScriptEngineInitializer initializer = ScriptEngineFactory.getInitializer(ENGINE_NAME);
+                ScriptEngineInitializer initializer = ScriptEngineFactory.getInitializer(language);
                 String message = initializer.extractUserFriendlyErrorMessage(exceptionHolder.scriptException);
                 int col = exceptionHolder.scriptException.getColumnNumber();
                 int line = exceptionHolder.scriptException.getLineNumber();
@@ -203,7 +226,7 @@ public class CliSender extends AlertSender<CliComponent> {
                 sessionManager.invalidate(subjectWithSession.getSessionId());
             }
             if (engine != null) {
-                returnEngine(engine);
+                returnEngine(engine, language);
             }
 
             if (reader != null) {
@@ -264,7 +287,8 @@ public class CliSender extends AlertSender<CliComponent> {
         return results;
     }
 
-    private static ScriptEngine getScriptEngine(Alert alert, PrintWriter output, Config config) throws ScriptException,
+    private static ScriptEngine getScriptEngine(Alert alert, PrintWriter output, Config config, String language)
+        throws ScriptException,
         IOException, InterruptedException {
         Subject user = config.subject;
 
@@ -273,14 +297,14 @@ public class CliSender extends AlertSender<CliComponent> {
         StandardBindings bindings = new StandardBindings(output, client);
         bindings.put("alert", alert);
 
-        ScriptEngine engine = takeEngine(bindings);
+        ScriptEngine engine = takeEngine(bindings, language);
         engine.getContext().setWriter(output);
         engine.getContext().setErrorWriter(output);
 
         return engine;
     }
 
-    private static InputStream getPackageBits(int packageId, int repoId) throws IOException {
+    private static BitsAndFileExtension getPackageBits(int packageId, int repoId) throws IOException {
         final ContentSourceManagerLocal csm = LookupUtil.getContentSourceManager();
         RepoManagerLocal rm = LookupUtil.getRepoManagerLocal();
         final PackageVersion versionToUse = rm.getLatestPackageVersion(LookupUtil.getSubjectManager().getOverlord(),
@@ -293,8 +317,8 @@ public class CliSender extends AlertSender<CliComponent> {
                     + " either doesn't exist at all or doesn't have any version. Can't execute a CLI script without a script to run.");
         }
 
-        PipedInputStream ret = new PipedInputStream();
-        final PipedOutputStream out = new PipedOutputStream(ret);
+        PipedInputStream bits = new PipedInputStream();
+        final PipedOutputStream out = new PipedOutputStream(bits);
 
         Thread reader = new Thread(new Runnable() {
             public void run() {
@@ -320,6 +344,20 @@ public class CliSender extends AlertSender<CliComponent> {
         reader.setDaemon(true);
         reader.start();
 
+        BitsAndFileExtension ret = new BitsAndFileExtension();
+        ret.packageBits = bits;
+        String fileName = versionToUse.getFileName();
+        String extension = "";
+
+        if (fileName != null) {
+            int dotIdx = fileName.lastIndexOf('.');
+            if (dotIdx >= 0) {
+                extension = fileName.substring(dotIdx + 1);
+            }
+        }
+
+        ret.scriptFileExtension = extension;
+
         return ret;
     }
 
@@ -417,17 +455,24 @@ public class CliSender extends AlertSender<CliComponent> {
         }
     }
 
-    private static ScriptEngine takeEngine(StandardBindings bindings) throws InterruptedException, ScriptException,
+    private static ScriptEngine takeEngine(StandardBindings bindings, String language) throws InterruptedException,
+        ScriptException,
         IOException {
         synchronized (SCRIPT_ENGINES) {
             if (ENGINES_IN_USE >= MAX_SCRIPT_ENGINES) {
                 SCRIPT_ENGINES.wait();
             }
 
-            ScriptEngine engine = SCRIPT_ENGINES.poll();
+            Queue<ScriptEngine> q = SCRIPT_ENGINES.get(language);
+            if (q == null) {
+                q = new ArrayDeque<ScriptEngine>();
+                SCRIPT_ENGINES.put(language, q);
+            }
+
+            ScriptEngine engine = q.poll();
 
             if (engine == null) {
-                engine = ScriptEngineFactory.getSecuredScriptEngine(ENGINE_NAME,
+                engine = ScriptEngineFactory.getSecuredScriptEngine(language,
                     new PackageFinder(Collections.<File> emptyList()), bindings, new StandardScriptPermissions());
             }
             //TODO is this OK, or should we use a different classloader than the context classloader?
@@ -440,9 +485,16 @@ public class CliSender extends AlertSender<CliComponent> {
         }
     }
 
-    private static void returnEngine(ScriptEngine engine) {
+    private static void returnEngine(ScriptEngine engine, String language) {
         synchronized (SCRIPT_ENGINES) {
-            SCRIPT_ENGINES.offer(engine);
+            Queue<ScriptEngine> q = SCRIPT_ENGINES.get(language);
+            if (q == null) {
+                //hmm... this is very strange and should not happen, because we should have initied the queue in the 
+                //takeEngine() method...
+                q = new ArrayDeque<ScriptEngine>();
+                SCRIPT_ENGINES.put(language, q);
+            }
+            q.offer(engine);
             --ENGINES_IN_USE;
             SCRIPT_ENGINES.notify();
         }


commit 5f0388a7ba23c1f395892950c322e3d649840d2f
Author: Jirka Kremser <jkremser at redhat.com>
Date:   Fri Jul 13 13:10:34 2012 +0200

    [BZ 839720 - The alert notifications dialog initially shows wrong UI] This was caused by commit 1c7723b

diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/NewNotificationEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/NewNotificationEditor.java
index 9cf0850..c66b207 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/NewNotificationEditor.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/NewNotificationEditor.java
@@ -118,6 +118,7 @@ public class NewNotificationEditor extends LocatableDynamicForm {
                         notificationSenderSelectItem.setDisabled(false);
                         notificationSenderSelectItem.redraw();
 
+                        notificationSenderSelectItem.setValue(result[0]);
                         switchToAlertSender(result[0]);
                         senderCanvasItem.show();
                     } else {


commit f5bbb1ef7b8b7ae50086dac59ab36b61aeceb762
Author: Lukas Krejci <lkrejci at redhat.com>
Date:   Fri Jul 13 11:29:40 2012 +0200

    Fixing the dev profile of the lang support modules to copy the final
    repackaged jars to the dev-container.

diff --git a/modules/enterprise/scripting/javascript/pom.xml b/modules/enterprise/scripting/javascript/pom.xml
index 06bed89..38ead44 100644
--- a/modules/enterprise/scripting/javascript/pom.xml
+++ b/modules/enterprise/scripting/javascript/pom.xml
@@ -86,7 +86,7 @@
 
                      <execution>
                         <id>deploy</id>
-                        <phase>compile</phase>
+                        <phase>install</phase>
                         <configuration>
                            <tasks>
                               <mkdir dir="${rhq.deploymentDir}" />
@@ -94,8 +94,7 @@
                                  location="${rhq.deploymentDir}/${project.build.finalName}.jar" />
                               <echo>*** Updating
                                  ${deployment.file}...</echo>
-                              <jar destfile="${deployment.file}"
-                                 basedir="${project.build.outputDirectory}" />
+                              <copy tofile="${deployment.file}" file="${project.build.directory}/${project.build.finalName}.jar" />
                            </tasks>
                         </configuration>
                         <goals>
diff --git a/modules/enterprise/scripting/python/pom.xml b/modules/enterprise/scripting/python/pom.xml
index b657dd2..39d3895 100644
--- a/modules/enterprise/scripting/python/pom.xml
+++ b/modules/enterprise/scripting/python/pom.xml
@@ -85,14 +85,14 @@
 
                             <execution>
                                 <id>deploy</id>
-                                <phase>compile</phase>
+                                <phase>install</phase>
                                 <configuration>
                                     <tasks>
                                         <mkdir dir="${rhq.deploymentDir}" />
                                         <property name="deployment.file" location="${rhq.deploymentDir}/${project.build.finalName}.jar" />
                                         <echo>*** Updating
                                             ${deployment.file}...</echo>
-                                        <jar destfile="${deployment.file}" basedir="${project.build.outputDirectory}" />
+                                        <copy tofile="${deployment.file}" file="${project.build.directory}/${project.build.finalName}.jar" />
                                     </tasks>
                                 </configuration>
                                 <goals>


commit 97c9424489cbb8cf65f44d83c06015ed4b0b7c32
Author: Mike Thompson <mithomps at redhat.com>
Date:   Thu Jul 12 15:49:38 2012 -0700

    HotFix: The min/max fields on PropertyDefinitionList broke some other plugins. I didn't see this until I created new schema. This is a temp fix until real fix.

diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/definition/PropertyDefinitionList.java b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/definition/PropertyDefinitionList.java
index 92c8df6..1b1f248 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/definition/PropertyDefinitionList.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/definition/PropertyDefinitionList.java
@@ -48,8 +48,10 @@ import java.lang.Integer;
 public class PropertyDefinitionList extends PropertyDefinition {
     private static final long serialVersionUID = 1L;
 
+    @Transient
     private int min = 0;
 
+    @Transient
     private int max = Integer.MAX_VALUE;
 
     @JoinColumn(name = "parent_list_definition_id")


commit c80c45065a6e0f1977e0c04fae5a8f05593ecd40
Author: Mike Thompson <mithomps at redhat.com>
Date:   Thu Jul 12 14:14:36 2012 -0700

    For Test page move save button to bottom of screen for consistency.

diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/ResourceConfigurationEditView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/ResourceConfigurationEditView.java
index 9d2d1a2..52e3c69 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/ResourceConfigurationEditView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/ResourceConfigurationEditView.java
@@ -80,13 +80,11 @@ public class ResourceConfigurationEditView extends LocatableVLayout implements P
     protected void onDraw() {
         super.onDraw();
 
-        //createButtonBar();
-
         refresh();
 
         if (!this.resourcePermission.isConfigureWrite()) {
-            Message message = new Message(MSG.view_configurationDetails_noPermission(), Message.Severity.Info, EnumSet
-                .of(Message.Option.Transient, Message.Option.Sticky));
+            Message message = new Message(MSG.view_configurationDetails_noPermission(), Message.Severity.Info,
+                    EnumSet.of(Message.Option.Transient, Message.Option.Sticky));
             CoreGUI.getMessageCenter().notify(message);
         }
     }
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/test/configuration/TestConfigurationView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/test/configuration/TestConfigurationView.java
index 31d17a3..b0d9154 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/test/configuration/TestConfigurationView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/test/configuration/TestConfigurationView.java
@@ -51,6 +51,7 @@ public class TestConfigurationView
 
     private ConfigurationEditor editor;
     private LocatableIButton saveButton;
+    private LocatableToolStrip buttonBar;
     private ConfigurationDefinition configurationDefinition;
     private Configuration configuration;
 
@@ -67,7 +68,16 @@ public class TestConfigurationView
     public void build() {
         setWidth100();
         setHeight100();
-        
+
+        buttonBar = createButtonBar();
+
+        this.configurationDefinition = TestConfigurationFactory.createConfigurationDefinition();
+        this.configuration = TestConfigurationFactory.createConfiguration();
+
+        reloadConfiguration();
+    }
+
+    private LocatableToolStrip createButtonBar() {
         LocatableToolStrip toolStrip = new LocatableToolStrip(extendLocatorId("ToolStrip"));
         toolStrip.setWidth100();
 
@@ -81,13 +91,8 @@ public class TestConfigurationView
         });
         this.saveButton.disable();
         toolStrip.addMember(this.saveButton);
-
-        addMember(toolStrip);
-
-        this.configurationDefinition = TestConfigurationFactory.createConfigurationDefinition();
-        this.configuration = TestConfigurationFactory.createConfiguration();
-
-        reloadConfiguration();
+        toolStrip.addSpacer(40);
+        return toolStrip;
     }
 
     @Override
@@ -120,10 +125,13 @@ public class TestConfigurationView
         if (editor != null) {
             editor.destroy();
             removeMember(editor);
+            buttonBar.destroy();
+            removeMember(buttonBar);
         }
 
         editor = createConfigurationEditor();
         addMember(editor);
+        addMember(createButtonBar());
         markForRedraw();
     }
 
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/test/configuration/TestGroupConfigurationView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/test/configuration/TestGroupConfigurationView.java
index d2d9c94..054af8e 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/test/configuration/TestGroupConfigurationView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/test/configuration/TestGroupConfigurationView.java
@@ -53,6 +53,7 @@ public class TestGroupConfigurationView
 
     private ConfigurationEditor editor;
     private LocatableIButton saveButton;
+    private ToolStrip buttonBar;
     private ConfigurationDefinition configurationDefinition;
     private List<GroupMemberConfiguration> memberConfigurations;
 
@@ -67,22 +68,6 @@ public class TestGroupConfigurationView
         setWidth100();
         setHeight100();
 
-        ToolStrip toolStrip = new ToolStrip();
-        toolStrip.setWidth100();
-
-        toolStrip.addMember(new LayoutSpacer());
-
-        this.saveButton = new LocatableIButton(this.extendLocatorId("Save"), "Save");
-        this.saveButton.addClickHandler(new ClickHandler() {
-            public void onClick(ClickEvent clickEvent) {
-                save();
-            }
-        });
-        this.saveButton.disable();
-        toolStrip.addMember(this.saveButton);
-
-        addMember(toolStrip);
-
         this.configurationDefinition = TestConfigurationFactory.createConfigurationDefinition();
         this.memberConfigurations = new ArrayList<GroupMemberConfiguration>(GROUP_SIZE);
         for (int i = 0; i < GROUP_SIZE; i++) {
@@ -91,10 +76,26 @@ public class TestGroupConfigurationView
                 configuration);
             this.memberConfigurations.add(memberConfiguration);
         }
-
         reloadConfiguration();
     }
 
+    private ToolStrip createButtonBar() {
+        buttonBar = new ToolStrip();
+        buttonBar.setWidth100();
+        buttonBar.addMember(new LayoutSpacer());
+
+        this.saveButton = new LocatableIButton(this.extendLocatorId("Save"), "Save");
+        this.saveButton.addClickHandler(new ClickHandler() {
+            public void onClick(ClickEvent clickEvent) {
+                save();
+            }
+        });
+        this.saveButton.disable();
+        buttonBar.addMember(this.saveButton);
+        buttonBar.addSpacer(40);
+        return buttonBar;
+    }
+
     @Override
     public void propertyValueChanged(PropertyValueChangeEvent event) {
         MessageCenter messageCenter = CoreGUI.getMessageCenter();
@@ -120,14 +121,17 @@ public class TestGroupConfigurationView
     }
 
     private void reloadConfiguration() {
-        this.saveButton.disable();
         if (editor != null) {
             editor.destroy();
             removeMember(editor);
+            buttonBar.destroy();
+            removeMember(buttonBar);
         }
 
         editor = createConfigurationEditor();
         addMember(editor);
+        addMember(createButtonBar());
+        markForRedraw();
     }
 
     protected GroupConfigurationEditor createConfigurationEditor() {


commit 336ce7c5c794775f7517fbc3a0770ffa2d3e7974
Author: Mike Thompson <mithomps at redhat.com>
Date:   Thu Jul 12 13:02:59 2012 -0700

    [BZ 815305] Min/max constraints on plugin PropertyList not honored in UI.

diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/definition/PropertyDefinitionList.java b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/definition/PropertyDefinitionList.java
index 4c85a62..92c8df6 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/definition/PropertyDefinitionList.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/definition/PropertyDefinitionList.java
@@ -33,6 +33,8 @@ import javax.xml.bind.annotation.XmlSeeAlso;
 
 import org.jetbrains.annotations.NotNull;
 
+import java.lang.Integer;
+
 /**
  * The definition of a list of properties where each member of the list has the same definition. The definition of the
  * entries may be null in the case of arbitrary lists.
@@ -46,17 +48,9 @@ import org.jetbrains.annotations.NotNull;
 public class PropertyDefinitionList extends PropertyDefinition {
     private static final long serialVersionUID = 1L;
 
-    /**
-     * See JBNADM-1595
-     */
-    @Transient
-    private int min;
+    private int min = 0;
 
-    /**
-     * See JBNADM-1595
-     */
-    @Transient
-    private int max;
+    private int max = Integer.MAX_VALUE;
 
     @JoinColumn(name = "parent_list_definition_id")
     @OneToOne(cascade = CascadeType.ALL)
@@ -99,4 +93,4 @@ public class PropertyDefinitionList extends PropertyDefinition {
     public void setMin(int min) {
         this.min = min;
     }
-}
\ No newline at end of file
+}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/ConfigurationEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/ConfigurationEditor.java
index 48df2d6..aec7274 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/ConfigurationEditor.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/ConfigurationEditor.java
@@ -293,78 +293,86 @@ public class ConfigurationEditor extends LocatableVLayout {
         if (configurationDefinition == null || configuration == null) {
 
             if (configType == ConfigType.resource) {
-                configurationService.getResourceConfiguration(resourceId, new AsyncCallback<Configuration>() {
-                    public void onFailure(Throwable caught) {
-                        showError(caught);
-                        if (loadHandler != null) {
-                            loadHandler.loadedConfiguration(null);
-                        }
-                    }
+                loadResourceConfiguration(start);
 
-                    public void onSuccess(Configuration result) {
-                        configuration = result;
-                        Log.info("Config retrieved in: " + (System.currentTimeMillis() - start));
-                        reload();
-                        if (loadHandler != null) {
-                            loadHandler.loadedConfiguration(configuration);
-                        }
-                    }
-                });
+            } else if (configType == ConfigType.plugin) {
+                loadPluginConfiguration(start);
+            }
+        }
 
-                ResourceTypeRepository.Cache.getInstance().getResourceTypes(new Integer[] { resourceTypeId },
-                    EnumSet.of(ResourceTypeRepository.MetadataType.resourceConfigurationDefinition),
-                    new ResourceTypeRepository.TypesLoadedCallback() {
-                        public void onTypesLoaded(Map<Integer, ResourceType> types) {
-                            Log.debug("ConfigDef retrieved in: " + (System.currentTimeMillis() - start));
-                            configurationDefinition = types.get(resourceTypeId).getResourceConfigurationDefinition();
-                            if (configurationDefinition == null) {
-                                loadingLabel.hide();
-                                showError(MSG.view_configEdit_error_1());
-                            }
-                            reload();
-                            if (loadHandler != null) {
-                                loadHandler.loadedConfigurationDefinition(configurationDefinition);
-                            }
-                        }
-                    });
+        reload();
+    }
 
-            } else if (configType == ConfigType.plugin) {
-                configurationService.getPluginConfiguration(resourceId, new AsyncCallback<Configuration>() {
-                    public void onFailure(Throwable caught) {
-                        showError(caught);
-                        if (loadHandler != null) {
-                            loadHandler.loadedConfiguration(null);
-                        }
-                    }
+    private void loadPluginConfiguration(final long start) {
+        configurationService.getPluginConfiguration(resourceId, new AsyncCallback<Configuration>() {
+            public void onFailure(Throwable caught) {
+                showError(caught);
+                if (loadHandler != null) {
+                    loadHandler.loadedConfiguration(null);
+                }
+            }
 
-                    public void onSuccess(Configuration result) {
-                        configuration = result;
-                        reload();
-                        if (loadHandler != null) {
-                            loadHandler.loadedConfiguration(configuration);
-                        }
+            public void onSuccess(Configuration result) {
+                configuration = result;
+                reload();
+                if (loadHandler != null) {
+                    loadHandler.loadedConfiguration(configuration);
+                }
+            }
+        });
+
+        ResourceTypeRepository.Cache.getInstance().getResourceTypes(new Integer[] { resourceTypeId },
+            EnumSet.of(ResourceTypeRepository.MetadataType.pluginConfigurationDefinition),
+            new ResourceTypeRepository.TypesLoadedCallback() {
+                public void onTypesLoaded(Map<Integer, ResourceType> types) {
+                    Log.debug("ConfigDef retrieved in: " + (System.currentTimeMillis() - start));
+                    configurationDefinition = types.get(resourceTypeId).getPluginConfigurationDefinition();
+                    if (configurationDefinition == null) {
+                        showError(MSG.view_configEdit_error_2());
                     }
-                });
+                    reload();
+                    if (loadHandler != null) {
+                        loadHandler.loadedConfigurationDefinition(configurationDefinition);
+                    }
+                }
+            });
+    }
 
-                ResourceTypeRepository.Cache.getInstance().getResourceTypes(new Integer[] { resourceTypeId },
-                    EnumSet.of(ResourceTypeRepository.MetadataType.pluginConfigurationDefinition),
-                    new ResourceTypeRepository.TypesLoadedCallback() {
-                        public void onTypesLoaded(Map<Integer, ResourceType> types) {
-                            Log.debug("ConfigDef retrieved in: " + (System.currentTimeMillis() - start));
-                            configurationDefinition = types.get(resourceTypeId).getPluginConfigurationDefinition();
-                            if (configurationDefinition == null) {
-                                showError(MSG.view_configEdit_error_2());
-                            }
-                            reload();
-                            if (loadHandler != null) {
-                                loadHandler.loadedConfigurationDefinition(configurationDefinition);
-                            }
-                        }
-                    });
+    private void loadResourceConfiguration(final long start) {
+        configurationService.getResourceConfiguration(resourceId, new AsyncCallback<Configuration>() {
+            public void onFailure(Throwable caught) {
+                showError(caught);
+                if (loadHandler != null) {
+                    loadHandler.loadedConfiguration(null);
+                }
             }
-        }
 
-        reload();
+            public void onSuccess(Configuration result) {
+                configuration = result;
+                Log.info("Config retrieved in: " + (System.currentTimeMillis() - start));
+                reload();
+                if (loadHandler != null) {
+                    loadHandler.loadedConfiguration(configuration);
+                }
+            }
+        });
+
+        ResourceTypeRepository.Cache.getInstance().getResourceTypes(new Integer[] { resourceTypeId },
+            EnumSet.of(ResourceTypeRepository.MetadataType.resourceConfigurationDefinition),
+            new ResourceTypeRepository.TypesLoadedCallback() {
+                public void onTypesLoaded(Map<Integer, ResourceType> types) {
+                    Log.debug("ConfigDef retrieved in: " + (System.currentTimeMillis() - start));
+                    configurationDefinition = types.get(resourceTypeId).getResourceConfigurationDefinition();
+                    if (configurationDefinition == null) {
+                        loadingLabel.hide();
+                        showError(MSG.view_configEdit_error_1());
+                    }
+                    reload();
+                    if (loadHandler != null) {
+                        loadHandler.loadedConfigurationDefinition(configurationDefinition);
+                    }
+                }
+            });
     }
 
     public void reload() {
@@ -389,7 +397,7 @@ public class ConfigurationEditor extends LocatableVLayout {
 
         if (configurationDefinition.getConfigurationFormat() == ConfigurationFormat.STRUCTURED
             || configurationDefinition.getConfigurationFormat() == ConfigurationFormat.STRUCTURED_AND_RAW) {
-            Log.info("Building structured configuration editor...");
+            Log.debug("Building structured configuration editor...");
             LocatableVLayout structuredConfigLayout = buildStructuredPane();
             addMember(structuredConfigLayout);
         } else {
@@ -561,31 +569,18 @@ public class ConfigurationEditor extends LocatableVLayout {
     }
 
     private void addHeaderItems(List<FormItem> fields) {
-        final String CELL_STYLE = "configurationEditorHeaderCell";
-
-        StaticTextItem nameHeader = new StaticTextItem();
-        nameHeader.setValue(MSG.view_configEdit_property());
-        nameHeader.setShowTitle(false);
-        nameHeader.setCellStyle(CELL_STYLE);
-        fields.add(nameHeader);
+        fields.add(createHeaderTextItem(MSG.view_configEdit_property()));
+        fields.add(createHeaderTextItem(MSG.view_configEdit_unset()));
+        fields.add(createHeaderTextItem(MSG.common_title_value()));
+        fields.add(createHeaderTextItem(MSG.common_title_description()));
+    }
 
+    private StaticTextItem createHeaderTextItem(String value){
         StaticTextItem unsetHeader = new StaticTextItem();
-        unsetHeader.setValue(MSG.view_configEdit_unset());
+        unsetHeader.setValue(value);
         unsetHeader.setShowTitle(false);
-        unsetHeader.setCellStyle(CELL_STYLE);
-        fields.add(unsetHeader);
-
-        StaticTextItem valueHeader = new StaticTextItem();
-        valueHeader.setValue(MSG.common_title_value());
-        valueHeader.setShowTitle(false);
-        valueHeader.setCellStyle(CELL_STYLE);
-        fields.add(valueHeader);
-
-        StaticTextItem descriptionHeader = new StaticTextItem();
-        descriptionHeader.setValue(MSG.common_title_description());
-        descriptionHeader.setShowTitle(false);
-        descriptionHeader.setCellStyle(CELL_STYLE);
-        fields.add(descriptionHeader);
+        unsetHeader.setCellStyle("configurationEditorHeaderCell");
+        return unsetHeader;
     }
 
     private void addItemsForPropertiesRecursively(String locatorId, Collection<PropertyDefinition> propertyDefinitions,
@@ -618,6 +613,7 @@ public class ConfigurationEditor extends LocatableVLayout {
             fieldsForThisProperty = buildFieldsForPropertySimple(propertyDefinition, propertyDefinitionSimple,
                 propertySimple);
         } else if (propertyDefinition instanceof PropertyDefinitionList) {
+            ///@TODO
             PropertyDefinitionList propertyDefinitionList = (PropertyDefinitionList) propertyDefinition;
             PropertyDefinition memberDefinition = propertyDefinitionList.getMemberDefinition();
             PropertyList propertyList = (PropertyList) property;
@@ -688,7 +684,6 @@ public class ConfigurationEditor extends LocatableVLayout {
         } else if (memberDefinition instanceof PropertyDefinitionSimple) {
             SpacerItem spacerItem = new SpacerItem();
             fields.add(spacerItem);
-
             CanvasItem listOfSimplesItem = buildListOfSimplesField(locatorId, propertyDefinitionList, propertyList);
             fields.add(listOfSimplesItem);
 
@@ -1005,12 +1000,16 @@ public class ConfigurationEditor extends LocatableVLayout {
                     SC.confirm(MSG.view_configEdit_confirm_2(), new BooleanCallback() {
                         public void execute(Boolean confirmed) {
                             if (confirmed) {
-                                PropertyMapListGridRecord recordToBeDeleted = (PropertyMapListGridRecord) recordClickEvent
-                                    .getRecord();
-                                propertyList.getList().remove(recordToBeDeleted.getIndex());
-                                ListGridRecord[] rows = buildSummaryRecords(propertyList, propertyDefinitions);
-                                summaryTable.setData(rows);
-                                firePropertyChangedEvent(propertyList, propertyDefinitionList, true);
+                                if( summaryTable.getRecordList().getLength() <= propertyDefinitionList.getMin()){
+                                    SC.say(MSG.view_configEdit_minBoundsExceeded(String.valueOf(propertyDefinitionList.getMin())));
+                                }else {
+                                    PropertyMapListGridRecord recordToBeDeleted = (PropertyMapListGridRecord) recordClickEvent
+                                        .getRecord();
+                                    propertyList.getList().remove(recordToBeDeleted.getIndex());
+                                    ListGridRecord[] rows = buildSummaryRecords(propertyList, propertyDefinitions);
+                                    summaryTable.setData(rows);
+                                    firePropertyChangedEvent(propertyList, propertyDefinitionList, true);
+                                }
                             }
                         }
                     });
@@ -1109,7 +1108,6 @@ public class ConfigurationEditor extends LocatableVLayout {
         final DynamicForm listGrid = new DynamicForm();
         vLayout.addMember(listGrid);
 
-        // TODO (ips, 03/14/11): Make this a ListGrid, rather than a SelectItem.
         final SelectItem membersItem = new SelectItem(propertyList.getName());
         membersItem.setShowTitle(false);
         membersItem.setMultiple(true);
@@ -1138,28 +1136,32 @@ public class ConfigurationEditor extends LocatableVLayout {
                     final String noun = (selectedValues.length == 1) ? MSG.common_label_item() : MSG
                         .common_label_items();
                     String message = MSG.view_configEdit_confirm_3(Integer.toString(selectedValues.length), noun);
-                    SC.ask(message, new BooleanCallback() {
-                        public void execute(Boolean confirmed) {
-                            if (confirmed) {
-                                for (int i = selectedValues.length - 1; i >= 0; i--) {
-                                    String selectedValue = selectedValues[i];
-                                    int index = Integer.valueOf(selectedValue);
-                                    propertyList.getList().remove(index);
-
-                                    // Rebuild the select item options.
-                                    LinkedHashMap<String, String> memberValueToIndexMap = buildValueMap(propertyList);
-                                    membersItem.setValueMap(memberValueToIndexMap);
-
-                                    deleteButton.disable();
-
-                                    firePropertyChangedEvent(propertyList, propertyDefinitionList, true);
-                                    CoreGUI.getMessageCenter().notify(
-                                        new Message(MSG.view_configEdit_msg_3(Integer.toString(selectedValues.length),
-                                            noun), EnumSet.of(Message.Option.Transient)));
+                    if(propertyList.getList().size() <= propertyDefinitionList.getMin()){
+                        SC.say("You cannot delete this entry because the minimum size bounds has been met: "+ propertyDefinitionList.getMin());
+                    }else {
+                        SC.ask(message, new BooleanCallback() {
+                            public void execute(Boolean confirmed) {
+                                if (confirmed) {
+                                    for (int i = selectedValues.length - 1; i >= 0; i--) {
+                                        String selectedValue = selectedValues[i];
+                                        int index = Integer.valueOf(selectedValue);
+                                        propertyList.getList().remove(index);
+
+                                        // Rebuild the select item options.
+                                        LinkedHashMap<String, String> memberValueToIndexMap = buildValueMap(propertyList);
+                                        membersItem.setValueMap(memberValueToIndexMap);
+
+                                        deleteButton.disable();
+
+                                        firePropertyChangedEvent(propertyList, propertyDefinitionList, true);
+                                        CoreGUI.getMessageCenter().notify(
+                                            new Message(MSG.view_configEdit_msg_3(Integer.toString(selectedValues.length),
+                                                noun), EnumSet.of(Message.Option.Transient)));
+                                    }
                                 }
                             }
-                        }
-                    });
+                        });
+                    }
                 }
             });
             footer.addMember(deleteButton);
@@ -1178,93 +1180,92 @@ public class ConfigurationEditor extends LocatableVLayout {
             newButton.setTooltip(MSG.view_configEdit_tooltip_2());
             newButton.addClickHandler(new com.smartgwt.client.widgets.events.ClickHandler() {
                 public void onClick(ClickEvent clickEvent) {
-                    final Window popup = new Window();
-                    popup.setTitle(MSG.view_configEdit_addItem());
-                    popup.setWidth(300);
-                    popup.setHeight(145);
-                    popup.setIsModal(true);
-                    popup.setShowModalMask(true);
-                    popup.setShowCloseButton(false);
-                    popup.centerInPage();
-
-                    VLayout vLayout = new VLayout();
-                    vLayout.setMargin(10);
-                    
-                    HTMLFlow description = new HTMLFlow(propertyDefinitionList.getDescription());
-                    vLayout.addMember(description);
-
-                    final DynamicForm form = new DynamicForm();
-
-                    PropertyDefinitionSimple memberPropertyDefinitionSimple = (PropertyDefinitionSimple) propertyDefinitionList
-                        .getMemberDefinition();
-                    final String propertyName = memberPropertyDefinitionSimple.getName();
-                    final PropertySimple newMemberPropertySimple = new PropertySimple(propertyName, null);
-
-                    FormItem simpleField = buildSimpleField(memberPropertyDefinitionSimple, newMemberPropertySimple);
-                    simpleField.setTitle(memberPropertyDefinitionSimple.getDisplayName());
-                    simpleField.setShowTitle(true);
-                    simpleField.setAlign(Alignment.CENTER);
-                    simpleField.setDisabled(false);
-                    simpleField.setRequired(true);
-                    simpleField.setEndRow(true);
-
-                    SpacerItem spacer = new SpacerItem();
-                    spacer.setHeight(9);
-
-                    form.setItems(simpleField, spacer);
-                    vLayout.addMember(form);
-
-                    final IButton okButton = new LocatableIButton(extendLocatorId("OK"), MSG.common_button_ok());
-                    okButton.disable();
-                    okButton.addClickHandler(new com.smartgwt.client.widgets.events.ClickHandler() {
-                        public void onClick(ClickEvent clickEvent) {
-                            propertyList.add(newMemberPropertySimple);
 
-                            // Rebuild the select item options.
-                            LinkedHashMap<String, String> memberValueToIndexMap = buildValueMap(propertyList);
-                            membersItem.setValueMap(memberValueToIndexMap);
+                    if(propertyList.getList().size() >= propertyDefinitionList.getMax()){
+                        SC.say(MSG.view_configEdit_maxBoundsExceeded(String.valueOf(propertyDefinitionList.getMax())));
+                    }else {
+                        final LocatableWindow popup = createPopup(MSG.view_configEdit_addItem(), 300, 145);
 
-                            firePropertyChangedEvent(propertyList, propertyDefinitionList, true);
-                            CoreGUI.getMessageCenter().notify(
-                                new Message(MSG.view_configEdit_msg_4(), EnumSet.of(Message.Option.Transient)));
+                        VLayout vLayout = new VLayout();
+                        vLayout.setMargin(10);
 
-                            popup.destroy();
-                        }
-                    });
+                        HTMLFlow description = new HTMLFlow(propertyDefinitionList.getDescription());
+                        vLayout.addMember(description);
 
-                    form.addItemChangedHandler(new ItemChangedHandler() {
-                        public void onItemChanged(ItemChangedEvent itemChangedEvent) {
-                            Object newValue = itemChangedEvent.getNewValue();
-                            newMemberPropertySimple.setValue(newValue);
+                        final DynamicForm form = new DynamicForm();
 
-                            // Only enable the OK button, allowing the user to add the property to the map, if the
-                            // property is valid.
-                            boolean isValid = form.validate();
-                            okButton.setDisabled(!isValid);
-                        }
-                    });
+                        PropertyDefinitionSimple memberPropertyDefinitionSimple = (PropertyDefinitionSimple) propertyDefinitionList
+                            .getMemberDefinition();
+                        final String propertyName = memberPropertyDefinitionSimple.getName();
+                        final PropertySimple newMemberPropertySimple = new PropertySimple(propertyName, null);
 
-                    final IButton cancelButton = new LocatableIButton(extendLocatorId("Cancel"), MSG
-                        .common_button_cancel());
-                    cancelButton.addClickHandler(new com.smartgwt.client.widgets.events.ClickHandler() {
-                        public void onClick(ClickEvent clickEvent) {
-                            popup.destroy();
-                        }
-                    });
+                        FormItem simpleField = buildSimpleField(memberPropertyDefinitionSimple, newMemberPropertySimple);
+                        simpleField.setTitle(memberPropertyDefinitionSimple.getDisplayName());
+                        simpleField.setShowTitle(true);
+                        simpleField.setAlign(Alignment.CENTER);
+                        simpleField.setDisabled(false);
+                        simpleField.setRequired(true);
+                        simpleField.setEndRow(true);
+
+                        SpacerItem spacer = new SpacerItem();
+                        spacer.setHeight(9);
+
+                        form.setItems(simpleField, spacer);
+                        vLayout.addMember(form);
+
+                        final IButton okButton = new LocatableIButton(extendLocatorId("OK"), MSG.common_button_ok());
+                        okButton.disable();
+                        okButton.addClickHandler(new com.smartgwt.client.widgets.events.ClickHandler() {
+                            public void onClick(ClickEvent clickEvent) {
+                                propertyList.add(newMemberPropertySimple);
+
+                                // Rebuild the select item options.
+                                LinkedHashMap<String, String> memberValueToIndexMap = buildValueMap(propertyList);
+                                membersItem.setValueMap(memberValueToIndexMap);
+
+                                firePropertyChangedEvent(propertyList, propertyDefinitionList, true);
+                                CoreGUI.getMessageCenter().notify(
+                                    new Message(MSG.view_configEdit_msg_4(), EnumSet.of(Message.Option.Transient)));
+
+                                popup.destroy();
+                            }
+                        });
 
-                    HLayout buttons = new HLayout();
-                    buttons.setAlign(Alignment.CENTER);
-                    buttons.setTop(10);
-                    buttons.setMembersMargin(10);
-                    buttons.setMembers(okButton, cancelButton);
-                    vLayout.addMember(buttons);
+                        form.addItemChangedHandler(new ItemChangedHandler() {
+                            public void onItemChanged(ItemChangedEvent itemChangedEvent) {
+                                Object newValue = itemChangedEvent.getNewValue();
+                                newMemberPropertySimple.setValue(newValue);
 
-                    popup.addItem(vLayout);
-                    popup.show();
+                                // Only enable the OK button, allowing the user to add the property to the map, if the
+                                // property is valid.
+                                boolean isValid = form.validate();
+                                okButton.setDisabled(!isValid);
+                            }
+                        });
+
+                        final IButton cancelButton = new LocatableIButton(extendLocatorId("Cancel"), MSG
+                            .common_button_cancel());
+                        cancelButton.addClickHandler(new com.smartgwt.client.widgets.events.ClickHandler() {
+                            public void onClick(ClickEvent clickEvent) {
+                                popup.destroy();
+                            }
+                        });
 
-                    simpleField.focusInItem();
+                        HLayout buttons = new HLayout();
+                        buttons.setAlign(Alignment.CENTER);
+                        buttons.setTop(10);
+                        buttons.setMembersMargin(10);
+                        buttons.setMembers(okButton, cancelButton);
+                        vLayout.addMember(buttons);
+
+                        popup.addItem(vLayout);
+                        popup.show();
+
+                        simpleField.focusInItem();
                 }
+            }
             });
+
             footer.addMember(newButton);
         }
 
@@ -1675,15 +1676,8 @@ public class ConfigurationEditor extends LocatableVLayout {
         final PropertyMap workingMap = (newRow) ? new PropertyMap(memberMapDefinition.getName()) : memberMap
             .deepCopy(true);
 
-        final LocatableWindow popup = new LocatableWindow(extendLocatorId("MapEditor"));
-        String title = (mapReadOnly) ? MSG.view_configEdit_viewRow() : MSG.view_configEdit_editRow();
-        popup.setTitle(title);
-        popup.setWidth(800);
-        popup.setHeight(600);
-        popup.setIsModal(true);
-        popup.setShowModalMask(true);
-        popup.setShowCloseButton(false);
-        popup.centerInPage();
+        final String title = (mapReadOnly) ? MSG.view_configEdit_viewRow() : MSG.view_configEdit_editRow();
+        final LocatableWindow popup = createPopup(title, 800, 600);
 
         final LocatableVLayout layout = new LocatableVLayout(popup.extendLocatorId("Layout"));
         layout.setHeight100();
@@ -1756,6 +1750,18 @@ public class ConfigurationEditor extends LocatableVLayout {
         popup.show();
     }
 
+    private LocatableWindow createPopup(String title, int width, int height) {
+        final LocatableWindow popup = new LocatableWindow(extendLocatorId("MapEditor"));
+        popup.setTitle(title);
+        popup.setWidth(width);
+        popup.setHeight(height);
+        popup.setIsModal(true);
+        popup.setShowModalMask(true);
+        popup.setShowCloseButton(false);
+        popup.centerInPage();
+        return popup;
+    }
+
     private void mergePropertyMap(PropertyMap sourceMap, PropertyMap targetMap,
         List<PropertyDefinition> memberDefinitions) {
         for (PropertyDefinition subDef : memberDefinitions) {
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/test/configuration/TestConfigurationFactory.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/test/configuration/TestConfigurationFactory.java
index 2142764..c4cc0f7 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/test/configuration/TestConfigurationFactory.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/test/configuration/TestConfigurationFactory.java
@@ -138,6 +138,8 @@ public abstract class TestConfigurationFactory {
             "a list of Integer simples", true, new PropertyDefinitionSimple("integer", "an integer", false,
                 PropertySimpleType.INTEGER));
         listOfSimplesPropDef.setDisplayName(listOfSimplesPropDef.getName());
+        listOfSimplesPropDef.setMax(listOfSimplesPropDef.getMax());
+        listOfSimplesPropDef.setMin(listOfSimplesPropDef.getMin());
         addPropertyDefinition(configDef, listOfSimplesPropDef, orderIndex++);
 
         PropertyDefinitionMap mapInListPropDef =
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
index e8d267b..56766cd 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
@@ -1176,6 +1176,8 @@ view_configEdit_error_3 = Cannot add property named [{0}]. The property name is
 view_configEdit_files = Files
 view_configEdit_hideAll = Hide All
 view_configEdit_jumpToSection = Jump to Section
+view_configEdit_maxBoundsExceeded =  Cannot add another entry because the maximum size bounds has been met: {0}
+view_configEdit_minBoundsExceeded = Cannot delete this entry as the minimum has been set to: {0}
 view_configEdit_msg_1 = Added property [{0}] to the set.
 view_configEdit_msg_2 = Removed properties from the set.
 view_configEdit_msg_3 = [{0} {1}] deleted from list.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
index f02b83b..f7d4ef7 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
@@ -1195,6 +1195,8 @@ view_configEdit_error_3 = Nelze přidat vlastnost nazvanou [{0}]. Jméno té vla
 view_configEdit_files = Soubory
 view_configEdit_hideAll = Skrýt vše
 view_configEdit_jumpToSection = Přejít na sekci
+##view_configEdit_maxBoundsExceeded =  Cannot add another entry because the maximum size bounds has been met: {0}
+##view_configEdit_minBoundsExceeded = Cannot delete this entry as the minimum has been set to: {0}
 view_configEdit_msg_1 = Přidána vlastnost [{0}]
 view_configEdit_msg_2 = Vlastnost odebrána z množiny.
 view_configEdit_msg_3 = [{0} {1}] smazáno ze seznamu.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
index 4de4df2..a40cb2f 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
@@ -1060,6 +1060,8 @@ view_configEdit_confirm_2 = Sind Sie sicher dass sie diese Zeile löschen wollen
 view_configEdit_files = Dateien
 view_configEdit_hideAll = Alle verbergen
 view_configEdit_jumpToSection = Zum Abschnitt springen
+##view_configEdit_maxBoundsExceeded =  Cannot add another entry because the maximum size bounds has been met: {0}
+##view_configEdit_minBoundsExceeded = Cannot delete this entry as the minimum has been set to: {0}
 view_configEdit_msg_1 = Eigentschaft [{0}] zur Menge hinzugefügt
 ##view_configEdit_msg_2 = Removed properties from the set.
 view_configEdit_msg_3 = [{0} {1}] aus der Liste gelöscht.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
index ea692e6..e135c0d 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
@@ -1172,6 +1172,8 @@ view_configEdit_error_3 = [{0}] という名前のプロパティを追加でき
 view_configEdit_files = ファイル
 view_configEdit_hideAll = すべて隠す
 view_configEdit_jumpToSection = セクションへのジャンプ
+##view_configEdit_maxBoundsExceeded =  Cannot add another entry because the maximum size bounds has been met: {0}
+##view_configEdit_minBoundsExceeded = Cannot delete this entry as the minimum has been set to: {0}
 view_configEdit_msg_1 = プロパティ [{0}] をセットに追加しました
 view_configEdit_msg_2 = セットからプロパティを取り除きました
 view_configEdit_msg_3 = [{0} {1}] がリストから削除されました
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
index 26f3ab8..843d5d2 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
@@ -1182,6 +1182,8 @@ view_configEdit_error_3 = N\u00E3o f\u00F3 poss\u00EDvel adicionar a propriedade
 view_configEdit_files = Arquivos
 view_configEdit_hideAll = Ocultar todos
 view_configEdit_jumpToSection = Ir direto para a Sele\u00E7\u00E3o
+##view_configEdit_maxBoundsExceeded =  Cannot add another entry because the maximum size bounds has been met: {0}
+##view_configEdit_minBoundsExceeded = Cannot delete this entry as the minimum has been set to: {0}
 view_configEdit_msg_1 = Propriedade [{0}]  adicionada ao conjunto.
 view_configEdit_msg_2 = Propriedades removidas do conjunto.
 view_configEdit_msg_3 = [{0} {1}] removido da lista.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
index 394ecc9..512e087 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
@@ -1165,6 +1165,8 @@
 #view_configEdit_files = Files
 #view_configEdit_hideAll = Hide All
 #view_configEdit_jumpToSection = Jump to Section
+##view_configEdit_maxBoundsExceeded =  Cannot add another entry because the maximum size bounds has been met: {0}
+##view_configEdit_minBoundsExceeded = Cannot delete this entry as the minimum has been set to: {0}
 #view_configEdit_msg_1 = Added property [{0}] to the set.
 #view_configEdit_msg_2 = Removed properties from the set.
 #view_configEdit_msg_3 = [{0} {1}] deleted from list.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
index dff469a..269ed1c 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
@@ -1166,6 +1166,8 @@ view_configEdit_error_3 = \u65e0\u6cd5\u6dfb\u52a0\u540d\u4e3a[{0}]\u7684\u5c5e\
 view_configEdit_files = \u6587\u4ef6
 view_configEdit_hideAll = \u9690\u85cf\u6240\u6709
 view_configEdit_jumpToSection = \u8df3\u81f3\u6a21\u5757
+##view_configEdit_maxBoundsExceeded =  Cannot add another entry because the maximum size bounds has been met: {0}
+##view_configEdit_minBoundsExceeded = Cannot delete this entry as the minimum has been set to: {0}
 view_configEdit_msg_1 = \u589e\u52a0\u5c5e\u6027 [{0}]\u5230\u96c6\u5408.
 view_configEdit_msg_2 = \u79fb\u9664\u96c6\u5408\u5185\u6240\u6709\u7684\u5c5e\u6027.
 view_configEdit_msg_3 = \u4ece\u5217\u8868\u4e2d\u5220\u9664[{0} {1}]\u6210\u529f.


commit 4c3b4fdd3ad080d772b2932b526e08366694dc0f
Author: Heiko W. Rupp <hwr at redhat.com>
Date:   Thu Jul 12 21:06:36 2012 +0200

    Allow to pass the number of data points to the backend.

diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerBean.java
index 163d48d..cb7cc5c 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerBean.java
@@ -166,13 +166,16 @@ public class MetricHandlerBean  extends AbstractRestBean implements MetricHandle
     }
 
     public Response getMetricDataForGroupAndDefinition(int groupId, int definitionId, long startTime, long endTime,
-            boolean hideEmpty, Request request, HttpHeaders headers) {
+                                                       int dataPoints,boolean hideEmpty, Request request, HttpHeaders headers) {
 
         if (startTime==0) {
             endTime = System.currentTimeMillis();
             startTime = endTime - EIGHT_HOURS;
         }
 
+        if (dataPoints<1)
+            throw new IllegalArgumentException("datapoints must be >=0");
+
         MediaType mediaType = headers.getAcceptableMediaTypes().get(0);
         boolean isHtml = mediaType.equals(MediaType.TEXT_HTML_TYPE);
 
@@ -187,7 +190,7 @@ public class MetricHandlerBean  extends AbstractRestBean implements MetricHandle
         res.setGroup(true);
 
         List<List<MeasurementDataNumericHighLowComposite>> listList = dataManager.findDataForCompatibleGroup(caller,
-                groupId,definitionId,startTime,endTime,60); // TODO number of points
+                groupId,definitionId,startTime,endTime,dataPoints);
 
         if (listList.isEmpty()) {
             throw new StuffNotFoundException("Data for group with id " + groupId + " and definition " + definitionId);
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerLocal.java
index 4ea9343..4ae33f4 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerLocal.java
@@ -120,6 +120,7 @@ public interface MetricHandlerLocal {
             @ApiParam("Id of the metric definition to retrieve") @PathParam("definitionId") int definitionId,
             @ApiParam(value = "Start time since epoch.", defaultValue="End time - 8h") @QueryParam("startTime") long startTime,
             @ApiParam(value = "End time since epoch.", defaultValue = "Now") @QueryParam("endTime") long endTime,
+            @ApiParam("Number of buckets - currently fixed at 60") @QueryParam("dataPoints") @DefaultValue("60") int dataPoints,
             @ApiParam(value = "Hide rows that are NaN only", defaultValue = "false") @QueryParam("hideEmpty") boolean hideEmpty,
             @Context Request request,
             @Context HttpHeaders headers);
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/metadata/PluginManagerBeanTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/metadata/PluginManagerBeanTest.java
index 9b1d0bf..ec0fcd4 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/metadata/PluginManagerBeanTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/metadata/PluginManagerBeanTest.java
@@ -1,3 +1,22 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 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.resource.metadata;
 
 import static java.util.Arrays.asList;
@@ -32,8 +51,9 @@ public class PluginManagerBeanTest extends MetadataBeanTest {
     private PluginDeploymentScanner pluginScanner;
 
     @AfterClass
-    public void afterClass() {
+    public void afterClass() throws Exception {
         this.pluginScanner = null;
+        super.afterClass();
     }
 
     @Override


commit 9af5936fe96183531a393f68dd638ef79cc895cd
Author: Lukas Krejci <lkrejci at redhat.com>
Date:   Thu Jul 12 19:26:51 2012 +0200

    make sure CLI scripts on the server redirect standard and error output to
    the tracked writer.

diff --git a/modules/enterprise/server/plugins/alert-cli/src/main/java/org/rhq/enterprise/server/plugins/alertCli/CliSender.java b/modules/enterprise/server/plugins/alert-cli/src/main/java/org/rhq/enterprise/server/plugins/alertCli/CliSender.java
index 98246a0..0bca2fa 100644
--- a/modules/enterprise/server/plugins/alert-cli/src/main/java/org/rhq/enterprise/server/plugins/alertCli/CliSender.java
+++ b/modules/enterprise/server/plugins/alert-cli/src/main/java/org/rhq/enterprise/server/plugins/alertCli/CliSender.java
@@ -274,6 +274,8 @@ public class CliSender extends AlertSender<CliComponent> {
         bindings.put("alert", alert);
 
         ScriptEngine engine = takeEngine(bindings);
+        engine.getContext().setWriter(output);
+        engine.getContext().setErrorWriter(output);
 
         return engine;
     }


commit 12762b55b0add61b33ff861047acf2e7eac1cff5
Merge: 7095212 a49e075
Author: Lukas Krejci <lkrejci at redhat.com>
Date:   Thu Jul 12 18:00:02 2012 +0200

    Merge lkrejci/modular-scripting into master



commit 709521269eea8fa16f7c672e34ad90c0b748c0ee
Author: Lukas Krejci <lkrejci at redhat.com>
Date:   Thu Jul 12 16:39:49 2012 +0200

    Fixing the last javascript specific thing in the CLI - no more assumptions
    about the format of the error message.

diff --git a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java
index cfe1686..c7f6bbf 100644
--- a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java
+++ b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java
@@ -58,6 +58,7 @@ import org.rhq.enterprise.client.utility.CodeCompletionCompletorWrapper;
 import org.rhq.enterprise.client.utility.DummyCodeCompletion;
 import org.rhq.enterprise.clientapi.RemoteClient;
 import org.rhq.scripting.CodeCompletion;
+import org.rhq.scripting.ScriptEngineInitializer;
 
 /**
  * @author Greg Hinkle
@@ -108,6 +109,7 @@ public class ClientMain {
     private Recorder recorder = new NoOpRecorder();
 
     private ScriptEngine engine;
+    private ScriptEngineInitializer scriptEngineInitializer;
     
     private class StartupConfiguration {
         public boolean askForPassword;
@@ -675,6 +677,12 @@ public class ClientMain {
             try {
                 engine = ScriptEngineFactory.getScriptEngine(getLanguage(),
                     new PackageFinder(Arrays.asList(getLibDir())), null);
+
+                if (engine == null) {
+                    throw new IllegalStateException("The scripting language '" + getLanguage()
+                        + "' could not be loaded.");
+                }
+                scriptEngineInitializer = ScriptEngineFactory.getInitializer(getLanguage());
             } catch (ScriptException e) {
                 e.printStackTrace();
             } catch (IOException e) {
@@ -685,6 +693,10 @@ public class ClientMain {
         return engine;
     }
     
+    public String getUsefulErrorMessage(ScriptException e) {
+        return scriptEngineInitializer.extractUserFriendlyErrorMessage(e);
+    }
+
     public Map<String, ClientCommand> getCommands() {
         return commands;
     }
diff --git a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/ScriptCommand.java b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/ScriptCommand.java
index a511310..42137af 100644
--- a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/ScriptCommand.java
+++ b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/ScriptCommand.java
@@ -151,9 +151,7 @@ public class ScriptCommand implements ClientCommand {
             }
         } catch (ScriptException e) {
 
-            String message = e.getCause() != null ? e.getCause().getMessage() : e.getMessage();
-            message = message.replace("sun.org.mozilla.javascript.internal.EcmaError: ", "");
-            message = message.replace("(<Unknown source>#1) in <Unknown source> at line number 1", "");
+            String message = client.getUsefulErrorMessage(e);
 
             client.getPrintWriter().println(message);
             client.getPrintWriter().println(script);


commit 0520b77135d2be31dea003cb1b99bf75aac49a9b
Author: Lukas Krejci <lkrejci at redhat.com>
Date:   Thu Jul 12 16:35:16 2012 +0200

    Finishing up the python support for CLI.

diff --git a/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptSourceProvider.java b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptSourceProvider.java
index c91b706..e65f793 100644
--- a/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptSourceProvider.java
+++ b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptSourceProvider.java
@@ -34,5 +34,11 @@ import java.net.URI;
  */
 public interface ScriptSourceProvider {
 
+    /**
+     * Returns the reader of the source of the script specified by given location.
+     * 
+     * @param location the location of the script
+     * @return the reader of the script source or null if it could not be found
+     */
     Reader getScriptSource(URI location);
 }
diff --git a/modules/enterprise/scripting/javascript/pom.xml b/modules/enterprise/scripting/javascript/pom.xml
index 6009b1b..06bed89 100644
--- a/modules/enterprise/scripting/javascript/pom.xml
+++ b/modules/enterprise/scripting/javascript/pom.xml
@@ -23,7 +23,6 @@
          <artifactId>rhino</artifactId>
          <version>1.7R4</version>
       </dependency>
-
    </dependencies>
 
    <build>
diff --git a/modules/enterprise/scripting/python/pom.xml b/modules/enterprise/scripting/python/pom.xml
index 4b48e52..b657dd2 100644
--- a/modules/enterprise/scripting/python/pom.xml
+++ b/modules/enterprise/scripting/python/pom.xml
@@ -27,10 +27,39 @@
     <build>
         <plugins>
             <plugin>
-                <artifactId>maven-surefire-plugin</artifactId>
-                <configuration>
-                    <excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
-                </configuration>
+               <groupId>org.sonatype.plugins</groupId>
+               <artifactId>jarjar-maven-plugin</artifactId>
+               <version>1.5</version>
+               <executions>
+                  <execution>
+                     <phase>package</phase>
+                     <goals>
+                        <goal>jarjar</goal>
+                     </goals>
+                     <configuration>
+                        <includes>
+                           <include>org.python:jython-standalone</include>
+                        </includes>
+                        <rules>     
+                           <keep>
+                              <pattern>*.**</pattern>
+                           </keep>                          
+                        </rules>
+                     </configuration>
+                  </execution>
+               </executions>
+            </plugin>
+            
+            <plugin>
+               <artifactId>maven-surefire-plugin</artifactId>
+               <configuration>
+                  <excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
+                  <argLine>-Djava.security.manager
+                     -Djava.security.policy==${project.build.testOutputDirectory}/allow-all.policy</argLine>
+                  <!-- This is important, because some of the tests try to exit 
+                     the JVM. -->
+                  <failIfNoTests>true</failIfNoTests>
+               </configuration>
             </plugin>
         </plugins>
     </build>
diff --git a/modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonScriptEngineFactory.java b/modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonScriptEngineFactory.java
new file mode 100644
index 0000000..2d1ef65
--- /dev/null
+++ b/modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonScriptEngineFactory.java
@@ -0,0 +1,41 @@
+/*
+ * RHQ Management Platform
+ * Copyright 2012, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.scripting.python;
+
+import javax.script.ScriptEngine;
+
+import org.python.jsr223.PyScriptEngineFactory;
+
+/**
+ * @author Lukas Krejci
+ *
+ */
+public class PythonScriptEngineFactory extends PyScriptEngineFactory {
+
+    @Override
+    public Object getParameter(String key) {
+        if (ScriptEngine.NAME.equals(key)) {
+            return "python";
+        } else {
+            return super.getParameter(key);
+        }
+    }
+}
diff --git a/modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonScriptEngineInitializer.java b/modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonScriptEngineInitializer.java
index 07ed8eb..e868204 100644
--- a/modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonScriptEngineInitializer.java
+++ b/modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonScriptEngineInitializer.java
@@ -23,12 +23,19 @@ import java.lang.reflect.Method;
 import java.security.PermissionCollection;
 import java.util.Collections;
 import java.util.HashSet;
+import java.util.Properties;
 import java.util.Set;
 
 import javax.script.ScriptEngine;
 import javax.script.ScriptEngineManager;
 import javax.script.ScriptException;
 
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.python.core.Py;
+import org.python.core.PySystemState;
+import org.python.util.PythonInterpreter;
+
 import org.rhq.scripting.ScriptEngineInitializer;
 import org.rhq.scripting.ScriptSourceProvider;
 import org.rhq.scripting.util.SandboxedScriptEngine;
@@ -40,6 +47,16 @@ import org.rhq.scripting.util.SandboxedScriptEngine;
  */
 public class PythonScriptEngineInitializer implements ScriptEngineInitializer {
 
+    private static final Log LOG = LogFactory.getLog(PythonScriptEngineInitializer.class);
+
+    static {
+        Properties props = new Properties();
+        props.put("python.packages.paths", "java.class.path,sun.boot.class.path");
+        props.put("python.packages.directories", "java.ext.dirs");
+        props.put("python.cachedir.skip", false);
+        PythonInterpreter.initialize(System.getProperties(), props, null);
+    }
+
     private ScriptEngineManager engineManager = new ScriptEngineManager();
 
     @Override
@@ -47,17 +64,29 @@ public class PythonScriptEngineInitializer implements ScriptEngineInitializer {
 
         ScriptEngine eng = engineManager.getEngineByName("python");
 
+        //XXX this might not work perfectly in jython
+        //but we can't make it work perfectly either, so let's just
+        //keep our fingers crossed..
+        //http://www.jython.org/jythonbook/en/1.0/ModulesPackages.html#from-import-statements
         for (String pkg : packages) {
-            eng.eval("from " + pkg + " import *\n");
+            try {
+                eng.eval("from " + pkg + " import *\n");
+            } catch (ScriptException e) {
+                //well, let's just keep things going, this is not fatal...
+                LOG.info("Python script engine could not pre-import members of package '" + pkg + "'.");
+            }
         }
 
         //fingers crossed we can secure jython like this
-        return new SandboxedScriptEngine(eng, permissions);
+        return permissions == null ? eng : new SandboxedScriptEngine(eng, permissions);
     }
 
     @Override
     public void installScriptSourceProvider(ScriptEngine scriptEngine, ScriptSourceProvider provider) {
-        //TODO add support for script source providers... possibly using http://www.python.org/dev/peps/pep-0302/        
+        PySystemState sys = Py.getSystemState();
+        if (sys != null) {
+            sys.path_hooks.append(new PythonSourceProvider(provider));
+        }
     }
 
     @Override
diff --git a/modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonSourceProvider.java b/modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonSourceProvider.java
new file mode 100644
index 0000000..70688d4
--- /dev/null
+++ b/modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonSourceProvider.java
@@ -0,0 +1,136 @@
+/*
+ * RHQ Management Platform
+ * Copyright 2012, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.scripting.python;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import org.python.core.Py;
+import org.python.core.PyObject;
+import org.python.core.imp;
+
+import org.rhq.scripting.ScriptSourceProvider;
+
+/**
+ * This class translates the requests for modules in python using the import
+ * statement into calls to RHQ's script source providers.
+ * <p>
+ * For a script to be downloadable using RHQ, one must add a path prefix to 
+ * <code>sys.path</code> so that RHQ is aware of the available locations it should
+ * look into.
+ * <p>
+ * For example, if you have the RHQ repository script source provider available on 
+ * the classpath of the CLI, you can add the following to the <code>sys.path</code>:
+ * <pre>
+ * <code>
+ * import sys
+ * sys.path.append("__rhq__:rhq:/repositories/my_repository")
+ * </code>
+ * </pre>
+ * and then you can import a module from that repository by the ordinary import statement:
+ * <pre>
+ * <code>
+ * import my_module
+ * </code>
+ * </pre>
+ * This will translate into a download of the script from the following location:
+ * <code>rhq://repositories/my_repository/my_module.py</code>.
+ * 
+ * @author Lukas Krejci
+ */
+public class PythonSourceProvider extends PyObject {
+
+    private static final long serialVersionUID = 1L;
+
+    private static final String RHQ_PATH_EXTENSION_PREFIX = "__rhq__:";
+
+    private ScriptSourceProvider scriptSourceProvider;
+    private String currentPathPrefix;
+
+    public PyObject __call__(PyObject args[], String keywords[]) {
+        if (args[0].toString().startsWith(RHQ_PATH_EXTENSION_PREFIX)) {
+            currentPathPrefix = args[0].toString().substring(RHQ_PATH_EXTENSION_PREFIX.length());
+            return this;
+        }
+        throw Py.ImportError("unable to handle");
+    }
+
+    private static class ReaderInputStream extends InputStream {
+        private Reader rdr;
+
+        public ReaderInputStream(Reader rdr) {
+            this.rdr = rdr;
+        }
+
+        @Override
+        public int read() throws IOException {
+            return rdr.read();
+        }
+
+    }
+
+    public class Loader extends PyObject {
+
+        private static final long serialVersionUID = 1L;
+
+        private String prefix;
+
+        public Loader(String prefix) {
+            this.prefix = prefix;
+        }
+
+        public PyObject load_module(String name) {
+            try {
+                URI uri = new URI(prefix + name + ".py");
+                Reader rdr = scriptSourceProvider.getScriptSource(uri);
+                return imp.createFromSource(name, new ReaderInputStream(rdr), uri.toString());
+            } catch (URISyntaxException e) {
+                return Py.None;
+            }
+        }
+    }
+
+    public PythonSourceProvider(ScriptSourceProvider scriptSourceProvider) {
+        this.scriptSourceProvider = scriptSourceProvider;
+    }
+
+    public PyObject find_module(String name) {
+        return find_module(name, Py.None);
+    }
+
+    public PyObject find_module(String name, PyObject path) {
+        try {
+            URI uri = new URI(currentPathPrefix + name + ".py");
+
+            return scriptSourceProvider.getScriptSource(uri) == null ? Py.None : new Loader(currentPathPrefix);
+        } catch (URISyntaxException e) {
+            return Py.None;
+        }
+    }
+
+    @Override
+    public String toString() {
+        return getType().toString();
+    }
+}
diff --git a/modules/enterprise/scripting/python/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory b/modules/enterprise/scripting/python/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory
new file mode 100644
index 0000000..f2c5a71
--- /dev/null
+++ b/modules/enterprise/scripting/python/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory
@@ -0,0 +1 @@
+org.rhq.scripting.python.PythonScriptEngineFactory
diff --git a/modules/enterprise/scripting/python/src/test/java/org/rhq/scripting/python/PythonScriptEngineInitializerTest.java b/modules/enterprise/scripting/python/src/test/java/org/rhq/scripting/python/PythonScriptEngineInitializerTest.java
new file mode 100644
index 0000000..b1d4a65
--- /dev/null
+++ b/modules/enterprise/scripting/python/src/test/java/org/rhq/scripting/python/PythonScriptEngineInitializerTest.java
@@ -0,0 +1,178 @@
+/*
+ * RHQ Management Platform
+ * Copyright 2012, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.scripting.python;
+
+import java.io.FilePermission;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.lang.reflect.Method;
+import java.net.URI;
+import java.security.AccessControlException;
+import java.security.Permissions;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import javax.script.Bindings;
+import javax.script.ScriptContext;
+import javax.script.ScriptEngine;
+import javax.script.ScriptException;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import org.rhq.scripting.ScriptSourceProvider;
+
+/**
+ * @author Lukas Krejci
+ */
+ at Test
+public class PythonScriptEngineInitializerTest {
+
+    public static class Tester {
+        private int cnt = 0;
+
+        public void increment() {
+            ++cnt;
+        }
+
+        public int getInvocationCoung() {
+            return cnt;
+        }
+    }
+
+    private static final String EXPECTED_OUTPUT = "kachny";
+
+    public static class SourceProvider implements ScriptSourceProvider {
+        @Override
+        public Reader getScriptSource(URI scriptUri) {
+            if (scriptUri.toString().equals("test/test_module.py")) {
+                return new StringReader("print '" + EXPECTED_OUTPUT + "'");
+            }
+            return null;
+        }
+    }
+    
+    public void testEngineInitialization() throws Exception {
+        PythonScriptEngineInitializer initializer = new PythonScriptEngineInitializer();
+        ScriptEngine engine = initializer.instantiate(Collections.<String> emptySet(), null);
+
+        //just some code to test out this is python
+        engine.eval("from java.util import HashMap\nHashMap()");
+    }
+
+    public void testMethodIndirection() throws Exception {
+        PythonScriptEngineInitializer initializer = new PythonScriptEngineInitializer();
+        ScriptEngine engine = initializer.instantiate(Collections.<String> emptySet(), null);
+
+        Bindings bindings = engine.createBindings();
+        Tester tester = new Tester();
+        bindings.put("tester", tester);
+
+        engine.setBindings(bindings, ScriptContext.ENGINE_SCOPE);
+
+        engine.eval("tester.increment()");
+
+        Assert.assertEquals(tester.getInvocationCoung(), 1, "Unexpected number of tester invocations.");
+
+        Map<String, Set<Method>> methods = getMethodsByName(Tester.class);
+        for (Set<Method> ms : methods.values()) {
+            Set<String> fns = initializer.generateIndirectionMethods("tester", ms);
+            for (String fn : fns) {
+                engine.eval(fn);
+            }
+        }
+
+        engine.eval("increment()");
+        Assert.assertEquals(tester.getInvocationCoung(), 2,
+            "Unexpected number of tester invocations after calling an indirected method.");
+    }
+
+    public void testSecuredEngine() throws Exception {
+        PythonScriptEngineInitializer initializer = new PythonScriptEngineInitializer();
+
+        //jython seems to need these two..
+        Permissions perms = new Permissions();
+        perms.add(new RuntimePermission("createClassLoader"));
+        perms.add(new RuntimePermission("getProtectionDomain"));
+
+        //add permission to read files so that modules can be loaded, but writing should fail
+        perms.add(new FilePermission("<<ALL FILES>>", "read"));
+
+        ScriptEngine engine = initializer.instantiate(Collections.<String> emptySet(), perms);
+
+        try {
+            engine.eval("import os\nfp = open('pom.xml', 'w')");
+            Assert.fail("Opening a file for writing should have failed with a security exception.");
+        } catch (ScriptException e) {
+            checkIsCausedByAccessControlException(e);
+        }
+    }
+    
+    public void testSourceProvider() throws Exception {
+        PythonScriptEngineInitializer initializer = new PythonScriptEngineInitializer();
+        
+        ScriptEngine engine = initializer.instantiate(Collections.<String> emptySet(), null);
+
+        StringWriter wrt = new StringWriter();
+
+        engine.getContext().setWriter(wrt);
+        
+        initializer.installScriptSourceProvider(engine, new SourceProvider());
+
+        engine
+            .eval("import sys\nsys.path.append('__rhq__:test-unsupported/')\nsys.path.append('__rhq__:test/')\nimport test_module");
+
+        Assert.assertEquals(wrt.toString(), EXPECTED_OUTPUT + "\n", "Unexpected output from a custom module.");
+    }
+
+    private void checkIsCausedByAccessControlException(Throwable e) {
+        Throwable ex = e;
+        while (ex != null) {
+            if (ex instanceof AccessControlException) {
+                return;
+            }
+
+            ex = ex.getCause();
+        }
+
+        Assert.fail("Expected an AccessControlException but the exception doesn't seem to be caused by it.", e);
+    }
+
+    private static Map<String, Set<Method>> getMethodsByName(Class<?> cls) {
+        Map<String, Set<Method>> ret = new HashMap<String, Set<Method>>();
+
+        for (Method m : cls.getDeclaredMethods()) {
+            Set<Method> methods = ret.get(m.getName());
+            if (methods == null) {
+                methods = new HashSet<Method>();
+                ret.put(m.getName(), methods);
+            }
+
+            methods.add(m);
+        }
+
+        return ret;
+    }
+}
diff --git a/modules/enterprise/scripting/python/src/test/resources/allow-all.policy b/modules/enterprise/scripting/python/src/test/resources/allow-all.policy
new file mode 100644
index 0000000..cb9dbed
--- /dev/null
+++ b/modules/enterprise/scripting/python/src/test/resources/allow-all.policy
@@ -0,0 +1,3 @@
+grant {
+    permission java.security.AllPermission;
+};


commit a49e0754c248ee94a1252dc7dbbbd2048133c426
Author: Jirka Kremser <jkremser at redhat.com>
Date:   Thu Jul 12 14:50:02 2012 +0200

    Monitoring -> Tables -> Get Live Value, the resulting modal window has now sorted records

diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MeasurementTableView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MeasurementTableView.java
index fe00f1a..881a3a3 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MeasurementTableView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MeasurementTableView.java
@@ -19,12 +19,20 @@
 
 package org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.table;
 
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Set;
+
 import com.google.gwt.user.client.rpc.AsyncCallback;
 import com.smartgwt.client.types.SelectionStyle;
 import com.smartgwt.client.widgets.events.CloseClickEvent;
 import com.smartgwt.client.widgets.events.CloseClickHandler;
 import com.smartgwt.client.widgets.grid.ListGridField;
 import com.smartgwt.client.widgets.grid.ListGridRecord;
+
 import org.rhq.core.domain.measurement.MeasurementData;
 import org.rhq.core.domain.measurement.MeasurementUnits;
 import org.rhq.enterprise.gui.coregui.client.CoreGUI;
@@ -38,11 +46,6 @@ import org.rhq.enterprise.gui.coregui.client.util.MeasurementConverterClient;
 import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableListGrid;
 import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableWindow;
 
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Set;
-
 /**
  * Views a resource's measurements in a tabular view.
  * 
@@ -118,6 +121,11 @@ public class MeasurementTableView extends Table<MeasurementTableDataSource> {
                                     records.add(record);
                                 }
                             }
+                            Collections.sort(records, new Comparator<ListGridRecord>() {
+                                public int compare(ListGridRecord o1, ListGridRecord o2) {
+                                    return o1.getAttribute("name").compareTo(o2.getAttribute("name"));
+                                }
+                            });
                             showLiveData(records);
                         }
 


commit 6307139046317a3b9d0037e542197182c7ba1519
Author: Jirka Kremser <jkremser at redhat.com>
Date:   Thu Jul 12 11:17:15 2012 +0200

    [BZ Bug 808175 - Monitor>Traits subtab should provide a Get Live Value button] Added support for "getting live value" for resource's traits as well as for group's traits

diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/resource/Agent.java b/modules/core/domain/src/main/java/org/rhq/core/domain/resource/Agent.java
index 220af57..e96e1d3 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/resource/Agent.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/resource/Agent.java
@@ -62,6 +62,10 @@ import org.rhq.core.domain.cloud.Server;
     @NamedQuery(name = Agent.QUERY_REMOVE_SERVER_REFERENCE, query = "UPDATE Agent a SET a.server.id = NULL WHERE a.server.id = :serverId "),
     @NamedQuery(name = Agent.QUERY_COUNT_ALL, query = "SELECT count(a.id) FROM Agent a"),
     @NamedQuery(name = Agent.QUERY_FIND_RESOURCE_IDS_FOR_AGENT, query = "SELECT r.id FROM Resource r WHERE r.agent.id = :agentId"),
+    @NamedQuery(name = Agent.QUERY_FIND_RESOURCE_IDS_WITH_AGENTS_BY_RESOURCE_IDS, query = "" //
+        + "SELECT new org.rhq.core.domain.resource.composite.ResourceIdWithAgentComposite(r.id, r.agent) " //
+        + "  FROM Resource r " //
+        + " WHERE r.id IN (:resourceIds)"),
     @NamedQuery(name = Agent.QUERY_FIND_ALL_SUSPECT_AGENTS, query = "SELECT new org.rhq.core.domain.resource.composite.AgentLastAvailabilityPingComposite "
         + "       ( "
         + "          a.id,a.name,a.remoteEndpoint,a.lastAvailabilityPing,a.backFilled "
@@ -150,6 +154,7 @@ public class Agent implements Serializable {
     public static final String QUERY_FIND_BY_SERVER = "Agent.findByServer";
     public static final String QUERY_COUNT_ALL = "Agent.countAll";
     public static final String QUERY_FIND_RESOURCE_IDS_FOR_AGENT = "Agent.findResourceIdsForAgent";
+    public static final String QUERY_FIND_RESOURCE_IDS_WITH_AGENTS_BY_RESOURCE_IDS = "Agent.findResourceIdsWithAgentsByResourceIds";
     public static final String QUERY_FIND_ALL_SUSPECT_AGENTS = "Agent.findAllSuspectAgents";
     public static final String QUERY_FIND_BY_AFFINITY_GROUP = "Agent.findByAffinityGroup";
     public static final String QUERY_FIND_WITHOUT_AFFINITY_GROUP = "Agent.findWithoutAffinityGroup";
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/resource/composite/ResourceIdWithAgentComposite.java b/modules/core/domain/src/main/java/org/rhq/core/domain/resource/composite/ResourceIdWithAgentComposite.java
new file mode 100644
index 0000000..03fbef9
--- /dev/null
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/resource/composite/ResourceIdWithAgentComposite.java
@@ -0,0 +1,48 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 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.domain.resource.composite;
+
+import java.io.Serializable;
+
+import org.rhq.core.domain.resource.Agent;
+
+/**
+ * (resourceId, agent) tuple
+ * 
+ * @author Jirka Kremser
+ */
+public class ResourceIdWithAgentComposite implements Serializable {
+
+    private static final long serialVersionUID = 42L;
+    private final int resourceId;
+    private final Agent agent;
+
+    public ResourceIdWithAgentComposite(int resourceId, Agent agent) {
+        this.resourceId = resourceId;
+        this.agent = agent;
+    }
+
+    public int getResourceId() {
+        return resourceId;
+    }
+
+    public Agent getAgent() {
+        return agent;
+    }
+}
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/util/collection/ArrayUtils.java b/modules/core/domain/src/main/java/org/rhq/core/domain/util/collection/ArrayUtils.java
new file mode 100644
index 0000000..12fd15e
--- /dev/null
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/util/collection/ArrayUtils.java
@@ -0,0 +1,75 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2008 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.rhq.core.domain.util.collection;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * @author John Mazzitelli
+ * @author Joseph Marques
+ */
+public class ArrayUtils {
+
+    public static int[] unwrapCollection(Collection<Integer> input) {
+        if (input == null) {
+            return null;
+        }
+        Integer[] intermediate = input.toArray(new Integer[input.size()]);
+        return unwrapArray(intermediate);
+    }
+
+    public static int[] unwrapArray(Integer[] input) {
+        if (input == null) {
+            return null;
+        }
+        int[] output = new int[input.length];
+        for (int i = 0; i < input.length; i++) {
+            output[i] = input[i];
+        }
+        return output;
+    }
+
+    public static Integer[] wrapInArray(int[] input) {
+        if (input == null) {
+            return null;
+        }
+        Integer[] output = new Integer[input.length];
+        for (int i = 0; i < input.length; i++) {
+            output[i] = input[i];
+        }
+        return output;
+    }
+
+    public static List<Integer> wrapInList(int[] input) {
+        if (input == null) {
+            return null;
+        }
+        Integer[] intermediate = wrapInArray(input);
+
+        // do not use Arrays.asList because returned list needs to be modifiable
+        List<Integer> results = new ArrayList<Integer>();
+        for (Integer next : intermediate) {
+            results.add(next);
+        }
+        return results;
+    }
+
+}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/MeasurementDataGWTService.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/MeasurementDataGWTService.java
index 8db6354..8640383 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/MeasurementDataGWTService.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/MeasurementDataGWTService.java
@@ -50,6 +50,8 @@ public interface MeasurementDataGWTService extends RemoteService {
         throws RuntimeException;
 
     Set<MeasurementData> findLiveData(int resourceId, int[] definitionIds) throws RuntimeException;
+    
+    Set<MeasurementData> findLiveDataForGroup(int groupId, int resourceId[], int[] definitionIds) throws RuntimeException;
 
     List<List<MeasurementDataNumericHighLowComposite>> findDataForResource(int resourceId, int[] definitionIds,
         long beginTime, long endTime, int numPoints) throws RuntimeException;
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractMeasurementDataTraitDataSource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractMeasurementDataTraitDataSource.java
index 325a542..e640d1d 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractMeasurementDataTraitDataSource.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractMeasurementDataTraitDataSource.java
@@ -52,6 +52,10 @@ import org.rhq.enterprise.gui.coregui.client.util.RPCDataSource;
  */
 public abstract class AbstractMeasurementDataTraitDataSource extends
     RPCDataSource<MeasurementDataTrait, MeasurementDataTraitCriteria> {
+
+    public static final String FIELD_METRIC_SCHED_ID = "id";
+    public static final String FIELD_METRIC_NAME = "name";
+
     private MeasurementDataGWTServiceAsync measurementService = GWTServiceLookup.getMeasurementDataService();
 
     protected AbstractMeasurementDataTraitDataSource() {
@@ -70,9 +74,13 @@ public abstract class AbstractMeasurementDataTraitDataSource extends
         primaryKeyField.setHidden(true);
         fields.add(primaryKeyField);
 
-        DataSourceIntegerField idField = new DataSourceIntegerField("id", MSG.dataSource_traits_field_definitionID());
+        DataSourceIntegerField idField = new DataSourceIntegerField(FIELD_METRIC_SCHED_ID, MSG.dataSource_traits_field_definitionID());
         idField.setHidden(true);
         fields.add(idField);
+        
+        DataSourceIntegerField nameField = new DataSourceIntegerField(FIELD_METRIC_NAME, MSG.common_title_name());
+        nameField.setHidden(true);
+        fields.add(nameField);
 
         return fields;
     }
@@ -173,11 +181,13 @@ public abstract class AbstractMeasurementDataTraitDataSource extends
         ListGridRecord record = new ListGridRecord();
 
         record.setAttribute("primaryKey", from.getScheduleId() + ":" + from.getTimestamp());
-        record.setAttribute("id", from.getSchedule().getDefinition().getId()); // used for detail view
+        record.setAttribute(FIELD_METRIC_SCHED_ID, from.getSchedule().getDefinition().getId()); // used for detail view
         record.setAttribute(MeasurementDataTraitCriteria.SORT_FIELD_TIMESTAMP, new Date(from.getTimestamp()));
         record.setAttribute(MeasurementDataTraitCriteria.SORT_FIELD_DISPLAY_NAME, from.getSchedule().getDefinition()
             .getDisplayName());
         record.setAttribute(MeasurementDataTraitCriteria.SORT_FIELD_VALUE, from.getValue());
+        record.setAttribute(FIELD_METRIC_NAME, from.getSchedule().getDefinition().getName());
+        record.setAttribute(MeasurementDataTraitCriteria.FILTER_FIELD_RESOURCE_ID, from.getSchedule().getResource().getId());
 
         return record;
     }
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractMeasurementDataTraitListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractMeasurementDataTraitListView.java
index 2f842a8..6a9d35b 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractMeasurementDataTraitListView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractMeasurementDataTraitListView.java
@@ -19,16 +19,23 @@
 package org.rhq.enterprise.gui.coregui.client.inventory.common;
 
 import java.util.ArrayList;
+import java.util.List;
 
 import com.smartgwt.client.data.Criteria;
 import com.smartgwt.client.data.SortSpecifier;
 import com.smartgwt.client.types.SelectionStyle;
 import com.smartgwt.client.types.SortDirection;
+import com.smartgwt.client.widgets.events.CloseClickEvent;
+import com.smartgwt.client.widgets.events.CloseClickHandler;
 import com.smartgwt.client.widgets.grid.ListGrid;
 import com.smartgwt.client.widgets.grid.ListGridField;
+import com.smartgwt.client.widgets.grid.ListGridRecord;
 
 import org.rhq.core.domain.criteria.MeasurementDataTraitCriteria;
+import org.rhq.enterprise.gui.coregui.client.components.table.TableAction;
 import org.rhq.enterprise.gui.coregui.client.components.table.TableSection;
+import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableListGrid;
+import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableWindow;
 
 /**
  * A view that displays a non-paginated table of {@link org.rhq.core.domain.measurement.MeasurementDataTrait trait}s,
@@ -36,7 +43,7 @@ import org.rhq.enterprise.gui.coregui.client.components.table.TableSection;
  *
  * @author Ian Springer
  */
-public abstract class AbstractMeasurementDataTraitListView extends TableSection {
+public abstract class AbstractMeasurementDataTraitListView extends TableSection<AbstractMeasurementDataTraitDataSource> {
     private static final String TITLE = MSG.view_metric_traits();
     private static final String[] EXCLUDED_FIELD_NAMES = new String[0];
 
@@ -70,11 +77,45 @@ public abstract class AbstractMeasurementDataTraitListView extends TableSection
         // Set widths and cell formatters on the fields.
         ListGridField displayNameField = listGrid.getField(MeasurementDataTraitCriteria.SORT_FIELD_DISPLAY_NAME);
         displayNameField.setWidth("20%");
+
+        addTableAction(extendLocatorId("liveValue"), MSG.view_measureTable_getLive(), getLiveValueAction());
     }
+    
+    protected abstract TableAction getLiveValueAction();
+    
+    protected abstract LocatableListGrid decorateLiveDataGrid(List<ListGridRecord> records);
 
     @Override
     protected String getDetailsLinkColumnName() {
         return MeasurementDataTraitCriteria.SORT_FIELD_DISPLAY_NAME;
     }
+    
+    public void showLiveData(List<ListGridRecord> records) {
+        final LocatableWindow liveDataWindow = new LocatableWindow(extendLocatorId("liveDataWindow"));
+        liveDataWindow.setTitle(MSG.view_measureTable_live_title());
+        liveDataWindow.setShowModalMask(true);
+        liveDataWindow.setShowMinimizeButton(false);
+        liveDataWindow.setShowMaximizeButton(true);
+        liveDataWindow.setShowCloseButton(true);
+        liveDataWindow.setShowResizer(true);
+        liveDataWindow.setCanDragResize(true);
+        liveDataWindow.setDismissOnEscape(true);
+        liveDataWindow.setIsModal(true);
+        liveDataWindow.setWidth(700);
+        liveDataWindow.setHeight(425);
+        liveDataWindow.setAutoCenter(true);
+        liveDataWindow.centerInPage();
+        liveDataWindow.addCloseClickHandler(new CloseClickHandler() {
+            @Override
+            public void onCloseClick(CloseClickEvent event) {
+                liveDataWindow.destroy();
+                refreshTableInfo();
+            }
+        });
+
+        LocatableListGrid liveDataGrid = decorateLiveDataGrid(records); 
+        liveDataWindow.addItem(liveDataGrid);
+        liveDataWindow.show();
+    }
 
 }
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/monitoring/traits/TraitsView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/monitoring/traits/TraitsView.java
index ed91c6a..f7eb900 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/monitoring/traits/TraitsView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/monitoring/traits/TraitsView.java
@@ -18,7 +18,18 @@
  */
 package org.rhq.enterprise.gui.coregui.client.inventory.groups.detail.monitoring.traits;
 
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import com.google.gwt.user.client.rpc.AsyncCallback;
 import com.smartgwt.client.data.Criteria;
+import com.smartgwt.client.types.SelectionStyle;
 import com.smartgwt.client.widgets.Canvas;
 import com.smartgwt.client.widgets.grid.CellFormatter;
 import com.smartgwt.client.widgets.grid.HoverCustomizer;
@@ -27,9 +38,16 @@ import com.smartgwt.client.widgets.grid.ListGridField;
 import com.smartgwt.client.widgets.grid.ListGridRecord;
 
 import org.rhq.core.domain.criteria.MeasurementDataTraitCriteria;
+import org.rhq.core.domain.measurement.MeasurementData;
+import org.rhq.core.domain.util.collection.ArrayUtils;
+import org.rhq.enterprise.gui.coregui.client.CoreGUI;
 import org.rhq.enterprise.gui.coregui.client.LinkManager;
+import org.rhq.enterprise.gui.coregui.client.components.table.TableAction;
+import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
+import org.rhq.enterprise.gui.coregui.client.inventory.common.AbstractMeasurementDataTraitDataSource;
 import org.rhq.enterprise.gui.coregui.client.inventory.common.AbstractMeasurementDataTraitListView;
 import org.rhq.enterprise.gui.coregui.client.inventory.resource.AncestryUtil;
+import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableListGrid;
 import org.rhq.enterprise.gui.coregui.client.util.selenium.SeleniumUtility;
 
 /**
@@ -71,7 +89,6 @@ public class TraitsView extends AbstractMeasurementDataTraitListView {
         //resourceNameField.setCanGroupBy(true);
 
         AncestryUtil.setupAncestryListGridField(listGrid);
-        super.configureTable();
     }
 
     @Override
@@ -87,4 +104,92 @@ public class TraitsView extends AbstractMeasurementDataTraitListView {
 
         return criteria;
     }
+
+    @Override
+    protected TableAction getLiveValueAction() {
+        return new TableAction() {
+            @Override
+            public boolean isEnabled(ListGridRecord[] selection) {
+                return selection != null && selection.length > 0;
+            }
+
+            @Override
+            public void executeAction(ListGridRecord[] selection, Object actionValue) {
+                if (selection == null || selection.length == 0) {
+                    return;
+                }
+                final Map<String, ListGridRecord> selectedRecords = new HashMap<String, ListGridRecord>();
+                int[] definitionIds = new int[selection.length];
+                int i = 0;
+                Set<Integer> resourceIds = new HashSet<Integer>();
+                for (ListGridRecord record : selection) {
+                    Integer defId = record
+                        .getAttributeAsInt(AbstractMeasurementDataTraitDataSource.FIELD_METRIC_SCHED_ID);
+                    definitionIds[i++] = defId.intValue();
+                    int resourceId = record.getAttributeAsInt(MeasurementDataTraitCriteria.FILTER_FIELD_RESOURCE_ID);
+                    resourceIds.add(resourceId);
+
+                    selectedRecords.put(
+                        resourceId + ":"
+                            + record.getAttribute(AbstractMeasurementDataTraitDataSource.FIELD_METRIC_NAME), record);
+                }
+
+                // actually go out and ask the agents for the data
+                GWTServiceLookup.getMeasurementDataService(60000).findLiveDataForGroup(groupId,
+                    ArrayUtils.unwrapCollection(resourceIds), definitionIds, new AsyncCallback<Set<MeasurementData>>() {
+                        @Override
+                        public void onSuccess(Set<MeasurementData> result) {
+                            if (result == null) {
+                                result = new HashSet<MeasurementData>(0);
+                            }
+                            ArrayList<ListGridRecord> records = new ArrayList<ListGridRecord>(result.size());
+                            for (MeasurementData data : result) {
+                                ListGridRecord record = selectedRecords.get(data.getName());
+                                record.setAttribute("value", data.getValue());
+                                records.add(record);
+                            }
+                            Collections.sort(records, new Comparator<ListGridRecord>() {
+                                public int compare(ListGridRecord o1, ListGridRecord o2) {
+                                    return o1.getAttribute("name").compareTo(o2.getAttribute("name"));
+                                }
+                            });
+                            showLiveData(records);
+                        }
+
+                        @Override
+                        public void onFailure(Throwable caught) {
+                            CoreGUI.getErrorHandler().handleError(MSG.view_measureTable_getLive_failure(), caught);
+                        }
+                    });
+            }
+        };
+    }
+
+    @Override
+    protected LocatableListGrid decorateLiveDataGrid(List<ListGridRecord> records) {
+        LocatableListGrid liveDataGrid = new LocatableListGrid(extendLocatorId("liveDataListGrid"));
+        liveDataGrid.setShowAllRecords(true);
+        liveDataGrid.setData(records.toArray(new ListGridRecord[records.size()]));
+        liveDataGrid.setSelectionType(SelectionStyle.NONE);
+        ListGridField name = new ListGridField(MeasurementDataTraitCriteria.SORT_FIELD_DISPLAY_NAME,
+            MSG.dataSource_traits_field_trait());
+        ListGridField value = new ListGridField("value", MSG.common_title_value());
+        ListGridField resourceNameField = new ListGridField(MeasurementDataTraitCriteria.SORT_FIELD_RESOURCE_NAME,
+            MSG.common_title_resource());
+        resourceNameField.setCellFormatter(new CellFormatter() {
+            public String format(Object o, ListGridRecord listGridRecord, int i, int i1) {
+                String url = LinkManager.getResourceLink(listGridRecord.getAttributeAsInt(AncestryUtil.RESOURCE_ID));
+                return SeleniumUtility.getLocatableHref(url, o.toString(), null);
+            }
+        });
+        resourceNameField.setShowHover(true);
+        resourceNameField.setHoverCustomizer(new HoverCustomizer() {
+            public String hoverHTML(Object value, ListGridRecord listGridRecord, int rowNum, int colNum) {
+                return AncestryUtil.getResourceHoverHTML(listGridRecord, 0);
+            }
+        });
+        liveDataGrid.setFields(name, value, resourceNameField, AncestryUtil.setupAncestryListGridField());
+
+        return liveDataGrid;
+    }
 }
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/traits/TraitsView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/traits/TraitsView.java
index fe7b9ec..ad422b7 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/traits/TraitsView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/traits/TraitsView.java
@@ -18,11 +18,30 @@
  */
 package org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.traits;
 
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import com.google.gwt.user.client.rpc.AsyncCallback;
 import com.smartgwt.client.data.Criteria;
+import com.smartgwt.client.types.SelectionStyle;
 import com.smartgwt.client.widgets.Canvas;
+import com.smartgwt.client.widgets.grid.ListGridField;
+import com.smartgwt.client.widgets.grid.ListGridRecord;
 
 import org.rhq.core.domain.criteria.MeasurementDataTraitCriteria;
+import org.rhq.core.domain.measurement.MeasurementData;
+import org.rhq.enterprise.gui.coregui.client.CoreGUI;
+import org.rhq.enterprise.gui.coregui.client.components.table.TableAction;
+import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
+import org.rhq.enterprise.gui.coregui.client.inventory.common.AbstractMeasurementDataTraitDataSource;
 import org.rhq.enterprise.gui.coregui.client.inventory.common.AbstractMeasurementDataTraitListView;
+import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableListGrid;
 
 /**
  * The Resource Monitoring>Traits subtab.
@@ -55,4 +74,71 @@ public class TraitsView extends AbstractMeasurementDataTraitListView {
 
         return criteria;
     }
+    
+    @Override
+    protected TableAction getLiveValueAction() {
+        return new TableAction() {
+            @Override
+            public boolean isEnabled(ListGridRecord[] selection) {
+                return selection != null && selection.length > 0;
+            }
+
+            @Override
+            public void executeAction(ListGridRecord[] selection, Object actionValue) {
+                if (selection == null || selection.length == 0) {
+                    return;
+                }
+                final Map<String, String> scheduleNames = new HashMap<String, String>();
+                int[] definitionIds = new int[selection.length];
+                int i = 0;
+                for (ListGridRecord record : selection) {
+                    Integer defId = record.getAttributeAsInt(AbstractMeasurementDataTraitDataSource.FIELD_METRIC_SCHED_ID);
+                    definitionIds[i++] = defId.intValue();
+                    
+                    scheduleNames.put(record.getAttribute(AbstractMeasurementDataTraitDataSource.FIELD_METRIC_NAME), record.getAttribute(MeasurementDataTraitCriteria.SORT_FIELD_DISPLAY_NAME));
+                }
+
+                // actually go out and ask the agents for the data
+                GWTServiceLookup.getMeasurementDataService(60000).findLiveData(resourceId,
+                    definitionIds, new AsyncCallback<Set<MeasurementData>>() {
+                        public void onSuccess(Set<MeasurementData> result) {
+                            if (result == null) {
+                                result = new HashSet<MeasurementData>(0);
+                            }
+                            ArrayList<ListGridRecord> records = new ArrayList<ListGridRecord>(result.size());
+                            for (MeasurementData data : result) {
+                                    ListGridRecord record = new ListGridRecord();
+                                    record.setAttribute("name", scheduleNames.get(data.getName()));
+                                    record.setAttribute("value", data.getValue());
+                                    records.add(record);
+                            }
+                            Collections.sort(records, new Comparator<ListGridRecord>() {
+                                public int compare(ListGridRecord o1, ListGridRecord o2) {
+                                    return o1.getAttribute("name").compareTo(o2.getAttribute("name"));
+                                }
+                            });
+                            showLiveData(records);
+                        }
+
+                        @Override
+                        public void onFailure(Throwable caught) {
+                            CoreGUI.getErrorHandler().handleError(MSG.view_measureTable_getLive_failure(), caught);
+                        }
+                    });
+            }
+        };
+    }
+
+    @Override
+    protected LocatableListGrid decorateLiveDataGrid(List<ListGridRecord> records) {
+        LocatableListGrid liveDataGrid = new LocatableListGrid(extendLocatorId("liveDataListGrid"));
+        liveDataGrid.setShowAllRecords(true);
+        liveDataGrid.setData(records.toArray(new ListGridRecord[records.size()]));
+        liveDataGrid.setSelectionType(SelectionStyle.NONE);
+        ListGridField name = new ListGridField("name", MSG.dataSource_traits_field_trait());
+        ListGridField value = new ListGridField("value", MSG.common_title_value());
+        liveDataGrid.setFields(name, value);
+
+        return liveDataGrid;
+    }
 }
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/MeasurementDataGWTServiceImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/MeasurementDataGWTServiceImpl.java
index 071881e..eec590d 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/MeasurementDataGWTServiceImpl.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/MeasurementDataGWTServiceImpl.java
@@ -81,6 +81,15 @@ public class MeasurementDataGWTServiceImpl extends AbstractGWTServiceImpl implem
             throw getExceptionToThrowToClient(t);
         }
     }
+    
+    public Set<MeasurementData> findLiveDataForGroup(int groupId, int resourceId[], int[] definitionIds) throws RuntimeException {
+        try {
+            return SerialUtility.prepare(dataManager.findLiveDataForGroup(getSessionSubject(), groupId, resourceId, definitionIds),
+                "MeasurementDataService.findLiveDataForGroup");
+        } catch (Throwable t) {
+            throw getExceptionToThrowToClient(t);
+        }
+    }
 
     public List<List<MeasurementDataNumericHighLowComposite>> findDataForResource(int resourceId, int[] definitionIds,
         long beginTime, long endTime, int numPoints) throws RuntimeException {
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerBean.java
index 32567f0..65ec2a7 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerBean.java
@@ -73,6 +73,7 @@ import org.rhq.core.domain.measurement.ui.MetricDisplaySummary;
 import org.rhq.core.domain.resource.Agent;
 import org.rhq.core.domain.resource.Resource;
 import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.core.domain.resource.composite.ResourceIdWithAgentComposite;
 import org.rhq.core.domain.resource.group.ResourceGroup;
 import org.rhq.core.domain.server.PersistenceUtility;
 import org.rhq.core.domain.util.OrderingField;
@@ -775,6 +776,7 @@ public class MeasurementDataManagerBean implements MeasurementDataManagerLocal,
         return results;
     }
 
+    @Override
     @SuppressWarnings("unchecked")
     public Set<MeasurementData> findLiveData(Subject subject, int resourceId, int[] definitionIds) {
         if (authorizationManager.canViewResource(subject, resourceId) == false) {
@@ -782,10 +784,11 @@ public class MeasurementDataManagerBean implements MeasurementDataManagerLocal,
                 + "] does not have permission to view live measurement data for resource[id=" + resourceId + "]");
         }
 
-        Resource resource = entityManager.find(Resource.class, resourceId);
-        Agent agent = resource.getAgent();
+        Query query = entityManager.createNamedQuery(Agent.QUERY_FIND_BY_RESOURCE_ID);
+        query.setParameter("resourceId", resourceId);
+        Agent agent = (Agent) query.getSingleResult();
 
-        Query query = entityManager.createNamedQuery(MeasurementSchedule.FIND_BY_RESOURCE_IDS_AND_DEFINITION_IDS);
+        query = entityManager.createNamedQuery(MeasurementSchedule.FIND_BY_RESOURCE_IDS_AND_DEFINITION_IDS);
         query.setParameter("definitionIds", ArrayUtils.wrapInList(definitionIds));
         query.setParameter("resourceIds", Arrays.asList(resourceId));
         List<MeasurementSchedule> schedules = query.getResultList();
@@ -796,7 +799,7 @@ public class MeasurementDataManagerBean implements MeasurementDataManagerLocal,
         }
 
         AgentClient ac = agentClientManager.getAgentClient(agent);
-        Set<MeasurementData> values = ac.getMeasurementAgentService().getRealTimeMeasurementValue(resourceId,requests);
+        Set<MeasurementData> values = ac.getMeasurementAgentService().getRealTimeMeasurementValue(resourceId, requests);
         //[BZ 760139] always return non-null value even when there are errors on the server side.  Avoids cryptic
         //            Global UI Exceptions when attempting to serialize null responses.
         if (values == null) {
@@ -807,6 +810,49 @@ public class MeasurementDataManagerBean implements MeasurementDataManagerLocal,
     }
 
     @Override
+    @SuppressWarnings("unchecked")
+    public Set<MeasurementData> findLiveDataForGroup(Subject subject, int groupId, int resourceIds[],
+        int[] definitionIds) {
+        if (authorizationManager.canViewGroup(subject, groupId) == false) {
+            throw new PermissionException("User [" + subject.getName()
+                + "] does not have permission to view measurement data for resourceGroup[id=" + groupId + "]");
+        }
+        Set<MeasurementData> values = new HashSet<MeasurementData>();
+
+        if (resourceIds != null) {
+            Query query = entityManager.createNamedQuery(Agent.QUERY_FIND_RESOURCE_IDS_WITH_AGENTS_BY_RESOURCE_IDS);
+            query.setParameter("resourceIds", ArrayUtils.wrapInList(resourceIds));
+            List<ResourceIdWithAgentComposite> resourceIdsWithAgents = query.getResultList();
+
+            for (ResourceIdWithAgentComposite resourceIdWithAgent : resourceIdsWithAgents) {
+                query = entityManager.createNamedQuery(MeasurementSchedule.FIND_BY_RESOURCE_IDS_AND_DEFINITION_IDS);
+                query.setParameter("definitionIds", ArrayUtils.wrapInList(definitionIds));
+                query.setParameter("resourceIds", Arrays.asList(resourceIdWithAgent.getResourceId()));
+                List<MeasurementSchedule> schedules = query.getResultList();
+
+                Map<Integer, Integer> scheduleIdToResourceIdMap = new HashMap<Integer, Integer>(schedules.size());
+                Set<MeasurementScheduleRequest> requests = new HashSet<MeasurementScheduleRequest>(schedules.size());
+                for (MeasurementSchedule schedule : schedules) {
+                    requests.add(new MeasurementScheduleRequest(schedule));
+                    scheduleIdToResourceIdMap.put(schedule.getId(), resourceIdWithAgent.getResourceId());
+                }
+
+                AgentClient ac = agentClientManager.getAgentClient(resourceIdWithAgent.getAgent());
+                Set<MeasurementData> newValues = ac.getMeasurementAgentService().getRealTimeMeasurementValue(
+                    resourceIdWithAgent.getResourceId(), requests);
+                values.addAll(newValues);
+
+                // Add the resource id as a prefix of the name, because the name is not unique across different platforms
+                for (MeasurementData value : newValues) {
+                    value.setName(String.valueOf(scheduleIdToResourceIdMap.get(value.getScheduleId())) + ":"
+                        + value.getName());
+                }
+            }
+        }
+        return values;
+    }
+
+    @Override
     public List<MeasurementDataNumeric> findRawData(Subject subject, int scheduleId, long startTime, long endTime) {
 
         List<MeasurementDataNumeric> result = new ArrayList<MeasurementDataNumeric>();
@@ -817,23 +863,22 @@ public class MeasurementDataManagerBean implements MeasurementDataManagerLocal,
         try {
             connection = rhqDs.getConnection();
             ps = connection.prepareStatement( // TODO supply real impl that spans multiple tables
-                    "SELECT time_stamp,value FROM " + table + " WHERE schedule_id= ? AND time_stamp BETWEEN ? AND ?");
-            ps.setLong(1,scheduleId);
-            ps.setLong(2,startTime);
-            ps.setLong(3,endTime);
+                "SELECT time_stamp,value FROM " + table + " WHERE schedule_id= ? AND time_stamp BETWEEN ? AND ?");
+            ps.setLong(1, scheduleId);
+            ps.setLong(2, startTime);
+            ps.setLong(3, endTime);
             rs = ps.executeQuery();
 
             while (rs.next()) {
-                MeasurementDataNumeric point = new MeasurementDataNumeric(rs.getLong(1),scheduleId,rs.getDouble(2));
+                MeasurementDataNumeric point = new MeasurementDataNumeric(rs.getLong(1), scheduleId, rs.getDouble(2));
                 result.add(point);
             }
         } catch (SQLException e) {
-            e.printStackTrace();  // TODO: Customise this generated block
+            e.printStackTrace(); // TODO: Customise this generated block
         } finally {
             JDBCUtil.safeClose(connection, ps, rs);
         }
 
-
         return result;
     }
 
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerLocal.java
index 4ea8302..a285a7f 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerLocal.java
@@ -164,11 +164,24 @@ public interface MeasurementDataManagerLocal {
     /**
      * Get live metrics for a given MeasurementSchedule
      *
-     * @param  sched MeasurementSchedule to obtain the data for
+     * @param subject the user that is requesting the data
+     * @param resourceId the id of the resource
+     * @param definitionIds the array of ids of schedule definitions
      *
      * @return MeasurementData for this Schedule
      */
     Set<MeasurementData> findLiveData(Subject subject, int resourceId, int[] definitionIds);
+    
+    /**
+     * Get live metrics for a given MeasurementSchedule
+     *
+     * @param subject the user that is requesting the data
+     * @param resourceId the array of ids of the resources
+     * @param definitionIds the array of ids of schedule definitions
+     *
+     * @return MeasurementData for this Schedule
+     */
+    Set<MeasurementData> findLiveDataForGroup(Subject subject, int groupId, int[] resourceId, int[] definitionIds);
 
     /**
      * Returns a list of numeric data point lists for the given compatible group - one per specified measurement
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerRemote.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerRemote.java
index 032f8f9..d3163ec 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerRemote.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerRemote.java
@@ -71,6 +71,13 @@ public interface MeasurementDataManagerRemote {
         @WebParam(name = "subject") Subject subject, //
         @WebParam(name = "resourceId") int resourceId, //
         @WebParam(name = "definitionIds") int[] definitionIds);
+    
+    @WebMethod
+    Set<MeasurementData> findLiveDataForGroup(//
+        @WebParam(name = "subject") Subject subject, //
+        @WebParam(name = "groupId") int groupId,//
+        @WebParam(name = "resourceId") int[] resourceId, //
+        @WebParam(name = "definitionIds") int[] definitionIds);
 
     @WebMethod
     @XmlJavaTypeAdapter(MeasurementDataNumericHighLowCompositeAdapter.class)
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/webservices/WebservicesManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/webservices/WebservicesManagerBean.java
index 27cdabd..1ba4d97 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/webservices/WebservicesManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/webservices/WebservicesManagerBean.java
@@ -666,6 +666,10 @@ public class WebservicesManagerBean implements WebservicesRemote {
     public Set<MeasurementData> findLiveData(Subject subject, int resourceId, int[] definitionIds) {
         return measurementDataManager.findLiveData(subject, resourceId, definitionIds);
     }
+    
+    public Set<MeasurementData> findLiveDataForGroup(Subject subject, int groupId, int[] resourceId, int[] definitionIds) {
+        return measurementDataManager.findLiveDataForGroup(subject, groupId, resourceId, definitionIds);
+    }
 
     public List<MeasurementDataTrait> findTraits(Subject subject, int resourceId, int definitionId) {
         return measurementDataManager.findTraits(subject, resourceId, definitionId);


commit db5166849d9de681ec1ea65826799f445c272ef0
Author: Heiko W. Rupp <hwr at redhat.com>
Date:   Thu Jul 12 10:19:07 2012 +0200

    No-op plugin that is meant as base for jar-less plugins that should not be discovered on the agent side, but which are served through the server side REST-api.

diff --git a/modules/plugins/noop/pom.xml b/modules/plugins/noop/pom.xml
new file mode 100644
index 0000000..cc31433
--- /dev/null
+++ b/modules/plugins/noop/pom.xml
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ RHQ Management Platform
+  ~ Copyright (C) 2005-2012 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.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.rhq</groupId>
+    <artifactId>rhq-plugins-parent</artifactId>
+    <version>4.5.0-SNAPSHOT</version>
+  </parent>
+
+  <groupId>org.rhq</groupId>
+  <artifactId>rhq-no-op-plugin</artifactId>
+  <packaging>jar</packaging>
+
+  <name>RHQ No-op Plugin</name>
+  <description>An abstract plugin for plugins defining resource types without java-agent support.</description>
+
+  <profiles>
+
+    <profile>
+      <id>dev</id>
+
+      <properties>
+        <rhq.rootDir>../../..</rhq.rootDir>
+        <rhq.containerDir>${rhq.rootDir}/${rhq.defaultDevContainerPath}</rhq.containerDir>
+        <rhq.deploymentDir>${rhq.containerDir}/jbossas/server/default/deploy/${rhq.earName}/rhq-downloads/rhq-plugins
+        </rhq.deploymentDir>
+      </properties>
+
+      <build>
+        <plugins>
+
+          <plugin>
+            <artifactId>maven-antrun-plugin</artifactId>
+            <executions>
+
+              <execution>
+                <id>deploy</id>
+                <phase>compile</phase>
+                <configuration>
+                  <target>
+                    <mkdir dir="${rhq.deploymentDir}"/>
+                    <property name="deployment.file" location="${rhq.deploymentDir}/${project.build.finalName}.jar"/>
+                    <echo>*** Updating ${deployment.file}...</echo>
+                    <jar destfile="${deployment.file}" basedir="${project.build.outputDirectory}"/>
+                  </target>
+                </configuration>
+                <goals>
+                  <goal>run</goal>
+                </goals>
+              </execution>
+
+              <execution>
+                <id>deploy-jar-meta-inf</id>
+                <phase>package</phase>
+                <configuration>
+                  <target>
+                    <property name="deployment.file" location="${rhq.deploymentDir}/${project.build.finalName}.jar"/>
+                    <echo>*** Updating META-INF dir in ${deployment.file}...</echo>
+                    <unjar src="${project.build.directory}/${project.build.finalName}.jar"
+                           dest="${project.build.outputDirectory}">
+                      <patternset>
+                        <include name="META-INF/**"/>
+                      </patternset>
+                    </unjar>
+                    <jar destfile="${deployment.file}" manifest="${project.build.outputDirectory}/META-INF/MANIFEST.MF"
+                         update="true">
+                    </jar>
+                  </target>
+                </configuration>
+                <goals>
+                  <goal>run</goal>
+                </goals>
+              </execution>
+
+              <execution>
+                <id>undeploy</id>
+                <phase>clean</phase>
+                <configuration>
+                  <target>
+                    <property name="deployment.file" location="${rhq.deploymentDir}/${project.build.finalName}.jar"/>
+                    <echo>*** Deleting ${deployment.file}...</echo>
+                    <delete file="${deployment.file}"/>
+                  </target>
+                </configuration>
+                <goals>
+                  <goal>run</goal>
+                </goals>
+              </execution>
+
+            </executions>
+          </plugin>
+
+        </plugins>
+      </build>
+    </profile>
+  </profiles>
+</project>
\ No newline at end of file
diff --git a/modules/plugins/noop/src/main/java/org/rhq/plugins/noop/NoopComponent.java b/modules/plugins/noop/src/main/java/org/rhq/plugins/noop/NoopComponent.java
new file mode 100644
index 0000000..184397d
--- /dev/null
+++ b/modules/plugins/noop/src/main/java/org/rhq/plugins/noop/NoopComponent.java
@@ -0,0 +1,67 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 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.plugins.noop;
+
+import java.util.Collections;
+import java.util.Set;
+
+import org.rhq.core.domain.measurement.AvailabilityType;
+import org.rhq.core.pluginapi.inventory.DiscoveredResourceDetails;
+import org.rhq.core.pluginapi.inventory.ResourceComponent;
+import org.rhq.core.pluginapi.inventory.ResourceContext;
+import org.rhq.core.pluginapi.inventory.ResourceDiscoveryComponent;
+import org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext;
+
+/**
+ * Class that servers as discovery and component class
+ * The discovery will on purpose never discover a resource
+ * @author Heiko W. Rupp
+ */
+public class NoopComponent implements ResourceComponent, ResourceDiscoveryComponent {
+    @Override
+    public void start(ResourceContext context) throws Exception {
+        // nothing to do
+    }
+
+    @Override
+    public void stop() {
+        // nothing to do
+    }
+
+    @Override
+    public AvailabilityType getAvailability() {
+        return null;
+    }
+
+    /**
+     * Discovery method, that on purpose always returns an empty set of discovered resources.
+     * This plugin is meant as base for plugins that
+     * @param  context the discovery context that provides the information to the component that helps it perform its
+     *                 discovery
+     *
+     * @return An empty set
+     * @throws Exception in the case something is sooo wrong ..
+     */
+    @Override
+    public Set<DiscoveredResourceDetails> discoverResources(
+            ResourceDiscoveryContext context) throws  Exception {
+        return Collections.emptySet();
+    }
+}
diff --git a/modules/plugins/noop/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/noop/src/main/resources/META-INF/rhq-plugin.xml
new file mode 100644
index 0000000..721f737
--- /dev/null
+++ b/modules/plugins/noop/src/main/resources/META-INF/rhq-plugin.xml
@@ -0,0 +1,25 @@
+<!--
+  ~ RHQ Management Platform
+  ~ Copyright (C) 2005-2012 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.
+  -->
+
+<plugin name="No-op"
+        displayName="Abstract NO-OP plugin"
+        description="Abstract plugin supporting concrete plugins that don't want java-agent support"
+        package="org.rhq.plugins.noop"
+        xmlns="urn:xmlns:rhq-plugin">
+</plugin>
\ No newline at end of file
diff --git a/modules/plugins/pom.xml b/modules/plugins/pom.xml
index d101f55..350c11e 100644
--- a/modules/plugins/pom.xml
+++ b/modules/plugins/pom.xml
@@ -53,14 +53,14 @@
          <type>test-jar</type>
          <scope>test</scope>
       </dependency>
-      
+
       <dependency>
          <groupId>${rhq.groupId}</groupId>
          <artifactId>test-utils</artifactId>
          <version>${project.version}</version>
          <scope>test</scope>
       </dependency>
-      
+
       <!--
          TODO: This is a fix for the Javac bug requiring annotations to be available when compiling dependent classes.
          It is fixed in JDK 6.
@@ -93,7 +93,8 @@
       <!--  core plugins  -->
       <module>platform</module>
       <module>jmx</module>
-      <module>rhq-agent</module>      
+      <module>rhq-agent</module>
+      <module>noop</module>
    </modules>
 
   <profiles>


commit 1656f7c935fe1b9aedd3807d12b3ac635f3ab530
Author: Heiko W. Rupp <hwr at redhat.com>
Date:   Thu Jul 12 10:17:13 2012 +0200

    BZ 74168 - allow to deploy descriptor-only "agent" plugins.

diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/AgentPluginScanner.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/AgentPluginScanner.java
index c787943..cbed5c8 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/AgentPluginScanner.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/AgentPluginScanner.java
@@ -24,6 +24,7 @@ import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.FilenameFilter;
+import java.io.IOException;
 import java.io.InputStream;
 import java.net.URL;
 import java.sql.Connection;
@@ -34,6 +35,8 @@ import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.jar.JarEntry;
+import java.util.jar.JarOutputStream;
 
 import javax.sql.DataSource;
 import javax.transaction.TransactionManager;
@@ -94,8 +97,14 @@ public class AgentPluginScanner {
     void registerAgentPlugins() throws Exception {
         try {
             for (DeploymentInfo di : this.scanned) {
-                log.debug("Hot deploying agent plugin [" + di.url + "]...");
-                this.agentPluginDeployer.pluginDetected(di);
+                if (di.url.getFile().endsWith("-rhq-plugin.xml")) {
+                    // Create a plugin jar and deploy next time
+                    createPluginJarFromDescriptorFile(di.url.getFile());
+                }
+                else {
+                    log.debug("Hot deploying agent plugin [" + di.url + "]...");
+                    this.agentPluginDeployer.pluginDetected(di);
+                }
             }
 
             // Register all the new plugins.
@@ -107,6 +116,53 @@ public class AgentPluginScanner {
         }
     }
 
+    /**
+     * We take a plugin descriptor and wrap it into a jar file. The original file is
+     * deleted if the wrapping succeeds.
+     * @param fileName Full path of the file to wrap.
+     */
+    private void createPluginJarFromDescriptorFile(String fileName) throws Exception {
+        if (!fileName.endsWith("-rhq-plugin.xml")) {
+            log.warn("The passed file does not end in -rhq-plugin.xml, will not process it");
+            return;
+        }
+
+        log.info("Found a plugin-descriptor at [" + fileName + "], creating a jar from it to be deployed at the next scan");
+        File descriptor = new File(fileName);
+        String name = descriptor.getName();
+        int pos = name.lastIndexOf(".xml");
+        name = name.substring(0,pos) + ".jar"; // TODO special name for those plugins?
+        String parent = descriptor.getParent();
+        JarOutputStream jos = null;
+        FileInputStream fis = null;
+        boolean success = false;
+        try {
+            jos = new JarOutputStream(new FileOutputStream(new File(parent,name)));
+            JarEntry jarEntry = new JarEntry("META-INF");
+            jos.putNextEntry(jarEntry);
+            jarEntry = new JarEntry("META-INF/rhq-plugin.xml");
+            jos.putNextEntry(jarEntry);
+            fis = new FileInputStream(descriptor);
+            int i;
+            while ((i= fis.read())>0) {
+                jos.write(i);
+            }
+            jos.flush();
+            success = true;
+        } catch (IOException e) {
+            log.error("Failed creating the plugin jar from the descriptor: " + e.getMessage());
+            throw e;
+        }
+        finally {
+            JDBCUtil.safeClose(jos);
+            JDBCUtil.safeClose(fis);
+        }
+        if (success) {
+            boolean deleted = descriptor.delete();
+            log.info("Deleted the now obsolete plugin descriptor: " + deleted);
+        }
+    }
+
     void agentPluginScan() throws Exception {
         // this method just scans the filesystem and database for agent plugin changes but makes
         // no attempt to register them or do anything with the agent plugin deployer.
@@ -136,7 +192,7 @@ public class AgentPluginScanner {
     /**
      * Scans the plugin directory and updates our cache of known plugin files.
      * This will purge any old plugins that are deemed obsolete.
-     * 
+     *
      * @return a list of files that appear to be new or updated and should be deployed
      */
     List<File> agentPluginScanFilesystem() {
@@ -145,7 +201,7 @@ public class AgentPluginScanner {
         // get the current list of plugins deployed on the filesystem
         File[] pluginJars = this.agentPluginDeployer.getPluginDir().listFiles(new FilenameFilter() {
             public boolean accept(File dir, String name) {
-                return name.endsWith(".jar");
+                return name.endsWith(".jar") || name.endsWith("-rhq-plugin.xml");
             }
         });
 
@@ -384,10 +440,10 @@ public class AgentPluginScanner {
                                 log.debug(message);
                             }
                         } else {
-                            //inform on the info level so that it's clear from the logs that the new file 
+                            //inform on the info level so that it's clear from the logs that the new file
                             //is going to be used.
                             log.info(message);
-                        }                
+                        }
                     }
                 } else {
                     log.info("Found agent plugin in the DB that we do not yet have: " + name);
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/PluginDeploymentScanner.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/PluginDeploymentScanner.java
index 05865c9..2093041 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/PluginDeploymentScanner.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/PluginDeploymentScanner.java
@@ -200,12 +200,12 @@ public class PluginDeploymentScanner implements PluginDeploymentScannerMBean {
         if (listFiles == null || listFiles.length == 0) {
             return; // nothing to do
         }
-
         for (File file : listFiles) {
             File destinationDirectory;
-            if (file.getName().endsWith(".jar")) {
+            boolean isJarLess = file.getName().endsWith("-rhq-plugin.xml");
+            if (file.getName().endsWith(".jar") || isJarLess ) {
                 try {
-                    if (null == AgentPluginDescriptorUtil.loadPluginDescriptorFromUrl(file.toURI().toURL())) {
+                    if (!isJarLess && null == AgentPluginDescriptorUtil.loadPluginDescriptorFromUrl(file.toURI().toURL())) {
                         throw new NullPointerException("no xml descriptor found in jar");
                     }
                     destinationDirectory = getAgentPluginDir();
@@ -244,10 +244,18 @@ public class PluginDeploymentScanner implements PluginDeploymentScannerMBean {
                                 log.error("Failed to set mtime to [" + new Date(file.lastModified()) + "] on file ["
                                     + realPluginFile + "].");
                             }
-                            log.info("Found plugin jar at [" + file.getAbsolutePath() + "] and placed it at ["
+                            String tmp;
+                            if (!isJarLess)
+                                tmp = "jar";
+                            else
+                                tmp = "descriptor";
+                            log.info("Found plugin " + tmp + " at [" + file.getAbsolutePath() + "] and placed it at ["
                                 + realPluginFile.getAbsolutePath() + "]");
                         }
                     }
+                    else {
+                        log.info("Found a plugin at [" + file.getAbsolutePath() + "], which is the same as the existing one. It will be ignored");
+                    }
                     boolean deleted = file.delete();
                     if (!deleted) {
                         log.info("The plugin jar found at[" + file.getAbsolutePath()


commit 7c360f94c89a59f008065b737f6c10a01826fb61
Author: Mike Thompson <mithomps at redhat.com>
Date:   Wed Jul 11 08:54:21 2012 -0700

    Trivial: fix incorrect imports on ConfigurationEditor

diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/ConfigurationEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/ConfigurationEditor.java
index 4e188dd..48df2d6 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/ConfigurationEditor.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/ConfigurationEditor.java
@@ -52,8 +52,26 @@ import com.smartgwt.client.widgets.form.DynamicForm;
 import com.smartgwt.client.widgets.form.ValuesManager;
 import com.smartgwt.client.widgets.form.events.ItemChangedEvent;
 import com.smartgwt.client.widgets.form.events.ItemChangedHandler;
-import com.smartgwt.client.widgets.form.fields.*;
-import com.smartgwt.client.widgets.form.fields.events.*;
+import com.smartgwt.client.widgets.form.fields.ButtonItem;
+import com.smartgwt.client.widgets.form.fields.CanvasItem;
+import com.smartgwt.client.widgets.form.fields.CheckboxItem;
+import com.smartgwt.client.widgets.form.fields.ComboBoxItem;
+import com.smartgwt.client.widgets.form.fields.FloatItem;
+import com.smartgwt.client.widgets.form.fields.FormItem;
+import com.smartgwt.client.widgets.form.fields.PasswordItem;
+import com.smartgwt.client.widgets.form.fields.RadioGroupItem;
+import com.smartgwt.client.widgets.form.fields.SelectItem;
+import com.smartgwt.client.widgets.form.fields.SpacerItem;
+import com.smartgwt.client.widgets.form.fields.SpinnerItem;
+import com.smartgwt.client.widgets.form.fields.StaticTextItem;
+import com.smartgwt.client.widgets.form.fields.TextAreaItem;
+import com.smartgwt.client.widgets.form.fields.TextItem;
+import com.smartgwt.client.widgets.form.fields.events.BlurEvent;
+import com.smartgwt.client.widgets.form.fields.events.BlurHandler;
+import com.smartgwt.client.widgets.form.fields.events.ChangedEvent;
+import com.smartgwt.client.widgets.form.fields.events.ChangedHandler;
+import com.smartgwt.client.widgets.form.fields.events.FocusEvent;
+import com.smartgwt.client.widgets.form.fields.events.FocusHandler;
 import com.smartgwt.client.widgets.form.validator.CustomValidator;
 import com.smartgwt.client.widgets.form.validator.FloatRangeValidator;
 import com.smartgwt.client.widgets.form.validator.IntegerRangeValidator;
@@ -118,7 +136,6 @@ import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableSectionStack
 import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableToolStrip;
 import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableVLayout;
 import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableWindow;
-import sun.net.www.content.image.png;
 
 /**
  * A SmartGWT widget for editing an RHQ {@link Configuration} that conforms to a {@link ConfigurationDefinition}.


commit c0721b423ae75cc18d6969d56a128be882b8edc0
Author: Mike Thompson <mithomps at redhat.com>
Date:   Tue Jul 10 08:56:48 2012 -0700

    Add Swagger documentation annotations to CSV Export Reports.

diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/AlertDefinitionLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/AlertDefinitionLocal.java
index d106ed6..373643b 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/AlertDefinitionLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/AlertDefinitionLocal.java
@@ -17,7 +17,7 @@ public interface AlertDefinitionLocal {
     @GZIP
     @GET
     @Produces({"text/csv"})
-    @ApiOperation(value = "Export the AlertDefinitions in the system")
+    @ApiOperation(value = "Export the AlertDefinitions as CSV")
     StreamingOutput alertDefinitions(@Context HttpServletRequest request);
 
 }
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/ConfigurationHistoryLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/ConfigurationHistoryLocal.java
index 00079e7..31c3df8 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/ConfigurationHistoryLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/ConfigurationHistoryLocal.java
@@ -9,6 +9,7 @@ import javax.ws.rs.core.Context;
 import javax.ws.rs.core.StreamingOutput;
 
 import com.wordnik.swagger.annotations.Api;
+import com.wordnik.swagger.annotations.ApiOperation;
 import org.jboss.resteasy.annotations.GZIP;
 
 @Path("/configurationHistory")
@@ -19,5 +20,6 @@ public interface ConfigurationHistoryLocal {
     @GZIP
     @GET
     @Produces({"text/csv"})
+    @ApiOperation(value = "Export the Configuration History data as CSV")
     StreamingOutput configurationHistory(@Context HttpServletRequest request);
 }
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/DriftComplianceLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/DriftComplianceLocal.java
index f3da333..fed7590 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/DriftComplianceLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/DriftComplianceLocal.java
@@ -28,6 +28,7 @@ import javax.ws.rs.core.Context;
 import javax.ws.rs.core.StreamingOutput;
 
 import com.wordnik.swagger.annotations.Api;
+import com.wordnik.swagger.annotations.ApiOperation;
 import org.jboss.resteasy.annotations.GZIP;
 
 @Path("/driftCompliance")
@@ -38,6 +39,7 @@ public interface DriftComplianceLocal {
     @GZIP
     @GET
     @Produces({"text/csv", "application/xml"})
+    @ApiOperation(value = "Export the drift compliance data")
     StreamingOutput generateReport(
         @Context HttpServletRequest request,
         @QueryParam("resourceTypeId") String resourceTypeId,
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/InventorySummaryLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/InventorySummaryLocal.java
index 43f2ee1..6b046dc 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/InventorySummaryLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/InventorySummaryLocal.java
@@ -28,11 +28,13 @@ import javax.ws.rs.core.Context;
 import javax.ws.rs.core.StreamingOutput;
 
 import com.wordnik.swagger.annotations.Api;
+import com.wordnik.swagger.annotations.ApiOperation;
 import org.jboss.resteasy.annotations.GZIP;
 
 @Path("/inventorySummary")
 @Local
 @Api(basePath="http://localhost:7080/coregui/reports", value = "The inventory summary report")
+
 public interface InventorySummaryLocal {
 
     /**
@@ -49,6 +51,7 @@ public interface InventorySummaryLocal {
     @GZIP
     @GET
     @Produces({"text/csv"})
+    @ApiOperation(value = "Export the Inventory Summary data as CSV")
     StreamingOutput generateReport(
         @Context HttpServletRequest request,
         @QueryParam("resourceTypeId") String resourceTypeId,
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/PlatformUtilizationLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/PlatformUtilizationLocal.java
index 7ee299a..1567fb5 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/PlatformUtilizationLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/PlatformUtilizationLocal.java
@@ -30,6 +30,7 @@ import javax.ws.rs.core.Context;
 import javax.ws.rs.core.StreamingOutput;
 
 import com.wordnik.swagger.annotations.Api;
+import com.wordnik.swagger.annotations.ApiOperation;
 import org.jboss.resteasy.annotations.GZIP;
 
 @Path("/platformUtilization")
@@ -40,6 +41,7 @@ public interface PlatformUtilizationLocal {
     @GZIP
     @GET
     @Produces({"text/csv"})
+    @ApiOperation(value = "Export the Platform utilization data as CSV")
     StreamingOutput generateReport(@Context HttpServletRequest request);
 
 }
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/RecentAlertLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/RecentAlertLocal.java
index 606be2b..979cb29 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/RecentAlertLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/RecentAlertLocal.java
@@ -11,6 +11,7 @@ import javax.ws.rs.core.Context;
 import javax.ws.rs.core.StreamingOutput;
 
 import com.wordnik.swagger.annotations.Api;
+import com.wordnik.swagger.annotations.ApiOperation;
 import org.jboss.resteasy.annotations.GZIP;
 
 @Path("/recentAlerts")
@@ -21,6 +22,7 @@ public interface RecentAlertLocal {
     @GZIP
     @GET
     @Produces({"text/csv"})
+    @ApiOperation(value = "Export the Recent Alert data as CSV")
     StreamingOutput recentAlerts(
             @QueryParam("alertPriority") @DefaultValue("high,medium,low") String alertPriority,
             @QueryParam("startTime") Long startTime,
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/RecentDriftLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/RecentDriftLocal.java
index fe2fd8b..8bea6c7 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/RecentDriftLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/RecentDriftLocal.java
@@ -10,14 +10,18 @@ import javax.ws.rs.core.Context;
 import javax.ws.rs.core.StreamingOutput;
 
 import com.wordnik.swagger.annotations.Api;
+import com.wordnik.swagger.annotations.ApiOperation;
+import org.jboss.resteasy.annotations.GZIP;
 
 @Path("/recentDrift")
 @Local
 @Api(basePath="http://localhost:7080/coregui/reports", value = "The recent drift report")
 public interface RecentDriftLocal {
 
+    @GZIP
     @GET
     @Produces({"text/csv"})
+    @ApiOperation(value = "Export the Recent drift data as CSV")
     StreamingOutput recentDrift(
             @QueryParam("categories") String categories,
             @QueryParam("snapshot") Integer snapshot,
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/RecentOperationsLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/RecentOperationsLocal.java
index 187ad1d..191623a 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/RecentOperationsLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/RecentOperationsLocal.java
@@ -11,6 +11,7 @@ import javax.ws.rs.core.Context;
 import javax.ws.rs.core.StreamingOutput;
 
 import com.wordnik.swagger.annotations.Api;
+import com.wordnik.swagger.annotations.ApiOperation;
 import org.jboss.resteasy.annotations.GZIP;
 
 @Path("/recentOperations")
@@ -21,6 +22,7 @@ public interface RecentOperationsLocal {
     @GZIP
     @GET
     @Produces({"text/csv"})
+    @ApiOperation(value = "Export the Recent Operations Data as CSV")
     StreamingOutput recentOperations(
             @QueryParam("status") @DefaultValue("inprogress,success,failure,canceled") String operationRequestStatus,
             @QueryParam("startTime") Long startTime,
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/SuspectMetricLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/SuspectMetricLocal.java
index 217920f..019a715 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/SuspectMetricLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/SuspectMetricLocal.java
@@ -9,6 +9,7 @@ import javax.ws.rs.core.Context;
 import javax.ws.rs.core.StreamingOutput;
 
 import com.wordnik.swagger.annotations.Api;
+import com.wordnik.swagger.annotations.ApiOperation;
 import org.jboss.resteasy.annotations.GZIP;
 
 @Path("/suspectMetrics")
@@ -19,6 +20,7 @@ public interface SuspectMetricLocal {
     @GZIP
     @GET
     @Produces("text/csv")
+    @ApiOperation(value = "Export the Suspect Metrics data as CSV")
     StreamingOutput suspectMetrics(@Context HttpServletRequest request);
 
 }


commit db20267b46527836cbe22b9a2138a4b70ee26885
Author: Heiko W. Rupp <hwr at redhat.com>
Date:   Wed Jul 11 13:53:56 2012 +0200

    Make AlertManagerBeanTest I18N aware.

diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/i18n/AlertI18NResourceKeys.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/i18n/AlertI18NResourceKeys.java
index 7700e1a..ade9639 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/i18n/AlertI18NResourceKeys.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/i18n/AlertI18NResourceKeys.java
@@ -68,7 +68,7 @@ public interface AlertI18NResourceKeys {
     @I18NMessages({ @I18NMessage("Avail stays NOT UP") })
     String ALERT_AVAILABILITY_DURATION_NOT_UP_SHORT = "alert.condition.availability.duration.notup.short";
 
-    // Foo Prop > 10.0% of Baseline Mean Value 
+    // Foo Prop > 10.0% of Baseline Mean Value
     @I18NMessages({ @I18NMessage("{0} {1} {2} of Baseline Mean Value") /*, @I18NMessage(locale = "de", value = "") */})
     String ALERT_BASELINE_MEAN = "alert.condition.baseline.mean";
 
@@ -137,7 +137,8 @@ public interface AlertI18NResourceKeys {
     @I18NMessages({ @I18NMessage("{0} Val Chg"), @I18NMessage(locale = "de", value = "{0} Wert�nd.") })
     String ALERT_METRIC_CHANGED_SHORT = "alert.condition.metric.changed.short";
 
-    @I18NMessages({ @I18NMessage("Operation [{0}] has status=[{1}]") /*, @I18NMessage(locale = "de", value = "") */})
+    @I18NMessages({ @I18NMessage("Operation [{0}] has status=[{1}]") ,
+            @I18NMessage(locale = "de", value = "Operation [{0}] hat den Status [{1}]") })
     String ALERT_OPERATION = "alert.condition.op";
 
     @I18NMessages({ @I18NMessage("Op [{0}]={1}") /*, @I18NMessage(locale = "de", value = "") */})
@@ -188,11 +189,11 @@ public interface AlertI18NResourceKeys {
 
     // Foo Value is Between 1.0B and 2.0B, Inclusive
     @I18NMessages({ @I18NMessage("{0} Value is Between {1} and {2}, Inclusive"),
-        @I18NMessage(locale = "de", value = "{0} Der Wert zwischen {1} und {2}, pauschal") })
+        @I18NMessage(locale = "de", value = "{0} Der Wert ist zwischen {1} und {2}, inklusiv") })
     String ALERT_RANGE_INSIDE_INCL = "alert.condition.range.in.incl";
 
     @I18NMessages({ @I18NMessage("{0} Between {1} - {2}, incl"),
-        @I18NMessage(locale = "de", value = "{0} zwischen {1} und {2}, paus") })
+        @I18NMessage(locale = "de", value = "{0} zwischen {1} und {2}, inkl") })
     String ALERT_RANGE_INSIDE_INCL_SHORT = "alert.condition.range.in.incl.short";
 
     @I18NMessages({ @I18NMessage("{0} Value is Between {1} and {2}, Exclusive"),
@@ -228,4 +229,8 @@ public interface AlertI18NResourceKeys {
     @I18NMessages({ @I18NMessage("\\  - Cond {0}: {1}\\n\\\n" + "\\  - Time: {2}\\n\\\n" + "\\  - Det: {3}\\n\\\n"),
         @I18NMessage(locale = "de", value = "  - Bed {0}: {1}\\n\\\n  - Zeit: {2}\\n\\\n" + "\\  - Det: {3}\\n\\\n") })
     String ALERT_EMAIL_CONDITION_LOG_FORMAT_SHORT = "alert.email.condition.log.format.short";
+
+    // Needed for the AlertManagerBeanTest
+    @I18NMessages({ @I18NMessage("Cond(?:ition)?"), @I18NMessage(locale = "de", value = "Bed(?:ingung)?")})
+    String ALERT_CONDITION_PATTERN = "alert.condition.pattern";
 }
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/alert/test/AlertManagerBeanTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/alert/test/AlertManagerBeanTest.java
index b6fcf14..131db7d 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/alert/test/AlertManagerBeanTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/alert/test/AlertManagerBeanTest.java
@@ -19,40 +19,44 @@ import org.rhq.core.domain.operation.OperationRequestStatus;
 import org.rhq.core.domain.resource.ResourceCategory;
 import org.rhq.core.domain.resource.ResourceType;
 import org.rhq.enterprise.server.alert.AlertManagerBean;
+import org.rhq.enterprise.server.alert.i18n.AlertI18NFactory;
+import org.rhq.enterprise.server.alert.i18n.AlertI18NResourceKeys;
 
 @Test
 public class AlertManagerBeanTest {
 
+    private static final String TEN_PERCENT = String.format("%2.1f%%", 10d);
+    private static final String TWELVE_DOT_5_B = String.format("%2.1fB", 12.5d);
     private String pretty;
 
     public void testPrettyPrintAVAILABILITY() {
         AlertCondition condition = createCondition(AlertConditionCategory.AVAILABILITY,
             AlertConditionOperator.AVAIL_GOES_UP.name(), null, null, null, null);
         pretty = getPrettyAlertConditionString(condition);
-        assert "Availability goes UP".equals(pretty) : pretty;
+        check(AlertI18NResourceKeys.ALERT_AVAILABILITY_GOES_UP);
         pretty = getShortPrettyAlertConditionString(condition);
-        assert "Avail goes UP".equals(pretty) : pretty;
+        check(AlertI18NResourceKeys.ALERT_AVAILABILITY_GOES_UP_SHORT);
 
         condition = createCondition(AlertConditionCategory.AVAILABILITY, AlertConditionOperator.AVAIL_GOES_DOWN.name(),
             null, null, null, null);
         pretty = getPrettyAlertConditionString(condition);
-        assert "Availability goes DOWN".equals(pretty) : pretty;
+        check(AlertI18NResourceKeys.ALERT_AVAILABILITY_GOES_DOWN);
         pretty = getShortPrettyAlertConditionString(condition);
-        assert "Avail goes DOWN".equals(pretty) : pretty;
+        check(AlertI18NResourceKeys.ALERT_AVAILABILITY_GOES_DOWN_SHORT);
 
         condition = createCondition(AlertConditionCategory.AVAILABILITY,
             AlertConditionOperator.AVAIL_GOES_DISABLED.name(), null, null, null, null);
         pretty = getPrettyAlertConditionString(condition);
-        assert "Availability goes DISABLED".equals(pretty) : pretty;
+        check(AlertI18NResourceKeys.ALERT_AVAILABILITY_GOES_DISABLED);
         pretty = getShortPrettyAlertConditionString(condition);
-        assert "Avail goes DISABLED".equals(pretty) : pretty;
+        check(AlertI18NResourceKeys.ALERT_AVAILABILITY_GOES_DISABLED_SHORT);
 
         condition = createCondition(AlertConditionCategory.AVAILABILITY,
             AlertConditionOperator.AVAIL_GOES_UNKNOWN.name(), null, null, null, null);
         pretty = getPrettyAlertConditionString(condition);
-        assert "Availability goes UNKNOWN".equals(pretty) : pretty;
+        check(AlertI18NResourceKeys.ALERT_AVAILABILITY_GOES_UNKNOWN);
         pretty = getShortPrettyAlertConditionString(condition);
-        assert "Avail goes UNKNOWN".equals(pretty) : pretty;
+        check(AlertI18NResourceKeys.ALERT_AVAILABILITY_GOES_UNKNOWN_SHORT);
 
     }
 
@@ -77,9 +81,10 @@ public class AlertManagerBeanTest {
         AlertCondition condition = createCondition(AlertConditionCategory.THRESHOLD, md.getDisplayName(), ">", 12.5d,
             null, md);
         pretty = getPrettyAlertConditionString(condition);
-        assert "Foo Prop > 12.5B".equals(pretty) : pretty;
+        String ref = String.format("Foo Prop > %2.1fB",12.5d);
+        assert ref.equals(pretty) : pretty;
         pretty = getShortPrettyAlertConditionString(condition);
-        assert "Foo Prop > 12.5B".equals(pretty) : pretty;
+        assert ref.equals(pretty) : pretty;
     }
 
     public void testPrettyPrintTHRESHOLD_Calltime() {
@@ -88,17 +93,19 @@ public class AlertManagerBeanTest {
 
         AlertCondition condition = createCondition(AlertConditionCategory.THRESHOLD, regex, ">", 12.5d, "MAX", md);
         pretty = getPrettyAlertConditionString(condition);
-        assert "Calltime Metric CT Prop MAX > 12.5B with calltime destination matching \"some.*(reg)?ex$\""
-            .equals(pretty) : pretty;
+        check(AlertI18NResourceKeys.ALERT_METRIC_CALLTIME_THRESHOLD_WITH_EXPR, "CT Prop", "MAX", ">",
+                TWELVE_DOT_5_B, regex);
         pretty = getShortPrettyAlertConditionString(condition);
-        assert "CT Prop MAX > 12.5B matching \"some.*(reg)?ex$\"".equals(pretty) : pretty;
+        check(AlertI18NResourceKeys.ALERT_METRIC_CALLTIME_THRESHOLD_WITH_EXPR_SHORT, "CT Prop", "MAX", ">",
+                TWELVE_DOT_5_B, regex);
 
         // no regex
         condition = createCondition(AlertConditionCategory.THRESHOLD, null, ">", 12.5d, "MAX", md);
         pretty = getPrettyAlertConditionString(condition);
-        assert "Calltime Metric CT Prop MAX > 12.5B".equals(pretty) : pretty;
+        check(AlertI18NResourceKeys.ALERT_METRIC_CALLTIME_THRESHOLD,"CT Prop","MAX",">", TWELVE_DOT_5_B);
         pretty = getShortPrettyAlertConditionString(condition);
-        assert "CT Prop MAX > 12.5B".equals(pretty) : pretty;
+        check(AlertI18NResourceKeys.ALERT_METRIC_CALLTIME_THRESHOLD_SHORT, "CT Prop", "MAX", ">",
+                TWELVE_DOT_5_B);
     }
 
     public void testPrettyPrintBASELINE() {
@@ -106,21 +113,21 @@ public class AlertManagerBeanTest {
         AlertCondition condition = createCondition(AlertConditionCategory.BASELINE, md.getDisplayName(), ">", 0.10d,
             "mean", md);
         pretty = getPrettyAlertConditionString(condition);
-        assert "Foo Prop > 10.0% of Baseline Mean Value".equals(pretty) : pretty;
+        check(AlertI18NResourceKeys.ALERT_BASELINE_MEAN,"Foo Prop",">", TEN_PERCENT);
         pretty = getShortPrettyAlertConditionString(condition);
-        assert "Foo Prop > 10.0% bl mean".equals(pretty) : pretty;
+        check(AlertI18NResourceKeys.ALERT_BASELINE_MEAN_SHORT,"Foo Prop",">", TEN_PERCENT);
 
         condition = createCondition(AlertConditionCategory.BASELINE, md.getDisplayName(), ">", 0.10d, "min", md);
         pretty = getPrettyAlertConditionString(condition);
-        assert "Foo Prop > 10.0% of Baseline Minimum Value".equals(pretty) : pretty;
+        check(AlertI18NResourceKeys.ALERT_BASELINE_MIN,"Foo Prop",">", TEN_PERCENT);
         pretty = getShortPrettyAlertConditionString(condition);
-        assert "Foo Prop > 10.0% bl min".equals(pretty) : pretty;
+        check(AlertI18NResourceKeys.ALERT_BASELINE_MIN_SHORT,"Foo Prop",">", TEN_PERCENT);
 
         condition = createCondition(AlertConditionCategory.BASELINE, md.getDisplayName(), ">", 0.10d, "max", md);
         pretty = getPrettyAlertConditionString(condition);
-        assert "Foo Prop > 10.0% of Baseline Maximum Value".equals(pretty) : pretty;
+        check(AlertI18NResourceKeys.ALERT_BASELINE_MAX,"Foo Prop",">", TEN_PERCENT);
         pretty = getShortPrettyAlertConditionString(condition);
-        assert "Foo Prop > 10.0% bl max".equals(pretty) : pretty;
+        check(AlertI18NResourceKeys.ALERT_BASELINE_MAX_SHORT,"Foo Prop",">", TEN_PERCENT);
     }
 
     public void testPrettyPrintCHANGE() {
@@ -128,9 +135,9 @@ public class AlertManagerBeanTest {
         AlertCondition condition = createCondition(AlertConditionCategory.CHANGE, md.getDisplayName(), null, null,
             null, md);
         pretty = getPrettyAlertConditionString(condition);
-        assert "Foo Prop Value Changed".equals(pretty) : pretty;
+        check(AlertI18NResourceKeys.ALERT_METRIC_CHANGED, "Foo Prop");
         pretty = getShortPrettyAlertConditionString(condition);
-        assert "Foo Prop Val Chg".equals(pretty) : pretty;
+        check(AlertI18NResourceKeys.ALERT_METRIC_CHANGED_SHORT, "Foo Prop");
     }
 
     public void testPrettyPrintCHANGE_Calltime() {
@@ -139,85 +146,100 @@ public class AlertManagerBeanTest {
 
         AlertCondition condition = createCondition(AlertConditionCategory.CHANGE, regex, "LO", 0.10d, "MIN", md);
         pretty = getPrettyAlertConditionString(condition);
-        assert "Calltime Metric CT Prop MIN shrinks by at least 10.0% with calltime destination matching \"some.*(reg)?ex$\""
-            .equals(pretty) : pretty;
+        String msg = AlertI18NFactory.getMessage(AlertI18NResourceKeys.ALERT_METRIC_CALLTIME_CHANGE_SHRINKS);
+        String ref = "Calltime Metric CT Prop MIN %s by at least %2.1f%% with calltime destination matching \"some.*(reg)?ex$\"";
+        String refs = "CT Prop MIN %s by %2.1f%% matching \"some.*(reg)?ex$\"";
+        assert String.format(ref,msg,10.0f).equals(pretty) : pretty ;
         pretty = getShortPrettyAlertConditionString(condition);
-        assert "CT Prop MIN shrinks by 10.0% matching \"some.*(reg)?ex$\"".equals(pretty) : pretty;
+        assert String.format(refs,msg,10.0f).equals(pretty) : pretty +  " \n<=> " +String.format(refs,msg,10.0f);
 
         condition = createCondition(AlertConditionCategory.CHANGE, regex, "CH", 0.10d, "MIN", md);
         pretty = getPrettyAlertConditionString(condition);
-        assert "Calltime Metric CT Prop MIN changes by at least 10.0% with calltime destination matching \"some.*(reg)?ex$\""
-            .equals(pretty) : pretty;
+        msg = AlertI18NFactory.getMessage(AlertI18NResourceKeys.ALERT_METRIC_CALLTIME_CHANGE_CHANGES);
+        assert String.format(ref,msg,10.0f).equals(pretty)  ;
         pretty = getShortPrettyAlertConditionString(condition);
-        assert "CT Prop MIN changes by 10.0% matching \"some.*(reg)?ex$\"".equals(pretty) : pretty;
+        assert String.format(refs,msg,10.0f).equals(pretty)  ;
+
 
         condition = createCondition(AlertConditionCategory.CHANGE, regex, "HI", 0.10d, "MIN", md);
+        msg = AlertI18NFactory.getMessage(AlertI18NResourceKeys.ALERT_METRIC_CALLTIME_CHANGE_GROWS);
         pretty = getPrettyAlertConditionString(condition);
-        assert "Calltime Metric CT Prop MIN grows by at least 10.0% with calltime destination matching \"some.*(reg)?ex$\""
-            .equals(pretty) : pretty;
+        assert String.format(ref,msg,10.0f).equals(pretty) : pretty ;
         pretty = getShortPrettyAlertConditionString(condition);
-        assert "CT Prop MIN grows by 10.0% matching \"some.*(reg)?ex$\"".equals(pretty) : pretty;
+        assert String.format(refs,msg,10.0f).equals(pretty) : pretty +  " \n<=> " +String.format(refs,msg,10.0f);
+
+        ref = "Calltime Metric CT Prop MAX %s by at least %2.1f%% with calltime destination matching \"some.*(reg)?ex$\"";
+        refs = "CT Prop MAX %s by %2.1f%% matching \"some.*(reg)?ex$\"";
 
         condition = createCondition(AlertConditionCategory.CHANGE, regex, "LO", 0.10d, "MAX", md);
+        msg = AlertI18NFactory.getMessage(AlertI18NResourceKeys.ALERT_METRIC_CALLTIME_CHANGE_SHRINKS);
         pretty = getPrettyAlertConditionString(condition);
-        assert "Calltime Metric CT Prop MAX shrinks by at least 10.0% with calltime destination matching \"some.*(reg)?ex$\""
-            .equals(pretty) : pretty;
+        assert String.format(ref,msg,10.0f).equals(pretty) : pretty ;
         pretty = getShortPrettyAlertConditionString(condition);
-        assert "CT Prop MAX shrinks by 10.0% matching \"some.*(reg)?ex$\"".equals(pretty) : pretty;
+        assert String.format(refs,msg,10.0f).equals(pretty) : pretty +  " \n<=> " +String.format(refs,msg,10.0f);
 
         condition = createCondition(AlertConditionCategory.CHANGE, regex, "CH", 0.10d, "MAX", md);
+        msg = AlertI18NFactory.getMessage(AlertI18NResourceKeys.ALERT_METRIC_CALLTIME_CHANGE_CHANGES);
         pretty = getPrettyAlertConditionString(condition);
-        assert "Calltime Metric CT Prop MAX changes by at least 10.0% with calltime destination matching \"some.*(reg)?ex$\""
-            .equals(pretty) : pretty;
+        assert String.format(ref,msg,10.0f).equals(pretty) : pretty ;
         pretty = getShortPrettyAlertConditionString(condition);
-        assert "CT Prop MAX changes by 10.0% matching \"some.*(reg)?ex$\"".equals(pretty) : pretty;
+        assert String.format(refs,msg,10.0f).equals(pretty) : pretty +  " \n<=> " +String.format(refs,msg,10.0f);
 
         condition = createCondition(AlertConditionCategory.CHANGE, regex, "HI", 0.10d, "MAX", md);
+        msg = AlertI18NFactory.getMessage(AlertI18NResourceKeys.ALERT_METRIC_CALLTIME_CHANGE_GROWS);
         pretty = getPrettyAlertConditionString(condition);
-        assert "Calltime Metric CT Prop MAX grows by at least 10.0% with calltime destination matching \"some.*(reg)?ex$\""
-            .equals(pretty) : pretty;
+        assert String.format(ref,msg,10.0f).equals(pretty) : pretty ;
         pretty = getShortPrettyAlertConditionString(condition);
-        assert "CT Prop MAX grows by 10.0% matching \"some.*(reg)?ex$\"".equals(pretty) : pretty;
+        assert String.format(refs,msg,10.0f).equals(pretty) : pretty +  " \n<=> " +String.format(refs,msg,10.0f);
+
+        ref = "Calltime Metric CT Prop AVG %s by at least %2.1f%% with calltime destination matching \"some.*(reg)?ex$\"";
+        refs = "CT Prop AVG %s by %2.1f%% matching \"some.*(reg)?ex$\"";
 
         condition = createCondition(AlertConditionCategory.CHANGE, regex, "LO", 0.10d, "AVG", md);
+        msg = AlertI18NFactory.getMessage(AlertI18NResourceKeys.ALERT_METRIC_CALLTIME_CHANGE_SHRINKS);
         pretty = getPrettyAlertConditionString(condition);
-        assert "Calltime Metric CT Prop AVG shrinks by at least 10.0% with calltime destination matching \"some.*(reg)?ex$\""
-            .equals(pretty) : pretty;
+        assert String.format(ref,msg,10.0f).equals(pretty) : pretty ;
         pretty = getShortPrettyAlertConditionString(condition);
-        assert "CT Prop AVG shrinks by 10.0% matching \"some.*(reg)?ex$\"".equals(pretty) : pretty;
+        assert String.format(refs,msg,10.0f).equals(pretty) : pretty +  " \n<=> " +String.format(refs,msg,10.0f);
 
         condition = createCondition(AlertConditionCategory.CHANGE, regex, "CH", 0.10d, "AVG", md);
+        msg = AlertI18NFactory.getMessage(AlertI18NResourceKeys.ALERT_METRIC_CALLTIME_CHANGE_CHANGES);
         pretty = getPrettyAlertConditionString(condition);
-        assert "Calltime Metric CT Prop AVG changes by at least 10.0% with calltime destination matching \"some.*(reg)?ex$\""
-            .equals(pretty) : pretty;
+        assert String.format(ref,msg,10.0f).equals(pretty) : pretty ;
         pretty = getShortPrettyAlertConditionString(condition);
-        assert "CT Prop AVG changes by 10.0% matching \"some.*(reg)?ex$\"".equals(pretty) : pretty;
+        assert String.format(refs,msg,10.0f).equals(pretty) : pretty +  " \n<=> " +String.format(refs,msg,10.0f);
 
         condition = createCondition(AlertConditionCategory.CHANGE, regex, "HI", 0.10d, "AVG", md);
+        msg = AlertI18NFactory.getMessage(AlertI18NResourceKeys.ALERT_METRIC_CALLTIME_CHANGE_GROWS);
         pretty = getPrettyAlertConditionString(condition);
-        assert "Calltime Metric CT Prop AVG grows by at least 10.0% with calltime destination matching \"some.*(reg)?ex$\""
-            .equals(pretty) : pretty;
+        assert String.format(ref,msg,10.0f).equals(pretty) : pretty ;
         pretty = getShortPrettyAlertConditionString(condition);
-        assert "CT Prop AVG grows by 10.0% matching \"some.*(reg)?ex$\"".equals(pretty) : pretty;
+        assert String.format(refs,msg,10.0f).equals(pretty) : pretty +  " \n<=> " +String.format(refs,msg,10.0f);
 
         // no regex
+        ref = "Calltime Metric CT Prop AVG %s by at least %2.1f%%";
+        refs = "CT Prop AVG %s by %2.1f%%";
+
         condition = createCondition(AlertConditionCategory.CHANGE, null, "LO", 0.10d, "AVG", md);
+        msg = AlertI18NFactory.getMessage(AlertI18NResourceKeys.ALERT_METRIC_CALLTIME_CHANGE_SHRINKS);
         pretty = getPrettyAlertConditionString(condition);
-        assert "Calltime Metric CT Prop AVG shrinks by at least 10.0%".equals(pretty) : pretty;
+        assert String.format(ref,msg,10.0f).equals(pretty) : pretty ;
         pretty = getShortPrettyAlertConditionString(condition);
-        assert "CT Prop AVG shrinks by 10.0%".equals(pretty) : pretty;
+        assert String.format(refs,msg,10.0f).equals(pretty) : pretty +  " \n<=> " +String.format(refs,msg,10.0f);
 
         condition = createCondition(AlertConditionCategory.CHANGE, null, "CH", 0.10d, "AVG", md);
+        msg = AlertI18NFactory.getMessage(AlertI18NResourceKeys.ALERT_METRIC_CALLTIME_CHANGE_CHANGES);
         pretty = getPrettyAlertConditionString(condition);
-        assert "Calltime Metric CT Prop AVG changes by at least 10.0%".equals(pretty) : pretty;
+        assert String.format(ref,msg,10.0f).equals(pretty) : pretty ;
         pretty = getShortPrettyAlertConditionString(condition);
-        assert "CT Prop AVG changes by 10.0%".equals(pretty) : pretty;
+        assert String.format(refs,msg,10.0f).equals(pretty) : pretty +  " \n<=> " +String.format(refs,msg,10.0f);
 
         condition = createCondition(AlertConditionCategory.CHANGE, null, "HI", 0.10d, "AVG", md);
+        msg = AlertI18NFactory.getMessage(AlertI18NResourceKeys.ALERT_METRIC_CALLTIME_CHANGE_GROWS);
         pretty = getPrettyAlertConditionString(condition);
-        assert "Calltime Metric CT Prop AVG grows by at least 10.0%".equals(pretty) : pretty;
+        assert String.format(ref,msg,10.0f).equals(pretty) : pretty ;
         pretty = getShortPrettyAlertConditionString(condition);
-        assert "CT Prop AVG grows by 10.0%".equals(pretty) : pretty;
+        assert String.format(refs,msg,10.0f).equals(pretty) : pretty +  " \n<=> " +String.format(refs,msg,10.0f);
     }
 
     public void testPrettyPrintTRAIT() {
@@ -225,25 +247,25 @@ public class AlertManagerBeanTest {
         AlertCondition condition = createCondition(AlertConditionCategory.TRAIT, md.getDisplayName(), null, null, null,
             md);
         pretty = getPrettyAlertConditionString(condition);
-        assert "Blah Trait Value Changed".equals(pretty) : pretty;
+        check(AlertI18NResourceKeys.ALERT_METRIC_CHANGED,"Blah Trait");
         pretty = getShortPrettyAlertConditionString(condition);
-        assert "Blah Trait Val Chg".equals(pretty) : pretty;
+        check(AlertI18NResourceKeys.ALERT_METRIC_CHANGED_SHORT,"Blah Trait");
     }
 
     public void testPrettyPrintCONTROL() {
         AlertCondition condition = createCondition(AlertConditionCategory.CONTROL, "opNameHere", null, null,
             OperationRequestStatus.FAILURE.name(), null);
         pretty = getPrettyAlertConditionString(condition);
-        assert "Operation [opNameHere] has status=[FAILURE]".equals(pretty) : pretty;
+        check(AlertI18NResourceKeys.ALERT_OPERATION,"opNameHere","FAILURE");
         pretty = getShortPrettyAlertConditionString(condition);
-        assert "Op [opNameHere]=FAILURE".equals(pretty) : pretty;
+        check(AlertI18NResourceKeys.ALERT_OPERATION_SHORT,"opNameHere","FAILURE");
 
         condition = createCondition(AlertConditionCategory.CONTROL, "opNameHere", null, null,
             OperationRequestStatus.SUCCESS.name(), null);
         pretty = getPrettyAlertConditionString(condition);
-        assert "Operation [opNameHere] has status=[SUCCESS]".equals(pretty) : pretty;
+        check(AlertI18NResourceKeys.ALERT_OPERATION,"opNameHere","SUCCESS");
         pretty = getShortPrettyAlertConditionString(condition);
-        assert "Op [opNameHere]=SUCCESS".equals(pretty) : pretty;
+        check(AlertI18NResourceKeys.ALERT_OPERATION_SHORT,"opNameHere","SUCCESS");
     }
 
     public void testPrettyPrintEVENT() {
@@ -303,27 +325,27 @@ public class AlertManagerBeanTest {
         AlertCondition condition = createCondition(AlertConditionCategory.RANGE, md.getDisplayName(), "<=", 1.0,
             "22.2", md);
         pretty = getPrettyAlertConditionString(condition);
-        assert "Foo Prop Value is Between 1.0B and 22.2B, Inclusive".equals(pretty) : pretty;
+        check(AlertI18NResourceKeys.ALERT_RANGE_INSIDE_INCL,"Foo Prop",String.format("%1.1fB",1d),String.format("%2.1fB",22.2d));
         pretty = getShortPrettyAlertConditionString(condition);
-        assert "Foo Prop Between 1.0B - 22.2B, incl".equals(pretty) : pretty;
+        check(AlertI18NResourceKeys.ALERT_RANGE_INSIDE_INCL_SHORT,"Foo Prop",String.format("%1.1fB",1d),String.format("%2.1fB",22.2d));
 
         condition = createCondition(AlertConditionCategory.RANGE, md.getDisplayName(), ">=", 1.0, "22.2", md);
         pretty = getPrettyAlertConditionString(condition);
-        assert "Foo Prop Value is Outside 1.0B and 22.2B, Inclusive".equals(pretty) : pretty;
+        check(AlertI18NResourceKeys.ALERT_RANGE_OUTSIDE_INCL,"Foo Prop",String.format("%1.1fB",1d),String.format("%2.1fB",22.2d));
         pretty = getShortPrettyAlertConditionString(condition);
-        assert "Foo Prop Outside 1.0B - 22.2B, incl".equals(pretty) : pretty;
+        check(AlertI18NResourceKeys.ALERT_RANGE_OUTSIDE_INCL_SHORT,"Foo Prop",String.format("%1.1fB",1d),String.format("%2.1fB",22.2d));
 
         condition = createCondition(AlertConditionCategory.RANGE, md.getDisplayName(), "<", 1.0, "22.2", md);
         pretty = getPrettyAlertConditionString(condition);
-        assert "Foo Prop Value is Between 1.0B and 22.2B, Exclusive".equals(pretty) : pretty;
+        check(AlertI18NResourceKeys.ALERT_RANGE_INSIDE_EXCL,"Foo Prop",String.format("%1.1fB",1d),String.format("%2.1fB",22.2d));
         pretty = getShortPrettyAlertConditionString(condition);
-        assert "Foo Prop Between 1.0B - 22.2B, excl".equals(pretty) : pretty;
+        check(AlertI18NResourceKeys.ALERT_RANGE_INSIDE_EXCL_SHORT,"Foo Prop",String.format("%1.1fB",1d),String.format("%2.1fB",22.2d));
 
         condition = createCondition(AlertConditionCategory.RANGE, md.getDisplayName(), ">", 1.0, "22.2", md);
         pretty = getPrettyAlertConditionString(condition);
-        assert "Foo Prop Value is Outside 1.0B and 22.2B, Exclusive".equals(pretty) : pretty;
+        check(AlertI18NResourceKeys.ALERT_RANGE_OUTSIDE_EXCL,"Foo Prop",String.format("%1.1fB",1d),String.format("%2.1fB",22.2d));
         pretty = getShortPrettyAlertConditionString(condition);
-        assert "Foo Prop Outside 1.0B - 22.2B, excl".equals(pretty) : pretty;
+        check(AlertI18NResourceKeys.ALERT_RANGE_OUTSIDE_EXCL_SHORT,"Foo Prop",String.format("%1.1fB",1d),String.format("%2.1fB",22.2d));
     }
 
     private String getPrettyAlertConditionString(AlertCondition condition) {
@@ -392,10 +414,23 @@ public class AlertManagerBeanTest {
     }
 
     private String extractCondition(String prettyString) {
+        String cond = AlertI18NFactory.getMessage(AlertI18NResourceKeys.ALERT_CONDITION_PATTERN); // Take i18n into account
         //System.out.println(prettyString);
-        Pattern pattern = Pattern.compile(" - Cond(?:ition)? 1: (.*)\n"); // short form has " - Cond 1: ...", long form has " - Condition 1: ..."
+        Pattern pattern = Pattern.compile("- " + cond + " 1: (.*)\n"); //en short form has " - Cond 1: ...", long form has " - Condition 1: ..."
         Matcher matcher = pattern.matcher(prettyString);
         assert matcher.find() : "could not find the condition string";
         return matcher.group(1);
     }
+
+    private void check(String msg) {
+        String ref = AlertI18NFactory.getMessage(msg);
+        assert ref != null : "Could not find reference message";
+        assert ref.equals(pretty) : pretty;
+    }
+
+    private void check(String msg, Object... args) {
+        String ref = AlertI18NFactory.getMessage(msg,args);
+        assert ref != null : "Could not find reference message";
+        assert ref.equals(pretty) : "Got : >>" + pretty + "<<   Expect: >>" + ref + "<<";
+    }
 }


commit 4bfd07c96ff3eeca302cb28871d6e7979e9035ec
Author: Heiko W. Rupp <hwr at redhat.com>
Date:   Tue Jul 10 18:27:22 2012 +0200

    Don't pass the query param in the path.

diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerBean.java
index a1645d3..e6f9335 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerBean.java
@@ -252,7 +252,7 @@ public class GroupHandlerBean extends AbstractRestBean implements GroupHandlerLo
                     def.getUnits().getName(),def.getDisplayType().toString());
             if (def.getDataType()== DataType.MEASUREMENT) {
                 UriBuilder uriBuilder = uriInfo.getBaseUriBuilder();
-                uriBuilder.path("/metric/data/group/{groupId}/{definitionId}?hideEmpty=true");
+                uriBuilder.path("/metric/data/group/{groupId}/{definitionId}");
                 URI uri = uriBuilder.build(id,def.getId());
                 Link link = new Link("metric",uri.toString());
                 schedule.addLink(link);


commit 1e102dc66868f2a07d572e56a560e8c60ac93933
Merge: cdd639d fce34e6
Author: Lukas Krejci <lkrejci at redhat.com>
Date:   Tue Jul 10 15:16:16 2012 +0200

    Merge remote-tracking branch 'origin/master' into lkrejci/modular-scripting



commit fce34e60ab6708ed7fc1d59f76fd78970e950aea
Author: Heiko W. Rupp <hwr at redhat.com>
Date:   Tue Jul 10 15:10:16 2012 +0200

    BZ 838686 -  Provide the server status (OperationMode) to unprivileged users.

diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/StatusHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/StatusHandlerBean.java
index a6fce0c..176b72e 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/StatusHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/StatusHandlerBean.java
@@ -23,25 +23,14 @@ import java.util.Map;
 import javax.ejb.EJB;
 import javax.ejb.Stateless;
 import javax.interceptor.Interceptors;
-import javax.ws.rs.core.GenericEntity;
 import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 
-import org.rhq.core.domain.alert.Alert;
-import org.rhq.core.domain.alert.AlertDefinition;
-import org.rhq.core.domain.criteria.AlertCriteria;
-import org.rhq.core.domain.criteria.AlertDefinitionCriteria;
-import org.rhq.core.domain.criteria.Criteria;
-import org.rhq.core.domain.criteria.ResourceCriteria;
-import org.rhq.core.domain.resource.Resource;
-import org.rhq.core.domain.resource.ResourceCategory;
-import org.rhq.core.domain.util.PageList;
-import org.rhq.enterprise.server.alert.AlertDefinitionManagerLocal;
-import org.rhq.enterprise.server.alert.AlertManagerLocal;
-import org.rhq.enterprise.server.measurement.MeasurementScheduleManagerLocal;
-import org.rhq.enterprise.server.resource.ResourceManagerLocal;
+import org.rhq.core.domain.cloud.Server;
+import org.rhq.enterprise.server.cloud.instance.ServerManagerLocal;
 import org.rhq.enterprise.server.rest.domain.Status;
+import org.rhq.enterprise.server.rest.domain.StringValue;
 import org.rhq.enterprise.server.system.SystemInfoManagerLocal;
 
 /**
@@ -55,11 +44,13 @@ public class StatusHandlerBean extends AbstractRestBean implements StatusHandler
 
     @EJB
     SystemInfoManagerLocal infoMgr;
+    @EJB
+    ServerManagerLocal serverManager;
 
     @Override
     public Response getStatus(HttpHeaders httpHeaders) {
 
-        Map<String,String> statusMap = infoMgr.getSystemInformation (caller);
+        Map<String,String> statusMap = infoMgr.getSystemInformation(caller);
         Status status = new Status();
         status.setValues(statusMap);
 
@@ -74,4 +65,11 @@ public class StatusHandlerBean extends AbstractRestBean implements StatusHandler
 
         return builder.build();
     }
+
+    @Override
+    public StringValue serverState() {
+        Server server = serverManager.getServer();
+        StringValue sv = new StringValue(server.getOperationMode().name());
+        return sv;
+    }
 }
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/StatusHandlerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/StatusHandlerLocal.java
index c03244d..f149d8c 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/StatusHandlerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/StatusHandlerLocal.java
@@ -31,6 +31,8 @@ import com.wordnik.swagger.annotations.ApiOperation;
 
 import org.jboss.resteasy.annotations.GZIP;
 
+import org.rhq.enterprise.server.rest.domain.StringValue;
+
 /**
  * Return some status information about the system
  * @author Heiko W. Rupp
@@ -42,9 +44,15 @@ import org.jboss.resteasy.annotations.GZIP;
 public interface StatusHandlerLocal {
 
     @GZIP
-    @ApiOperation(value="Retrieve the current configured state of the server along with some runtime information",
+    @ApiOperation(value="Retrieve the current configured state of the server along with some runtime information." +
+            "Caller must have MANAGE_SETTINGS to access this endpoint.",
     responseClass = "Map 'values' with map of key-value pairs describing the status")
     @GET
     @Path("/")
     Response getStatus(@Context HttpHeaders httpHeaders);
+
+    @GET
+    @Path("/server")
+    @ApiOperation(value = "Get the operation mode of this server")
+    StringValue serverState();
 }


commit cdd639d3a1324412aded642a31d8eb4d88c73115
Author: Lukas Krejci <lkrejci at redhat.com>
Date:   Tue Jul 10 13:54:35 2012 +0200

    Bumping Rhino to 1.7R4.

diff --git a/modules/enterprise/scripting/javascript/pom.xml b/modules/enterprise/scripting/javascript/pom.xml
index 11f3784..6009b1b 100644
--- a/modules/enterprise/scripting/javascript/pom.xml
+++ b/modules/enterprise/scripting/javascript/pom.xml
@@ -21,7 +21,7 @@
       <dependency>
          <groupId>org.mozilla</groupId>
          <artifactId>rhino</artifactId>
-         <version>1.7R3</version>
+         <version>1.7R4</version>
       </dependency>
 
    </dependencies>


commit 5d58a155a00362b6a5eb4e44ab69471ef577258b
Author: Lukas Krejci <lkrejci at redhat.com>
Date:   Tue Jul 10 13:54:23 2012 +0200

    Do not compile the scripts to new classes to save the permgen space.

diff --git a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/RhinoScriptEngine.java b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/RhinoScriptEngine.java
index 0456e94..e8069a6 100644
--- a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/RhinoScriptEngine.java
+++ b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/RhinoScriptEngine.java
@@ -193,12 +193,19 @@ public class RhinoScriptEngine  extends AbstractScriptEngine
                 }
             }
                         
+            protected Context makeContext() {
+                Context cx = super.makeContext();
+                cx.setOptimizationLevel(-1);
+                return cx;
+            }
+
             private Object superDoTopCall(final Callable callable,
                 final Context cx, final Scriptable scope,
                 final Scriptable thisObj, final Object[] args) {
                 
                 return super.doTopCall(callable, cx, scope, thisObj, args);
-            }            
+            }
+
         });
     }
     


commit 4344f843a8bdd16454def73be245ada673d259b9
Author: Lukas Krejci <lkrejci at redhat.com>
Date:   Tue Jul 10 13:53:34 2012 +0200

    Setting the require function to NOT be sandboxed (which doesn't make much
    difference) and make the require function use the correct scope so that it
    can resolve all the variables defined by the script engine.

diff --git a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/RhinoScriptEngine.java b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/RhinoScriptEngine.java
index a2dca22..0456e94 100644
--- a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/RhinoScriptEngine.java
+++ b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/RhinoScriptEngine.java
@@ -266,7 +266,8 @@ public class RhinoScriptEngine  extends AbstractScriptEngine
             
             requireBuilder = new RequireBuilder();            
             setModuleSourceProvider(moduleSourceProvider);
-                        
+            requireBuilder.setSandboxed(false);
+
             new LazilyLoadedCtor(topLevel, "JSAdapter",
                 "org.rhq.scripting.javascript.engine.JSAdapter",
                 false);
@@ -484,7 +485,7 @@ public class RhinoScriptEngine  extends AbstractScriptEngine
         Context cx = enterContext();
         try {
             cx.evaluateString(newScope, printSource, "print", 1, null);
-            requireBuilder.createRequire(cx, topLevel).install(newScope);
+            requireBuilder.createRequire(cx, newScope).install(newScope);
         } finally {
             Context.exit();
         }


commit 35bad6163b91cc55d2bee67be67f10a6aabdd4bb
Author: Lukas Krejci <lkrejci at redhat.com>
Date:   Tue Jul 10 13:51:40 2012 +0200

    Adding a script source provider able to handle the "file://" scheme.
    This is for the scripts to be able to access the file system using absolute
    paths.

diff --git a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/script/FileSystemScriptSourceProvider.java b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/script/FileSystemScriptSourceProvider.java
new file mode 100644
index 0000000..531222b
--- /dev/null
+++ b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/script/FileSystemScriptSourceProvider.java
@@ -0,0 +1,72 @@
+/*
+ * RHQ Management Platform
+ * Copyright 2012, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.client.script;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.Reader;
+import java.net.URI;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.rhq.scripting.ScriptSourceProvider;
+
+/**
+ * @author Lukas Krejci
+ */
+public class FileSystemScriptSourceProvider implements ScriptSourceProvider {
+
+    private static final Log LOG = LogFactory.getLog(FileSystemScriptSourceProvider.class);
+    private static final String SCHEME = "file";
+
+    @Override
+    public Reader getScriptSource(URI location) {
+        String scheme = location.getScheme();
+
+        //return early if we can't handle this URI
+        if (scheme != null && !SCHEME.equals(scheme)) {
+            return null;
+        }
+
+        String path = location.getSchemeSpecificPart();
+
+        if (scheme != null) {
+            // leave out the leading '//';
+            path = path.substring(2);
+        }
+
+        File f = new File(path);
+
+        try {
+            if (f.exists() && f.isFile() && f.canRead()) {
+                return new FileReader(f);
+            }
+        } catch (FileNotFoundException e) {
+            LOG.debug("File '" + f.getAbsolutePath() + "' seems to have disappeared while we were trying to open it.",
+                e);
+        }
+
+        return null;
+    }
+
+}
diff --git a/modules/enterprise/remoting/cli/src/main/resources/META-INF/services/org.rhq.scripting.ScriptSourceProvider b/modules/enterprise/remoting/cli/src/main/resources/META-INF/services/org.rhq.scripting.ScriptSourceProvider
index 9722a1c..a935c58 100644
--- a/modules/enterprise/remoting/cli/src/main/resources/META-INF/services/org.rhq.scripting.ScriptSourceProvider
+++ b/modules/enterprise/remoting/cli/src/main/resources/META-INF/services/org.rhq.scripting.ScriptSourceProvider
@@ -1 +1,2 @@
 org.rhq.enterprise.client.script.SamplesScriptSourceProvider
+org.rhq.enterprise.client.script.FileSystemScriptSourceProvider


commit 5f651047a7d1a147de9ec3f3cabcdba195b42483
Author: Lukas Krejci <lkrejci at redhat.com>
Date:   Tue Jul 10 13:50:30 2012 +0200

    Fixed the method resolution in the abstract rhq facade proxy.
    The old impl assumed the simplified class implements the original interface
    which is no longer true. I therefore added some auxiliary annotations on
    the simplified class and methods to aid in recovering the original method
    even though the simplified interface no longer implements the original
    interface.

diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/AbstractRhqFacadeProxy.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/AbstractRhqFacadeProxy.java
index bd37131..5a6d1c5 100644
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/AbstractRhqFacadeProxy.java
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/AbstractRhqFacadeProxy.java
@@ -22,7 +22,6 @@ import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Method;
 
 import org.rhq.bindings.util.InterfaceSimplifier;
-import org.rhq.core.domain.auth.Subject;
 
 /**
  * An abstract {@link InvocationHandler} to help the script users create proxies to actually call the
@@ -50,38 +49,21 @@ public abstract class AbstractRhqFacadeProxy<T extends RhqFacade> implements Inv
     }
     
     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
-        Class<?>[] interfaces = method.getDeclaringClass().getInterfaces();
-        Class<?> originalClass;
-        if (interfaces != null && interfaces.length > 0) {
-            originalClass = interfaces[0];
-        } else {
-            originalClass = method.getDeclaringClass();
-        }
-        
-        try {
-            // See if this method really exists or if its a simplified set of parameters
-            originalClass.getMethod(method.getName(), method.getParameterTypes());
-        } catch (NoSuchMethodException e) {
-            // If this was not in the original interface it must've been added in the Simplifier... add back the subject argument
-            Class<?>[] origParams = method.getParameterTypes();
-            Class<?>[] params = new Class<?>[origParams.length + 1];
-            params[0] = Subject.class;
-            System.arraycopy(method.getParameterTypes(), 0, params, 1, origParams.length);
-            
-            try {
-                method = originalClass.getMethod(method.getName(), params);
-            } catch (NoSuchMethodException e2) {
-                throw new IllegalArgumentException("Method " + method + " doesn't seem to be present on the interface "
-                    + originalClass + " neither in its original or simplified form.");
-            }
+        Method origMethod = InterfaceSimplifier.getOriginalMethod(method);
+
+        if (origMethod != null) {
+            if (InterfaceSimplifier.isSimplified(method)) {
+                // If this was not in the original interface it must've been added in the Simplifier... add back the subject argument
+                int numArgs = (null == args) ? 0 : args.length;
+                Object[] newArgs = new Object[numArgs + 1];
+                if (numArgs > 0) {
+                    System.arraycopy(args, 0, newArgs, 1, numArgs);
+                }
+                newArgs[0] = getRhqFacade().getSubject();
 
-            int numArgs = (null == args) ? 0 : args.length;
-            Object[] newArgs = new Object[numArgs + 1];
-            if (numArgs > 0) {
-                System.arraycopy(args, 0, newArgs, 1, numArgs);
+                args = newArgs;
             }
-            newArgs[0] = getRhqFacade().getSubject();
-            args = newArgs;
+            method = origMethod;
         }
         
         return doInvoke(proxy, method, args);
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/InterfaceSimplifier.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/InterfaceSimplifier.java
index dc07d4e..8ce7bc6 100644
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/InterfaceSimplifier.java
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/InterfaceSimplifier.java
@@ -18,6 +18,7 @@
  */
 package org.rhq.bindings.util;
 
+import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -69,6 +70,77 @@ public class InterfaceSimplifier {
 
     }
 
+    /**
+     * Returns the method on the original interface that the simplified interface with given method was generated from
+     * using the {@link #simplify(Class)} method (i.e. this method is kind of reverse to the {@link #simplify(Class)} 
+     * method).
+     * <p>
+     * The returned method may or may not have different signature from the supplied method - that depends on whether
+     * the {@link #simplify(Class)} simplified the method or not.
+     *  
+     * @param method the potentially simplified method
+     * @return null if the method doesn't come from a simplified class, otherwise a method on the original interface
+     * that the supplied method was generated from.
+     */
+    public static Method getOriginalMethod(Method method) {
+        SimplifiedClass simplifiedClass = method.getDeclaringClass().getAnnotation(SimplifiedClass.class);
+        if (simplifiedClass == null) {
+            return null;
+        } else {
+            SimplifiedMethod simplifiedMethod = method.getAnnotation(SimplifiedMethod.class);
+            Class<?> origClass = simplifiedClass.originalClass();
+
+            if (simplifiedMethod == null) {
+                try {
+                    return origClass.getMethod(method.getName(), method.getParameterTypes());
+                } catch (NoSuchMethodException e) {
+                    throw new IllegalStateException("Inconsisten interface simplification. The non-simplified method "
+                        + method + " should have had a counterpart with the exact signature on the interface "
+                        + origClass + " but it could not be found.", e);
+                }
+            } else {
+
+                Class<?>[] paramTypes = new Class<?>[method.getParameterTypes().length + 1];
+                paramTypes[0] = Subject.class;
+                System.arraycopy(method.getParameterTypes(), 0, paramTypes, 1, paramTypes.length - 1);
+
+                try {
+                    return origClass.getMethod(method.getName(), paramTypes);
+                } catch (NoSuchMethodException e) {
+                    throw new IllegalStateException("Inconsistent interface simplification. The simplified method "
+                        + method + " should have had a counterpart on the interface " + origClass
+                        + " but it couldn't be found.", e);
+                }
+            }
+        }
+    }
+
+    /**
+     * Determines whether given class is simplified or not. This method will return true for any class returned from 
+     * {@link #simplify(Class)}.
+     * 
+     * @param cls the class
+     * @return true if the class object was created by the {@link #simplify(Class)} method, false otherwise.
+     */
+    public static boolean isSimplified(Class<?> cls) {
+        return cls.getAnnotation(SimplifiedClass.class) != null;
+    }
+
+    /**
+     * Determines whether the method (declared on the simplified interface, i.e. 
+     * <code>isSimplified(method.getDeclaringClass()</code> returns true) has been "tampered with" by the simplifier or
+     * has been left intact.
+     * <p>
+     * If you want to get the original method that the supplied method corresponds to, use 
+     * the {@link #getOriginalMethod(Method)} method.
+     * 
+     * @param method the potentially simplified method present on a simplified class
+     * @return true if the method's signature has been modified by the simplifier, false otherwise.
+     */
+    public static boolean isSimplified(Method method) {
+        return method.getAnnotation(SimplifiedMethod.class) != null;
+    }
+
     public static Class<?> simplify(Class<?> intf) {
         try {
             ClassPool classPool = ClassPool.getDefault();
@@ -107,9 +179,10 @@ public class InterfaceSimplifier {
             AnnotationsAttribute annotations = (AnnotationsAttribute) originalClassFile
                 .getAttribute(AnnotationsAttribute.visibleTag);
             AnnotationsAttribute newAnnotations = copyAnnotations(annotations, constPool);
-            if (newAnnotations != null) {
-                newClassFile.addAttribute(newAnnotations);
-            }
+
+            //add our @Simplified annotation to the new class
+            newAnnotations = addSimplifiedClassAnnotation(originalClass.getName(), newAnnotations, constPool);
+            newClassFile.addAttribute(newAnnotations);
 
             //copy the generic signature of the class
             SignatureAttribute signature = (SignatureAttribute) originalClassFile.getAttribute(SignatureAttribute.tag);
@@ -160,6 +233,9 @@ public class InterfaceSimplifier {
                 annotations = copyAnnotations(annotations, constPool);
 
                 if (simplify) {
+                    //add the @SimplifiedMethod to the method annotations
+                    annotations = addSimplifiedMethodAnnotation(annotations, constPool);
+
                     if (signature != null) {
                         //fun, we need to modify the signature, too, because we have left out the parameter
                         MethodSignature sig = MethodSignature.parse(signature.getSignature());
@@ -475,4 +551,31 @@ public class InterfaceSimplifier {
             return bld.toString();
         }
     }
+
+    private static AnnotationsAttribute addSimplifiedClassAnnotation(String originalClassName,
+        AnnotationsAttribute annotations, ConstPool constPool) {
+
+        if (annotations == null) {
+            annotations = new AnnotationsAttribute(constPool, AnnotationsAttribute.visibleTag);
+        }
+
+        Annotation simplified = new Annotation(SimplifiedClass.class.getName(), constPool);
+        simplified.addMemberValue("originalClass", new ClassMemberValue(originalClassName, constPool));
+
+        annotations.addAnnotation(simplified);
+
+        return annotations;
+    }
+
+    private static AnnotationsAttribute addSimplifiedMethodAnnotation(AnnotationsAttribute annotations,
+        ConstPool constPool) {
+
+        if (annotations == null) {
+            annotations = new AnnotationsAttribute(constPool, AnnotationsAttribute.visibleTag);
+        }
+
+        annotations.addAnnotation(new Annotation(SimplifiedMethod.class.getName(), constPool));
+
+        return annotations;
+    }
 }
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/SimplifiedClass.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/SimplifiedClass.java
new file mode 100644
index 0000000..50edede
--- /dev/null
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/SimplifiedClass.java
@@ -0,0 +1,38 @@
+/*
+ * RHQ Management Platform
+ * Copyright 2012, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.bindings.util;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation to keep track of the original class on the simplified classes.
+ * Used by the {@link InterfaceSimplifier}.
+ * 
+ * @author Lukas Krejci
+ */
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target(ElementType.TYPE)
+public @interface SimplifiedClass {
+    Class<?> originalClass();
+}
\ No newline at end of file
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/SimplifiedMethod.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/SimplifiedMethod.java
new file mode 100644
index 0000000..290b807
--- /dev/null
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/SimplifiedMethod.java
@@ -0,0 +1,41 @@
+/*
+ * RHQ Management Platform
+ * Copyright 2012, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.bindings.util;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotates a method on a simplified class as being simplified.
+ * This is to distinguish the simplified methods on a simplified class
+ * from the non-simplified methods on that class.
+ * <p>
+ * Used by the {@link InterfaceSimplifier}.
+ * 
+ * @author Lukas Krejci
+ */
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target(ElementType.METHOD)
+public @interface SimplifiedMethod {
+
+}
diff --git a/modules/enterprise/binding/src/test/java/org/rhq/bindings/client/AbstractRhqFacadeProxyTest.java b/modules/enterprise/binding/src/test/java/org/rhq/bindings/client/AbstractRhqFacadeProxyTest.java
new file mode 100644
index 0000000..d1042df
--- /dev/null
+++ b/modules/enterprise/binding/src/test/java/org/rhq/bindings/client/AbstractRhqFacadeProxyTest.java
@@ -0,0 +1,185 @@
+/*
+ * RHQ Management Platform
+ * Copyright 2012, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.bindings.client;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.ArrayList;
+import java.util.EnumMap;
+import java.util.List;
+import java.util.Map;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import org.rhq.bindings.util.InterfaceSimplifier;
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.enterprise.server.resource.ResourceManagerRemote;
+
+/**
+ * @author Lukas Krejci
+ */
+ at Test
+public class AbstractRhqFacadeProxyTest {
+
+    public interface TestInterface {
+        void method();
+    }
+
+    public static class TestFacade implements RhqFacade {
+
+        private Subject subject;
+
+        @Override
+        public Subject getSubject() {
+            return subject;
+        }
+
+        public void setSubject(Subject subject) {
+            this.subject = subject;
+        }
+
+        @Override
+        public Subject login(String user, String password) throws Exception {
+            return subject;
+        }
+
+        @Override
+        public void logout() {
+            subject = null;
+        }
+
+        @Override
+        public boolean isLoggedIn() {
+            return subject != null;
+        }
+
+        @Override
+        public Map<RhqManager, Object> getScriptingAPI() {
+            EnumMap<RhqManager, Object> ret = new EnumMap<RhqManager, Object>(RhqManager.class);
+
+            for (RhqManager m : RhqManager.values()) {
+                Class<?> iface = InterfaceSimplifier.simplify(m.remote());
+                Object proxy = Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class<?>[] { iface },
+                    new TestProxy(this, m));
+                ret.put(m, proxy);
+            }
+
+            return ret;
+        }
+
+        @Override
+        public <T> T getProxy(Class<T> remoteApiIface) {
+            RhqManager m = RhqManager.forInterface(remoteApiIface);
+            if (m == null) {
+                throw new IllegalArgumentException();
+            }
+
+            return remoteApiIface.cast(Proxy.newProxyInstance(this.getClass().getClassLoader(),
+                new Class<?>[] { remoteApiIface }, new TestProxy(this, m)));
+        }
+
+    }
+
+    public static class InvocationRecord {
+        public Method method;
+        public Object[] args;
+    }
+
+    public static class TestProxy extends AbstractRhqFacadeProxy<TestFacade> {
+
+        private static List<InvocationRecord> pastInvocations = new ArrayList<InvocationRecord>();
+
+        /**
+         * @param facade
+         * @param manager
+         */
+        public TestProxy(TestFacade facade, RhqManager manager) {
+            super(facade, manager);
+        }
+
+        @Override
+        protected Object doInvoke(Object proxy, Method originalMethod, Object[] args) throws Throwable {
+            InvocationRecord inv = new InvocationRecord();
+            inv.method = originalMethod;
+            inv.args = args;
+
+            pastInvocations.add(inv);
+
+            return null;
+        }
+
+        public static List<InvocationRecord> getPastInvocations() {
+            return pastInvocations;
+        }
+
+        public static void clearPastInvocations() {
+            pastInvocations.clear();
+        }
+    }
+
+    public void testInvocationOfSimplifiedMethods() throws Exception {
+        TestProxy.clearPastInvocations();
+
+        TestFacade facade = new TestFacade();
+        Subject subject = new Subject();
+        
+        facade.setSubject(subject);
+        
+        Object resourceManager = facade.getScriptingAPI().get(RhqManager.ResourceManager);
+        
+        Method getResource = resourceManager.getClass().getMethod("getResource", int.class);
+
+        getResource.invoke(resourceManager, 1);
+
+        Assert.assertEquals(TestProxy.getPastInvocations().size(), 1, "Unexpected number of proxy invocations");
+
+        InvocationRecord inv = TestProxy.getPastInvocations().get(0);
+
+        Assert.assertEquals(inv.method, ResourceManagerRemote.class.getMethod("getResource", Subject.class, int.class),
+            "Unexpected method invoked.");
+
+        Assert.assertEquals(subject, inv.args[0], "Unexpected subject passed to the invocation.");
+        Assert.assertEquals(inv.args[1], new Integer(1), "Unexpected resource id passed to the invocation.");
+    }
+
+    public void testProxyRobustAgainstNonSimplifiedMethods() throws Exception {
+        TestProxy.clearPastInvocations();
+
+        Class<?> iface = InterfaceSimplifier.simplify(TestInterface.class);
+
+        Object proxy = Proxy.newProxyInstance(getClass().getClassLoader(), new Class<?>[] { iface },
+            new TestProxy(null, null));
+
+        Method charAt = proxy.getClass().getMethod("method");
+
+        charAt.invoke(proxy);
+
+        Assert.assertEquals(TestProxy.getPastInvocations().size(), 1, "Unexpected number of proxy invocations");
+
+        InvocationRecord inv = TestProxy.getPastInvocations().get(0);
+
+        Assert.assertEquals(inv.method, TestInterface.class.getMethod("method"),
+            "Unexpected method invoked.");
+
+        Assert.assertNull(inv.args, "Unexpected number of arguments passed to the invocation.");
+    }
+}
diff --git a/modules/enterprise/binding/src/test/java/org/rhq/bindings/util/InterfaceSimplifierTest.java b/modules/enterprise/binding/src/test/java/org/rhq/bindings/util/InterfaceSimplifierTest.java
index 4312153..8c581ce 100644
--- a/modules/enterprise/binding/src/test/java/org/rhq/bindings/util/InterfaceSimplifierTest.java
+++ b/modules/enterprise/binding/src/test/java/org/rhq/bindings/util/InterfaceSimplifierTest.java
@@ -243,7 +243,9 @@ public class InterfaceSimplifierTest {
         Class<?> iface = InterfaceSimplifier.simplify(Annotations.class);
 
         Annotation[] annotations = iface.getAnnotations();
-        Assert.assertEquals(annotations.length, 1, "UNexpected number of annotations on the 'Annotations' class.");
+        //we add the @SimplifiedClass annotation
+        Assert.assertEquals(annotations.length, Annotations.class.getAnnotations().length + 1,
+            "Unexpected number of annotations on the 'Annotations' class.");
         Annotation annotation = annotations[0];
         Assert.assertEquals(annotation.annotationType(), MyAnnotation.class,
             "Unexpected annotation type on the class 'Annotations");
@@ -284,8 +286,9 @@ public class InterfaceSimplifierTest {
 
         method = iface.getMethod("methodSimplified", int.class);
         annotations = method.getAnnotations();
+        //we add the @SimplifiedMethod on the method
         Assert
-            .assertEquals(annotations.length, 1, "Unexpected number of annotations on the 'methodSimplified' method.");
+            .assertEquals(annotations.length, 2, "Unexpected number of annotations on the 'methodSimplified' method.");
 
         annotation = annotations[0];
         Assert.assertEquals(annotation.annotationType(), MyAnnotation.class,
@@ -314,4 +317,35 @@ public class InterfaceSimplifierTest {
             .assertEquals(((MyAnnotation) annotation).parameter(), "d",
                 "Unexpected value of the 'parameter' of the annotation on the parameter p of 'Annotations.methodSimplified(int)'.");
     }
+
+    public void testOriginalMethodRetrieval() throws Exception {
+        Class<?> iface = InterfaceSimplifier.simplify(Generics.class);
+
+        Method simplifiedMethod = iface.getMethod("typeParametersSimplified", Type.class, int.class);
+        Method origMethod = InterfaceSimplifier.getOriginalMethod(simplifiedMethod);
+
+        Assert.assertTrue(InterfaceSimplifier.isSimplified(iface),
+            "Unable to determine that the simplified interface was simplified.");
+        Assert.assertTrue(InterfaceSimplifier.isSimplified(simplifiedMethod));
+        Assert.assertFalse(InterfaceSimplifier.isSimplified(String.class), "String class is NOT simplified.");
+        Assert.assertFalse(InterfaceSimplifier.isSimplified(Object.class.getMethod("toString")),
+            "Object.toString() is NOT simplified.");
+
+        Assert.assertEquals(origMethod.getDeclaringClass(), Generics.class,
+            "Unexpected declaring class of the original method.");
+        Assert.assertEquals(origMethod.getParameterTypes().length, simplifiedMethod.getParameterTypes().length + 1,
+            "Unexpected number of params on the original method.");
+        Assert.assertEquals(origMethod.getParameterTypes()[0], Subject.class,
+            "Unexpected first param of the original method.");
+
+        Method nonSimplifiedMethod = iface.getMethod("typeParameters", Type.class, int.class);
+        origMethod = InterfaceSimplifier.getOriginalMethod(nonSimplifiedMethod);
+
+        Assert.assertFalse(InterfaceSimplifier.isSimplified(nonSimplifiedMethod));
+
+        Assert.assertEquals(origMethod.getDeclaringClass(), Generics.class,
+            "Unexpected declaring class of the original method.");
+        Assert.assertEquals(origMethod.getParameterTypes(), nonSimplifiedMethod.getParameterTypes(),
+            "Unexpected params on the original method.");
+    }
 }


commit 12b6a37abf5be2f7dc0541563e70a8fe94590a08
Author: Heiko W. Rupp <hwr at redhat.com>
Date:   Tue Jul 10 12:33:58 2012 +0200

    Support metrics for compatible groups.

diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java
index 79012a1..615ba6c 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java
@@ -55,7 +55,10 @@ import org.jboss.cache.TreeCacheMBean;
 import org.rhq.core.domain.auth.Subject;
 import org.rhq.core.domain.resource.Resource;
 import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.core.domain.resource.group.GroupCategory;
+import org.rhq.core.domain.resource.group.ResourceGroup;
 import org.rhq.enterprise.server.resource.ResourceManagerLocal;
+import org.rhq.enterprise.server.resource.group.ResourceGroupManagerLocal;
 import org.rhq.enterprise.server.rest.domain.Link;
 import org.rhq.enterprise.server.rest.domain.ResourceWithType;
 
@@ -78,6 +81,8 @@ public class AbstractRestBean {
     TreeCacheMBean treeCache;
     @EJB
     ResourceManagerLocal resMgr;
+    @EJB
+    ResourceGroupManagerLocal resourceGroupManager;
 
     /**
      * Renders the passed object with the help of a freemarker template into a string. Freemarket templates
@@ -397,4 +402,26 @@ public class AbstractRestBean {
 */
         return res;
     }
+
+    /**
+     * Fetch the group with the passed id
+     *
+     * @param groupId id of the resource group
+     * @param requireCompatible Does the group have to be a compatible group?
+     * @return the group object if found
+     * @throws org.rhq.enterprise.server.rest.StuffNotFoundException if the group is not found (or not accessible by the caller)
+     * @throws IllegalArgumentException if a compatible group is required, but the found one is not a compatible one
+     */
+    protected ResourceGroup fetchGroup(int groupId, boolean requireCompatible) {
+        ResourceGroup resourceGroup;
+        resourceGroup = resourceGroupManager.getResourceGroup(caller, groupId);
+        if (resourceGroup == null)
+            throw new StuffNotFoundException("Group with id " + groupId);
+        if (requireCompatible) {
+            if (resourceGroup.getGroupCategory() != GroupCategory.COMPATIBLE) {
+                throw new IllegalArgumentException("Group with id " + groupId + " is no compatible group");
+            }
+        }
+        return resourceGroup;
+    }
 }
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerBean.java
index 5fa0089..a1645d3 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerBean.java
@@ -22,6 +22,8 @@ import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
 import org.rhq.core.domain.criteria.ResourceGroupCriteria;
+import org.rhq.core.domain.measurement.DataType;
+import org.rhq.core.domain.measurement.MeasurementDefinition;
 import org.rhq.core.domain.resource.Resource;
 import org.rhq.core.domain.resource.ResourceType;
 import org.rhq.core.domain.resource.group.GroupDefinition;
@@ -32,7 +34,6 @@ import org.rhq.enterprise.server.resource.ResourceManagerLocal;
 import org.rhq.enterprise.server.resource.ResourceTypeManagerLocal;
 import org.rhq.enterprise.server.resource.ResourceTypeNotFoundException;
 import org.rhq.enterprise.server.resource.group.ResourceGroupDeleteException;
-import org.rhq.enterprise.server.resource.group.ResourceGroupManagerLocal;
 import org.rhq.enterprise.server.resource.group.definition.GroupDefinitionManagerLocal;
 import org.rhq.enterprise.server.resource.group.definition.exception.GroupDefinitionAlreadyExistsException;
 import org.rhq.enterprise.server.resource.group.definition.exception.GroupDefinitionCreateException;
@@ -41,6 +42,7 @@ import org.rhq.enterprise.server.resource.group.definition.exception.GroupDefini
 import org.rhq.enterprise.server.rest.domain.GroupDefinitionRest;
 import org.rhq.enterprise.server.rest.domain.GroupRest;
 import org.rhq.enterprise.server.rest.domain.Link;
+import org.rhq.enterprise.server.rest.domain.MetricSchedule;
 import org.rhq.enterprise.server.rest.domain.ResourceWithType;
 
 /**
@@ -54,9 +56,6 @@ public class GroupHandlerBean extends AbstractRestBean implements GroupHandlerLo
     private final Log log = LogFactory.getLog(GroupHandlerBean.class);
 
     @EJB
-    ResourceGroupManagerLocal resourceGroupManager;
-
-    @EJB
     ResourceManagerLocal resourceManager;
 
     @EJB
@@ -94,7 +93,7 @@ public class GroupHandlerBean extends AbstractRestBean implements GroupHandlerLo
     public Response getGroup(int id, @Context Request request, @Context HttpHeaders headers,
                              @Context UriInfo uriInfo) {
 
-        ResourceGroup group = fetchGroup(id);
+        ResourceGroup group = fetchGroup(id, false);
 
         GroupRest groupRest = fillGroup(group, uriInfo);
 
@@ -149,7 +148,7 @@ public class GroupHandlerBean extends AbstractRestBean implements GroupHandlerLo
                                 @Context HttpHeaders headers,
                                 @Context UriInfo uriInfo) {
 
-        ResourceGroup resourceGroup = fetchGroup(id);
+        ResourceGroup resourceGroup = fetchGroup(id, false);
         resourceGroup.setName(in.getName());
         Response.ResponseBuilder builder;
 
@@ -182,7 +181,7 @@ public class GroupHandlerBean extends AbstractRestBean implements GroupHandlerLo
     public Response getResources(int id, @Context Request request, @Context HttpHeaders headers,
                                  @Context UriInfo uriInfo) {
 
-        ResourceGroup resourceGroup = fetchGroup(id);
+        ResourceGroup resourceGroup = fetchGroup(id, false);
 
         Set<Resource> resources = resourceGroup.getExplicitResources();
         List<ResourceWithType> rwtList = new ArrayList<ResourceWithType>(resources.size());
@@ -208,7 +207,7 @@ public class GroupHandlerBean extends AbstractRestBean implements GroupHandlerLo
     public Response addResource(int id, int resourceId,
                                 @Context Request request, @Context HttpHeaders headers, @Context UriInfo uriInfo) {
 
-        ResourceGroup resourceGroup = fetchGroup(id);
+        ResourceGroup resourceGroup = fetchGroup(id, false);
         Resource res = resourceManager.getResource(caller,resourceId);
         if (res==null)
             throw new StuffNotFoundException("Resource with id " + resourceId);
@@ -230,7 +229,7 @@ public class GroupHandlerBean extends AbstractRestBean implements GroupHandlerLo
     public Response removeResource(int id, int resourceId,
                                    @Context Request request, @Context HttpHeaders headers, @Context UriInfo uriInfo) {
 
-        ResourceGroup resourceGroup = fetchGroup(id);
+        ResourceGroup resourceGroup = fetchGroup(id, false);
         Resource res = resourceManager.getResource(caller,resourceId);
         if (res==null)
             throw new StuffNotFoundException("Resource with id " + resourceId);
@@ -241,21 +240,38 @@ public class GroupHandlerBean extends AbstractRestBean implements GroupHandlerLo
 
     }
 
-    /**
-     * Fetch the group with the passed id
-     * @param groupId id of the resource group
-     * @return the group object if found
-     * @throws StuffNotFoundException if the group is not found (or not accessible by the caller)
-     */
-    private ResourceGroup fetchGroup(int groupId) {
-        ResourceGroup resourceGroup;
-        resourceGroup = resourceGroupManager.getResourceGroup(caller, groupId);
-        if (resourceGroup==null)
-            throw new StuffNotFoundException("Group with id " + groupId);
-        return resourceGroup;
-    }
+    @Override
+    public Response getMetricDefinitionsForGroup(int id,  Request request,  HttpHeaders headers,
+                                                  UriInfo uriInfo) {
+        ResourceGroup group = fetchGroup(id, true);
+
+        Set<MeasurementDefinition> definitions = group.getResourceType().getMetricDefinitions();
+        List<MetricSchedule> schedules = new ArrayList<MetricSchedule>(definitions.size());
+        for (MeasurementDefinition def : definitions) {
+            MetricSchedule schedule = new MetricSchedule(def.getId(),def.getName(),def.getDisplayName(),false,def.getDefaultInterval(),
+                    def.getUnits().getName(),def.getDisplayType().toString());
+            if (def.getDataType()== DataType.MEASUREMENT) {
+                UriBuilder uriBuilder = uriInfo.getBaseUriBuilder();
+                uriBuilder.path("/metric/data/group/{groupId}/{definitionId}?hideEmpty=true");
+                URI uri = uriBuilder.build(id,def.getId());
+                Link link = new Link("metric",uri.toString());
+                schedule.addLink(link);
+            }
 
+            schedules.add(schedule);
+        }
 
+        MediaType mediaType = headers.getAcceptableMediaTypes().get(0);
+        Response.ResponseBuilder builder;
+        if (mediaType.equals(MediaType.TEXT_HTML_TYPE)) {
+            builder = Response.ok(renderTemplate("listMetricDefinitions",schedules));
+        }
+        else {
+            GenericEntity<List<MetricSchedule>> ret = new GenericEntity<List<MetricSchedule>>(schedules) {};
+            builder = Response.ok(ret);
+        }
+        return builder.build();
+    }
 
     private GroupRest fillGroup(ResourceGroup group, UriInfo uriInfo) {
 
@@ -270,10 +286,15 @@ public class GroupHandlerBean extends AbstractRestBean implements GroupHandlerLo
         UriBuilder uriBuilder = uriInfo.getBaseUriBuilder();
         uriBuilder.path("/group/{id}");
         URI uri = uriBuilder.build(group.getId());
-
         Link link = new Link("edit",uri.toASCIIString());
         gr.getLinks().add(link);
 
+        uriBuilder = uriInfo.getBaseUriBuilder();
+        uriBuilder.path("/group/{id}/metricDefinitions");
+        uri = uriBuilder.build(group.getId());
+        link = new Link("metricDefinitions",uri.toASCIIString());
+        gr.getLinks().add(link);
+
         return gr;
     }
 
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerLocal.java
index ac77cce..39e0c2a 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerLocal.java
@@ -57,6 +57,14 @@ public interface GroupHandlerLocal {
                              @Context UriInfo uriInfo);
 
 
+    @GET
+    @GZIP
+    @Path("{id}/metricDefinitions")
+    @ApiOperation(value = "Get the metric definitions for the compatible group with the passed id")
+    public Response getMetricDefinitionsForGroup(@ApiParam(value = "Id of the group") @PathParam("id") int id,
+                                 @Context Request request, @Context HttpHeaders headers,
+                                 @Context UriInfo uriInfo);
+
     @POST
     @Path("/")
     @ApiOperation(value = "Create a new group")
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerBean.java
index 7c664b7..163d48d 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerBean.java
@@ -71,10 +71,13 @@ import org.rhq.core.domain.measurement.MeasurementDataTrait;
 import org.rhq.core.domain.measurement.MeasurementDefinition;
 import org.rhq.core.domain.measurement.MeasurementSchedule;
 import org.rhq.core.domain.measurement.composite.MeasurementDataNumericHighLowComposite;
+import org.rhq.core.domain.resource.group.ResourceGroup;
 import org.rhq.core.util.jdbc.JDBCUtil;
 import org.rhq.enterprise.server.RHQConstants;
+import org.rhq.enterprise.server.measurement.MeasurementDefinitionManagerLocal;
 import org.rhq.enterprise.server.measurement.util.MeasurementDataManagerUtility;
 import org.rhq.enterprise.server.resource.ResourceManagerLocal;
+import org.rhq.enterprise.server.resource.group.ResourceGroupManagerLocal;
 import org.rhq.enterprise.server.rest.domain.Baseline;
 import org.rhq.enterprise.server.rest.domain.Link;
 import org.rhq.enterprise.server.rest.domain.MetricAggregate;
@@ -99,7 +102,11 @@ public class MetricHandlerBean  extends AbstractRestBean implements MetricHandle
     @EJB
     MeasurementScheduleManagerLocal scheduleManager;
     @EJB
+    MeasurementDefinitionManagerLocal definitionManager;
+    @EJB
     ResourceManagerLocal resMgr;
+    @EJB
+    ResourceGroupManagerLocal groupMgr;
     @PersistenceContext(unitName = RHQConstants.PERSISTENCE_UNIT_NAME)
     EntityManager em;
 
@@ -158,6 +165,56 @@ public class MetricHandlerBean  extends AbstractRestBean implements MetricHandle
         return builder.build();
     }
 
+    public Response getMetricDataForGroupAndDefinition(int groupId, int definitionId, long startTime, long endTime,
+            boolean hideEmpty, Request request, HttpHeaders headers) {
+
+        if (startTime==0) {
+            endTime = System.currentTimeMillis();
+            startTime = endTime - EIGHT_HOURS;
+        }
+
+        MediaType mediaType = headers.getAcceptableMediaTypes().get(0);
+        boolean isHtml = mediaType.equals(MediaType.TEXT_HTML_TYPE);
+
+        fetchGroup(groupId,true); // Make sure the group exists and is compatible
+        MeasurementDefinition definition = definitionManager.getMeasurementDefinition(caller,definitionId);
+        if (definition==null) {
+            throw new StuffNotFoundException("There is no definition with id " + definitionId);
+        }
+
+        MeasurementAggregate aggr = dataManager.getAggregate(caller, groupId, definitionId, startTime, endTime);
+        MetricAggregate res = new MetricAggregate(definitionId, aggr.getMin(),aggr.getAvg(),aggr.getMax());
+        res.setGroup(true);
+
+        List<List<MeasurementDataNumericHighLowComposite>> listList = dataManager.findDataForCompatibleGroup(caller,
+                groupId,definitionId,startTime,endTime,60); // TODO number of points
+
+        if (listList.isEmpty()) {
+            throw new StuffNotFoundException("Data for group with id " + groupId + " and definition " + definitionId);
+        }
+        List<MeasurementDataNumericHighLowComposite> list = listList.get(0);
+        if (!listList.isEmpty()) {
+            fill(res, list,definitionId,hideEmpty,isHtml);
+        }
+
+        CacheControl cc = new CacheControl();
+        int maxAge = (int) (definition.getDefaultInterval() / 1000L)/2; // millis  ; half of schedule interval
+        cc.setMaxAge(maxAge); // these are seconds
+        cc.setPrivate(false);
+        cc.setNoCache(false);
+
+        Response.ResponseBuilder builder;
+        if (isHtml) {
+            String htmlString = renderTemplate("metricData", res);
+            builder = Response.ok(htmlString,mediaType);
+        }
+        else
+            builder= Response.ok(res,mediaType);
+        builder.cacheControl(cc);
+
+        return builder.build();
+    }
+
     /**
      * Get the schedule for the passed schedule id
      *
@@ -419,6 +476,30 @@ public class MetricHandlerBean  extends AbstractRestBean implements MetricHandle
     }
 
     @Override
+    public List<MetricAggregate> getAggregatesForGroup(int groupId, long startTime, long endTime) {
+        long now = System.currentTimeMillis();
+        if (endTime==0)
+            endTime = now;
+        if (startTime==0) {
+            startTime = endTime - EIGHT_HOURS;
+        }
+        ResourceGroup group = fetchGroup(groupId, true);
+
+        Set<MeasurementDefinition> definitions = group.getResourceType().getMetricDefinitions();
+
+        List<MetricAggregate> ret = new ArrayList<MetricAggregate>(definitions.size());
+        for (MeasurementDefinition def : definitions) {
+            if (def.getDataType()==DataType.MEASUREMENT) {
+                MeasurementAggregate aggregate = dataManager.getAggregate(caller, groupId, def.getId(), startTime, endTime);
+                MetricAggregate res = new MetricAggregate(def.getId(), aggregate.getMin(),aggregate.getAvg(),aggregate.getMax());
+                res.setGroup(true);
+                ret.add(res);
+            }
+        }
+        return ret;
+    }
+
+    @Override
     public Response updateSchedule(int scheduleId, MetricSchedule in,HttpHeaders httpHeaders) {
         if (in==null)
             throw new StuffNotFoundException("Input is null"); // TODO other type of exception
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerLocal.java
index 8ec3d82..4ea9343 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerLocal.java
@@ -77,7 +77,7 @@ public interface MetricHandlerLocal {
                            @ApiParam(value="Start time since epoch.", defaultValue = "End time - 8h") @QueryParam("startTime")  long startTime,
                            @ApiParam(value="End time since epoch.", defaultValue = "Now") @QueryParam("endTime") long endTime,
                            @ApiParam("Number of buckets - currently fixed at 60") @QueryParam("dataPoints") @DefaultValue("60") int dataPoints,
-                                  @QueryParam("hideEmpty") boolean hideEmpty,
+                           @ApiParam(value = "Hide rows that are NaN only", defaultValue = "false") @QueryParam("hideEmpty") boolean hideEmpty,
                                   @Context Request request,
                                   @Context HttpHeaders headers);
 
@@ -98,10 +98,33 @@ public interface MetricHandlerLocal {
     @ApiOperation("Retrieve a list of high/low/average/data aggregate for the resource")
     @ApiError(code = 404, reason = NO_RESOURCE_FOR_ID)
     List<MetricAggregate> getAggregatesForResource(
-            @ApiParam("Resource to query") @PathParam("resourceId") int resourceId,
+            @ApiParam("Id of the resource to query") @PathParam("resourceId") int resourceId,
+            @ApiParam(value = "Start time since epoch.", defaultValue="End time - 8h") @QueryParam("startTime") long startTime,
+            @ApiParam(value = "End time since epoch.", defaultValue = "Now") @QueryParam("endTime") long endTime);
+
+    @GET
+    @Path("data/group/{groupId}")
+    @ApiOperation("Retrieve a list of high/low/average/data aggregate for the group")
+    List<MetricAggregate> getAggregatesForGroup(
+            @ApiParam("Id of the group to query") @PathParam("groupId") int groupId,
             @ApiParam(value = "Start time since epoch.", defaultValue="End time - 8h") @QueryParam("startTime") long startTime,
             @ApiParam(value = "End time since epoch.", defaultValue = "Now") @QueryParam("endTime") long endTime);
 
+    @GZIP
+    @GET
+    @Path("data/group/{groupId}/{definitionId}")
+    @ApiOperation(value = "Get the bucketized metric values for the metric definition of the group ")
+    @Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML,MediaType.TEXT_HTML})
+    Response getMetricDataForGroupAndDefinition(
+            @ApiParam("Id of the group to query") @PathParam("groupId") int groupId,
+            @ApiParam("Id of the metric definition to retrieve") @PathParam("definitionId") int definitionId,
+            @ApiParam(value = "Start time since epoch.", defaultValue="End time - 8h") @QueryParam("startTime") long startTime,
+            @ApiParam(value = "End time since epoch.", defaultValue = "Now") @QueryParam("endTime") long endTime,
+            @ApiParam(value = "Hide rows that are NaN only", defaultValue = "false") @QueryParam("hideEmpty") boolean hideEmpty,
+            @Context Request request,
+            @Context HttpHeaders headers);
+
+
     /**
      * Get information about the schedule
      * @param scheduleId id of the schedule
@@ -169,7 +192,7 @@ public interface MetricHandlerLocal {
      * @param point Datapoint of class NumericDataPoint
      * @param headers Injected HTTP headers
      * @param uriInfo Injected info about the uri
-     * @return
+     * @return Created response
      */
     @PUT
     @Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/MetricAggregate.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/MetricAggregate.java
index 4f17e61..46605cf 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/MetricAggregate.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/MetricAggregate.java
@@ -25,7 +25,7 @@ import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlRootElement;
 
 /**
- * Raw data that could be used to draw a chart
+ * Metric data that could be used to draw a chart
  * @author Heiko W. Rupp
  */
 @XmlRootElement
@@ -39,6 +39,7 @@ public class MetricAggregate {
     List<DataPoint> dataPoints;
     long minTimeStamp;
     long maxTimeStamp;
+    boolean isGroup = false;
 
     public MetricAggregate() {
         dataPoints = new ArrayList<DataPoint>();
@@ -127,6 +128,14 @@ public class MetricAggregate {
         this.maxTimeStamp = maxTimeStamp;
     }
 
+    public boolean isGroup() {
+        return isGroup;
+    }
+
+    public void setGroup(boolean group) {
+        isGroup = group;
+    }
+
     public static class DataPoint {
         long timeStamp;
         Double value;
diff --git a/modules/enterprise/server/jar/src/main/resources/rest_templates/group.ftl b/modules/enterprise/server/jar/src/main/resources/rest_templates/group.ftl
index 03a69bb..c88c072 100644
--- a/modules/enterprise/server/jar/src/main/resources/rest_templates/group.ftl
+++ b/modules/enterprise/server/jar/src/main/resources/rest_templates/group.ftl
@@ -31,7 +31,7 @@
             <td>Name</td><td>${var.name}</td>
         </tr>
         <tr>
-            <td>Id</td><td>${var.id}</td>
+            <td>Id</td><td>${var.id?c}</td>
         </tr>
         <tr>
             <td>Category</td><td>${var.category}</td>
@@ -57,4 +57,10 @@
         </tr>
     </table>
     <a href="/rest/1/group/${var.id?c}/resources.html">Resources</a><br/>
+    <#if (var.category?contains("compatible"))>
+        <a href="/rest/1/group/${var.id?c}/metricDefinitions.html">Metric Definitions</a><br/>
+    </#if>
+    <#if (var.dynaGroupDefinitionId >0)>
+        <a href="/rest/1/group/definition/${var.dynaGroupDefinitionId?c}.html">DynaGroup definition</a>
+    </#if>
 </html>
diff --git a/modules/enterprise/server/jar/src/main/resources/rest_templates/listMetricDefinitions.ftl b/modules/enterprise/server/jar/src/main/resources/rest_templates/listMetricDefinitions.ftl
new file mode 100644
index 0000000..5c87d5f
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/resources/rest_templates/listMetricDefinitions.ftl
@@ -0,0 +1,38 @@
+<#ftl >
+<#--
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 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.
+ */
+-->
+<#-- @ftlvariable name="var" type="java.util.List<org.rhq.enterprise.server.rest.domain.MetricSchedule>" -->
+<html>
+<#if (var?size>0) >
+<ul>
+    <#-- the next looks odd, but the incoming var is a list -->
+
+    <#list var as var>
+    <li>
+        <#include "metricDefinition.ftl"/>
+    </li>
+    </#list>
+
+</ul>
+<#else>
+   <strong>No Schedules have been set up</strong>
+</#if>
+<html>
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/main/resources/rest_templates/metricData.ftl b/modules/enterprise/server/jar/src/main/resources/rest_templates/metricData.ftl
index fdf2f88..61c9280 100644
--- a/modules/enterprise/server/jar/src/main/resources/rest_templates/metricData.ftl
+++ b/modules/enterprise/server/jar/src/main/resources/rest_templates/metricData.ftl
@@ -33,7 +33,13 @@
     </thead>
     <tr>
         <#assign sched=var.scheduleId/>
-        <td>ScheduleId</td><td><a href="/rest/1/metric/schedule/${sched?c}.html">${sched?c}</a></td>    </tr>
+        <#if var.isGroup()>
+            <td>DefinitionId</td><td>${sched?c}</a></td>
+        <#else>
+            <td>ScheduleId</td><td><a href="/rest/1/metric/schedule/${sched?c}.html">${sched?c}</a></td>
+        </#if>
+    </tr>
+
     <tr>
         <td>Min</td><td>
         <#if var.min?has_content>
@@ -64,7 +70,9 @@
         </td>
     </tr>
     <tr>
-        <td><a align="top" href="javascript:rhq.whisker(${sched?c},'one',400,200)">DataPoints</a></td><td>
+        <#if !var.isGroup()>
+            <td><a align="top" href="javascript:rhq.whisker(${sched?c},'one',400,200)">DataPoints</a></td><td>
+        </#if>
         <table>
             <thead>
             <tr>
diff --git a/modules/enterprise/server/jar/src/main/resources/rest_templates/metricDefinition.ftl b/modules/enterprise/server/jar/src/main/resources/rest_templates/metricDefinition.ftl
new file mode 100644
index 0000000..df277e1
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/resources/rest_templates/metricDefinition.ftl
@@ -0,0 +1,52 @@
+<#ftl >
+<#--
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 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.
+ */
+-->
+<#-- @ftlvariable name="var" type="org.rhq.enterprise.server.rest.domain.MetricSchedule" -->
+<html>
+    <table border=1>
+        <tr>
+            <th>Name</th><th>Value</th>
+        </tr>
+        <tr>
+            <td>Id</td><td>${var.scheduleId}</td>
+        </tr>
+        <tr>
+            <td>Internal Name</td><td>${var.scheduleName}</td>
+        </tr>
+        <tr>
+            <td>Name</td><td>${var.displayName}</td>
+        </tr>
+        <tr>
+            <td>Default collection interval (ms)</td><td>${var.collectionInterval}</td>
+        </tr>
+        <tr>
+            <td>Units</td><td>${var.unit}</td>
+        </tr>
+        <tr>
+            <td>Links</td>
+            <td>
+                <#list var.links as link>
+                    <li><a href="${link.href}.html">${link.rel}</a> </li>
+                </#list>
+            </td>
+        </tr>
+    </table>
+</html>
\ No newline at end of file


commit 5d33eb1fcb0114ebce98c834bc7e54e89f03eb8c
Author: Mike Thompson <mithomps at redhat.com>
Date:   Mon Jul 9 08:17:09 2012 -0700

    Add GZIP compression to REST reports.

diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/AlertDefinitionLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/AlertDefinitionLocal.java
index f42c190..d106ed6 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/AlertDefinitionLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/AlertDefinitionLocal.java
@@ -7,12 +7,14 @@ import javax.ws.rs.core.*;
 
 import com.wordnik.swagger.annotations.Api;
 import com.wordnik.swagger.annotations.ApiOperation;
+import org.jboss.resteasy.annotations.GZIP;
 
 @Path("/alertDefinitions")
 @Local
 @Api(basePath="http://localhost:7080/coregui/reports", value = "The Alert definitions report")
 public interface AlertDefinitionLocal {
 
+    @GZIP
     @GET
     @Produces({"text/csv"})
     @ApiOperation(value = "Export the AlertDefinitions in the system")
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/ConfigurationHistoryLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/ConfigurationHistoryLocal.java
index 1eb4d38..00079e7 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/ConfigurationHistoryLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/ConfigurationHistoryLocal.java
@@ -9,12 +9,14 @@ import javax.ws.rs.core.Context;
 import javax.ws.rs.core.StreamingOutput;
 
 import com.wordnik.swagger.annotations.Api;
+import org.jboss.resteasy.annotations.GZIP;
 
 @Path("/configurationHistory")
 @Local
 @Api(basePath="http://localhost:7080/coregui/reports", value = "The configuration history report")
 public interface ConfigurationHistoryLocal {
 
+    @GZIP
     @GET
     @Produces({"text/csv"})
     StreamingOutput configurationHistory(@Context HttpServletRequest request);
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/DriftComplianceLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/DriftComplianceLocal.java
index f9dbed3..f3da333 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/DriftComplianceLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/DriftComplianceLocal.java
@@ -28,12 +28,14 @@ import javax.ws.rs.core.Context;
 import javax.ws.rs.core.StreamingOutput;
 
 import com.wordnik.swagger.annotations.Api;
+import org.jboss.resteasy.annotations.GZIP;
 
 @Path("/driftCompliance")
 @Local
 @Api(basePath="http://localhost:7080/coregui/reports", value = "The drift compliance report")
 public interface DriftComplianceLocal {
 
+    @GZIP
     @GET
     @Produces({"text/csv", "application/xml"})
     StreamingOutput generateReport(
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/InventorySummaryLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/InventorySummaryLocal.java
index 4f09b7e..43f2ee1 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/InventorySummaryLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/InventorySummaryLocal.java
@@ -28,6 +28,7 @@ import javax.ws.rs.core.Context;
 import javax.ws.rs.core.StreamingOutput;
 
 import com.wordnik.swagger.annotations.Api;
+import org.jboss.resteasy.annotations.GZIP;
 
 @Path("/inventorySummary")
 @Local
@@ -45,6 +46,7 @@ public interface InventorySummaryLocal {
      * specified to generate the details version of the report.
      * @return An output stream that contains the CSV report.
      */
+    @GZIP
     @GET
     @Produces({"text/csv"})
     StreamingOutput generateReport(
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/PlatformUtilizationLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/PlatformUtilizationLocal.java
index cfda23a..7ee299a 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/PlatformUtilizationLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/PlatformUtilizationLocal.java
@@ -30,12 +30,14 @@ import javax.ws.rs.core.Context;
 import javax.ws.rs.core.StreamingOutput;
 
 import com.wordnik.swagger.annotations.Api;
+import org.jboss.resteasy.annotations.GZIP;
 
 @Path("/platformUtilization")
 @Local
 @Api(basePath="http://localhost:7080/coregui/reports", value = "The platform utilization report")
 public interface PlatformUtilizationLocal {
 
+    @GZIP
     @GET
     @Produces({"text/csv"})
     StreamingOutput generateReport(@Context HttpServletRequest request);
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/RecentAlertLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/RecentAlertLocal.java
index 6efe5b2..606be2b 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/RecentAlertLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/RecentAlertLocal.java
@@ -11,12 +11,14 @@ import javax.ws.rs.core.Context;
 import javax.ws.rs.core.StreamingOutput;
 
 import com.wordnik.swagger.annotations.Api;
+import org.jboss.resteasy.annotations.GZIP;
 
 @Path("/recentAlerts")
 @Local
 @Api(basePath="http://localhost:7080/coregui/reports", value = "The recent alerts report")
 public interface RecentAlertLocal {
 
+    @GZIP
     @GET
     @Produces({"text/csv"})
     StreamingOutput recentAlerts(
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/RecentOperationsLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/RecentOperationsLocal.java
index ec161b0..187ad1d 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/RecentOperationsLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/RecentOperationsLocal.java
@@ -11,12 +11,14 @@ import javax.ws.rs.core.Context;
 import javax.ws.rs.core.StreamingOutput;
 
 import com.wordnik.swagger.annotations.Api;
+import org.jboss.resteasy.annotations.GZIP;
 
 @Path("/recentOperations")
 @Local
 @Api(basePath="http://localhost:7080/coregui/reports", value = "The recent operations report")
 public interface RecentOperationsLocal {
 
+    @GZIP
     @GET
     @Produces({"text/csv"})
     StreamingOutput recentOperations(
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/SuspectMetricLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/SuspectMetricLocal.java
index 78ab8a1..217920f 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/SuspectMetricLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/reporting/SuspectMetricLocal.java
@@ -9,12 +9,14 @@ import javax.ws.rs.core.Context;
 import javax.ws.rs.core.StreamingOutput;
 
 import com.wordnik.swagger.annotations.Api;
+import org.jboss.resteasy.annotations.GZIP;
 
 @Path("/suspectMetrics")
 @Local
 @Api(basePath="http://localhost:7080/coregui/reports", value = "The suspect metrics report")
 public interface SuspectMetricLocal {
 
+    @GZIP
     @GET
     @Produces("text/csv")
     StreamingOutput suspectMetrics(@Context HttpServletRequest request);


commit 34c1b99a067c54c875b83a646c8cf309b32d0d34
Merge: 9287b7e e704b68
Author: Lukas Krejci <lkrejci at redhat.com>
Date:   Mon Jul 9 14:53:41 2012 +0200

    Merge remote-tracking branch 'origin/master' into lkrejci/modular-scripting



commit 9287b7e475adc4a182270624913b7cc926ff0664
Author: Lukas Krejci <lkrejci at redhat.com>
Date:   Mon Jul 9 14:50:00 2012 +0200

    Improvements to javascript code completion - we now are able to complete
    the properties/functions of native javascript objects. This makes
    code completion on required modules return the defined functions.

diff --git a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JavascriptCompletor.java b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JavascriptCompletor.java
index f90969a..d4d68bc 100644
--- a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JavascriptCompletor.java
+++ b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JavascriptCompletor.java
@@ -20,6 +20,7 @@
 package org.rhq.scripting.javascript;
 
 import java.beans.BeanInfo;
+import java.beans.IntrospectionException;
 import java.beans.Introspector;
 import java.beans.MethodDescriptor;
 import java.beans.PropertyDescriptor;
@@ -28,6 +29,7 @@ import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Type;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -40,6 +42,8 @@ import javax.script.ScriptContext;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.mozilla.javascript.Function;
+import org.mozilla.javascript.ScriptableObject;
 
 import org.rhq.scripting.CodeCompletion;
 import org.rhq.scripting.MetadataProvider;
@@ -231,8 +235,10 @@ public class JavascriptCompletor implements CodeCompletion {
             }
 
             if (matches.size() == 1 && matches.containsKey(call[0])) {
-                if (matches.get(call[0]).get(0) instanceof Method) {
-                    list.add("(" + (((Method) matches.get(call[0]).get(0)).getParameterTypes().length == 0 ? ")" : ""));
+                Object obj = matches.get(call[0]).get(0);
+                if (isMethod(obj)) {
+                    boolean close = obj instanceof Method && ((Method) obj).getParameterTypes().length == 0;
+                    list.add("(" + (close ? ")" : ""));
                 }
                 return call[0].length() + 1;
             }
@@ -446,53 +452,80 @@ public class JavascriptCompletor implements CodeCompletion {
         }
 
         try {
-            if (baseObjectClass.equals(Void.TYPE))
+            if (baseObjectClass.equals(Void.TYPE)) {
                 return found;
-
-            BeanInfo info = null;
-            if (baseObjectClass.isInterface() || baseObjectClass.equals(Object.class)) {
-                info = Introspector.getBeanInfo(baseObjectClass);
+            } else if (ScriptableObject.class.isAssignableFrom(baseObjectClass)) {
+                return findJavascriptContextMatches((ScriptableObject) baseObject, start);
             } else {
-                info = Introspector.getBeanInfo(baseObjectClass, Object.class);
+                return findJavaBeanContextMatches(baseObject, baseObjectClass, start);
             }
 
-            Set<Method> methodsCovered = new HashSet<Method>();
+        } catch (Exception e) {
+            LOG.info("Failure during code completion", e);
+            e.printStackTrace(output);
+        }
 
-            PropertyDescriptor[] descriptors = info.getPropertyDescriptors();
-            for (PropertyDescriptor desc : descriptors) {
-                if (desc.getName().startsWith(start) && (!IGNORED_METHODS.contains(desc.getName()))) {
+        return found;
+    }
 
-                    List<Object> list = found.get(desc.getName());
-                    if (list == null) {
-                        list = new ArrayList<Object>();
-                        found.put(desc.getName(), list);
-                    }
-                    list.add(desc);
+    private Map<String, List<Object>> findJavascriptContextMatches(ScriptableObject object, String start) {
+        HashMap<String, List<Object>> ret = new HashMap<String, List<Object>>();
+        for (Object o : object.getIds()) {
+            String key = o.toString();
 
-                    methodsCovered.add(desc.getReadMethod());
-                    methodsCovered.add(desc.getWriteMethod());
-                }
+            if (start == null || start.isEmpty() || key.startsWith(start)) {
+                Object target = object.get(key);
+                ret.put(key, new ArrayList<Object>(Arrays.asList(target)));
             }
+        }
 
-            MethodDescriptor[] methods = info.getMethodDescriptors();
-            for (MethodDescriptor desc : methods) {
-                if (desc.getName().startsWith(start) && !methodsCovered.contains(desc.getMethod())
-                    && !desc.getName().startsWith("_d") && !IGNORED_METHODS.contains(desc.getName())) {
+        return ret;
+    }
 
-                    Method m = desc.getMethod();
+    private Map<String, List<Object>> findJavaBeanContextMatches(Object baseObject, Class<?> baseObjectClass,
+        String start) throws IntrospectionException {
 
-                    List<Object> list = found.get(desc.getName());
-                    if (list == null) {
-                        list = new ArrayList<Object>();
-                        found.put(desc.getName(), list);
-                    }
-                    list.add(m);
+        Map<String, List<Object>> found = new HashMap<String, List<Object>>();
+
+        BeanInfo info = null;
+        if (baseObjectClass.isInterface() || baseObjectClass.equals(Object.class)) {
+            info = Introspector.getBeanInfo(baseObjectClass);
+        } else {
+            info = Introspector.getBeanInfo(baseObjectClass, Object.class);
+        }
+
+        Set<Method> methodsCovered = new HashSet<Method>();
+
+        PropertyDescriptor[] descriptors = info.getPropertyDescriptors();
+        for (PropertyDescriptor desc : descriptors) {
+            if (desc.getName().startsWith(start) && (!IGNORED_METHODS.contains(desc.getName()))) {
+
+                List<Object> list = found.get(desc.getName());
+                if (list == null) {
+                    list = new ArrayList<Object>();
+                    found.put(desc.getName(), list);
                 }
+                list.add(desc);
+
+                methodsCovered.add(desc.getReadMethod());
+                methodsCovered.add(desc.getWriteMethod());
             }
+        }
 
-        } catch (Exception e) {
-            LOG.info("Failure during code completion", e);
-            e.printStackTrace(output);
+        MethodDescriptor[] methods = info.getMethodDescriptors();
+        for (MethodDescriptor desc : methods) {
+            if (desc.getName().startsWith(start) && !methodsCovered.contains(desc.getMethod())
+                && !desc.getName().startsWith("_d") && !IGNORED_METHODS.contains(desc.getName())) {
+
+                Method m = desc.getMethod();
+
+                List<Object> list = found.get(desc.getName());
+                if (list == null) {
+                    list = new ArrayList<Object>();
+                    found.put(desc.getName(), list);
+                }
+                list.add(m);
+            }
         }
 
         return found;
@@ -546,4 +579,8 @@ public class JavascriptCompletor implements CodeCompletion {
             m.setAccessible(access);
         }
     }
+
+    private static boolean isMethod(Object object) {
+        return object != null && object instanceof Method || object instanceof Function;
+    }
 }


commit eb1ade1290dedc3c83ef12f8cdf6531df5433278
Author: Lukas Krejci <lkrejci at redhat.com>
Date:   Mon Jul 9 14:42:46 2012 +0200

    Make the summary print all the "summary" properties of the object, including the inherited ones from the super classes.

diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/SummaryFilter.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/SummaryFilter.java
index 871484f..7015068 100644
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/SummaryFilter.java
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/SummaryFilter.java
@@ -22,13 +22,11 @@
  */
 package org.rhq.bindings.util;
 
-import org.rhq.core.domain.util.Summary;
-
 import java.beans.BeanInfo;
+import java.beans.IndexedPropertyDescriptor;
 import java.beans.IntrospectionException;
 import java.beans.Introspector;
 import java.beans.PropertyDescriptor;
-import java.beans.IndexedPropertyDescriptor;
 import java.lang.reflect.Field;
 import java.lang.reflect.Method;
 import java.util.Arrays;
@@ -36,13 +34,15 @@ import java.util.Comparator;
 import java.util.HashMap;
 import java.util.Map;
 
+import org.rhq.core.domain.util.Summary;
+
 public class SummaryFilter {
 
 
 
     public PropertyDescriptor[] getPropertyDescriptors(Object object, boolean exportMode) throws IntrospectionException {
 
-        BeanInfo info = Introspector.getBeanInfo(object.getClass(), object.getClass().getSuperclass());
+        BeanInfo info = Introspector.getBeanInfo(object.getClass(), Object.class);
 
         final Map<PropertyDescriptor, Integer> indexes = new HashMap<PropertyDescriptor, Integer>();
 


commit e704b68d713a9bc956e826880d6fb0a93be322c9
Author: Heiko W. Rupp <hwr at redhat.com>
Date:   Mon Jul 9 12:11:27 2012 +0200

    BZ 837903 - remove thread ids from configuration and add an operation to retrieve them.

diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ThreadingComponent.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ThreadingComponent.java
new file mode 100644
index 0000000..9080262
--- /dev/null
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ThreadingComponent.java
@@ -0,0 +1,61 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 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.modules.plugins.jbossas7;
+
+import java.util.List;
+
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.pluginapi.operation.OperationResult;
+import org.rhq.modules.plugins.jbossas7.json.Operation;
+import org.rhq.modules.plugins.jbossas7.json.ReadAttribute;
+import org.rhq.modules.plugins.jbossas7.json.Result;
+
+/**
+ * Component class for Threading within the runtime
+ * @author Heiko W. Rupp
+ */
+public class ThreadingComponent extends BaseComponent<ThreadingComponent> {
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public OperationResult invokeOperation(String name,
+                                           Configuration parameters) throws  Exception {
+
+        if (name.equals("get-all-thread-ids")) {
+            Operation op = new ReadAttribute(getAddress(), "all-thread-ids");
+            Result res = getASConnection().execute(op);
+            OperationResult operationResult;
+            if (res.isSuccess()) {
+                List<Long> ids = (List<Long>) res.getResult();
+                operationResult = new OperationResult(ids.toString());
+            } else {
+                operationResult = new OperationResult();
+                String errorMessage = "Got no result back";
+                if (!res.isSuccess()) {
+                    errorMessage += ": " + res.getFailureDescription();
+                }
+                operationResult.setErrorMessage(errorMessage);
+            }
+            return operationResult;
+        }
+
+        return super.invokeOperation(name, parameters);
+    }
+}
diff --git a/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml
index e096c0e..77bacfb 100644
--- a/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml
@@ -7028,7 +7028,7 @@
 
     <service name="Threading"
              discovery="SubsystemDiscovery"
-             class="BaseComponent">
+             class="ThreadingComponent">
 
       <plugin-configuration>
         <c:simple-property name="path" readOnly="true" default="type=threading"/>
@@ -7124,6 +7124,16 @@
         </results>
       </operation>
 
+      <operation name="get-all-thread-ids"
+                 description="Get all live thread IDs. If a security manager is installed and the caller does not have ManagementPermission('monitor'), the result will be undefined."
+                 displayName="Get All thread ids">
+
+        <results>
+          <c:simple-property name="operationResult"
+                             description="List of thread ids"/>
+        </results>
+      </operation>
+
       <metric property="thread-count" description="The current number of live threads including both daemon and non-daemon threads."/>
       <metric property="peak-thread-count" description="The peak live thread count since the Java virtual machine started or peak was reset."/>
       <metric property="total-started-thread-count" description="The total number of threads created and also started since the Java virtual machine started."/>
@@ -7133,9 +7143,6 @@
       <resource-configuration>
         <c:simple-property name="thread-contention-monitoring-enabled" required="false" type="boolean" readOnly="false" description="Whether thread contention monitoring is enabled."/>
         <c:simple-property name="thread-cpu-time-enabled" required="false" type="boolean" readOnly="false" description="Whether thread CPU time measurement is enabled."/>
-        <c:list-property name="all-thread-ids" description="All live thread IDs. If a security manager is installed and the caller does not have ManagementPermission('monitor'), the result will be undefined." readOnly="true">
-          <c:simple-property name="all-thread-ids" readOnly="true"/>
-        </c:list-property>
         <c:simple-property name="thread-contention-monitoring-supported" required="false" type="boolean" readOnly="true" description="Whether the Java virtual machine supports thread contention monitoring."/>
         <c:simple-property name="thread-cpu-time-supported" required="false" type="boolean" readOnly="true" description="Whether the Java virtual machine implementation supports CPU time measurement for any thread."/>
         <c:simple-property name="current-thread-cpu-time-supported" required="false" type="boolean" readOnly="true" description="Whether the Java virtual machine supports CPU time measurement for the current thread."/>


commit dba33e0ce637e3e16217027ed25c3c28a5b5ef34
Author: Heiko W. Rupp <hwr at redhat.com>
Date:   Sun Jul 8 11:25:55 2012 +0200

    Don't fail if a resource has been deleted, but is still listed in favorites.

diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/UserHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/UserHandlerBean.java
index c4bf673..11ac93f 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/UserHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/UserHandlerBean.java
@@ -41,6 +41,7 @@ import org.rhq.core.domain.configuration.PropertySimple;
 import org.rhq.core.domain.resource.Resource;
 import org.rhq.enterprise.server.auth.SubjectManagerLocal;
 import org.rhq.enterprise.server.resource.ResourceManagerLocal;
+import org.rhq.enterprise.server.resource.ResourceNotFoundException;
 import org.rhq.enterprise.server.rest.domain.ResourceWithType;
 import org.rhq.enterprise.server.rest.domain.UserRest;
 
@@ -83,10 +84,18 @@ public class UserHandlerBean extends AbstractRestBean implements UserHandlerLoca
 
         MediaType mediaType = httpHeaders.getAcceptableMediaTypes().get(0);
         for (Integer id : favIds) {
-            Resource res = resourceManager.getResource(caller,id);
+            try {
+                Resource res = resourceManager.getResource(caller,id);
 
-            ResourceWithType rwt = fillRWT(res,uriInfo);
-            ret.add(rwt);
+                ResourceWithType rwt = fillRWT(res,uriInfo);
+                ret.add(rwt);
+            }
+            catch (Exception e) {
+                if (e.getCause()!=null && e.getCause() instanceof ResourceNotFoundException)
+                    log.debug("Favorite resource with id "+ id + " not found - not returning to the user");
+                else
+                    log.warn("Retrieving resource with id " + id + " failed: " + e.getLocalizedMessage());
+            }
         }
         Response.ResponseBuilder builder;
         if (mediaType.equals(MediaType.TEXT_HTML_TYPE)) {


commit 7329628734f5afc504c90c6b97e5315d8736c6a8
Author: Heiko W. Rupp <hwr at redhat.com>
Date:   Sat Jul 7 22:27:02 2012 +0200

    Allow more endpoints to return gzip'ed data

diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerLocal.java
index 4912ca1..c032481 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerLocal.java
@@ -39,6 +39,7 @@ import com.wordnik.swagger.annotations.Api;
 import com.wordnik.swagger.annotations.ApiOperation;
 import com.wordnik.swagger.annotations.ApiParam;
 
+import org.jboss.resteasy.annotations.GZIP;
 import org.jboss.resteasy.annotations.cache.Cache;
 
 import org.rhq.enterprise.server.rest.domain.AlertRest;
@@ -54,6 +55,7 @@ import org.rhq.enterprise.server.rest.domain.AlertDefinitionRest;
 @Api(value = "Deal with Alerts",description = "This api deals with alerts that have fired. It does not offer to create/update AlertDefinitions (yet)")
 public interface AlertHandlerLocal {
 
+    @GZIP
     @GET
     @Path("/")
     @ApiOperation(value = "List all alerts", multiValueResponse = true, responseClass = "List<AlertRest")
@@ -116,6 +118,7 @@ public interface AlertHandlerLocal {
     AlertDefinitionRest getDefinitionForAlert(@ApiParam("Id of the alert to show the definition") @PathParam("id") int alertId);
 
 
+    @GZIP
     @GET
     @Path("/definition")
     @ApiOperation("List all Alert Definition")
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerLocal.java
index 87026cd..ac77cce 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerLocal.java
@@ -24,6 +24,7 @@ import com.wordnik.swagger.annotations.ApiErrors;
 import com.wordnik.swagger.annotations.ApiOperation;
 import com.wordnik.swagger.annotations.ApiParam;
 
+import org.jboss.resteasy.annotations.GZIP;
 import org.jboss.resteasy.annotations.cache.Cache;
 
 import org.rhq.enterprise.server.rest.domain.GroupDefinitionRest;
@@ -39,6 +40,7 @@ import org.rhq.enterprise.server.rest.domain.GroupRest;
 @Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML,MediaType.TEXT_HTML, "application/yaml"})
 public interface GroupHandlerLocal {
 
+    @GZIP
     @GET
     @Path("/")
     @ApiOperation(value = "List all groups", multiValueResponse = true)
@@ -82,6 +84,7 @@ public interface GroupHandlerLocal {
                              @Context UriInfo uriInfo);
 
 
+    @GZIP
     @GET
     @Path("{id}/resources")
     @Cache(isPrivate = true,maxAge = 60)
@@ -114,12 +117,14 @@ public interface GroupHandlerLocal {
                              @Context Request request, @Context HttpHeaders headers,
                              @Context UriInfo uriInfo);
 
+    @GZIP
     @GET
     @Path("/definitions")
     @ApiOperation(value="List all existing GroupDefinitions",multiValueResponse = true)
     public Response getGroupDefinitions(@Context Request request, @Context HttpHeaders headers,
                                         @Context UriInfo uriInfo);
 
+    @GZIP
     @GET
     @Path("/definition/{id}")
     @Cache(isPrivate = true,maxAge = 60)
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerLocal.java
index 8cce452..dcf5943 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerLocal.java
@@ -38,6 +38,7 @@ import javax.ws.rs.core.UriInfo;
 import com.wordnik.swagger.annotations.ApiOperation;
 import com.wordnik.swagger.annotations.ApiParam;
 
+import org.jboss.resteasy.annotations.GZIP;
 import org.jboss.resteasy.annotations.cache.Cache;
 
 import org.rhq.enterprise.server.rest.domain.OperationRest;
@@ -63,6 +64,7 @@ public interface OperationsHandlerLocal {
                @Context Request request,
                @Context HttpHeaders httpHeaders);
 
+    @GZIP
     @GET
     @Path("definitions")
     @Cache(maxAge = 1200)
@@ -102,6 +104,7 @@ public interface OperationsHandlerLocal {
     public Response cancelOperation(
             @ApiParam("Id of the operation to remove") @PathParam("id") int operationId);
 
+    @GZIP
     @GET
     @Path("history/{id}")
     @ApiOperation("Return the outcome of the scheduled operation")
@@ -112,9 +115,10 @@ public interface OperationsHandlerLocal {
             @Context Request request,
             @Context HttpHeaders httpHeaders);
 
+    @GZIP
     @GET
     @Path("history")
-    @ApiOperation("Return the outcome of the scheduled operations")
+    @ApiOperation("Return the outcome of the executed operations for a resource")
     @Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML,MediaType.TEXT_HTML})
     public Response listHistory(
             @ApiParam("Id of a resource to limit to") @QueryParam("resourceId") int resourceId,
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/StatusHandlerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/StatusHandlerLocal.java
index cceb213..c03244d 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/StatusHandlerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/StatusHandlerLocal.java
@@ -29,6 +29,8 @@ import javax.ws.rs.core.Response;
 import com.wordnik.swagger.annotations.Api;
 import com.wordnik.swagger.annotations.ApiOperation;
 
+import org.jboss.resteasy.annotations.GZIP;
+
 /**
  * Return some status information about the system
  * @author Heiko W. Rupp
@@ -39,6 +41,7 @@ import com.wordnik.swagger.annotations.ApiOperation;
 @Produces({"application/json","application/xml","text/html"})
 public interface StatusHandlerLocal {
 
+    @GZIP
     @ApiOperation(value="Retrieve the current configured state of the server along with some runtime information",
     responseClass = "Map 'values' with map of key-value pairs describing the status")
     @GET
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/UserHandlerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/UserHandlerLocal.java
index 9893e8e..cdc3b5f 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/UserHandlerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/UserHandlerLocal.java
@@ -35,6 +35,7 @@ import com.wordnik.swagger.annotations.Api;
 import com.wordnik.swagger.annotations.ApiOperation;
 import com.wordnik.swagger.annotations.ApiParam;
 
+import org.jboss.resteasy.annotations.GZIP;
 import org.jboss.resteasy.annotations.cache.Cache;
 
 
@@ -48,6 +49,7 @@ import org.jboss.resteasy.annotations.cache.Cache;
 @Api(value="Api that deals with user related stuff")
 public interface UserHandlerLocal {
 
+    @GZIP
     @GET
     @Path("favorites/resource")
     @ApiOperation(value = "Return a list of favorite resources of the caller", multiValueResponse = true, responseClass = "ResourceWithType")


commit 6a23948ca9b2c87c3414ac78b4d20ee1a55b7fe5
Author: Heiko W. Rupp <hwr at redhat.com>
Date:   Fri Jul 6 10:06:15 2012 +0200

    Don't shut down the PC between tests and don't assume we have a MySQL server running.

diff --git a/modules/plugins/mysql/src/test/java/org/rhq/plugins/mysql/ComponentTest.java b/modules/plugins/mysql/src/test/java/org/rhq/plugins/mysql/ComponentTest.java
index 1e5b9e8..511d686 100644
--- a/modules/plugins/mysql/src/test/java/org/rhq/plugins/mysql/ComponentTest.java
+++ b/modules/plugins/mysql/src/test/java/org/rhq/plugins/mysql/ComponentTest.java
@@ -1,3 +1,22 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 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.plugins.mysql;
 
 import static org.testng.AssertJUnit.assertEquals;
@@ -329,7 +348,6 @@ public abstract class ComponentTest {
     protected void after() throws Exception {
         for (ResourceComponent c : components.keySet())
             c.stop();
-        PluginContainer.getInstance().shutdown();
     }
 
     /**
diff --git a/modules/plugins/mysql/src/test/java/org/rhq/plugins/mysql/PluginTest.java b/modules/plugins/mysql/src/test/java/org/rhq/plugins/mysql/PluginTest.java
index 3f35c65..498fe22 100644
--- a/modules/plugins/mysql/src/test/java/org/rhq/plugins/mysql/PluginTest.java
+++ b/modules/plugins/mysql/src/test/java/org/rhq/plugins/mysql/PluginTest.java
@@ -1,3 +1,22 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 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.plugins.mysql;
 
 import org.rhq.core.domain.configuration.Configuration;
@@ -34,8 +53,9 @@ public class PluginTest extends ComponentTest {
 
     public void test() throws Exception {
         manuallyAdd("MySql Server");
-        ResourceComponent resource = getComponent("MySql Server");
-        assertUp(resource);
+        ResourceComponent resourceComponent = getComponent("MySql Server");
+//        assertUp(resource); // TODO this requires a running mysql server
+        assert resourceComponent != null;
     }
 
 }


commit 771656ba9c19fad7e2a61e518bcb2ab9bd470977
Author: Mike Thompson <mithomps at redhat.com>
Date:   Thu Jul 5 16:37:29 2012 -0700

    Move the save button to bottom of screen on configuration tab for groups. This was just done for non-groups.

diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/configuration/GroupResourceConfigurationEditView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/configuration/GroupResourceConfigurationEditView.java
index 454cbf7..f6d6657 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/configuration/GroupResourceConfigurationEditView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/configuration/GroupResourceConfigurationEditView.java
@@ -56,6 +56,8 @@ import org.rhq.enterprise.gui.coregui.client.util.message.MessageCenter;
 import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableIButton;
 import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableVLayout;
 
+import static java.util.EnumSet.*;
+
 /**
  * A view for editing a group's configuration.
  *
@@ -70,6 +72,7 @@ public class GroupResourceConfigurationEditView extends LocatableVLayout impleme
     private ConfigurationDefinition configurationDefinition;
     private List<GroupMemberConfiguration> memberConfigurations;
 
+    private ToolStrip buttonbar;
     private ConfigurationEditor editor;
     private IButton saveButton;
 
@@ -86,31 +89,35 @@ public class GroupResourceConfigurationEditView extends LocatableVLayout impleme
     protected void onDraw() {
         super.onDraw();
 
-        ToolStrip toolStrip = new ToolStrip();
-        toolStrip.setWidth100();
-        toolStrip.setExtraSpace(10);
-        toolStrip.setMembersMargin(5);
-        toolStrip.setLayoutMargin(5);
+        refresh();
+
+        if (!this.resourcePermission.isConfigureWrite()) {
+            Message message = new Message(MSG.view_group_resConfig_edit_noperm(), Message.Severity.Info, of(
+                    Message.Option.Transient, Message.Option.Sticky));
+            CoreGUI.getMessageCenter().notify(message);
+        }
+    }
+
+    private ToolStrip createButtonBar() {
+        this.buttonbar = new ToolStrip();
+        buttonbar.setWidth100();
+        buttonbar.setExtraSpace(10);
+        buttonbar.setMembersMargin(5);
+        buttonbar.setLayoutMargin(5);
 
         this.saveButton = new LocatableIButton(this.extendLocatorId("Save"), MSG.common_button_save());
-        this.saveButton.setTooltip(MSG.view_group_resConfig_edit_saveTooltip());
         this.saveButton.addClickHandler(new ClickHandler() {
             public void onClick(ClickEvent clickEvent) {
                 save();
             }
         });
-        toolStrip.addMember(saveButton);
-
-        addMember(toolStrip);
-        refresh();
-
-        if (!this.resourcePermission.isConfigureWrite()) {
-            Message message = new Message(MSG.view_group_resConfig_edit_noperm(), Message.Severity.Info, EnumSet.of(
-                Message.Option.Transient, Message.Option.Sticky));
-            CoreGUI.getMessageCenter().notify(message);
-        }
+        buttonbar.addMember(saveButton);
+        // The button bar will remain hidden until the configuration has been successfully loaded.
+        buttonbar.setVisible(false);
+        return buttonbar;
     }
 
+
     @Override
     public void refresh() {
         if (this.refreshing) {
@@ -122,6 +129,8 @@ public class GroupResourceConfigurationEditView extends LocatableVLayout impleme
         if (editor != null) {
             editor.destroy();
             removeMember(editor);
+            buttonbar.destroy();
+            removeMember(buttonbar);
         }
         // TODO (ips): If editor != null, use editor.reload() instead.
 
@@ -145,7 +154,7 @@ public class GroupResourceConfigurationEditView extends LocatableVLayout impleme
         if (this.configurationDefinition == null) {
             final ResourceType type = this.group.getResourceType();
             ResourceTypeRepository.Cache.getInstance().getResourceTypes(new Integer[] { type.getId() },
-                EnumSet.of(ResourceTypeRepository.MetadataType.resourceConfigurationDefinition),
+                of(ResourceTypeRepository.MetadataType.resourceConfigurationDefinition),
                 new ResourceTypeRepository.TypesLoadedCallback() {
                     public void onTypesLoaded(Map<Integer, ResourceType> types) {
                         configurationDefinition = types.get(type.getId()).getResourceConfigurationDefinition();
@@ -188,6 +197,7 @@ public class GroupResourceConfigurationEditView extends LocatableVLayout impleme
                                             "The server did not return the configuration for one or more member resources.");
                                     }
                                     memberConfigurations.add(memberConfiguration);
+                                    addMember(createButtonBar());
                                 }
                                 initEditor();
                             }


commit 26959a31d8c37bcb86dc6a845b5707a277bff3cb
Author: Elias Ross <genman at noderunner.net>
Date:   Thu Jul 5 21:41:32 2012 +0200

    BZ 796983 - Improve discovery and use of column formatted metrics of database plugin

diff --git a/modules/plugins/database/pom.xml b/modules/plugins/database/pom.xml
index d4da519..24d0e1c 100644
--- a/modules/plugins/database/pom.xml
+++ b/modules/plugins/database/pom.xml
@@ -16,7 +16,12 @@
    <description>An abstract plugin for managing databases via JDBC</description>
 
    <dependencies>
-
+     <dependency>
+       <groupId>com.h2database</groupId>
+       <artifactId>h2</artifactId>
+       <!-- NOTE: The version is defined in the root POM's dependencyManagement section. -->
+       <scope>test</scope>
+     </dependency>
    </dependencies>
 
    <profiles>
diff --git a/modules/plugins/database/src/main/java/org/rhq/plugins/database/AbstractDatabaseComponent.java b/modules/plugins/database/src/main/java/org/rhq/plugins/database/AbstractDatabaseComponent.java
index 1170668..5976695 100644
--- a/modules/plugins/database/src/main/java/org/rhq/plugins/database/AbstractDatabaseComponent.java
+++ b/modules/plugins/database/src/main/java/org/rhq/plugins/database/AbstractDatabaseComponent.java
@@ -24,6 +24,7 @@ import org.rhq.core.pluginapi.inventory.InvalidPluginConfigurationException;
 import org.rhq.core.pluginapi.inventory.ResourceContext;
 
 /**
+ * Base class for database components.
  * @author Greg Hinkle
  */
 public abstract class AbstractDatabaseComponent<T extends DatabaseComponent<?>> implements DatabaseComponent {
@@ -46,4 +47,9 @@ public abstract class AbstractDatabaseComponent<T extends DatabaseComponent<?>>
     public void removeConnection() {
         this.resourceContext.getParentResourceComponent().removeConnection();
     }
+
+    @Override
+    public String toString() {
+        return getClass().getName() + " key=" + resourceContext.getResourceKey();
+    }
 }
\ No newline at end of file
diff --git a/modules/plugins/database/src/main/java/org/rhq/plugins/database/CustomTableComponent.java b/modules/plugins/database/src/main/java/org/rhq/plugins/database/CustomTableComponent.java
index e78d5c1..f2e8fa7 100644
--- a/modules/plugins/database/src/main/java/org/rhq/plugins/database/CustomTableComponent.java
+++ b/modules/plugins/database/src/main/java/org/rhq/plugins/database/CustomTableComponent.java
@@ -57,14 +57,20 @@ public class CustomTableComponent implements DatabaseComponent<DatabaseComponent
     }
 
     public String getTable() {
-        return this.context.getPluginConfiguration().getSimpleValue("table", null);
+        return this.context.getPluginConfiguration().getSimpleValue("table", "");
     }
 
     public AvailabilityType getAvailability() {
+        if (getTable().isEmpty()) {
+            // not set
+            return AvailabilityType.UP;
+        }
         Statement statement = null;
         try {
             statement = getConnection().createStatement();
-            statement.executeQuery("SELECT COUNT(*) FROM " + getTable());
+            statement.setMaxRows(1);
+            statement.setFetchSize(1);
+            statement.executeQuery("SELECT * FROM " + getTable()).close();
             return AvailabilityType.UP;
         } catch (SQLException e) {
             return AvailabilityType.DOWN;
@@ -75,8 +81,8 @@ public class CustomTableComponent implements DatabaseComponent<DatabaseComponent
 
     public void getValues(MeasurementReport report, Set<MeasurementScheduleRequest> metrics) throws Exception {
 
-        Configuration conf = this.context.getPluginConfiguration();
-        String query = conf.getSimpleValue("metricQuery", null);
+        Configuration config = this.context.getPluginConfiguration();
+        String query = config.getSimpleValue("metricQuery", null);
 
         if (query == null) {
             if (log.isTraceEnabled()) {
@@ -93,9 +99,18 @@ public class CustomTableComponent implements DatabaseComponent<DatabaseComponent
             return;
         }
 
-        query = CustomTableRowDiscoveryComponent.formatMessage(query, conf.getSimpleValue("key", null));
-
-        Map<String, Double> values = DatabaseQueryUtility.getNumericQueryValueMap(this, query);
+        query = CustomTableRowDiscoveryComponent.formatMessage(query, config.getSimpleValue("key", null));
+        String column = config.getSimpleValue("column", "");
+        Map<String, Double> values;
+        if (Boolean.parseBoolean(column)) {
+            // data in column format
+            values = DatabaseQueryUtility.getNumericQueryValues(this, query);
+        } else {
+            // data in row format
+            values = DatabaseQueryUtility.getNumericQueryValueMap(this, query);
+        }
+        if (log.isDebugEnabled())
+            log.debug("returned values " + values);
 
         // this is a for loop because the name of each column can be the name of the metric
         for (MeasurementScheduleRequest request : metrics) {
@@ -126,4 +141,4 @@ public class CustomTableComponent implements DatabaseComponent<DatabaseComponent
     public void removeConnection() {
         this.context.getParentResourceComponent().removeConnection();
     }
-}
\ No newline at end of file
+}
diff --git a/modules/plugins/database/src/main/java/org/rhq/plugins/database/CustomTableDiscoveryComponent.java b/modules/plugins/database/src/main/java/org/rhq/plugins/database/CustomTableDiscoveryComponent.java
index f76a659..aeab429 100644
--- a/modules/plugins/database/src/main/java/org/rhq/plugins/database/CustomTableDiscoveryComponent.java
+++ b/modules/plugins/database/src/main/java/org/rhq/plugins/database/CustomTableDiscoveryComponent.java
@@ -24,7 +24,10 @@ import java.sql.Statement;
 import java.util.Collections;
 import java.util.Set;
 
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.resource.ResourceType;
 import org.rhq.core.pluginapi.inventory.DiscoveredResourceDetails;
 import org.rhq.core.pluginapi.inventory.InvalidPluginConfigurationException;
 import org.rhq.core.pluginapi.inventory.ManualAddFacet;
@@ -33,45 +36,61 @@ import org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext;
 import org.rhq.core.util.jdbc.JDBCUtil;
 
 /**
- * Discovery for a generic component that can read data out of a table for monitoring purposes. Neccessary configuration
- * properties table - the name of the table to search for during inventory metricQuery - the query run to load metric
- * data name - the name of the resource description - the description of the resource
+ * Discovery for a generic component that can read data out of a table for
+ * monitoring purposes. Necessary configuration properties
+ * <li> table - the name of the table to search for during inventory. Note: If absent only
+ * supports manual adding.
+ * <li> metricQuery - the query run to load metric data
+ * <li> name - the name of the resource
+ * <li> description - the description of the resource
  *
  * @author Greg Hinkle
  */
 public class CustomTableDiscoveryComponent implements ManualAddFacet<DatabaseComponent<?>>,
     ResourceDiscoveryComponent<DatabaseComponent<?>> {
+
+    protected Log log = LogFactory.getLog(getClass());
+
     public Set<DiscoveredResourceDetails> discoverResources(
         ResourceDiscoveryContext<DatabaseComponent<?>> resourceDiscoveryContext)
         throws InvalidPluginConfigurationException, Exception {
+
+        Configuration config = resourceDiscoveryContext.getDefaultPluginConfiguration();
+        String table = config.getSimpleValue("table", "");
+        ResourceType rt = resourceDiscoveryContext.getResourceType();
+        String resourceName = config.getSimpleValue("name", rt.getName());
+        String resourceDescription = config.getSimpleValue("description", rt.getDescription());
+
+        if (table.isEmpty()) {
+            log.debug("'table' value not set, cannot discover " + resourceName);
+            return Collections.emptySet();
+        }
+
         Statement statement = null;
         try {
             Connection conn = resourceDiscoveryContext.getParentResourceComponent().getConnection();
-
-            Configuration config = resourceDiscoveryContext.getDefaultPluginConfiguration();
-            String table = config.getSimpleValue("table", null);
-            String resourceName = config.getSimpleValue("name", table);
-            String resourceDescription = config.getSimpleValue("description", null);
+            if (conn == null)
+                throw new InvalidPluginConfigurationException("cannot obtain connection from parent");
 
             statement = conn.createStatement();
-            statement.executeQuery("SELECT COUNT(*) FROM " + table);
-
+            statement.setMaxRows(1);
+            statement.setFetchSize(1);
+            // This is more efficient than 'count(*)'
+            // unless the JDBC driver fails to support setMaxRows or doesn't stream results
+            statement.executeQuery("SELECT * FROM " + table).close();
             DiscoveredResourceDetails details = new DiscoveredResourceDetails(
                 resourceDiscoveryContext.getResourceType(), table + resourceName, resourceName, null,
                 resourceDescription, config, null);
 
+            log.debug("discovered " + details);
             return Collections.singleton(details);
         } catch (SQLException e) {
+            log.debug("discovery failed " + e + " for " + table);
             // table not found, don't inventory
         } finally {
             JDBCUtil.safeClose(statement);
         }
 
-        if (!resourceDiscoveryContext.getPluginConfigurations().isEmpty()) {
-            return Collections.singleton(discoverResource(resourceDiscoveryContext.getPluginConfigurations().get(0),
-                resourceDiscoveryContext));
-        }
-
         return Collections.emptySet();
     }
 
@@ -79,14 +98,15 @@ public class CustomTableDiscoveryComponent implements ManualAddFacet<DatabaseCom
         ResourceDiscoveryContext<DatabaseComponent<?>> discoveryContext) throws InvalidPluginConfigurationException {
 
         Configuration config = pluginConfiguration;
-
         String table = config.getSimpleValue("table", null);
         String resourceName = config.getSimpleValue("name", table);
-        String resourceDescription = config.getSimpleValue("description", null);
+        String resourceDescription = config.getSimpleValue("description",
+                discoveryContext.getResourceType().getDescription());
+        String resourceVersion = config.getSimpleValue("version", null);
 
         DiscoveredResourceDetails details = new DiscoveredResourceDetails(discoveryContext.getResourceType(), table
-            + resourceName, resourceName, null, resourceDescription, config, null);
+            + resourceName, resourceName, resourceVersion, resourceDescription, config, null);
 
         return details;
     }
-}
\ No newline at end of file
+}
diff --git a/modules/plugins/database/src/main/java/org/rhq/plugins/database/CustomTableRowDiscoveryComponent.java b/modules/plugins/database/src/main/java/org/rhq/plugins/database/CustomTableRowDiscoveryComponent.java
index 56d9ddd..50da33b 100644
--- a/modules/plugins/database/src/main/java/org/rhq/plugins/database/CustomTableRowDiscoveryComponent.java
+++ b/modules/plugins/database/src/main/java/org/rhq/plugins/database/CustomTableRowDiscoveryComponent.java
@@ -38,9 +38,12 @@ import org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext;
 import org.rhq.core.util.jdbc.JDBCUtil;
 
 /**
- * Discovery for a generic component that can read data out of a table for monitoring purposes. Neccessary configuration
- * properties table - the name of the table to search for during inventory metricQuery - the query run to load metric
- * data name - the name of the resource description - the description of the resource
+ * Discovery for a generic component that can read data out of a table for
+ * monitoring purposes. Necessary configuration properties:
+ * <li> table - the name of the table to search for during inventory
+ * <li> keyColumn - the key of the table used to load metric data
+ * <li> name - the name of the resource
+ * <li> description - the description of the resource
  *
  * @author Greg Hinkle
  */
@@ -112,4 +115,4 @@ public class CustomTableRowDiscoveryComponent implements ResourceDiscoveryCompon
         message = message.replaceAll("\\{key\\}", key);
         return message;
     }
-}
\ No newline at end of file
+}
diff --git a/modules/plugins/database/src/main/java/org/rhq/plugins/database/DatabaseQueryUtility.java b/modules/plugins/database/src/main/java/org/rhq/plugins/database/DatabaseQueryUtility.java
index 5bab090..95e981d 100644
--- a/modules/plugins/database/src/main/java/org/rhq/plugins/database/DatabaseQueryUtility.java
+++ b/modules/plugins/database/src/main/java/org/rhq/plugins/database/DatabaseQueryUtility.java
@@ -24,8 +24,10 @@ import java.sql.ResultSet;
 import java.sql.ResultSetMetaData;
 import java.sql.SQLException;
 import java.sql.Statement;
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 import org.apache.commons.logging.Log;
@@ -34,11 +36,25 @@ import org.apache.commons.logging.LogFactory;
 import org.rhq.core.util.exception.ThrowableUtil;
 
 /**
+ * Various database (JDBC) query functions.
+ *
  * @author Greg Hinkle
  */
 public class DatabaseQueryUtility {
+
     private static final Log LOG = LogFactory.getLog(DatabaseQueryUtility.class);
 
+    private DatabaseQueryUtility() {}
+
+    /**
+     * Executes a database update.
+     *
+     * @param databaseComponent
+     * @param query
+     * @param parameters
+     * @return
+     * @throws SQLException
+     */
     public static int executeUpdate(DatabaseComponent databaseComponent, String query, Object... parameters)
         throws SQLException {
         PreparedStatement statement = null;
@@ -55,6 +71,10 @@ public class DatabaseQueryUtility {
         }
     }
 
+    /**
+     * Returns the result of a query as a single Double value.
+     * Returns {@link Double#NaN} if the query fails.
+     */
     public static Double getSingleNumericQueryValue(DatabaseComponent databaseComponent, String query,
         Object... parameters) {
         PreparedStatement statement = null;
@@ -77,13 +97,15 @@ public class DatabaseQueryUtility {
     }
 
     /**
-     * Used to read a single row of columns into a map
+     * Executes a query, returning the results as a map where the keys
+     * are the column names and values are the value of that column.
+     * Note depending on the database, the column names may be uppercase (Oracle) or lowercase.
      *
      * @param  databaseComponent
-     * @param  query
-     * @param  parameters
+     * @param  query SQL query string
+     * @param  parameters optional bind parameters
      *
-     * @return
+     * @return a map of query results
      */
     public static Map<String, Double> getNumericQueryValues(DatabaseComponent databaseComponent, String query,
         Object... parameters) {
@@ -122,8 +144,48 @@ public class DatabaseQueryUtility {
     }
 
     /**
-     * Used to access a set of rows as key, value pairs where the key is the first column and is a string and the second
-     * is a value and is numeric
+     * Returns a list of values, one per row, containing a map of column names to values of that row.
+     * Note depending on the database, the column names may be uppercase (Oracle) or lowercase.
+     * @param databaseComponent database to query
+     * @param query SQL query
+     * @param parameters parameters to bind to the query
+     *
+     * @throws SQLException if query fails
+     */
+    public static List<Map<String, Object>> getGridValues(DatabaseComponent databaseComponent, String query,
+        Object... parameters) throws SQLException {
+        PreparedStatement statement = null;
+        ResultSet resultSet = null;
+        List<Map<String, Object>> l = new ArrayList<Map<String, Object>>();
+        try {
+            statement = databaseComponent.getConnection().prepareStatement(query);
+            bindParameters(statement, parameters);
+
+            resultSet = statement.executeQuery();
+
+            while (resultSet.next()) {
+                Map<String, Object> row = new HashMap<String, Object>();
+                l.add(row);
+
+                ResultSetMetaData md = resultSet.getMetaData();
+                String[] names = getColumns(md);
+
+                for (String name : names) {
+                    Object o = resultSet.getObject(name);
+                    row.put(name, o);
+                }
+            }
+
+        } finally {
+            close(statement, resultSet);
+        }
+        return l;
+
+    }
+
+    /**
+     * Returns a mapping of rows as key-value pairs where the key is the
+     * first column (a string) and the second column is a value numeric.
      *
      * @param  databaseComponent the component to execute on
      * @param  query             the sql query to run
@@ -166,6 +228,9 @@ public class DatabaseQueryUtility {
         return Collections.emptyMap();
     }
 
+    /**
+     * Binds arguments to a prepared statement.
+     */
     private static void bindParameters(PreparedStatement statement, Object... parameters) throws SQLException {
         int i = 1;
         for (Object p : parameters) {
@@ -179,6 +244,9 @@ public class DatabaseQueryUtility {
         }
     }
 
+    /**
+     * Returns an array of strings as upper-case column names.
+     */
     public static String[] getColumns(ResultSetMetaData rsmd) throws SQLException {
         String[] names = new String[rsmd.getColumnCount()];
         for (int i = 0; i < rsmd.getColumnCount(); i++) {
@@ -188,11 +256,9 @@ public class DatabaseQueryUtility {
         return names;
     }
 
-    public static class StatementParameter {
-        private String name;
-        private String value;
-    }
-
+    /**
+     * Closes statements and result sets.
+     */
     public static void close(Statement statement, ResultSet resultSet) {
         if (resultSet != null) {
             try {
@@ -208,4 +274,4 @@ public class DatabaseQueryUtility {
             }
         }
     }
-}
\ No newline at end of file
+}
diff --git a/modules/plugins/database/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/database/src/main/resources/META-INF/rhq-plugin.xml
index 7d92ce5..d1bcbfa 100644
--- a/modules/plugins/database/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/database/src/main/resources/META-INF/rhq-plugin.xml
@@ -7,4 +7,61 @@
         pluginLifecycleListener="DatabasePluginLifecycleListener"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="urn:xmlns:rhq-plugin">
-</plugin>
\ No newline at end of file
+
+<!-- Example use: Create a plugin to query from an Oracle database.
+
+    <depends plugin="Oracle" useClasses="true"/>
+
+    <server name="Generic Query" class="org.rhq.plugins.database.CustomTableComponent"
+        discovery="org.rhq.plugins.database.CustomTableDiscoveryComponent"
+        description="Query the database for various results"
+        supportsManualAdd="true" singleton="false"
+        createDeletePolicy="both">
+        <runs-inside>
+            ... note: this works for any database component that implements 'org.rhq.plugins.database.DatabaseComponent'
+            <parent-resource-type name="Oracle Server" plugin="Oracle"/>
+        </runs-inside>
+        <plugin-configuration>
+            <c:simple-property name="table" type="string" default="sometable"/>
+            ... table is optional; if table is not defined discovery will be skipped
+            <c:simple-property name="metricQuery" type="string" default="select a, b from sometable"/>
+            <c:simple-property name="column" type="boolean" default="true"/>
+            ... use column default='false' for data appearing like:
+            col1 col2
+            ~~~~~~~~
+            a    123
+            b    323
+
+            and query 'select col1, col2 from sometable'
+        </plugin-configuration>
+        ... columns from Oracle appear uppercase ...
+        <metric property="A" displayName="A results" displayType="summary"
+            description="Number appearing in A column"
+            units="none" dataType="measurement"/>
+        <metric property="B" displayName="B results" displayType="summary"
+            description="Number appearing in B column"
+            units="none" dataType="measurement"/>
+    </server>
+
+    ... select rows from a database and create sub-components based on that key
+
+    <service name="Oracle User"
+        discovery="org.rhq.plugins.database.CustomTableRowDiscoveryComponent"
+        class="org.rhq.plugins.oracle.OracleUserComponent">
+
+        <plugin-configuration>
+            <c:simple-property name="table" default="DBA_USERS"/>
+            <c:simple-property name="metricQuery" default="SELECT {key} FROM DBA_USERS"/>
+            <c:simple-property name="keyColumn" default="username"/>
+            <c:simple-property name="name" default="{key}"/>
+            <c:simple-property name="description" default="Oracle User"/>
+        </plugin-configuration>
+
+          <metric property="connections" displayName="Total Connections" displayType="summary"/>
+          <metric property="active" displayName="Active Connections" displayType="summary"/>
+
+    </service>
+
+-->
+
+</plugin>
diff --git a/modules/plugins/database/src/test/java/org/rhq/plugins/database/ComponentTest.java b/modules/plugins/database/src/test/java/org/rhq/plugins/database/ComponentTest.java
new file mode 100644
index 0000000..b9622c6
--- /dev/null
+++ b/modules/plugins/database/src/test/java/org/rhq/plugins/database/ComponentTest.java
@@ -0,0 +1,545 @@
+package org.rhq.plugins.database;
+
+import static org.testng.AssertJUnit.assertEquals;
+import static org.testng.AssertJUnit.assertNotNull;
+import static org.testng.AssertJUnit.assertTrue;
+import static org.testng.AssertJUnit.fail;
+
+import java.io.File;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+
+import javax.xml.bind.JAXBElement;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.rhq.core.clientapi.agent.metadata.PluginMetadataManager;
+import org.rhq.core.clientapi.descriptor.AgentPluginDescriptorUtil;
+import org.rhq.core.clientapi.descriptor.configuration.ConfigurationProperty;
+import org.rhq.core.clientapi.descriptor.plugin.MetricDescriptor;
+import org.rhq.core.clientapi.descriptor.plugin.PluginDescriptor;
+import org.rhq.core.clientapi.descriptor.plugin.ResourceDescriptor;
+import org.rhq.core.clientapi.descriptor.plugin.ServerDescriptor;
+import org.rhq.core.clientapi.descriptor.plugin.ServiceDescriptor;
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.PropertySimple;
+import org.rhq.core.domain.measurement.AvailabilityType;
+import org.rhq.core.domain.measurement.MeasurementDataNumeric;
+import org.rhq.core.domain.measurement.MeasurementDataTrait;
+import org.rhq.core.domain.measurement.MeasurementDefinition;
+import org.rhq.core.domain.measurement.MeasurementReport;
+import org.rhq.core.domain.measurement.MeasurementSchedule;
+import org.rhq.core.domain.measurement.MeasurementScheduleRequest;
+import org.rhq.core.domain.resource.ProcessScan;
+import org.rhq.core.domain.resource.Resource;
+import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.core.pc.PluginContainer;
+import org.rhq.core.pc.PluginContainerConfiguration;
+import org.rhq.core.pc.availability.AvailabilityContextImpl;
+import org.rhq.core.pc.content.ContentContextImpl;
+import org.rhq.core.pc.event.EventContextImpl;
+import org.rhq.core.pc.event.EventManager;
+import org.rhq.core.pc.inventory.ResourceContainer;
+import org.rhq.core.pc.operation.OperationContextImpl;
+import org.rhq.core.pluginapi.availability.AvailabilityContext;
+import org.rhq.core.pluginapi.configuration.ConfigurationFacet;
+import org.rhq.core.pluginapi.content.ContentContext;
+import org.rhq.core.pluginapi.event.EventContext;
+import org.rhq.core.pluginapi.inventory.DiscoveredResourceDetails;
+import org.rhq.core.pluginapi.inventory.PluginContainerDeployment;
+import org.rhq.core.pluginapi.inventory.ProcessScanResult;
+import org.rhq.core.pluginapi.inventory.ResourceComponent;
+import org.rhq.core.pluginapi.inventory.ResourceContext;
+import org.rhq.core.pluginapi.inventory.ResourceDiscoveryComponent;
+import org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext;
+import org.rhq.core.pluginapi.measurement.MeasurementFacet;
+import org.rhq.core.pluginapi.operation.OperationContext;
+import org.rhq.core.system.ProcessInfo;
+import org.rhq.core.system.SystemInfo;
+import org.rhq.core.system.SystemInfoFactory;
+import org.rhq.core.system.pquery.ProcessInfoQuery;
+import org.testng.annotations.AfterSuite;
+import org.testng.annotations.AfterTest;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeSuite;
+
+/**
+ * Base class for RHQ Component Testing.
+ * Initializes a plugin configuration.
+ *
+ * Methods to override:
+ *
+ * {@link #setConfiguration(Configuration, ResourceType)}
+ */
+public abstract class ComponentTest {
+
+    /**
+     * Logging component.
+     */
+    protected final Log log = LogFactory.getLog(getClass());
+
+    private static File temp = new File(System.getProperty("java.io.tmpdir"));
+
+    /**
+     * Associates a resource component with a resource.
+     */
+    protected Map<ResourceComponent, Resource> components = new LinkedHashMap<ResourceComponent, Resource>();
+
+    /**
+     * Associates a name of a resource with a resource descriptor.
+     */
+    protected Map<String, ResourceDescriptor> descriptors = new LinkedHashMap<String, ResourceDescriptor>();
+
+    /**
+     * Associates a name of a resource with a type.
+     * This is useful for manually adding resources.
+     *
+     * @see #manuallyAdd(ResourceType, Configuration)
+     */
+    protected Map<String, ResourceType> resourceTypes = new LinkedHashMap<String, ResourceType>();
+
+    /**
+     * Event manager; used to obtain events.
+     */
+    private EventManager eventManager;
+
+    private PluginContainer pluginContainer = PluginContainer.getInstance();
+
+    private SystemInfo systemInfo = SystemInfoFactory.createSystemInfo();
+
+    /**
+     * Scan all processes before starting; false will disable this feature.
+     * Disabling is suggested for running tests against a remote instance.
+     */
+    private boolean processScan = true;
+
+    // TODO
+
+    private final PluginMetadataManager pmm = new PluginMetadataManager();
+    private final File temporaryDirectory = temp;
+    private final File dataDirectory = temp;
+    private final String pluginContainerName = "rhq";
+    private final OperationContext operationContext = new OperationContextImpl(0);
+    private final ContentContext contentContext = new ContentContextImpl(0);
+    private final Executor availCollectorThreadPool = Executors.newCachedThreadPool();
+    private PluginContainerDeployment pluginContainerDeployment = null;
+    private Resource platform;
+    private ResourceContainer platformContainer;
+    private List<ProcessInfo> processInfo = Collections.emptyList();
+    private PluginDescriptor pluginDescriptor;
+    private AvailabilityContext availabilityContext;
+
+
+    /**
+     * Constructs a new component test.
+     */
+    protected ComponentTest() {
+    }
+
+    /**
+     * Initializes the plugin container.
+     * This is run before {@link #before()}.
+     */
+    @BeforeSuite
+    protected void beforeSuite() {
+        // Speed up propagation of events by adjusting delay/period to 1 second
+        PluginContainerConfiguration pcc = new PluginContainerConfiguration();
+        pcc.setEventSenderInitialDelay(1);
+        pcc.setEventSenderPeriod(1);
+        pluginContainer.setConfiguration(pcc);
+        pluginContainer.initialize();
+        eventManager = pluginContainer.getEventManager();
+        platform = pluginContainer.getInventoryManager().getPlatform();
+        platformContainer = pluginContainer.getInventoryManager().getResourceContainer(platform);
+        if (platformContainer == null) {
+            platformContainer = new ResourceContainer(platform, getClass().getClassLoader());
+        }
+    }
+
+    /**
+     * Initializes all plugins defined in the system; using auto-discovery where possible.
+     * This is run once per test class.
+     */
+    @BeforeClass
+    protected void before() throws Exception {
+        if (processScan) {
+            processInfo = getProcessInfos();
+            if (processInfo == null)
+                processInfo = Collections.emptyList();
+            log.debug("Process Info " + processInfo);
+            for (ProcessInfo i : processInfo) {
+                log.debug(i.getBaseName() + " " + Arrays.toString(i.getCommandLine()));
+            }
+        }
+        Enumeration<URL> e = getClass().getClassLoader().getResources("META-INF/rhq-plugin.xml");
+        List<URL> l = Collections.list(e);
+        Collections.sort(l, new Comparator<URL>() {
+            @Override
+            public int compare(URL u1, URL u2) {
+                return u2.toString().compareTo(u1.toString());
+            }
+        });
+        for (URL url : l) {
+            log.debug("parse " + url);
+            InputStream is = url.openStream();
+            PluginDescriptor pd = AgentPluginDescriptorUtil.parsePluginDescriptor(is);
+            processPluginDescriptor(pd);
+            log.debug("pmm names " + pmm.getPluginNames());
+            buildDesc(pd.getServers());
+            buildDesc(pd.getServices());
+            is.close();
+        }
+    }
+
+    @AfterSuite
+    protected void afterSuite() {
+        pluginContainer.shutdown();
+    }
+
+    /**
+     * Process a plugin descriptor.
+     */
+    private void processPluginDescriptor(PluginDescriptor pd) throws Exception {
+        this.pluginDescriptor = pd;
+        Set<ResourceType> types = pmm.loadPlugin(pd);
+        mapResourceTypeNames(types);
+        log.info("Resource types: " + resourceTypes);
+        resources(types, platform, platformContainer.getResourceComponent(), platformContainer.getResourceContext());
+        log.info("ResourceComponent map: " + components);
+    }
+
+    private void mapResourceTypeNames(Set<ResourceType> types) {
+        for (ResourceType type : types) {
+            this.resourceTypes.put(type.getName(), type);
+            mapResourceTypeNames(type.getChildResourceTypes());
+        }
+    }
+
+    /**
+     * Manually create a component by name.
+     */
+    public ResourceComponent manuallyAdd(String name) throws Exception {
+        ResourceType resourceType = resourceTypes.get(name);
+        if (resourceType == null)
+            throw new IllegalStateException("no type " + name);
+        Configuration configuration = resourceType.getPluginConfigurationDefinition().getDefaultTemplate().createConfiguration();
+        setConfiguration(configuration, resourceType);
+        return manuallyAdd(resourceType, configuration);
+    }
+
+    /**
+     * Manually create a component by resource type.
+     */
+    public ResourceComponent manuallyAdd(ResourceType type, Configuration configuration) throws Exception {
+        return manuallyAdd(type, configuration, platformContainer.getResourceComponent());
+    }
+
+    /**
+     * Manually create a component by resource type, configuration, parent.
+     */
+    public ResourceComponent manuallyAdd(ResourceType type, Configuration configuration, ResourceComponent parent) throws Exception {
+        DiscoveredResourceDetails drd = new DiscoveredResourceDetails(type,
+                "key", "name", "ver", "desc", configuration, (ProcessInfo) null);
+        ResourceDiscoveryComponent c = null;
+        return createChild(drd, platform, configuration, parent, c);
+    }
+
+    private ResourceComponent createChild(DiscoveredResourceDetails drd,
+            Resource resource,
+            Configuration configuration,
+            ResourceComponent parentComponent,
+            ResourceDiscoveryComponent rdc) throws Exception
+    {
+        ResourceType type = pmm.getType(drd.getResourceType());
+
+        Resource cresource = new Resource();
+        cresource.setResourceType(type);
+        cresource.setPluginConfiguration(configuration);
+        cresource.setResourceKey(drd.getResourceKey());
+        cresource.setParentResource(resource);
+        cresource.setName(drd.getResourceName());
+        cresource.setVersion(drd.getResourceVersion());
+
+        String rclassname = pmm.getComponentClass(type);
+        ResourceComponent component = (ResourceComponent) Class.forName(rclassname).newInstance();
+
+        availabilityContext = new AvailabilityContextImpl(cresource,availCollectorThreadPool);
+        EventContext eventContext = new EventContextImpl(resource);
+        ResourceContext context = new ResourceContext(cresource, parentComponent,
+                null, rdc, systemInfo, temporaryDirectory, dataDirectory,
+                pluginContainerName, eventContext, operationContext, contentContext,
+                availabilityContext, pluginContainerDeployment);
+
+        component.start(context);
+        components.put(component, cresource);
+        resources(type.getChildResourceTypes(), cresource, component, context);
+        return component;
+    }
+
+    private void resources(Set<ResourceType> types, Resource parent, ResourceComponent component, ResourceContext context) throws Exception {
+        for (ResourceType type : types) {
+            String s = pmm.getDiscoveryClass(type);
+            if (s == null) {
+                throw new NullPointerException("no discovery " + type);
+            }
+            ResourceDiscoveryComponent rdc = (ResourceDiscoveryComponent) Class.forName(s).newInstance();
+            log.debug("rdc=" + rdc);
+            ResourceDiscoveryContext resourceDiscoveryContext = new ResourceDiscoveryContext(type, component,
+                    context, systemInfo,
+                    performProcessScans(type), new ArrayList<Configuration>(),
+                    pluginContainerName, pluginContainerDeployment);
+            Set<DiscoveredResourceDetails> drds = rdc.discoverResources(resourceDiscoveryContext);
+            for (DiscoveredResourceDetails drd : drds) {
+                log.debug("discovered " + drd);
+                ResourceType resourceType = drd.getResourceType();
+                setConfiguration(drd.getPluginConfiguration(), resourceType);
+                createChild(drd, parent, drd.getPluginConfiguration(), component, rdc);
+            }
+            if (drds.isEmpty()) {
+                log.warn("not discovered " + type);
+                context.getPluginConfiguration();
+            }
+        }
+
+    }
+
+    /**
+     * Called before the configuration is processed; override to set specific plugin parameters.
+     */
+    protected void setConfiguration(Configuration configuration, ResourceType resourceType) {
+    }
+
+    /**
+     * Stops all components, stops the plugin container.
+     */
+    @AfterTest
+    protected void after() throws Exception {
+        for (ResourceComponent c : components.keySet())
+            c.stop();
+//        PluginContainer.getInstance().shutdown();
+    }
+
+    /**
+     * Returns a measurement report.
+     */
+    public MeasurementReport getMeasurementReport(ResourceComponent component) throws Exception {
+        Resource resource = this.components.get(component);
+        ResourceType type = resource.getResourceType();
+        MeasurementReport report = new MeasurementReport();
+        Set<MeasurementScheduleRequest> s = new HashSet<MeasurementScheduleRequest>();
+        for (MeasurementDefinition md : type.getMetricDefinitions())
+            s.add(new MeasurementScheduleRequest(new MeasurementSchedule(md, resource)));
+        ((MeasurementFacet)component).getValues(report, s);
+        return report;
+    }
+
+    /**
+     * Returns the first resource component by resource name, then looks by matching resource type name,
+     * then asserts failure if not found.
+     */
+    public ResourceComponent getComponent(String name) {
+        for (Map.Entry<ResourceComponent, Resource> c : components.entrySet())
+            if (c.getValue().getName().equals(name))
+                return c.getKey();
+        for (Map.Entry<ResourceComponent, Resource> c : components.entrySet())
+            if (c.getValue().getResourceType().getName().equals(name))
+                return c.getKey();
+        fail("component not found " + name + " in " + components.entrySet());
+        return null;
+    }
+
+    /**
+     * Returns a resource matching this component.
+     */
+    public Resource getResource(ResourceComponent rc) {
+        Resource r = components.get(rc);
+        if (r == null)
+            throw new IllegalStateException();
+        return r;
+    }
+
+    /**
+     * Returns a resource matching this name.
+     */
+    public Resource getResource(String name) {
+        return getResource(getComponent(name));
+    }
+
+    /**
+     * Builds a new configuration for a resource type.
+     */
+    public Configuration getConfiguration(ResourceType resourceType) {
+        Configuration configuration = resourceType.getPluginConfigurationDefinition().getDefaultTemplate().createConfiguration();
+        setConfiguration(configuration, resourceType);
+        return configuration;
+    }
+
+    // ASSERT METHOD
+
+    /**
+     * From a measurement report, returns a measurement value, or asserts failure if no such value exists.
+     */
+    public static Double getValue(MeasurementReport report, String name) {
+        for (MeasurementDataNumeric m: report.getNumericData()) {
+            if (m.getName().equals(name)) {
+                return m.getValue();
+            }
+        }
+        fail("report does not incude " + name + " report " + report.getNumericData());
+        return null;
+    }
+
+    /**
+     * Asserts the resource component is available.
+     */
+    public static void assertUp(ResourceComponent component) {
+        assertEquals("up " + component, AvailabilityType.UP, component.getAvailability());
+    }
+
+    /**
+     * Asserts the resource component is unavailable.
+     */
+    public static void assertDown(ResourceComponent component) {
+        assertEquals("down " + component, AvailabilityType.DOWN, component.getAvailability());
+    }
+
+    /**
+     * Sets a configuration option.
+     */
+    public static void set(Configuration config, String name, String value) {
+        PropertySimple s = config.getSimple(name);
+        if (s == null) {
+            s = new PropertySimple(name, value);
+            config.put(s);
+        } else {
+            s.setStringValue(value);
+        }
+    }
+
+    private List<ProcessScanResult> performProcessScans(ResourceType serverType) {
+        List<ProcessScanResult> scanResults = new ArrayList<ProcessScanResult>();
+        Set<ProcessScan> processScans = serverType.getProcessScans();
+        log.debug("Executing process scans for server type " + serverType + "...");
+        ProcessInfoQuery piq = new ProcessInfoQuery(processInfo);
+        for (ProcessScan processScan : processScans) {
+            List<ProcessInfo> queryResults = piq.query(processScan.getQuery());
+            for (ProcessInfo autoDiscoveredProcess : queryResults) {
+                scanResults.add(new ProcessScanResult(processScan, autoDiscoveredProcess));
+                log.info("Process scan auto-detected new server resource: scan=[" + processScan
+                        + "], discovered-process=[" + autoDiscoveredProcess + "]");
+            }
+        }
+        return scanResults;
+    }
+
+    /**
+     * AutoDiscoveryExecutor method.
+     */
+    private List<ProcessInfo> getProcessInfos() {
+        SystemInfo systemInfo = SystemInfoFactory.createSystemInfo();
+        log.debug("Retrieving process table...");
+        long startTime = System.currentTimeMillis();
+        List<ProcessInfo> processInfos = null;
+        try {
+            processInfos = systemInfo.getAllProcesses();
+        } catch (UnsupportedOperationException uoe) {
+            log.debug("Cannot perform process scan - not supported on this platform. (" + systemInfo.getClass() + ")");
+        }
+        long elapsedTime = System.currentTimeMillis() - startTime;
+        log.debug("Retrieval of process table took " + elapsedTime + " ms.");
+        return processInfos;
+    }
+
+    /**
+     * Returns the plugin descriptor.
+     */
+    public PluginDescriptor getPluginDescriptor() {
+        return pluginDescriptor;
+    }
+
+    /**
+     * Returns the plugin descriptor.
+     */
+    public ResourceDescriptor getResourceDescriptor(String name) {
+        ResourceDescriptor rd = descriptors.get(name);
+        if (rd == null)
+            throw new IllegalStateException("no descriptor " + name + " in " + descriptors.keySet());
+        return rd;
+    }
+
+    private void buildDesc(List<? extends ResourceDescriptor> l) {
+        for (ResourceDescriptor rd : l) {
+            descriptors.put(rd.getName(), rd);
+            if (rd instanceof ServerDescriptor) {
+                buildDesc(((ServerDescriptor)rd).getServers());
+                buildDesc(((ServerDescriptor)rd).getServices());
+            }
+            if (rd instanceof ServiceDescriptor) {
+                buildDesc(((ServiceDescriptor)rd).getServices());
+                buildDesc(((ServiceDescriptor)rd).getServices());
+            }
+        }
+    }
+
+    /**
+     * Asserts that all measurements in the report are present
+     * according to the resource descriptor.
+     *
+     * @see #getResourceDescriptor(String) for obtaining this.
+     * @param report
+     */
+    public static void assertAll(MeasurementReport report, ResourceDescriptor l) {
+        HashMap<String, MetricDescriptor> map = new HashMap<String, MetricDescriptor>();
+        for (MetricDescriptor md : l.getMetric()) {
+            map.put(md.getProperty(), md);
+        }
+        for (MeasurementDataNumeric n : report.getNumericData()) {
+            map.remove(n.getName());
+        }
+        for (MeasurementDataTrait n : report.getTraitData()) {
+            map.remove(n.getName());
+        }
+        assertTrue("Measurements not found " + map.keySet(), map.isEmpty());
+    }
+
+    /**
+     * Returns the event manager.
+     */
+    public EventManager getEventManager() {
+        return eventManager;
+    }
+
+    /**
+     * Set to false to avoid scanning local machine processes to speed up testing.
+     */
+    public void setProcessScan(boolean processScan) {
+        this.processScan = processScan;
+    }
+
+    public void assertAll(ConfigurationFacet cf, ResourceDescriptor rd) throws Exception {
+        Configuration config = cf.loadResourceConfiguration();
+        List<JAXBElement<? extends ConfigurationProperty>> templates = rd.getResourceConfiguration().getConfigurationProperty();
+        for (JAXBElement<? extends ConfigurationProperty> template : templates) {
+            String name = template.getValue().getName();
+            // Property property = config.get(name);
+            assertNotNull("config contains " + name, config.get(name));
+            Object value = config.getSimpleValue(name, null);
+            assertNotNull("value for " + name, value);
+            log.debug("config found " + name + " value " + value );
+        }
+    }
+
+}
diff --git a/modules/plugins/database/src/test/java/org/rhq/plugins/database/H2Database.java b/modules/plugins/database/src/test/java/org/rhq/plugins/database/H2Database.java
new file mode 100644
index 0000000..a81d998
--- /dev/null
+++ b/modules/plugins/database/src/test/java/org/rhq/plugins/database/H2Database.java
@@ -0,0 +1,79 @@
+package org.rhq.plugins.database;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.measurement.AvailabilityType;
+import org.rhq.core.pluginapi.inventory.InvalidPluginConfigurationException;
+import org.rhq.core.pluginapi.inventory.ResourceComponent;
+import org.rhq.core.pluginapi.inventory.ResourceContext;
+import org.rhq.core.util.jdbc.JDBCUtil;
+
+/**
+ * Tests using the H2Database.
+ */
+public class H2Database implements DatabaseComponent<ResourceComponent<?>> {
+
+    private Log log = LogFactory.getLog(this.getClass());
+    protected ResourceContext resourceContext;
+    private Connection connection;
+    private Configuration configuration;
+
+    public void start(ResourceContext resourceContext) throws InvalidPluginConfigurationException, Exception {
+        this.resourceContext = resourceContext;
+        this.configuration = resourceContext.getPluginConfiguration();
+    }
+
+    public void stop() {
+        removeConnection();
+    }
+
+    public AvailabilityType getAvailability() {
+        Connection conn = getConnection();
+        AvailabilityType result = AvailabilityType.DOWN;
+        if (conn != null) {
+            result = AvailabilityType.UP;
+        }
+        return result;
+
+    }
+
+    public Connection getConnection() {
+        try {
+            if (this.connection == null || connection.isClosed()) {
+                this.connection = buildConnection();
+            }
+        } catch (SQLException e) {
+            log.info("Unable to create connection", e);
+        }
+        return this.connection;
+    }
+
+    @Override
+    public void removeConnection() {
+        JDBCUtil.safeClose(connection);
+        this.connection = null;
+    }
+
+    private Connection buildConnection() throws SQLException {
+        String driverClass = configuration.getSimpleValue("driverClass", "org.h2.Driver");
+        try {
+            Class.forName(driverClass);
+        } catch (ClassNotFoundException e) {
+            throw new InvalidPluginConfigurationException("Specified JDBC driver class (" + driverClass
+                + ") not found.");
+        }
+
+        String url = configuration.getSimpleValue("url", "jdbc:h2:test");
+        String username = configuration.getSimpleValue("username", "sa");
+        String password = configuration.getSimpleValue("password", "");
+        log.debug("Attempting JDBC connection to [" + url + "]");
+        return DriverManager.getConnection(url, username, password);
+    }
+
+
+}
diff --git a/modules/plugins/database/src/test/java/org/rhq/plugins/database/H2DatabaseDiscovery.java b/modules/plugins/database/src/test/java/org/rhq/plugins/database/H2DatabaseDiscovery.java
new file mode 100644
index 0000000..dbce116
--- /dev/null
+++ b/modules/plugins/database/src/test/java/org/rhq/plugins/database/H2DatabaseDiscovery.java
@@ -0,0 +1,46 @@
+package org.rhq.plugins.database;
+
+import java.util.Collections;
+import java.util.Set;
+
+import org.jetbrains.annotations.Nullable;
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.pluginapi.inventory.DiscoveredResourceDetails;
+import org.rhq.core.pluginapi.inventory.InvalidPluginConfigurationException;
+import org.rhq.core.pluginapi.inventory.ManualAddFacet;
+import org.rhq.core.pluginapi.inventory.ResourceComponent;
+import org.rhq.core.pluginapi.inventory.ResourceDiscoveryComponent;
+import org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext;
+import org.rhq.core.system.ProcessInfo;
+
+public class H2DatabaseDiscovery implements ResourceDiscoveryComponent<ResourceComponent<?>>, ManualAddFacet<ResourceComponent<?>> {
+
+    @Override
+    public Set<DiscoveredResourceDetails> discoverResources(
+            ResourceDiscoveryContext<ResourceComponent<?>> context) {
+        return Collections.emptySet();
+    }
+
+    @Override
+    public DiscoveredResourceDetails discoverResource(Configuration pluginConfiguration,
+            ResourceDiscoveryContext<ResourceComponent<?>> context)
+            throws InvalidPluginConfigurationException {
+
+        String version = "";
+        DiscoveredResourceDetails details = createResourceDetails(context, pluginConfiguration,
+            version, null);
+        return details;
+
+    }
+
+    private static DiscoveredResourceDetails createResourceDetails(ResourceDiscoveryContext discoveryContext,
+            Configuration pluginConfig, String version, @Nullable
+            ProcessInfo processInfo) {
+            String key = pluginConfig.getSimpleValue("url", "");
+            String name = key;
+            String description = "Database " + version + " (" + key + ")";
+            return new DiscoveredResourceDetails(discoveryContext.getResourceType(), key, name, version, description,
+                pluginConfig, processInfo);
+        }
+
+}
diff --git a/modules/plugins/database/src/test/java/org/rhq/plugins/database/PluginTest.java b/modules/plugins/database/src/test/java/org/rhq/plugins/database/PluginTest.java
new file mode 100644
index 0000000..4ce8107
--- /dev/null
+++ b/modules/plugins/database/src/test/java/org/rhq/plugins/database/PluginTest.java
@@ -0,0 +1,52 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 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.plugins.database;
+
+import java.sql.Connection;
+import java.util.List;
+import java.util.Map;
+
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.measurement.MeasurementReport;
+import org.rhq.core.domain.resource.ResourceType;
+import org.testng.annotations.Test;
+import org.testng.AssertJUnit;
+
+ at Test
+public class PluginTest extends ComponentTest {
+
+    public void test() throws Exception {
+        H2Database db = (H2Database)manuallyAdd("H2 Database");
+        assertUp(db);
+        Connection connection = db.getConnection();
+        connection.prepareStatement("create table sometable(a int, b int)").execute();
+        connection.prepareStatement("insert into sometable values(42, 54)").execute();
+        ResourceType rt = resourceTypes.get("Generic Query");
+        Configuration configuration = getConfiguration(rt);
+        CustomTableComponent ctc = (CustomTableComponent) manuallyAdd(rt, configuration, db);
+        MeasurementReport report = getMeasurementReport(ctc);
+        assertAll(report, getResourceDescriptor("Generic Query"));
+        List<Map<String, Object>> grid = DatabaseQueryUtility.getGridValues(db, "select a, b from sometable");
+        assert grid.size() == 1;
+        Map<String, Object> map = grid.get(0);
+        AssertJUnit.assertEquals(42, map.get("A"));
+    }
+
+}
diff --git a/modules/plugins/database/src/test/resources/META-INF/rhq-plugin.xml b/modules/plugins/database/src/test/resources/META-INF/rhq-plugin.xml
new file mode 100644
index 0000000..1e8f7d1
--- /dev/null
+++ b/modules/plugins/database/src/test/resources/META-INF/rhq-plugin.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<plugin name="H2"
+        displayName="H2 Database"
+        description="Plugin supporting H2 database"
+        package="org.rhq.plugins.database"
+        pluginLifecycleListener="DatabasePluginLifecycleListener"
+        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xmlns:c="urn:xmlns:rhq-configuration"
+        xmlns="urn:xmlns:rhq-plugin">
+
+    <depends plugin="Database" useClasses="true"/>
+
+    <server name="H2 Database" class="org.rhq.plugins.database.H2Database" discovery="org.rhq.plugins.database.H2DatabaseDiscovery">
+        <plugin-configuration>
+            <c:simple-property name="url" type="string" default="jdbc:h2:mem:"/>
+            <c:simple-property name="username" type="string" default="sa"/>
+            <c:simple-property name="password" type="string" default=""/>
+        </plugin-configuration>
+
+    </server>
+
+    <service name="Generic Query" class="org.rhq.plugins.database.CustomTableComponent"
+        discovery="org.rhq.plugins.database.CustomTableDiscoveryComponent"
+        description="Query the database for various results"
+        supportsManualAdd="true" singleton="false"
+        createDeletePolicy="both">
+
+        <runs-inside>
+            <parent-resource-type name="H2 Database" plugin="H2"/>
+        </runs-inside>
+
+        <plugin-configuration>
+            <c:simple-property name="metricQuery" type="string" default="select a, b from sometable"/>
+            <c:simple-property name="column" type="boolean" default="true"/>
+        </plugin-configuration>
+        <metric property="A" displayName="A results" displayType="summary"
+            description="Number appearing in A column"
+            units="none" dataType="measurement"/>
+        <metric property="B" displayName="B results" displayType="summary"
+            description="Number appearing in B column"
+            units="none" dataType="measurement"/>
+    </service>
+
+
+</plugin>
+


commit cb5bd253f36a04710b2906f89429d36b9f9a1b8a
Author: Mike Thompson <mithomps at redhat.com>
Date:   Thu Jul 5 12:26:50 2012 -0700

    [BZ 815305] Min/max constraints on PropertyList not honored. Change IntegerItems to SpinnerItems on configuration screens making sure validations still work as SpinnerItem validations is little different than IntegerItems.

diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/ConfigurationEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/ConfigurationEditor.java
index 9932499..4e188dd 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/ConfigurationEditor.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/ConfigurationEditor.java
@@ -52,24 +52,8 @@ import com.smartgwt.client.widgets.form.DynamicForm;
 import com.smartgwt.client.widgets.form.ValuesManager;
 import com.smartgwt.client.widgets.form.events.ItemChangedEvent;
 import com.smartgwt.client.widgets.form.events.ItemChangedHandler;
-import com.smartgwt.client.widgets.form.fields.ButtonItem;
-import com.smartgwt.client.widgets.form.fields.CanvasItem;
-import com.smartgwt.client.widgets.form.fields.CheckboxItem;
-import com.smartgwt.client.widgets.form.fields.ComboBoxItem;
-import com.smartgwt.client.widgets.form.fields.FloatItem;
-import com.smartgwt.client.widgets.form.fields.FormItem;
-import com.smartgwt.client.widgets.form.fields.IntegerItem;
-import com.smartgwt.client.widgets.form.fields.PasswordItem;
-import com.smartgwt.client.widgets.form.fields.RadioGroupItem;
-import com.smartgwt.client.widgets.form.fields.SelectItem;
-import com.smartgwt.client.widgets.form.fields.SpacerItem;
-import com.smartgwt.client.widgets.form.fields.StaticTextItem;
-import com.smartgwt.client.widgets.form.fields.TextAreaItem;
-import com.smartgwt.client.widgets.form.fields.TextItem;
-import com.smartgwt.client.widgets.form.fields.events.ChangedEvent;
-import com.smartgwt.client.widgets.form.fields.events.ChangedHandler;
-import com.smartgwt.client.widgets.form.fields.events.FocusEvent;
-import com.smartgwt.client.widgets.form.fields.events.FocusHandler;
+import com.smartgwt.client.widgets.form.fields.*;
+import com.smartgwt.client.widgets.form.fields.events.*;
 import com.smartgwt.client.widgets.form.validator.CustomValidator;
 import com.smartgwt.client.widgets.form.validator.FloatRangeValidator;
 import com.smartgwt.client.widgets.form.validator.IntegerRangeValidator;
@@ -134,6 +118,7 @@ import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableSectionStack
 import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableToolStrip;
 import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableVLayout;
 import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableWindow;
+import sun.net.www.content.image.png;
 
 /**
  * A SmartGWT widget for editing an RHQ {@link Configuration} that conforms to a {@link ConfigurationDefinition}.
@@ -1031,13 +1016,13 @@ public class ConfigurationEditor extends LocatableVLayout {
         toolStrip.setWidth100();
         if (!propertyReadOnly) {
             IButton addRowButton = new IButton();
-            addRowButton.setIcon(Window.getImgURL("[SKIN]/actions/add.png"));
-            addRowButton.addClickHandler(new com.smartgwt.client.widgets.events.ClickHandler() {
-                public void onClick(ClickEvent clickEvent) {
-                    displayMapEditor(summaryTable, null, propertyDefinitionList, propertyList,
-                        memberPropertyDefinitionMap, null, mapReadOnly);
-                }
-            });
+            addRowButton.setIcon(Window.getImgURL(ImageManager.getAddIcon()));
+                    addRowButton.addClickHandler(new com.smartgwt.client.widgets.events.ClickHandler() {
+                        public void onClick(ClickEvent clickEvent) {
+                            displayMapEditor(summaryTable, null, propertyDefinitionList, propertyList,
+                                    memberPropertyDefinitionMap, null, mapReadOnly);
+                        }
+                    });
             toolStrip.addMember(addRowButton);
         }
 
@@ -1341,15 +1326,10 @@ public class ConfigurationEditor extends LocatableVLayout {
                     valueItem = radioGroupItem;
                     break;
                 case INTEGER:
-                    // Ideally, we'd use SpinnerItems for INTEGER props, but unfortunately, as of version 2.4, SmartGWT
-                    // has a nasty bug where it does not fire ValueChangedEvents or ItemChangedEvents when the value of
-                    // a SpinnerItem changes...
-                    /*SpinnerItem spinnerItem = new SpinnerItem();
+                    SpinnerItem spinnerItem = new SpinnerItem();
                     spinnerItem.setMin(Integer.MIN_VALUE);
                     spinnerItem.setMax(Integer.MAX_VALUE);
-                    // TODO: If an integer constraint is defined on the propdef, use that to set the min and max.
-                    valueItem = spinnerItem;*/
-                    valueItem = new IntegerItem();
+                    valueItem = spinnerItem;
                     break;
                 case FLOAT:
                 case DOUBLE:
@@ -1378,6 +1358,25 @@ public class ConfigurationEditor extends LocatableVLayout {
                         }
                     }
                 });
+                // Since spinnerItems only fire ChangedEvent once the spinner buttons are pushed
+                // we add blur handler to pick up any changes to that field when leaving
+                if(valueItem instanceof SpinnerItem){
+                    valueItem.addBlurHandler(new BlurHandler() {
+                        @Override
+                        public void onBlur(BlurEvent event) {
+                            updatePropertySimpleValue(event.getItem(), event.getItem().getValue(), propertySimple,
+                                    propertyDefinitionSimple);
+                            // Only fire a prop value change event if the prop's a top-level simple or a simple within a
+                            // top-level map.
+                            if (shouldFireEventOnPropertyValueChange(event.getItem(), propertyDefinitionSimple,
+                                    propertySimple)) {
+                                boolean isValid = event.getItem().validate();
+                                firePropertyChangedEvent(propertySimple, propertyDefinitionSimple, isValid);
+                            }
+
+                        }
+                    });
+                }
             }
         }
 


commit 21ca86fc1c1be1d5c4108918d965b03119ec9895
Author: Simeon Pinder <spinder at redhat.com>
Date:   Thu Jul 5 09:09:13 2012 -0400

     [BZ 828938] fix typo and add thread identification.

diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/PluginContainer.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/PluginContainer.java
index e1883e4..0470d9b 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/PluginContainer.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/PluginContainer.java
@@ -700,13 +700,14 @@ public class PluginContainer {
                 rebootListener.reboot();
             }
         });
+        rebootThread.setName("Plugin Container Reboot Thread");
         rebootThread.setDaemon(false);
         rebootThread.start();
         try {
             rebootThread.join();
         } catch (InterruptedException e) {
             log.error("Interrupted while rebooting agent after one or more resource types "
-                + " have been marked for deletion. You man need to manually reboot the agent/plugin container to purge "
+                + " have been marked for deletion. You may need to manually reboot the agent/plugin container to purge "
                 + "stale types.");
         }
     }


commit 2e121e658b517b35ccb8752ff4a8c0489d14d90b
Author: Lukas Krejci <lkrejci at redhat.com>
Date:   Wed Jul 4 18:44:51 2012 +0200

    Use the correct language name for the javascript language.

diff --git a/modules/enterprise/server/itests/src/test/java/org/rhq/enterprise/client/security/test/JndiAccessTest.java b/modules/enterprise/server/itests/src/test/java/org/rhq/enterprise/client/security/test/JndiAccessTest.java
index f96b081..302fa10 100644
--- a/modules/enterprise/server/itests/src/test/java/org/rhq/enterprise/client/security/test/JndiAccessTest.java
+++ b/modules/enterprise/server/itests/src/test/java/org/rhq/enterprise/client/security/test/JndiAccessTest.java
@@ -196,7 +196,8 @@ public class JndiAccessTest extends AbstractEJB3Test {
         
         PermissionCollection perms = new StandardScriptPermissions();
         
-        return ScriptEngineFactory.getSecuredScriptEngine("JavaScript", new PackageFinder(Collections.<File>emptyList()), bindings, perms);
+        return ScriptEngineFactory.getSecuredScriptEngine("javascript",
+            new PackageFinder(Collections.<File> emptyList()), bindings, perms);
     }
     
     private static void checkIsDesiredSecurityException(ScriptException e) {
diff --git a/modules/enterprise/server/plugins/alert-cli/src/main/java/org/rhq/enterprise/server/plugins/alertCli/CliSender.java b/modules/enterprise/server/plugins/alert-cli/src/main/java/org/rhq/enterprise/server/plugins/alertCli/CliSender.java
index 8ca0b39..98246a0 100644
--- a/modules/enterprise/server/plugins/alert-cli/src/main/java/org/rhq/enterprise/server/plugins/alertCli/CliSender.java
+++ b/modules/enterprise/server/plugins/alert-cli/src/main/java/org/rhq/enterprise/server/plugins/alertCli/CliSender.java
@@ -71,7 +71,7 @@ import org.rhq.scripting.ScriptSourceProviderFactory;
  */
 public class CliSender extends AlertSender<CliComponent> {
 
-    private static final String ENGINE_NAME = "JavaScript";
+    private static final String ENGINE_NAME = "javascript";
 
     private static final int MAX_RESULT_SIZE = 4000;
 


commit f94c0df7851ee1ae64cb0995abf75ed9ec93cf32
Author: Lukas Krejci <lkrejci at redhat.com>
Date:   Wed Jul 4 18:44:20 2012 +0200

    LocalClient now generates proxies inside a privileged block to correctly
    work in the restricted environment of the RHQ server where we disallow
    the scripts to do "unattended" JNDI lookups against the RHQ server.

diff --git a/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClient.java b/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClient.java
index 7f8efad..5cbed7e 100644
--- a/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClient.java
+++ b/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClient.java
@@ -97,19 +97,24 @@ public class LocalClient implements RhqFacade {
     }
 
     @Override
-    public <T> T getProxy(Class<T> remoteApiIface) {
-        RhqManager manager = RhqManager.forInterface(remoteApiIface);
+    public <T> T getProxy(final Class<T> remoteApiIface) {
+        final RhqManager manager = RhqManager.forInterface(remoteApiIface);
 
         if (manager == null) {
             throw new IllegalArgumentException("Unknown remote interface " + remoteApiIface);
         }
 
-        Object localSLSB = getLocalSLSB(manager);
+        return AccessController.doPrivileged(new PrivilegedAction<T>() {
+            @Override
+            public T run() {
+                Object localSLSB = getLocalSLSB(manager);
 
-        Object proxy = Proxy.newProxyInstance(remoteApiIface.getClassLoader(), new Class<?>[] { remoteApiIface },
-            new LocalClientProxy(localSLSB, this, manager));
+                Object proxy = Proxy.newProxyInstance(remoteApiIface.getClassLoader(),
+                    new Class<?>[] { remoteApiIface }, new LocalClientProxy(localSLSB, LocalClient.this, manager));
 
-        return remoteApiIface.cast(proxy);
+                return remoteApiIface.cast(proxy);
+            }
+        });
     }
 
     private Object getScriptingProxy(Object slsb, RhqManager manager) {


commit b63714a7093588f7688c196e649e5003b7cdf701
Author: Lukas Krejci <lkrejci at redhat.com>
Date:   Wed Jul 4 18:41:51 2012 +0200

    Fixed a problem with copying annotations with no attributes.

diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/InterfaceSimplifier.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/InterfaceSimplifier.java
index dc29bc9..dc07d4e 100644
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/InterfaceSimplifier.java
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/InterfaceSimplifier.java
@@ -229,15 +229,17 @@ public class InterfaceSimplifier {
 
         Annotation ret = new Annotation(annotation.getTypeName(), constPool);
 
-        for (Object m : annotation.getMemberNames()) {
-            final String memberName = (String) m;
+        if (annotation.getMemberNames() != null) {
+            for (Object m : annotation.getMemberNames()) {
+                final String memberName = (String) m;
 
-            MemberValue origValue = annotation.getMemberValue(memberName);
-            final MemberValue[] newValue = new MemberValue[1];
+                MemberValue origValue = annotation.getMemberValue(memberName);
+                final MemberValue[] newValue = new MemberValue[1];
 
-            origValue.accept(new ArrayIndexAssigningVisitor(newValue, 0, constPool));
+                origValue.accept(new ArrayIndexAssigningVisitor(newValue, 0, constPool));
 
-            ret.addMemberValue(memberName, newValue[0]);
+                ret.addMemberValue(memberName, newValue[0]);
+            }
         }
 
         return ret;


commit fd22cb9644d17d43d876945f34689492bcf84c9b
Author: Lukas Krejci <lkrejci at redhat.com>
Date:   Wed Jul 4 18:41:20 2012 +0200

    Fixing the build. The RHQ's javascript language module now bundles
    Rhino in the jar itself to ease the deployment, added the javascript module
    as a test dep to a number of modules that have tests utilizing scripting.

diff --git a/modules/enterprise/binding/pom.xml b/modules/enterprise/binding/pom.xml
index 945b4bc..7d37053 100644
--- a/modules/enterprise/binding/pom.xml
+++ b/modules/enterprise/binding/pom.xml
@@ -209,6 +209,20 @@
             <artifactId>javassist</artifactId>
         </dependency>
 
+        <dependency>
+            <groupId>org.powermock</groupId>
+            <artifactId>powermock-module-testng</artifactId>
+            <version>${powermock.version}</version>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.powermock</groupId>
+            <artifactId>powermock-api-mockito</artifactId>
+            <version>${powermock.version}</version>
+            <scope>test</scope>
+        </dependency>
+
     </dependencies>
 
     <build>
diff --git a/modules/enterprise/remoting/cli/pom.xml b/modules/enterprise/remoting/cli/pom.xml
index ae77f1e..3924ff0 100644
--- a/modules/enterprise/remoting/cli/pom.xml
+++ b/modules/enterprise/remoting/cli/pom.xml
@@ -163,19 +163,6 @@
          </plugin>
 
          <plugin>
-            <artifactId>maven-jar-plugin</artifactId>
-            <configuration>
-               <includes>
-                  <include>org/rhq/**</include>
-                  <include>client-messages*</include>
-               </includes>
-               <archive>
-                  <index>true</index>
-               </archive>
-            </configuration>
-         </plugin>
-
-         <plugin>
             <artifactId>maven-assembly-plugin</artifactId>
             <configuration>
                <descriptors>
diff --git a/modules/enterprise/remoting/cli/src/main/scripts/rhq-client.build.xml b/modules/enterprise/remoting/cli/src/main/scripts/rhq-client.build.xml
index 202bef7..808bd82 100644
--- a/modules/enterprise/remoting/cli/src/main/scripts/rhq-client.build.xml
+++ b/modules/enterprise/remoting/cli/src/main/scripts/rhq-client.build.xml
@@ -70,7 +70,6 @@
 
       <copy file="${settings.localRepository}/org/rhq/rhq-scripting-api/${project.version}/rhq-scripting-api-${project.version}.jar" tofile="${lib.home}/rhq-scripting-api-${project.version}.jar" verbose="true" />
       <copy file="${settings.localRepository}/org/rhq/rhq-scripting-javascript/${project.version}/rhq-scripting-javascript-${project.version}.jar" tofile="${lib.home}/rhq-scripting-javascript-${project.version}.jar" verbose="true" />
-   	  <copy file="${settings.localRepository}/org/mozilla/rhino/${rhino.version}/rhino-${rhino.version}.jar" tofile="${lib.home}/rhino-${rhino.version}.jar" verbose="true" />
    </target>
 
    <target name="prepare-samples-dir">
diff --git a/modules/enterprise/scripting/javascript/pom.xml b/modules/enterprise/scripting/javascript/pom.xml
index e813d3b..11f3784 100644
--- a/modules/enterprise/scripting/javascript/pom.xml
+++ b/modules/enterprise/scripting/javascript/pom.xml
@@ -1,205 +1,230 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-    <parent>
-        <artifactId>rhq-scripting-parent</artifactId>
-        <groupId>org.rhq</groupId>
-        <version>4.5.0-SNAPSHOT</version>
-    </parent>
-    <artifactId>rhq-scripting-javascript</artifactId>
-    <version>4.5.0-SNAPSHOT</version>
-    <name>RHQ Javascript support</name>
-    <description>Provides RHQ scripting in Javascript using Rhino</description>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+   <modelVersion>4.0.0</modelVersion>
+   <parent>
+      <artifactId>rhq-scripting-parent</artifactId>
+      <groupId>org.rhq</groupId>
+      <version>4.5.0-SNAPSHOT</version>
+   </parent>
+   <artifactId>rhq-scripting-javascript</artifactId>
+   <version>4.5.0-SNAPSHOT</version>
+   <name>RHQ Javascript support</name>
+   <description>Provides RHQ scripting in Javascript using Rhino</description>
 
-    <dependencies>
-       <dependency>
-          <groupId>${project.groupId}</groupId>
-          <artifactId>rhq-scripting-api</artifactId>
-          <version>${project.version}</version>
-       </dependency>
-       
-       <dependency>
-          <groupId>org.mozilla</groupId>
-          <artifactId>rhino</artifactId>
-          <version>1.7R3</version>
-       </dependency>
-       
-<!-- we no longer depend on Phobos because we now bundle the Phobos script engine with
-     our own modifications. 
-       <dependency>
-          <groupId>com.sun.phobos</groupId>
-          <artifactId>phobos-js</artifactId>
-          <version>0.6.2</version>
-          <exclusions>
-             <exclusion>
-                <groupId>com.sun.phobos</groupId>
-                <artifactId>phobos-rhino</artifactId>
-             </exclusion>
-          </exclusions>
-       </dependency>
- -->              
-    </dependencies>
-    
-    <build>
-        <plugins>
-            <plugin>
-                <artifactId>maven-surefire-plugin</artifactId>
-                <configuration>
-                    <excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
-                    <argLine>-Djava.security.manager -Djava.security.policy==${project.build.testOutputDirectory}/allow-all.policy</argLine>    
-                    <!-- This is important, because some of the tests try to exit the JVM. -->
-                    <failIfNoTests>true</failIfNoTests>                    
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
+   <dependencies>
+      <dependency>
+         <groupId>${project.groupId}</groupId>
+         <artifactId>rhq-scripting-api</artifactId>
+         <version>${project.version}</version>
+      </dependency>
 
-    <profiles>
+      <dependency>
+         <groupId>org.mozilla</groupId>
+         <artifactId>rhino</artifactId>
+         <version>1.7R3</version>
+      </dependency>
 
-        <profile>
-            <id>dev</id>
+   </dependencies>
 
-            <properties>
-                <rhq.rootDir>../../..</rhq.rootDir>
-                <rhq.containerDir>${rhq.rootDir}/${rhq.defaultDevContainerPath}</rhq.containerDir>
-                <rhq.deploymentDir>${rhq.containerDir}/jbossas/server/default/deploy/${rhq.earName}/lib</rhq.deploymentDir>
-            </properties>
+   <build>
+      <plugins>
+         <plugin>
+            <groupId>org.sonatype.plugins</groupId>
+            <artifactId>jarjar-maven-plugin</artifactId>
+            <version>1.5</version>
+            <executions>
+               <execution>
+                  <phase>package</phase>
+                  <goals>
+                     <goal>jarjar</goal>
+                  </goals>
+                  <configuration>
+                     <includes>
+                        <include>org.mozilla:rhino</include>
+                     </includes>
+                     <rules>
+                        <keep>
+                           <pattern>*.**</pattern>
+                        </keep>                          
+                     </rules>
+                  </configuration>
+               </execution>
+            </executions>
+         </plugin>
 
-            <build>
-                <plugins>
+         <plugin>
+            <artifactId>maven-surefire-plugin</artifactId>
+            <configuration>
+               <excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
+               <argLine>-Djava.security.manager
+                  -Djava.security.policy==${project.build.testOutputDirectory}/allow-all.policy</argLine>
+               <!-- This is important, because some of the tests try to exit 
+                  the JVM. -->
+               <failIfNoTests>true</failIfNoTests>
+            </configuration>
+         </plugin>
+      </plugins>
+   </build>
 
-                    <plugin>
-                        <artifactId>maven-antrun-plugin</artifactId>
-                        <version>1.1</version>
-                        <executions>
+   <profiles>
 
-                            <execution>
-                                <id>deploy</id>
-                                <phase>compile</phase>
-                                <configuration>
-                                    <tasks>
-                                        <mkdir dir="${rhq.deploymentDir}" />
-                                        <property name="deployment.file" location="${rhq.deploymentDir}/${project.build.finalName}.jar" />
-                                        <echo>*** Updating
-                                            ${deployment.file}...</echo>
-                                        <jar destfile="${deployment.file}" basedir="${project.build.outputDirectory}" />
-                                    </tasks>
-                                </configuration>
-                                <goals>
-                                    <goal>run</goal>
-                                </goals>
-                            </execution>
+      <profile>
+         <id>dev</id>
 
-                            <execution>
-                                <id>undeploy</id>
-                                <phase>clean</phase>
-                                <configuration>
-                                    <tasks>
-                                        <property name="deployment.file" location="${rhq.deploymentDir}/${project.build.finalName}.jar" />
-                                        <echo>*** Deleting
-                                            ${deployment.file}...</echo>
-                                        <delete file="${deployment.file}" />
-                                    </tasks>
-                                </configuration>
-                                <goals>
-                                    <goal>run</goal>
-                                </goals>
-                            </execution>
+         <properties>
+            <rhq.rootDir>../../..</rhq.rootDir>
+            <rhq.containerDir>${rhq.rootDir}/${rhq.defaultDevContainerPath}</rhq.containerDir>
+            <rhq.deploymentDir>${rhq.containerDir}/jbossas/server/default/deploy/${rhq.earName}/lib</rhq.deploymentDir>
+         </properties>
 
-                        </executions>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
+         <build>
+            <plugins>
 
-        <profile>
-            <id>cobertura-plugins</id>
-            <activation>
-                <activeByDefault>false</activeByDefault>
-            </activation>
-            <build>
-                <plugins>
-                    <plugin>
-                        <artifactId>maven-antrun-plugin</artifactId>
-                        <dependencies>
-                            <dependency>
-                                <groupId>net.sourceforge.cobertura</groupId>
-                                <artifactId>cobertura</artifactId>
-                                <version>1.9.4.1</version>
-                            </dependency>
-                        </dependencies>
-                        <executions>
-                            <execution>
-                                <id>cobertura-instrument</id>
-                                <phase>pre-integration-test</phase>
-                                <configuration>
-                                    <tasks>
-                                        <!-- prepare directory structure 
-                                            for cobertura -->
-                                        <mkdir dir="target/cobertura" />
-                                        <mkdir dir="target/cobertura/backup" />
-                                        <!-- backup all classes so that we 
-                                            can instrument the original classes -->
-                                        <copy toDir="target/cobertura/backup" verbose="true" overwrite="true">
-                                            <fileset dir="target/classes">
-                                                <include name="**/*.class" />
-                                            </fileset>
-                                        </copy>
-                                        <!-- create a properties file and 
-                                            save there location of cobertura data file -->
-                                        <touch file="target/classes/cobertura.properties" />
-                                        <echo file="target/classes/cobertura.properties">net.sourceforge.cobertura.datafile=${project.build.directory}/cobertura/cobertura.ser</echo>
-                                        <taskdef classpathref="maven.plugin.classpath" resource="tasks.properties" />
-                                        <!-- instrument all classes in target/classes 
-                                            directory -->
-                                        <cobertura-instrument datafile="${project.build.directory}/cobertura/cobertura.ser" todir="${project.build.directory}/classes">
-                                            <fileset dir="${project.build.directory}/classes">
-                                                <include name="**/*.class" />
-                                            </fileset>
-                                        </cobertura-instrument>
-                                    </tasks>
-                                </configuration>
-                                <goals>
-                                    <goal>run</goal>
-                                </goals>
-                            </execution>
-                            <execution>
-                                <id>cobertura-report</id>
-                                <phase>post-integration-test</phase>
-                                <configuration>
-                                    <tasks>
-                                        <taskdef classpathref="maven.plugin.classpath" resource="tasks.properties" />
-                                        <!-- prepare directory structure 
-                                            for cobertura -->
-                                        <mkdir dir="target/cobertura" />
-                                        <mkdir dir="target/site/cobertura" />
-                                        <!-- restore classes from backup 
-                                            folder to classes folder -->
-                                        <copy toDir="target/classes" verbose="true" overwrite="true">
-                                            <fileset dir="target/cobertura/backup">
-                                                <include name="**/*.class" />
-                                            </fileset>
-                                        </copy>
-                                        <!-- delete backup folder -->
-                                        <delete dir="target/cobertura/backup" />
-                                        <!-- create a code coverage report -->
-                                        <cobertura-report format="html" datafile="${project.build.directory}/cobertura/cobertura.ser" destdir="${project.build.directory}/site/cobertura">
-                                            <fileset dir="${basedir}/src/main/java">
-                                                <include name="**/*.java" />
-                                            </fileset>
-                                        </cobertura-report>
-                                        <!-- delete cobertura.properties 
-                                            file -->
-                                        <delete file="target/classes/cobertura.properties" />
-                                    </tasks>
-                                </configuration>
-                                <goals>
-                                    <goal>run</goal>
-                                </goals>
-                            </execution>
-                        </executions>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-    </profiles>
+               <plugin>
+                  <artifactId>maven-antrun-plugin</artifactId>
+                  <version>1.1</version>
+                  <executions>
+
+                     <execution>
+                        <id>deploy</id>
+                        <phase>compile</phase>
+                        <configuration>
+                           <tasks>
+                              <mkdir dir="${rhq.deploymentDir}" />
+                              <property name="deployment.file"
+                                 location="${rhq.deploymentDir}/${project.build.finalName}.jar" />
+                              <echo>*** Updating
+                                 ${deployment.file}...</echo>
+                              <jar destfile="${deployment.file}"
+                                 basedir="${project.build.outputDirectory}" />
+                           </tasks>
+                        </configuration>
+                        <goals>
+                           <goal>run</goal>
+                        </goals>
+                     </execution>
+
+                     <execution>
+                        <id>undeploy</id>
+                        <phase>clean</phase>
+                        <configuration>
+                           <tasks>
+                              <property name="deployment.file"
+                                 location="${rhq.deploymentDir}/${project.build.finalName}.jar" />
+                              <echo>*** Deleting
+                                 ${deployment.file}...</echo>
+                              <delete file="${deployment.file}" />
+                           </tasks>
+                        </configuration>
+                        <goals>
+                           <goal>run</goal>
+                        </goals>
+                     </execution>
+
+                  </executions>
+               </plugin>
+            </plugins>
+         </build>
+      </profile>
+
+      <profile>
+         <id>cobertura-plugins</id>
+         <activation>
+            <activeByDefault>false</activeByDefault>
+         </activation>
+         <build>
+            <plugins>
+               <plugin>
+                  <artifactId>maven-antrun-plugin</artifactId>
+                  <dependencies>
+                     <dependency>
+                        <groupId>net.sourceforge.cobertura</groupId>
+                        <artifactId>cobertura</artifactId>
+                        <version>1.9.4.1</version>
+                     </dependency>
+                  </dependencies>
+                  <executions>
+                     <execution>
+                        <id>cobertura-instrument</id>
+                        <phase>pre-integration-test</phase>
+                        <configuration>
+                           <tasks>
+                              <!-- prepare directory structure for cobertura -->
+                              <mkdir dir="target/cobertura" />
+                              <mkdir dir="target/cobertura/backup" />
+                              <!-- backup all classes so that we can instrument 
+                                 the original classes -->
+                              <copy toDir="target/cobertura/backup"
+                                 verbose="true" overwrite="true">
+                                 <fileset dir="target/classes">
+                                    <include name="**/*.class" />
+                                 </fileset>
+                              </copy>
+                              <!-- create a properties file and save there 
+                                 location of cobertura data file -->
+                              <touch
+                                 file="target/classes/cobertura.properties" />
+                              <echo
+                                 file="target/classes/cobertura.properties">net.sourceforge.cobertura.datafile=${project.build.directory}/cobertura/cobertura.ser</echo>
+                              <taskdef classpathref="maven.plugin.classpath"
+                                 resource="tasks.properties" />
+                              <!-- instrument all classes in target/classes 
+                                 directory -->
+                              <cobertura-instrument
+                                 datafile="${project.build.directory}/cobertura/cobertura.ser"
+                                 todir="${project.build.directory}/classes">
+                                 <fileset
+                                    dir="${project.build.directory}/classes">
+                                    <include name="**/*.class" />
+                                 </fileset>
+                              </cobertura-instrument>
+                           </tasks>
+                        </configuration>
+                        <goals>
+                           <goal>run</goal>
+                        </goals>
+                     </execution>
+                     <execution>
+                        <id>cobertura-report</id>
+                        <phase>post-integration-test</phase>
+                        <configuration>
+                           <tasks>
+                              <taskdef classpathref="maven.plugin.classpath"
+                                 resource="tasks.properties" />
+                              <!-- prepare directory structure for cobertura -->
+                              <mkdir dir="target/cobertura" />
+                              <mkdir dir="target/site/cobertura" />
+                              <!-- restore classes from backup folder to 
+                                 classes folder -->
+                              <copy toDir="target/classes" verbose="true"
+                                 overwrite="true">
+                                 <fileset dir="target/cobertura/backup">
+                                    <include name="**/*.class" />
+                                 </fileset>
+                              </copy>
+                              <!-- delete backup folder -->
+                              <delete dir="target/cobertura/backup" />
+                              <!-- create a code coverage report -->
+                              <cobertura-report format="html"
+                                 datafile="${project.build.directory}/cobertura/cobertura.ser"
+                                 destdir="${project.build.directory}/site/cobertura">
+                                 <fileset dir="${basedir}/src/main/java">
+                                    <include name="**/*.java" />
+                                 </fileset>
+                              </cobertura-report>
+                              <!-- delete cobertura.properties file -->
+                              <delete
+                                 file="target/classes/cobertura.properties" />
+                           </tasks>
+                        </configuration>
+                        <goals>
+                           <goal>run</goal>
+                        </goals>
+                     </execution>
+                  </executions>
+               </plugin>
+            </plugins>
+         </build>
+      </profile>
+   </profiles>
 </project>
diff --git a/modules/enterprise/server/ear/pom.xml b/modules/enterprise/server/ear/pom.xml
index 46ec595..10b613e 100644
--- a/modules/enterprise/server/ear/pom.xml
+++ b/modules/enterprise/server/ear/pom.xml
@@ -97,6 +97,12 @@
       </dependency>
 
       <dependency>
+         <groupId>org.rhq</groupId>
+         <artifactId>rhq-scripting-javascript</artifactId>
+         <version>${project.version}</version>
+      </dependency>
+      
+      <dependency>
         <groupId>org.rhq</groupId>
         <artifactId>rhq-server-client-api</artifactId>
         <version>${project.version}</version>
diff --git a/modules/enterprise/server/itests/pom.xml b/modules/enterprise/server/itests/pom.xml
index 3f3f03f..43a14c8 100644
--- a/modules/enterprise/server/itests/pom.xml
+++ b/modules/enterprise/server/itests/pom.xml
@@ -99,6 +99,13 @@
       
       <dependency>
          <groupId>org.rhq</groupId>
+         <artifactId>rhq-scripting-javascript</artifactId>
+         <version>${project.version}</version>
+         <scope>test</scope>
+      </dependency>
+      
+      <dependency>
+         <groupId>org.rhq</groupId>
          <artifactId>rhq-server-client-api</artifactId>
          <version>${project.version}</version>
          <scope>test</scope>


commit b70072126da6810a1fc96d6e33cbd100c438e369
Author: Elias Ross <genman at noderunner.net>
Date:   Wed Jul 4 14:19:46 2012 +0200

    BZ 797356 - Allow to disable automatic table discovery per database

diff --git a/modules/plugins/mysql/src/main/java/org/rhq/plugins/mysql/MySqlDatabaseDiscoveryComponent.java b/modules/plugins/mysql/src/main/java/org/rhq/plugins/mysql/MySqlDatabaseDiscoveryComponent.java
index c8f8673..100e536 100644
--- a/modules/plugins/mysql/src/main/java/org/rhq/plugins/mysql/MySqlDatabaseDiscoveryComponent.java
+++ b/modules/plugins/mysql/src/main/java/org/rhq/plugins/mysql/MySqlDatabaseDiscoveryComponent.java
@@ -61,7 +61,7 @@ public class MySqlDatabaseDiscoveryComponent implements ResourceDiscoveryCompone
 
                 while (resultSet.next()) {
                     String databaseName = resultSet.getString(1);
-                    Configuration config = new Configuration();
+                    Configuration config = context.getDefaultPluginConfiguration();
                     config.put(new PropertySimple("databaseName",databaseName));
                     DiscoveredResourceDetails details =
                             new DiscoveredResourceDetails(
diff --git a/modules/plugins/mysql/src/main/java/org/rhq/plugins/mysql/MySqlTableDiscoveryComponent.java b/modules/plugins/mysql/src/main/java/org/rhq/plugins/mysql/MySqlTableDiscoveryComponent.java
index 5b62118..4d7b354 100644
--- a/modules/plugins/mysql/src/main/java/org/rhq/plugins/mysql/MySqlTableDiscoveryComponent.java
+++ b/modules/plugins/mysql/src/main/java/org/rhq/plugins/mysql/MySqlTableDiscoveryComponent.java
@@ -35,11 +35,12 @@ import org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext;
 import org.rhq.plugins.database.DatabaseQueryUtility;
 
 /**
- *
+ * Discovers MySQL tables.
  * @author Steve Millidge (C2B2 Consulting Limited)
  */
 public class MySqlTableDiscoveryComponent implements ResourceDiscoveryComponent {
 
+    private static final String TABLE_DISCOVERY = "tableDiscovery";
     private Log log = LogFactory.getLog(this.getClass());
 
     @Override
@@ -47,6 +48,14 @@ public class MySqlTableDiscoveryComponent implements ResourceDiscoveryComponent
 
         HashSet<DiscoveredResourceDetails> set = new HashSet<DiscoveredResourceDetails>();
         MySqlDatabaseComponent parent = (MySqlDatabaseComponent)rdc.getParentResourceComponent();
+        Configuration pconfig = rdc.getParentResourceContext().getPluginConfiguration();
+        // If the user has disabled table discovery on the parent, we don't autodiscover
+        // them, as we may hit temporary ones that go away any time soon again
+        // See BZ-797356
+        if (!Boolean.parseBoolean(pconfig.getSimpleValue(TABLE_DISCOVERY, "true"))) {
+            log.debug("table discovery disabled");
+            return set;
+        }
         Connection conn = parent.getConnection();
 
         if (conn != null) {
diff --git a/modules/plugins/mysql/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/mysql/src/main/resources/META-INF/rhq-plugin.xml
index 439370e..a2986e9 100644
--- a/modules/plugins/mysql/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/mysql/src/main/resources/META-INF/rhq-plugin.xml
@@ -335,6 +335,7 @@
       <service name="Database" class="MySqlDatabaseComponent" discovery="MySqlDatabaseDiscoveryComponent">
          <plugin-configuration>
             <c:simple-property name="databaseName" displayName="Database Name" readOnly="true" />
+            <c:simple-property name="tableDiscovery" displayName="Table Discovery" readOnly="false" type="boolean" default="true"/>
          </plugin-configuration>
 
           <operation name="invokeSql" description="Execute arbitrary SQL">
diff --git a/modules/plugins/mysql/src/test/java/org/rhq/plugins/mysql/ComponentTest.java b/modules/plugins/mysql/src/test/java/org/rhq/plugins/mysql/ComponentTest.java
new file mode 100644
index 0000000..1e5b9e8
--- /dev/null
+++ b/modules/plugins/mysql/src/test/java/org/rhq/plugins/mysql/ComponentTest.java
@@ -0,0 +1,545 @@
+package org.rhq.plugins.mysql;
+
+import static org.testng.AssertJUnit.assertEquals;
+import static org.testng.AssertJUnit.assertNotNull;
+import static org.testng.AssertJUnit.assertTrue;
+import static org.testng.AssertJUnit.fail;
+
+import java.io.File;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+
+import javax.xml.bind.JAXBElement;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.rhq.core.clientapi.agent.metadata.PluginMetadataManager;
+import org.rhq.core.clientapi.descriptor.AgentPluginDescriptorUtil;
+import org.rhq.core.clientapi.descriptor.configuration.ConfigurationProperty;
+import org.rhq.core.clientapi.descriptor.plugin.MetricDescriptor;
+import org.rhq.core.clientapi.descriptor.plugin.PluginDescriptor;
+import org.rhq.core.clientapi.descriptor.plugin.ResourceDescriptor;
+import org.rhq.core.clientapi.descriptor.plugin.ServerDescriptor;
+import org.rhq.core.clientapi.descriptor.plugin.ServiceDescriptor;
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.PropertySimple;
+import org.rhq.core.domain.measurement.AvailabilityType;
+import org.rhq.core.domain.measurement.MeasurementDataNumeric;
+import org.rhq.core.domain.measurement.MeasurementDataTrait;
+import org.rhq.core.domain.measurement.MeasurementDefinition;
+import org.rhq.core.domain.measurement.MeasurementReport;
+import org.rhq.core.domain.measurement.MeasurementSchedule;
+import org.rhq.core.domain.measurement.MeasurementScheduleRequest;
+import org.rhq.core.domain.resource.ProcessScan;
+import org.rhq.core.domain.resource.Resource;
+import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.core.pc.PluginContainer;
+import org.rhq.core.pc.PluginContainerConfiguration;
+import org.rhq.core.pc.availability.AvailabilityContextImpl;
+import org.rhq.core.pc.content.ContentContextImpl;
+import org.rhq.core.pc.event.EventContextImpl;
+import org.rhq.core.pc.event.EventManager;
+import org.rhq.core.pc.inventory.ResourceContainer;
+import org.rhq.core.pc.operation.OperationContextImpl;
+import org.rhq.core.pluginapi.availability.AvailabilityContext;
+import org.rhq.core.pluginapi.configuration.ConfigurationFacet;
+import org.rhq.core.pluginapi.content.ContentContext;
+import org.rhq.core.pluginapi.event.EventContext;
+import org.rhq.core.pluginapi.inventory.DiscoveredResourceDetails;
+import org.rhq.core.pluginapi.inventory.PluginContainerDeployment;
+import org.rhq.core.pluginapi.inventory.ProcessScanResult;
+import org.rhq.core.pluginapi.inventory.ResourceComponent;
+import org.rhq.core.pluginapi.inventory.ResourceContext;
+import org.rhq.core.pluginapi.inventory.ResourceDiscoveryComponent;
+import org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext;
+import org.rhq.core.pluginapi.measurement.MeasurementFacet;
+import org.rhq.core.pluginapi.operation.OperationContext;
+import org.rhq.core.system.ProcessInfo;
+import org.rhq.core.system.SystemInfo;
+import org.rhq.core.system.SystemInfoFactory;
+import org.rhq.core.system.pquery.ProcessInfoQuery;
+import org.testng.annotations.AfterSuite;
+import org.testng.annotations.AfterTest;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeSuite;
+
+/**
+ * Base class for RHQ Component Testing.
+ * Initializes a plugin configuration.
+ *
+ * Methods to override:
+ *
+ * {@link #setConfiguration(Configuration, ResourceType)}
+ */
+public abstract class ComponentTest {
+
+    /**
+     * Logging component.
+     */
+    protected final Log log = LogFactory.getLog(getClass());
+
+    private static File temp = new File(System.getProperty("java.io.tmpdir"));
+
+    /**
+     * Associates a resource component with a resource.
+     */
+    protected Map<ResourceComponent, Resource> components = new LinkedHashMap<ResourceComponent, Resource>();
+
+    /**
+     * Associates a name of a resource with a resource descriptor.
+     */
+    protected Map<String, ResourceDescriptor> descriptors = new LinkedHashMap<String, ResourceDescriptor>();
+
+    /**
+     * Associates a name of a resource with a type.
+     * This is useful for manually adding resources.
+     *
+     * @see #manuallyAdd(ResourceType, Configuration)
+     */
+    protected Map<String, ResourceType> resourceTypes = new LinkedHashMap<String, ResourceType>();
+
+    /**
+     * Event manager; used to obtain events.
+     */
+    private EventManager eventManager;
+
+    private PluginContainer pluginContainer = PluginContainer.getInstance();
+
+    private SystemInfo systemInfo = SystemInfoFactory.createSystemInfo();
+
+    /**
+     * Scan all processes before starting; false will disable this feature.
+     * Disabling is suggested for running tests against a remote instance.
+     */
+    private boolean processScan = true;
+
+    // TODO
+
+    private final PluginMetadataManager pmm = new PluginMetadataManager();
+    private final File temporaryDirectory = temp;
+    private final File dataDirectory = temp;
+    private final String pluginContainerName = "rhq";
+    private final OperationContext operationContext = new OperationContextImpl(0);
+    private final ContentContext contentContext = new ContentContextImpl(0);
+    private final Executor availCollectorThreadPool = Executors.newCachedThreadPool();
+    private PluginContainerDeployment pluginContainerDeployment = null;
+    private Resource platform;
+    private ResourceContainer platformContainer;
+    private List<ProcessInfo> processInfo = Collections.emptyList();
+    private PluginDescriptor pluginDescriptor;
+
+    /**
+     * Constructs a new component test.
+     */
+    protected ComponentTest() {
+    }
+
+    /**
+     * Initializes the plugin container.
+     * This is run before {@link #before()}.
+     */
+    @BeforeSuite
+    protected void beforeSuite() {
+        // Speed up propagation of events by adjusting delay/period to 1 second
+        PluginContainerConfiguration pcc = new PluginContainerConfiguration();
+        pcc.setEventSenderInitialDelay(1);
+        pcc.setEventSenderPeriod(1);
+        pluginContainer.setConfiguration(pcc);
+        pluginContainer.initialize();
+        eventManager = pluginContainer.getEventManager();
+        platform = pluginContainer.getInventoryManager().getPlatform();
+        platformContainer = pluginContainer.getInventoryManager().getResourceContainer(platform);
+        if (platformContainer == null) {
+            platformContainer = new ResourceContainer(platform, getClass().getClassLoader());
+        }
+    }
+
+    /**
+     * Initializes all plugins defined in the system; using auto-discovery where possible.
+     * This is run once per test class.
+     */
+    @BeforeClass
+    protected void before() throws Exception {
+        if (processScan) {
+            processInfo = getProcessInfos();
+            if (processInfo == null)
+                processInfo = Collections.emptyList();
+            log.debug("Process Info " + processInfo);
+            for (ProcessInfo i : processInfo) {
+                log.debug(i.getBaseName() + " " + Arrays.toString(i.getCommandLine()));
+            }
+        }
+        Enumeration<URL> e = getClass().getClassLoader().getResources("META-INF/rhq-plugin.xml");
+        List<URL> l = Collections.list(e);
+        Collections.sort(l, new Comparator<URL>() {
+            @Override
+            public int compare(URL u1, URL u2) {
+                return u2.toString().compareTo(u1.toString());
+            }
+        });
+        for (URL url : l) {
+            log.debug("parse " + url);
+            InputStream is = url.openStream();
+            PluginDescriptor pd = AgentPluginDescriptorUtil.parsePluginDescriptor(is);
+            processPluginDescriptor(pd);
+            log.debug("pmm names " + pmm.getPluginNames());
+            buildDesc(pd.getServers());
+            buildDesc(pd.getServices());
+            is.close();
+        }
+    }
+
+    @AfterSuite
+    protected void afterSuite() {
+        pluginContainer.shutdown();
+    }
+
+    /**
+     * Process a plugin descriptor.
+     */
+    private void processPluginDescriptor(PluginDescriptor pd) throws Exception {
+        this.pluginDescriptor = pd;
+        Set<ResourceType> types = pmm.loadPlugin(pd);
+        mapResourceTypeNames(types);
+        log.info("Resource types: " + resourceTypes);
+        resources(types, platform, platformContainer.getResourceComponent(), platformContainer.getResourceContext());
+        log.info("ResourceComponent map: " + components);
+    }
+
+    private void mapResourceTypeNames(Set<ResourceType> types) {
+        for (ResourceType type : types) {
+            this.resourceTypes.put(type.getName(), type);
+            mapResourceTypeNames(type.getChildResourceTypes());
+        }
+    }
+
+    /**
+     * Manually create a component by name.
+     */
+    public ResourceComponent manuallyAdd(String name) throws Exception {
+        ResourceType resourceType = resourceTypes.get(name);
+        if (resourceType == null)
+            throw new IllegalStateException("no type " + name);
+        Configuration configuration = resourceType.getPluginConfigurationDefinition().getDefaultTemplate().createConfiguration();
+        setConfiguration(configuration, resourceType);
+        return manuallyAdd(resourceType, configuration);
+    }
+
+    /**
+     * Manually create a component by resource type.
+     */
+    public ResourceComponent manuallyAdd(ResourceType type, Configuration configuration) throws Exception {
+        return manuallyAdd(type, configuration, platformContainer.getResourceComponent());
+    }
+
+    /**
+     * Manually create a component by resource type, configuration, parent.
+     */
+    public ResourceComponent manuallyAdd(ResourceType type, Configuration configuration, ResourceComponent parent) throws Exception {
+        DiscoveredResourceDetails drd = new DiscoveredResourceDetails(type,
+                "key", "name", "ver", "desc", configuration, (ProcessInfo) null);
+        ResourceDiscoveryComponent c = null;
+        return createChild(drd, platform, configuration, parent, c);
+    }
+
+    private ResourceComponent createChild(DiscoveredResourceDetails drd,
+            Resource resource,
+            Configuration configuration,
+            ResourceComponent parentComponent,
+            ResourceDiscoveryComponent rdc) throws Exception
+    {
+        ResourceType type = pmm.getType(drd.getResourceType());
+
+        Resource cresource = new Resource();
+        cresource.setResourceType(type);
+        cresource.setPluginConfiguration(configuration);
+        cresource.setResourceKey(drd.getResourceKey());
+        cresource.setParentResource(resource);
+        cresource.setName(drd.getResourceName());
+        cresource.setVersion(drd.getResourceVersion());
+
+        String rclassname = pmm.getComponentClass(type);
+        ResourceComponent component = (ResourceComponent) Class.forName(rclassname).newInstance();
+
+        AvailabilityContext availContext = new AvailabilityContextImpl(cresource,availCollectorThreadPool);
+
+        EventContext eventContext = new EventContextImpl(resource);
+        ResourceContext context = new ResourceContext(cresource, parentComponent,
+                null, rdc, systemInfo, temporaryDirectory, dataDirectory,
+                pluginContainerName, eventContext, operationContext, contentContext,
+                availContext, pluginContainerDeployment);
+
+        component.start(context);
+        components.put(component, cresource);
+        resources(type.getChildResourceTypes(), cresource, component, context);
+        return component;
+    }
+
+    private void resources(Set<ResourceType> types, Resource parent, ResourceComponent component, ResourceContext context) throws Exception {
+        for (ResourceType type : types) {
+            String s = pmm.getDiscoveryClass(type);
+            if (s == null) {
+                throw new NullPointerException("no discovery " + type);
+            }
+            ResourceDiscoveryComponent rdc = (ResourceDiscoveryComponent) Class.forName(s).newInstance();
+            log.debug("rdc=" + rdc);
+            List<Configuration> configList = new ArrayList<Configuration>();
+            ResourceDiscoveryContext resourceDiscoveryContext = new ResourceDiscoveryContext(type, component,
+                    context, systemInfo,
+                    performProcessScans(type), configList,
+                    pluginContainerName, pluginContainerDeployment);
+            Set<DiscoveredResourceDetails> drds = rdc.discoverResources(resourceDiscoveryContext);
+            for (DiscoveredResourceDetails drd : drds) {
+                log.debug("discovered " + drd);
+                ResourceType resourceType = drd.getResourceType();
+                setConfiguration(drd.getPluginConfiguration(), resourceType);
+                createChild(drd, parent, drd.getPluginConfiguration(), component, rdc);
+            }
+            if (drds.isEmpty()) {
+                log.warn("not discovered " + type);
+                context.getPluginConfiguration();
+            }
+        }
+
+    }
+
+    /**
+     * Called before the configuration is processed; override to set specific plugin parameters.
+     */
+    protected void setConfiguration(Configuration configuration, ResourceType resourceType) {
+    }
+
+    /**
+     * Stops all components, stops the plugin container.
+     */
+    @AfterTest
+    protected void after() throws Exception {
+        for (ResourceComponent c : components.keySet())
+            c.stop();
+        PluginContainer.getInstance().shutdown();
+    }
+
+    /**
+     * Returns a measurement report.
+     */
+    public MeasurementReport getMeasurementReport(ResourceComponent component) throws Exception {
+        Resource resource = this.components.get(component);
+        ResourceType type = resource.getResourceType();
+        MeasurementReport report = new MeasurementReport();
+        Set<MeasurementScheduleRequest> s = new HashSet<MeasurementScheduleRequest>();
+        for (MeasurementDefinition md : type.getMetricDefinitions())
+            s.add(new MeasurementScheduleRequest(new MeasurementSchedule(md, resource)));
+        ((MeasurementFacet)component).getValues(report, s);
+        return report;
+    }
+
+    /**
+     * Returns the first resource component by resource name, then looks by matching resource type name,
+     * then asserts failure if not found.
+     */
+    public ResourceComponent getComponent(String name) {
+        for (Map.Entry<ResourceComponent, Resource> c : components.entrySet())
+            if (c.getValue().getName().equals(name))
+                return c.getKey();
+        for (Map.Entry<ResourceComponent, Resource> c : components.entrySet())
+            if (c.getValue().getResourceType().getName().equals(name))
+                return c.getKey();
+        fail("component not found " + name + " in " + components.entrySet());
+        return null;
+    }
+
+    /**
+     * Returns a resource matching this component.
+     */
+    public Resource getResource(ResourceComponent rc) {
+        Resource r = components.get(rc);
+        if (r == null)
+            throw new IllegalStateException();
+        return r;
+    }
+
+    /**
+     * Returns a resource matching this name.
+     */
+    public Resource getResource(String name) {
+        return getResource(getComponent(name));
+    }
+
+    /**
+     * Builds a new configuration for a resource type.
+     */
+    public Configuration getConfiguration(ResourceType resourceType) {
+        Configuration configuration = resourceType.getPluginConfigurationDefinition().getDefaultTemplate().createConfiguration();
+        setConfiguration(configuration, resourceType);
+        return configuration;
+    }
+
+    // ASSERT METHOD
+
+    /**
+     * From a measurement report, returns a measurement value, or asserts failure if no such value exists.
+     */
+    public static Double getValue(MeasurementReport report, String name) {
+        for (MeasurementDataNumeric m: report.getNumericData()) {
+            if (m.getName().equals(name)) {
+                return m.getValue();
+            }
+        }
+        fail("report does not incude " + name + " report " + report.getNumericData());
+        return null;
+    }
+
+    /**
+     * Asserts the resource component is available.
+     */
+    public static void assertUp(ResourceComponent component) {
+        assertEquals("up " + component, AvailabilityType.UP, component.getAvailability());
+    }
+
+    /**
+     * Asserts the resource component is unavailable.
+     */
+    public static void assertDown(ResourceComponent component) {
+        assertEquals("down " + component, AvailabilityType.DOWN, component.getAvailability());
+    }
+
+    /**
+     * Sets a configuration option.
+     */
+    public static void set(Configuration config, String name, String value) {
+        PropertySimple s = config.getSimple(name);
+        if (s == null) {
+            s = new PropertySimple(name, value);
+            config.put(s);
+        } else {
+            s.setStringValue(value);
+        }
+    }
+
+    private List<ProcessScanResult> performProcessScans(ResourceType serverType) {
+        List<ProcessScanResult> scanResults = new ArrayList<ProcessScanResult>();
+        Set<ProcessScan> processScans = serverType.getProcessScans();
+        log.debug("Executing process scans for server type " + serverType + "...");
+        ProcessInfoQuery piq = new ProcessInfoQuery(processInfo);
+        for (ProcessScan processScan : processScans) {
+            List<ProcessInfo> queryResults = piq.query(processScan.getQuery());
+            for (ProcessInfo autoDiscoveredProcess : queryResults) {
+                scanResults.add(new ProcessScanResult(processScan, autoDiscoveredProcess));
+                log.info("Process scan auto-detected new server resource: scan=[" + processScan
+                        + "], discovered-process=[" + autoDiscoveredProcess + "]");
+            }
+        }
+        return scanResults;
+    }
+
+    /**
+     * AutoDiscoveryExecutor method.
+     */
+    private List<ProcessInfo> getProcessInfos() {
+        SystemInfo systemInfo = SystemInfoFactory.createSystemInfo();
+        log.debug("Retrieving process table...");
+        long startTime = System.currentTimeMillis();
+        List<ProcessInfo> processInfos = null;
+        try {
+            processInfos = systemInfo.getAllProcesses();
+        } catch (UnsupportedOperationException uoe) {
+            log.debug("Cannot perform process scan - not supported on this platform. (" + systemInfo.getClass() + ")");
+        }
+        long elapsedTime = System.currentTimeMillis() - startTime;
+        log.debug("Retrieval of process table took " + elapsedTime + " ms.");
+        return processInfos;
+    }
+
+    /**
+     * Returns the plugin descriptor.
+     */
+    public PluginDescriptor getPluginDescriptor() {
+        return pluginDescriptor;
+    }
+
+    /**
+     * Returns the plugin descriptor.
+     */
+    public ResourceDescriptor getResourceDescriptor(String name) {
+        ResourceDescriptor rd = descriptors.get(name);
+        if (rd == null)
+            throw new IllegalStateException("no descriptor " + name + " in " + descriptors.keySet());
+        return rd;
+    }
+
+    private void buildDesc(List<? extends ResourceDescriptor> l) {
+        for (ResourceDescriptor rd : l) {
+            descriptors.put(rd.getName(), rd);
+            if (rd instanceof ServerDescriptor) {
+                buildDesc(((ServerDescriptor)rd).getServers());
+                buildDesc(((ServerDescriptor)rd).getServices());
+            }
+            if (rd instanceof ServiceDescriptor) {
+                buildDesc(((ServiceDescriptor)rd).getServices());
+                buildDesc(((ServiceDescriptor)rd).getServices());
+            }
+        }
+    }
+
+    /**
+     * Asserts that all measurements in the report are present
+     * according to the resource descriptor.
+     *
+     * @see #getResourceDescriptor(String) for obtaining this.
+     * @param report
+     */
+    public static void assertAll(MeasurementReport report, ResourceDescriptor l) {
+        HashMap<String, MetricDescriptor> map = new HashMap<String, MetricDescriptor>();
+        for (MetricDescriptor md : l.getMetric()) {
+            map.put(md.getProperty(), md);
+        }
+        for (MeasurementDataNumeric n : report.getNumericData()) {
+            map.remove(n.getName());
+        }
+        for (MeasurementDataTrait n : report.getTraitData()) {
+            map.remove(n.getName());
+        }
+        assertTrue("Measurements not found " + map.keySet(), map.isEmpty());
+    }
+
+    /**
+     * Returns the event manager.
+     */
+    public EventManager getEventManager() {
+        return eventManager;
+    }
+
+    /**
+     * Set to false to avoid scanning local machine processes to speed up testing.
+     */
+    public void setProcessScan(boolean processScan) {
+        this.processScan = processScan;
+    }
+
+    public void assertAll(ConfigurationFacet cf, ResourceDescriptor rd) throws Exception {
+        Configuration config = cf.loadResourceConfiguration();
+        List<JAXBElement<? extends ConfigurationProperty>> templates = rd.getResourceConfiguration().getConfigurationProperty();
+        for (JAXBElement<? extends ConfigurationProperty> template : templates) {
+            String name = template.getValue().getName();
+            // Property property = config.get(name);
+            assertNotNull("config contains " + name, config.get(name));
+            Object value = config.getSimpleValue(name, null);
+            assertNotNull("value for " + name, value);
+            log.debug("config found " + name + " value " + value );
+        }
+    }
+
+}
diff --git a/modules/plugins/mysql/src/test/java/org/rhq/plugins/mysql/PluginTest.java b/modules/plugins/mysql/src/test/java/org/rhq/plugins/mysql/PluginTest.java
new file mode 100644
index 0000000..3f35c65
--- /dev/null
+++ b/modules/plugins/mysql/src/test/java/org/rhq/plugins/mysql/PluginTest.java
@@ -0,0 +1,41 @@
+package org.rhq.plugins.mysql;
+
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.core.pluginapi.inventory.ResourceComponent;
+import org.testng.annotations.Test;
+
+/**
+ * Tests MySql Server.
+ */
+ at Test
+public class PluginTest extends ComponentTest {
+
+    String host = System.getProperty("host", "localhost");
+    String principal = System.getProperty("principal", "mysql");
+    String credentials = System.getProperty("credentials", "");
+    String rtn = "MySql Server";
+
+    {
+        setProcessScan(false);
+    }
+
+    @Override
+    protected void setConfiguration(Configuration c, ResourceType resourceType) {
+        if (resourceType.getName().equals(rtn)) {
+            c.getSimple("host").setStringValue(host);
+            c.getSimple("principal").setStringValue(principal);
+            c.getSimple("credentials").setStringValue(credentials);
+        }
+        if (resourceType.getName().equals("Database")) {
+            c.getSimple("tableDiscovery").setBooleanValue(false);
+        }
+    }
+
+    public void test() throws Exception {
+        manuallyAdd("MySql Server");
+        ResourceComponent resource = getComponent("MySql Server");
+        assertUp(resource);
+    }
+
+}
diff --git a/modules/plugins/mysql/src/test/resources/log4j.xml b/modules/plugins/mysql/src/test/resources/log4j.xml
new file mode 100644
index 0000000..69a897c
--- /dev/null
+++ b/modules/plugins/mysql/src/test/resources/log4j.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+
+<!-- tests configuration that only dumps WARN or higher messages due to appender threadhold -->
+
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="false">
+
+   <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
+      <param name="Threshold" value="ERROR"/>
+      <param name="Target" value="System.out"/>
+
+      <layout class="org.apache.log4j.PatternLayout">
+         <param name="ConversionPattern" value="%d{ABSOLUTE} %-5p [%t] (%c{5}) - %m%n"/>
+      </layout>
+   </appender>
+
+   <appender name="FILE" class="org.apache.log4j.FileAppender">
+      <param name="File" value="target/test.log"/>
+      <param name="Threshold" value="DEBUG"/>
+      <param name="Append" value="false"/>
+      <layout class="org.apache.log4j.PatternLayout">
+         <param name="ConversionPattern" value="%-5p %d{dd-MM HH:mm:ss,SSS} (%F:%M:%L)  -%m%n"/>
+      </layout>
+   </appender>
+
+   <category name="org.jboss.on">
+      <priority value="DEBUG"/>
+   </category>
+
+   <root>
+      <appender-ref ref="CONSOLE"/>
+      <appender-ref ref="FILE"/>
+   </root>
+
+</log4j:configuration>


commit 005484491e18d138e1c58c5f65a330abf435bbe4
Author: Heiko W. Rupp <hwr at redhat.com>
Date:   Wed Jul 4 09:46:11 2012 +0200

    BZ 797331 - If a network adapter is down on plugin component start, mark it as disabled.

diff --git a/modules/plugins/platform/src/main/java/org/rhq/plugins/platform/NetworkAdapterComponent.java b/modules/plugins/platform/src/main/java/org/rhq/plugins/platform/NetworkAdapterComponent.java
index 774dd08..72cea4e 100644
--- a/modules/plugins/platform/src/main/java/org/rhq/plugins/platform/NetworkAdapterComponent.java
+++ b/modules/plugins/platform/src/main/java/org/rhq/plugins/platform/NetworkAdapterComponent.java
@@ -1,99 +1,106 @@
-/*
- * 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, 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.plugins.platform;
-
-import java.net.InetAddress;
-import java.util.List;
-import java.util.Set;
-
-import org.rhq.core.domain.measurement.AvailabilityType;
-import org.rhq.core.domain.measurement.MeasurementDataNumeric;
-import org.rhq.core.domain.measurement.MeasurementDataTrait;
-import org.rhq.core.domain.measurement.MeasurementReport;
-import org.rhq.core.domain.measurement.MeasurementScheduleRequest;
-import org.rhq.core.pluginapi.inventory.ResourceComponent;
-import org.rhq.core.pluginapi.inventory.ResourceContext;
-import org.rhq.core.pluginapi.measurement.MeasurementFacet;
-import org.rhq.core.pluginapi.util.ObjectUtil;
-import org.rhq.core.system.NetworkAdapterInfo;
-import org.rhq.core.system.NetworkAdapterStats;
-
-public class NetworkAdapterComponent implements ResourceComponent<PlatformComponent>, MeasurementFacet {
-    //private final Log log = LogFactory.getLog(NetworkAdapterComponent.class);
-
-    private ResourceContext<PlatformComponent> context;
-
-    public void start(ResourceContext<PlatformComponent> resourceContext) {
-        this.context = resourceContext;
-    }
-
-    public void stop() {
-    }
-
-    public AvailabilityType getAvailability() {
-        if (getInfo().getOperationalStatus() == NetworkAdapterInfo.OperationState.UP) {
-            return AvailabilityType.UP;
-        }
-
-        return AvailabilityType.DOWN;
-    }
-
-    private NetworkAdapterInfo getInfo() {
-        for (NetworkAdapterInfo info : this.context.getSystemInformation().getAllNetworkAdapters()) {
-            if (context.getResourceKey().equals(info.getName())) {
-                return info;
-            }
-        }
-
-        throw new RuntimeException("Could not find network adapter info [" + context.getResourceKey() + "]");
-    }
-
-    public void getValues(MeasurementReport report, Set<MeasurementScheduleRequest> metrics) {
-        NetworkAdapterInfo info = getInfo();
-        NetworkAdapterStats stats = this.context.getSystemInformation().getNetworkAdapterStats(info.getName());
-
-        for (MeasurementScheduleRequest request : metrics) {
-            String property = request.getName();
-
-            if (property.startsWith("Trait.net4.address")) // TODO
-            { // this trait is supported regardless of having native support or not
-                List<InetAddress> addrs = info.getUnicastAddresses();
-                String ifAddrs = (addrs.size() > 0) ? addrs.get(0).getHostAddress() : "";
-                for (int i = 1; i < addrs.size(); i++) {
-                    ifAddrs += "," + addrs.get(i).getHostAddress();
-                }
-
-                report.addData(new MeasurementDataTrait(request, ifAddrs));
-            } else if (property.equals("Trait.interfaceFlags")) {
-                report.addData(new MeasurementDataTrait(request, info.getAllFlags()));
-            } else {
-                Number number = ((Number) ObjectUtil.lookupAttributeProperty(stats, request.getName()));
-                if (number != null) {
-                    report.addData(new MeasurementDataNumeric(request, number.doubleValue()));
-                }
-            }
-        }
-
-        return;
-    }
+/*
+ * 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, 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.plugins.platform;
+
+import java.net.InetAddress;
+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.measurement.AvailabilityType;
+import org.rhq.core.domain.measurement.MeasurementDataNumeric;
+import org.rhq.core.domain.measurement.MeasurementDataTrait;
+import org.rhq.core.domain.measurement.MeasurementReport;
+import org.rhq.core.domain.measurement.MeasurementScheduleRequest;
+import org.rhq.core.pluginapi.inventory.ResourceComponent;
+import org.rhq.core.pluginapi.inventory.ResourceContext;
+import org.rhq.core.pluginapi.measurement.MeasurementFacet;
+import org.rhq.core.pluginapi.util.ObjectUtil;
+import org.rhq.core.system.NetworkAdapterInfo;
+import org.rhq.core.system.NetworkAdapterStats;
+
+public class NetworkAdapterComponent implements ResourceComponent<PlatformComponent>, MeasurementFacet {
+    private final Log log = LogFactory.getLog(NetworkAdapterComponent.class);
+
+    private ResourceContext<PlatformComponent> context;
+
+    public void start(ResourceContext<PlatformComponent> resourceContext) {
+        this.context = resourceContext;
+        if (getInfo().getOperationalStatus()==NetworkAdapterInfo.OperationState.DOWN) {
+            context.getAvailabilityContext().disable();
+            log.info("Disabled " + context.getResourceKey() + " as it was down on start");
+        }
+    }
+
+    public void stop() {
+    }
+
+    public AvailabilityType getAvailability() {
+        if (getInfo().getOperationalStatus() == NetworkAdapterInfo.OperationState.UP) {
+            return AvailabilityType.UP;
+        }
+
+        return AvailabilityType.DOWN;
+    }
+
+    private NetworkAdapterInfo getInfo() {
+        for (NetworkAdapterInfo info : this.context.getSystemInformation().getAllNetworkAdapters()) {
+            if (context.getResourceKey().equals(info.getName())) {
+                return info;
+            }
+        }
+
+        throw new RuntimeException("Could not find network adapter info [" + context.getResourceKey() + "]");
+    }
+
+    public void getValues(MeasurementReport report, Set<MeasurementScheduleRequest> metrics) {
+        NetworkAdapterInfo info = getInfo();
+        NetworkAdapterStats stats = this.context.getSystemInformation().getNetworkAdapterStats(info.getName());
+
+        for (MeasurementScheduleRequest request : metrics) {
+            String property = request.getName();
+
+            if (property.startsWith("Trait.net4.address")) // TODO
+            { // this trait is supported regardless of having native support or not
+                List<InetAddress> addrs = info.getUnicastAddresses();
+                String ifAddrs = (addrs.size() > 0) ? addrs.get(0).getHostAddress() : "";
+                for (int i = 1; i < addrs.size(); i++) {
+                    ifAddrs += "," + addrs.get(i).getHostAddress();
+                }
+
+                report.addData(new MeasurementDataTrait(request, ifAddrs));
+            } else if (property.equals("Trait.interfaceFlags")) {
+                report.addData(new MeasurementDataTrait(request, info.getAllFlags()));
+            } else {
+                Number number = ((Number) ObjectUtil.lookupAttributeProperty(stats, request.getName()));
+                if (number != null) {
+                    report.addData(new MeasurementDataNumeric(request, number.doubleValue()));
+                }
+            }
+        }
+
+        return;
+    }
 }
\ No newline at end of file


commit 0a0c9a990684675cecf7b0dbef03a6a37bc20432
Author: Simeon Pinder <spinder at redhat.com>
Date:   Tue Jul 3 16:59:03 2012 -0400

     [BZ 828938] make sure reboot listener persists when agent is running in background.

diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/PluginContainer.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/PluginContainer.java
index 3515c55..e1883e4 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/PluginContainer.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/PluginContainer.java
@@ -693,7 +693,22 @@ public class PluginContainer {
     }
 
     public void notifyRebootRequestListener() {
-        rebootListener.reboot();
+        //BZ 828938: the thread needs to run as non-daemon so that it's allowed to complete cleanup in daemon mode
+        Thread rebootThread = new Thread(new Runnable() {
+            @Override
+            public void run() {
+                rebootListener.reboot();
+            }
+        });
+        rebootThread.setDaemon(false);
+        rebootThread.start();
+        try {
+            rebootThread.join();
+        } catch (InterruptedException e) {
+            log.error("Interrupted while rebooting agent after one or more resource types "
+                + " have been marked for deletion. You man need to manually reboot the agent/plugin container to purge "
+                + "stale types.");
+        }
     }
 
     /**


commit fc82a357767f64e22356588cb5645f17fa626fc0
Author: John Mazzitelli <mazz at redhat.com>
Date:   Tue Jul 3 16:05:35 2012 -0400

    [BZ 836664] allow oracle plugin to connect using the "service name URL". Thanks go to Richard Hensman for the patch.

diff --git a/modules/plugins/oracle/src/main/java/org/rhq/plugins/oracle/OracleServerComponent.java b/modules/plugins/oracle/src/main/java/org/rhq/plugins/oracle/OracleServerComponent.java
index 3d70eef..3849657 100644
--- a/modules/plugins/oracle/src/main/java/org/rhq/plugins/oracle/OracleServerComponent.java
+++ b/modules/plugins/oracle/src/main/java/org/rhq/plugins/oracle/OracleServerComponent.java
@@ -24,8 +24,10 @@ import java.sql.SQLException;
 import java.util.Map;
 import java.util.Properties;
 import java.util.Set;
+
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+
 import org.rhq.core.domain.configuration.Configuration;
 import org.rhq.core.domain.measurement.AvailabilityType;
 import org.rhq.core.domain.measurement.MeasurementDataNumeric;
@@ -128,7 +130,13 @@ public class OracleServerComponent implements DatabaseComponent, MeasurementFace
     }
 
     private static String buildUrl(Configuration configuration) {
-        return "jdbc:oracle:thin:@" + configuration.getSimpleValue("host", "localhost") + ":"
-            + configuration.getSimpleValue("port", "1521") + ":" + configuration.getSimpleValue("sid", "XE");
+        String connMethod = configuration.getSimpleValue("connectionMethod", "SID");
+        if (connMethod.equalsIgnoreCase("SID")) {
+            return "jdbc:oracle:thin:@" + configuration.getSimpleValue("host", "localhost") + ":"
+                + configuration.getSimpleValue("port", "1521") + ":" + configuration.getSimpleValue("sid", "XE");
+        } else {
+            return "jdbc:oracle:thin:@//" + configuration.getSimpleValue("host", "localhost") + ":"
+                + configuration.getSimpleValue("port", "1521") + "/" + configuration.getSimpleValue("sid", "XE");
+        }
     }
 }
\ No newline at end of file
diff --git a/modules/plugins/oracle/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/oracle/src/main/resources/META-INF/rhq-plugin.xml
index 27c9033..00f0284 100644
--- a/modules/plugins/oracle/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/oracle/src/main/resources/META-INF/rhq-plugin.xml
@@ -21,7 +21,16 @@
       <plugin-configuration>
          <c:simple-property name="host" default="localhost" displayName="Listen host" description="the hostname or IP address that the database is listening on"/>
          <c:simple-property name="port" default="1521" displayName="Listen port" description="the TCP port that the database is listening on"/>
-         <c:simple-property name="sid" default="XE" displayName="Database SID" description="the name of the database to connect to"/>
+
+         <c:simple-property name="connectionMethod" displayName="Connection Method" type="string" required="true" default="SID"
+                            description="The method used to connect to Oracle; defaults to 'SID'.">
+            <c:property-options>
+               <c:option value="SID"         name="SID"/>
+               <c:option value="SERVICENAME" name="Service name"/>
+            </c:property-options>
+         </c:simple-property>
+
+         <c:simple-property name="sid" default="XE" displayName="Database SID/Service name" description="SID or service name of the database to connect to"/>
 
          <c:simple-property name="driverClass" default="oracle.jdbc.driver.OracleDriver" displayName="JDBC driver class"
                             description="the fully-qualified classname of the JDBC driver class" required="false"/>


commit a0b4f34693d070063c74c22dc463b34fd8b82cdf
Author: Heiko W. Rupp <hwr at redhat.com>
Date:   Tue Jul 3 21:39:22 2012 +0200

    Update RESTEasy to 2.3.4.Final and enable GZIP compression on some methods.

diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerBean.java
index d602751..7c664b7 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerBean.java
@@ -60,8 +60,6 @@ import javax.ws.rs.core.StreamingOutput;
 import javax.ws.rs.core.UriBuilder;
 import javax.ws.rs.core.UriInfo;
 
-import com.arjuna.ats.internal.jdbc.drivers.modifiers.list;
-
 import org.jboss.cache.Fqn;
 
 import org.rhq.core.domain.common.EntityContext;
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerLocal.java
index 472fd1c..8ec3d82 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerLocal.java
@@ -45,6 +45,8 @@ import com.wordnik.swagger.annotations.ApiErrors;
 import com.wordnik.swagger.annotations.ApiOperation;
 import com.wordnik.swagger.annotations.ApiParam;
 
+import org.jboss.resteasy.annotations.GZIP;
+
 import org.rhq.enterprise.server.rest.domain.Baseline;
 import org.rhq.enterprise.server.rest.domain.MetricAggregate;
 import org.rhq.enterprise.server.rest.domain.MetricSchedule;
@@ -65,6 +67,7 @@ public interface MetricHandlerLocal {
     static String NO_RESOURCE_FOR_ID = "If no resource with the passed id exists";
     static String NO_SCHEDULE_FOR_ID = "No schedule with the passed id exists";
 
+    @GZIP
     @GET
     @Path("data/{scheduleId}")
     @Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML,MediaType.TEXT_HTML})
@@ -143,6 +146,7 @@ public interface MetricHandlerLocal {
      * @param headers Injected HttpHeaders
      * @return an encoded stream of numerical values
      */
+    @GZIP
     @ApiOperation(value = "Expose the raw metrics of a single schedule. This can only expose raw data, which means the start date may "
         + "not be older than 7 days.")
     @GET
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerLocal.java
index 867a0e4..b30f8ce 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerLocal.java
@@ -41,6 +41,7 @@ import com.wordnik.swagger.annotations.ApiError;
 import com.wordnik.swagger.annotations.ApiOperation;
 import com.wordnik.swagger.annotations.ApiParam;
 
+import org.jboss.resteasy.annotations.GZIP;
 import org.jboss.resteasy.annotations.cache.Cache;
 import org.jboss.resteasy.links.AddLinks;
 import org.jboss.resteasy.links.LinkResource;
@@ -74,6 +75,7 @@ public interface ResourceHandlerLocal {
             @Context Request request, @Context HttpHeaders headers,
                          @Context UriInfo uriInfo);
 
+    @GZIP
     @GET
     @Path("/platforms")
     @Cache(isPrivate = true,maxAge = 300)
@@ -97,6 +99,7 @@ public interface ResourceHandlerLocal {
     Response getAvailability(
             @ApiParam("Id of the resource to query") @PathParam("id") int resourceId, @Context HttpHeaders headers);
 
+    @GZIP
     @GET
     @Path("/{id}/availability/history")
     @ApiError(code = 404, reason = NO_RESOURCE_FOR_ID)
@@ -115,6 +118,7 @@ public interface ResourceHandlerLocal {
             @ApiParam("Id of the resource to update") @PathParam("id") int resourceId,
             @ApiParam(value= "New Availability setting", required = true) AvailabilityRest avail);
 
+    @GZIP
     @GET
     @Path("/{id}/schedules")
     @LinkResource(rel="schedules",value = MetricSchedule.class)
@@ -130,6 +134,7 @@ public interface ResourceHandlerLocal {
           @Context UriInfo uriInfo);
 
 
+    @GZIP
     @GET
     @Path("/{id}/children")
     @LinkResource(rel="children", value = ResourceWithType.class)
@@ -141,6 +146,7 @@ public interface ResourceHandlerLocal {
                          @Context UriInfo uriInfo);
 
 
+    @GZIP
     @AddLinks
     @GET
     @Path(("/{id}/alerts"))
diff --git a/modules/enterprise/server/jar/src/main/xsl/apiout2docbook.xsl b/modules/enterprise/server/jar/src/main/xsl/apiout2docbook.xsl
index f9a5f83..d97645a 100644
--- a/modules/enterprise/server/jar/src/main/xsl/apiout2docbook.xsl
+++ b/modules/enterprise/server/jar/src/main/xsl/apiout2docbook.xsl
@@ -97,6 +97,9 @@
         </emphasis>
       </simpara>
       <simpara><xsl:value-of select="@description"/></simpara>
+      <xsl:if test="not(@gzip = '')">
+        <simpara>Supports returning a gzip'ed Content-Encoding</simpara>
+      </xsl:if>
       <xsl:choose>
         <xsl:when test="param">
           <table>
diff --git a/modules/enterprise/server/jar/src/main/xsl/apiout2html.xsl b/modules/enterprise/server/jar/src/main/xsl/apiout2html.xsl
index dff70ba..4cf7d4f 100644
--- a/modules/enterprise/server/jar/src/main/xsl/apiout2html.xsl
+++ b/modules/enterprise/server/jar/src/main/xsl/apiout2html.xsl
@@ -87,6 +87,9 @@
     </h3>
     <em><xsl:value-of select="@description"/></em>
     <br/>
+    <xsl:if test="not(@gzip = '')">
+      <p><em>Supports returning a gzip'ed Content-Encoding</em></p>
+    </xsl:if>
     <xsl:choose>
     <xsl:when test="param">
     Parameters:
diff --git a/modules/helpers/rest-docs-generator/pom.xml b/modules/helpers/rest-docs-generator/pom.xml
index 4010747..b6be916 100644
--- a/modules/helpers/rest-docs-generator/pom.xml
+++ b/modules/helpers/rest-docs-generator/pom.xml
@@ -149,6 +149,11 @@
       <version>1.1-SNAPSHOT</version>
     </dependency>
     <dependency>
+      <groupId>org.jboss.resteasy</groupId>
+      <artifactId>resteasy-jaxrs</artifactId>
+      <version>${resteasy.version}</version>
+    </dependency>
+    <dependency>
       <groupId>commons-logging</groupId>
       <artifactId>commons-logging</artifactId>
       <version>${commons-logging.version}</version>
diff --git a/modules/helpers/rest-docs-generator/src/main/java/org/rhq/helpers/rest_docs_generator/ClassLevelProcessor.java b/modules/helpers/rest-docs-generator/src/main/java/org/rhq/helpers/rest_docs_generator/ClassLevelProcessor.java
index 8144273..a3a6ddf 100644
--- a/modules/helpers/rest-docs-generator/src/main/java/org/rhq/helpers/rest_docs_generator/ClassLevelProcessor.java
+++ b/modules/helpers/rest-docs-generator/src/main/java/org/rhq/helpers/rest_docs_generator/ClassLevelProcessor.java
@@ -47,6 +47,8 @@ import org.apache.commons.logging.LogFactory;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
+import org.jboss.resteasy.annotations.GZIP;
+
 /**
  * Processor for JAX-RS classes
  * @author Heiko W. Rupp
@@ -213,6 +215,10 @@ public class ClassLevelProcessor extends AbstractProcessor {
 
         Element methodElement = doc.createElement("method");
         methodElement.setAttribute("path",path);
+        GZIP gzip = td.getAnnotation(GZIP.class);
+        if (gzip!=null) {
+            methodElement.setAttribute("gzip","true");
+        }
         classElement.appendChild(methodElement);
         Name elementName = td.getSimpleName();
         methodElement.setAttribute("name", elementName.toString());
diff --git a/pom.xml b/pom.xml
index 603b89d..8e99665 100644
--- a/pom.xml
+++ b/pom.xml
@@ -107,7 +107,7 @@
     <augeas.zip.location>${settings.localRepository}/net/augeas/augeas-native/${augeas.version}</augeas.zip.location>
     <augeas.zip.mask>*-${augeas.classifier}.zip</augeas.zip.mask>
     <ant.contrib.version>1.0b3</ant.contrib.version>
-    <resteasy.version>2.3.3.Final</resteasy.version>
+    <resteasy.version>2.3.4.Final</resteasy.version>
     <freemarker.version>2.3.18</freemarker.version>
     <powermock.version>1.4.11</powermock.version>
     <arquillian.version>1.0.1.Final</arquillian.version>


commit 4412e1e77d7914f7712a4426cb36f86d769f53c6
Author: Lukas Krejci <lkrejci at redhat.com>
Date:   Tue Jul 3 21:27:49 2012 +0200

    A couple of changes in this commit:
    1) RhqFacade.getManagers() returns a Map<RhqManager, Object> instead of
       a Map<String, Object>. Strong typing is good.
    2) ScriptSourceProviders hooked up with the ScriptEngineFactory and the
       StandardBindings so that they can be installed into the script engine
       and use the standard bindings or the rhq facade to do weird and wonderful
       things. A couple of basic impls of the ScriptSourceProviders were
       sprinkled about the codebase.
    3) ScriptSourceProviders are now loadable from META-INF/services so that
       it is easy for third parties to add their own impls.
    4) A new method added to RepoManagerRemote that enables download of an
       arbitrary package version from a repository (this is used by one of the
       script source providers to remotely download a script from the server).

diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/ScriptEngineFactory.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/ScriptEngineFactory.java
index fbaf1a7..9887958 100644
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/ScriptEngineFactory.java
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/ScriptEngineFactory.java
@@ -40,11 +40,14 @@ import javax.script.ScriptException;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
+import org.rhq.bindings.client.RhqManager;
+import org.rhq.bindings.util.MultiScriptSourceProvider;
 import org.rhq.bindings.util.NoTopLevelIndirection;
 import org.rhq.bindings.util.PackageFinder;
 import org.rhq.scripting.CodeCompletion;
 import org.rhq.scripting.ScriptEngineInitializer;
 import org.rhq.scripting.ScriptEngineProvider;
+import org.rhq.scripting.ScriptSourceProvider;
 
 /**
  * This is RHQ specific imitation of ScriptEngineFactory.
@@ -117,26 +120,26 @@ public class ScriptEngineFactory {
      * @param language the language of the script to instantiate
      * @param packageFinder the package finder to find the standard packages in user provided locations
      * @param bindings the initial standard bindings or null if none required
-     * @return the initialized engine or null if the engine for given language isn't known.
+     * 
+     * @return the initialized engine or null if a {@link ScriptEngineProvider} for given language isn't known.
      * 
      * @throws ScriptException on error during initialization of the script environment
      * @throws IOException if the package finder fails to find the packages
      */
-    public static ScriptEngine getScriptEngine(String language, PackageFinder packageFinder, StandardBindings bindings)
-        throws ScriptException, IOException {
-        
-        return getSecuredScriptEngine(language, packageFinder, bindings, null);         
+    public static ScriptEngine getScriptEngine(String language, PackageFinder packageFinder, StandardBindings bindings) throws ScriptException, IOException {
+
+        return getSecuredScriptEngine(language, packageFinder, bindings, null);
     }
 
     /**
-     * This method is similar to the {@link #getScriptEngine(String, PackageFinder, StandardBindings)} method
+     * This method is similar to the {@link #getScriptEngine(String, PackageFinder, StandardBindings, ScriptSourceProvider...)} method
      * but additionally applies a security wrapper on the returned script engine so that the scripts execute
      * with the provided java permissions.
      * 
-     * @see #getScriptEngine(String, PackageFinder, StandardBindings)
+     * @see #getScriptEngine(String, PackageFinder, StandardBindings, ScriptSourceProvider...)
      */
-    public static ScriptEngine getSecuredScriptEngine(final String language, final PackageFinder packageFinder,
-        final StandardBindings bindings, final PermissionCollection permissions) throws ScriptException, IOException {
+    public static ScriptEngine getSecuredScriptEngine(String language, PackageFinder packageFinder,
+        StandardBindings bindings, PermissionCollection permissions) throws ScriptException, IOException {
         
         ScriptEngineInitializer initializer = getInitializer(language);
 
@@ -144,9 +147,8 @@ public class ScriptEngineFactory {
             return null;
         }
 
-        //TODO change this so that we support supplying a custom module source provider so that callers
-        //have control over the location of the loadable scripts.
-        ScriptEngine engine = initializer.instantiate(packageFinder.findPackages("org.rhq.core.domain"), null, permissions);
+        ScriptEngine engine = initializer.instantiate(packageFinder.findPackages("org.rhq.core.domain"),
+            permissions);
 
         if (bindings != null) {
             injectStandardBindings(engine, bindings, true);
@@ -162,10 +164,15 @@ public class ScriptEngineFactory {
      * @param engine the engine
      * @param bindings the bindings
      * @param deleteExistingBindings true if the existing bindings should be replaced by the provided ones, false
-     * if the provided bindings should be added to the existing ones (possibly overwriting bindings with the same name).
+     *        if the provided bindings should be added to the existing ones (possibly overwriting bindings with the same name).
+     * @param scriptSourceProviders the list of script source providers to be used by the script engine to locate the scripts.
+     *        Note that the providers become associated with the script engine and its bindings and therefore should
+     *        not be used with any other script engine. If the providers implement the 
+     *        {@link StandardBindings.RhqFacadeChangeListener} interface, they will be automatically hooked up with the
+     *        <code>bindings</code> so that the providers will get notified whenever the rhq facade changes.
      */
     public static void injectStandardBindings(ScriptEngine engine, StandardBindings bindings,
-        boolean deleteExistingBindings) {
+        boolean deleteExistingBindings, ScriptSourceProvider... scriptSourceProviders) {
         bindings.preInject(engine);
 
         Bindings engineBindings = deleteExistingBindings ? engine.createBindings() : engine
@@ -175,6 +182,28 @@ public class ScriptEngineFactory {
             engineBindings.put(entry.getKey(), entry.getValue());
         }
 
+        if (scriptSourceProviders != null) {
+            //first figure out which initializer to use with this script engine
+            String language = (String) engine.getFactory().getParameter(ScriptEngine.NAME);
+            ScriptEngineProvider engineProvider = KNOWN_PROVIDERS.get(language);
+            if (engineProvider == null) {
+                throw new IllegalArgumentException("The supplied script engine [" + engine + "] is not supported.");
+            }
+
+            ScriptEngineInitializer initializer = engineProvider.getInitializer();
+
+            ScriptSourceProvider provider = null;
+
+            for (ScriptSourceProvider p : scriptSourceProviders) {
+                if (p instanceof StandardBindings.RhqFacadeChangeListener) {
+                    bindings.addRhqFacadeChangeListener((StandardBindings.RhqFacadeChangeListener) p);
+                }
+            }
+            provider = new MultiScriptSourceProvider(scriptSourceProviders);
+
+            initializer.installScriptSourceProvider(engine, provider);
+        }
+
         engine.setBindings(engineBindings, ScriptContext.ENGINE_SCOPE);
 
         bindings.postInject(engine);
@@ -186,12 +215,12 @@ public class ScriptEngineFactory {
      * @param engine the engine
      * @param keySet the binding keys to be removed
      */
-    public static void removeBindings(ScriptEngine engine, Set<String> keySet) {
+    public static void removeBindings(ScriptEngine engine, Set<RhqManager> keySet) {
 
         Bindings engineBindings = engine.getBindings(ScriptContext.ENGINE_SCOPE);
 
-        for (String key : keySet) {
-            engineBindings.remove(key);
+        for (RhqManager key : keySet) {
+            engineBindings.remove(key.name());
         }
 
         engine.setBindings(engineBindings, ScriptContext.ENGINE_SCOPE);
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/StandardBindings.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/StandardBindings.java
index 812b4ae..3e1e137 100644
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/StandardBindings.java
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/StandardBindings.java
@@ -22,13 +22,15 @@ package org.rhq.bindings;
 import java.io.PrintWriter;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Map;
+import java.util.Set;
 
-import javax.script.ScriptContext;
 import javax.script.ScriptEngine;
 
 import org.rhq.bindings.client.ResourceClientFactory;
 import org.rhq.bindings.client.RhqFacade;
+import org.rhq.bindings.client.RhqManager;
 import org.rhq.bindings.export.Exporter;
 import org.rhq.bindings.output.TabularWriter;
 import org.rhq.bindings.util.ScriptAssert;
@@ -49,6 +51,14 @@ import org.rhq.core.domain.util.PageControl;
  */
 public class StandardBindings extends HashMap<String, Object> {
 
+    /**
+     * A listener interface for objects that need to be aware of the fact that the
+     * RHQ facade associated with the bidings has changed.
+     */
+    public interface RhqFacadeChangeListener {
+        void rhqFacadeChanged(StandardBindings bindings);
+    }
+
     private static final long serialVersionUID = 1L;
 
     public static final String UNLIMITED_PC = "unlimitedPC";
@@ -60,7 +70,9 @@ public class StandardBindings extends HashMap<String, Object> {
     public static final String PROXY_FACTORY = "ProxyFactory";
     public static final String ASSERT = "Assert";
 
-    private Map<String, Object> managers;
+    private Map<RhqManager, Object> managers;
+    private Set<RhqFacadeChangeListener> facadeChangeListeners;
+    private RhqFacade rhqFacade;
 
     private static class CastingEntry<T> implements Map.Entry<String, T> {
 
@@ -90,6 +102,7 @@ public class StandardBindings extends HashMap<String, Object> {
     }
 
     public StandardBindings(PrintWriter output, RhqFacade rhqFacade) {
+        facadeChangeListeners = new HashSet<RhqFacadeChangeListener>();
         PageControl pc = new PageControl();
         pc.setPageNumber(-1);
 
@@ -110,8 +123,8 @@ public class StandardBindings extends HashMap<String, Object> {
     public void setFacade(PrintWriter output, RhqFacade rhqFacade) {
         // remove any existing managers    
         if (null != managers) {
-            for (String manager : managers.keySet()) {
-                remove(manager);
+            for (RhqManager manager : managers.keySet()) {
+                remove(manager.name());
             }
             managers.clear();
         }
@@ -130,7 +143,26 @@ public class StandardBindings extends HashMap<String, Object> {
             put(PROXY_FACTORY, null);
         }
 
-        putAll(managers);
+        for (Map.Entry<RhqManager, Object> entry : managers.entrySet()) {
+            put(entry.getKey().name(), entry.getValue());
+        }
+
+        this.rhqFacade = rhqFacade;
+
+        notifyFacadeChanged();
+    }
+
+    public RhqFacade getAssociatedRhqFacade() {
+        return rhqFacade;
+    }
+
+    public void addRhqFacadeChangeListener(RhqFacadeChangeListener listener) {
+        this.facadeChangeListeners.add(listener);
+        listener.rhqFacadeChanged(this);
+    }
+
+    public void removeRhqFacadeChangeListere(RhqFacadeChangeListener listener) {
+        this.facadeChangeListeners.remove(listener);
     }
 
     public void preInject(ScriptEngine scriptEngine) {
@@ -171,7 +203,7 @@ public class StandardBindings extends HashMap<String, Object> {
         return castEntry(PROXY_FACTORY, ResourceClientFactory.class);
     }
 
-    public Map<String, Object> getManagers() {
+    public Map<RhqManager, Object> getManagers() {
         //XXX ideally this should be a projection into our map          
         return (null == managers) ? managers = Collections.emptyMap() : managers;
     }
@@ -196,4 +228,10 @@ public class StandardBindings extends HashMap<String, Object> {
 
         return new CastingEntry<T>(entry, clazz);
     }
+
+    private void notifyFacadeChanged() {
+        for (RhqFacadeChangeListener listener : facadeChangeListeners) {
+            listener.rhqFacadeChanged(this);
+        }
+    }
 }
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/RhqFacade.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/RhqFacade.java
index b975436..2f80f0c 100644
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/RhqFacade.java
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/RhqFacade.java
@@ -47,7 +47,7 @@ public interface RhqFacade {
      * 
      * @return a map of all available proxied managers keyed by their names.
      */
-    Map<String, Object> getScriptingAPI();
+    Map<RhqManager, Object> getScriptingAPI();
 
     /**
      * Unlike the {@link #getScriptingAPI()} method that returns objects with modified signatures
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/script/BaseRhqSchemeScriptSourceProvider.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/script/BaseRhqSchemeScriptSourceProvider.java
new file mode 100644
index 0000000..d90403d
--- /dev/null
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/script/BaseRhqSchemeScriptSourceProvider.java
@@ -0,0 +1,63 @@
+/*
+ * RHQ Management Platform
+ * Copyright 2012, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.bindings.script;
+
+import java.io.Reader;
+import java.net.URI;
+
+import org.rhq.scripting.ScriptSourceProvider;
+
+/**
+ * @author Lukas Krejci
+ */
+public abstract class BaseRhqSchemeScriptSourceProvider implements ScriptSourceProvider {
+
+    public static final String SCHEME = "rhq";
+
+    @Override
+    public Reader getScriptSource(URI scriptUri) {
+        if (scriptUri == null || !SCHEME.equals(scriptUri.getScheme())) {
+            return null;
+        }
+
+        String path = scriptUri.getSchemeSpecificPart();
+
+        if (!path.startsWith("//")) {
+            return null;
+        }
+
+        return doGetScriptSource(scriptUri);
+    }
+
+    /**
+     * Implement this method to provide the script source.
+     * The base implementation of the {@link #getScriptSource(URI)} method
+     * only checks that the scheme of the URI is "rhq" and that the scheme
+     * specific part starts with "//".
+     * 
+     * @param scriptUri
+     * @return the reader of the script or null if the script could not be 
+     * found using the URI
+     * 
+     * @see #getScriptSource(URI)
+     */
+    protected abstract Reader doGetScriptSource(URI scriptUri);
+}
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/script/RepoScriptSourceProvider.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/script/RepoScriptSourceProvider.java
new file mode 100644
index 0000000..b316dea
--- /dev/null
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/script/RepoScriptSourceProvider.java
@@ -0,0 +1,127 @@
+/*
+ * RHQ Management Platform
+ * Copyright 2012, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.bindings.script;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.net.URI;
+import java.nio.charset.Charset;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.rhq.bindings.StandardBindings;
+import org.rhq.bindings.client.RhqFacade;
+import org.rhq.core.domain.content.Repo;
+import org.rhq.core.domain.content.composite.PackageAndLatestVersionComposite;
+import org.rhq.core.domain.criteria.PackageCriteria;
+import org.rhq.core.domain.criteria.RepoCriteria;
+import org.rhq.enterprise.server.content.ContentManagerRemote;
+import org.rhq.enterprise.server.content.RepoManagerRemote;
+
+/**
+ * The implementation of script source provider that is able to locate the script files
+ * in the repositories on the RHQ server.
+ * <p>
+ * The URI looks like:<br>
+ * <code>
+ * rhq://repositories/repositoryName/scriptFile
+ * </code>
+ *  
+ * @author Lukas Krejci
+ */
+public class RepoScriptSourceProvider extends BaseRhqSchemeScriptSourceProvider implements
+    StandardBindings.RhqFacadeChangeListener {
+
+    private static final Log LOG = LogFactory.getLog(RepoScriptSourceProvider.class);
+
+    private static final String PREFIX = "//repositories/";
+
+    private RhqFacade rhqFacade;
+
+    @Override
+    public void rhqFacadeChanged(StandardBindings bindings) {
+        this.rhqFacade = bindings.getAssociatedRhqFacade();
+    }
+
+    @Override
+    protected Reader doGetScriptSource(URI scriptUri) {
+        if (rhqFacade == null) {
+            return null;
+        }
+
+        String path = scriptUri.getSchemeSpecificPart();
+
+        if (!path.startsWith(PREFIX)) {
+            return null;
+        }
+
+        path = path.substring(PREFIX.length());
+
+        int slashIdx = path.indexOf('/');
+
+        if (slashIdx == -1) {
+            return null;
+        }
+
+        String repoName = path.substring(0, slashIdx);
+        String scriptName = path.substring(slashIdx + 1);
+
+        try {
+            RepoManagerRemote repoManager = rhqFacade.getProxy(RepoManagerRemote.class);
+
+            RepoCriteria repoCrit = new RepoCriteria();
+            repoCrit.addFilterName(repoName);
+            List<Repo> repos = repoManager.findReposByCriteria(rhqFacade.getSubject(), repoCrit);
+
+            if (repos.isEmpty()) {
+                return null;
+            }
+
+            ContentManagerRemote contentManager = rhqFacade.getProxy(ContentManagerRemote.class);
+
+            for (Repo repo : repos) {
+                PackageCriteria pCrit = new PackageCriteria();
+                pCrit.addFilterName(scriptName);
+                pCrit.addFilterRepoId(repo.getId());
+
+                List<PackageAndLatestVersionComposite> pvs = contentManager.findPackagesWithLatestVersion(
+                    rhqFacade.getSubject(), pCrit);
+
+                if (!pvs.isEmpty()) {
+                    PackageAndLatestVersionComposite pv = pvs.get(0);
+
+                    byte[] bytes = repoManager.getPackageVersionBytes(rhqFacade.getSubject(), repo.getId(), pv
+                        .getLatestPackageVersion().getId());
+
+                    return new InputStreamReader(new ByteArrayInputStream(bytes), Charset.forName("UTF-8"));
+                }
+            }
+        } catch (Exception e) {
+            LOG.debug("Failed to download bytes for the script: " + scriptUri.toString(), e);
+        }
+
+        return null;
+    }
+
+}
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/MultiScriptSourceProvider.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/MultiScriptSourceProvider.java
new file mode 100644
index 0000000..072e70f
--- /dev/null
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/MultiScriptSourceProvider.java
@@ -0,0 +1,66 @@
+/*
+ * RHQ Management Platform
+ * Copyright 2012, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.bindings.util;
+
+import java.io.Reader;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+
+import org.rhq.scripting.ScriptSourceProvider;
+
+/**
+ * An implementation of the script source provider that uses a collection of another
+ * providers to locate the scripts.
+ * <p>
+ * The providers are tried in the order they were supplied to the constructor of this class
+ * and the first script source provider that manages to provide a non-null reader for
+ * given URI "wins".
+ *  
+ * @author Lukas Krejci
+ */
+public class MultiScriptSourceProvider implements ScriptSourceProvider {
+
+    private Collection<ScriptSourceProvider> providers;
+
+    public MultiScriptSourceProvider(Collection<? extends ScriptSourceProvider> providers) {
+        this.providers = new ArrayList<ScriptSourceProvider>(providers);
+    }
+
+    public MultiScriptSourceProvider(ScriptSourceProvider... providers) {
+        this.providers = new ArrayList<ScriptSourceProvider>(Arrays.asList(providers));
+    }
+
+    @Override
+    public Reader getScriptSource(URI scriptUri) {
+
+        for (ScriptSourceProvider provider : providers) {
+            Reader rdr = provider.getScriptSource(scriptUri);
+            if (rdr != null) {
+                return rdr;
+            }
+        }
+
+        return null;
+    }
+
+}
diff --git a/modules/enterprise/binding/src/main/resources/META-INF/services/org.rhq.scripting.ScriptSourceProvider b/modules/enterprise/binding/src/main/resources/META-INF/services/org.rhq.scripting.ScriptSourceProvider
new file mode 100644
index 0000000..4d0472e
--- /dev/null
+++ b/modules/enterprise/binding/src/main/resources/META-INF/services/org.rhq.scripting.ScriptSourceProvider
@@ -0,0 +1 @@
+org.rhq.bindings.script.RepoScriptSourceProvider
diff --git a/modules/enterprise/binding/src/test/java/org/rhq/bindings/FakeRhqFacade.java b/modules/enterprise/binding/src/test/java/org/rhq/bindings/FakeRhqFacade.java
index d42f3e1..39cb145 100644
--- a/modules/enterprise/binding/src/test/java/org/rhq/bindings/FakeRhqFacade.java
+++ b/modules/enterprise/binding/src/test/java/org/rhq/bindings/FakeRhqFacade.java
@@ -23,6 +23,7 @@ import java.util.Collections;
 import java.util.Map;
 
 import org.rhq.bindings.client.RhqFacade;
+import org.rhq.bindings.client.RhqManager;
 import org.rhq.core.domain.auth.Subject;
 
 public class FakeRhqFacade implements RhqFacade {
@@ -43,7 +44,7 @@ public class FakeRhqFacade implements RhqFacade {
         return false;
     }
     
-    public Map<String, Object> getScriptingAPI() {
+    public Map<RhqManager, Object> getScriptingAPI() {
         return Collections.emptyMap();
     }
 
diff --git a/modules/enterprise/binding/src/test/java/org/rhq/bindings/script/RepoScriptSourceProviderTest.java b/modules/enterprise/binding/src/test/java/org/rhq/bindings/script/RepoScriptSourceProviderTest.java
new file mode 100644
index 0000000..db3953a
--- /dev/null
+++ b/modules/enterprise/binding/src/test/java/org/rhq/bindings/script/RepoScriptSourceProviderTest.java
@@ -0,0 +1,160 @@
+/*
+ * RHQ Management Platform
+ * Copyright 2012, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.bindings.script;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.Reader;
+import java.lang.reflect.Field;
+import java.net.URI;
+import java.nio.charset.Charset;
+import java.util.List;
+
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import org.rhq.bindings.StandardBindings;
+import org.rhq.bindings.client.RhqFacade;
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.content.PackageVersion;
+import org.rhq.core.domain.content.Repo;
+import org.rhq.core.domain.content.composite.PackageAndLatestVersionComposite;
+import org.rhq.core.domain.criteria.PackageCriteria;
+import org.rhq.core.domain.criteria.RepoCriteria;
+import org.rhq.core.domain.util.PageControl;
+import org.rhq.core.domain.util.PageList;
+import org.rhq.enterprise.server.content.ContentManagerRemote;
+import org.rhq.enterprise.server.content.RepoManagerRemote;
+
+/**
+ * @author Lukas Krejci
+ */
+ at Test
+public class RepoScriptSourceProviderTest {
+
+    private static final String SCRIPT_CONTENTS = "java.lang.System.out.println('This works!');";
+    private static final String CORRECT_REPO_NAME = "my-repo";
+    private static final int CORRECT_REPO_ID = 1;
+    private static final String CORRECT_PACKAGE_NAME = "my-script.js";
+    private static final int CORRECT_PACKAGE_VERSION_ID = 2;
+
+    public void testCanDownloadScript() throws Exception {
+        RhqFacade rhqFacade = mock(RhqFacade.class);
+
+        RepoManagerRemote repoManager = mock(RepoManagerRemote.class);
+        ContentManagerRemote contentManager = mock(ContentManagerRemote.class);
+        
+        when(rhqFacade.getProxy(RepoManagerRemote.class)).thenReturn(repoManager);
+        when(rhqFacade.getProxy(ContentManagerRemote.class)).thenReturn(contentManager);
+        
+        when(repoManager.findReposByCriteria(any(Subject.class), any(RepoCriteria.class))).then(
+            new Answer<List<Repo>>() {
+                @Override
+                public List<Repo> answer(InvocationOnMock invocation) throws Throwable {
+                    RepoCriteria crit = (RepoCriteria) invocation.getArguments()[1];
+
+                    //this is so wrong...
+                    Field f = RepoCriteria.class.getDeclaredField("filterName");
+                    f.setAccessible(true);
+                    String name = (String) f.get(crit);
+
+                    if (CORRECT_REPO_NAME.equals(name)) {
+                        Repo repo = new Repo(CORRECT_REPO_NAME);
+                        repo.setId(CORRECT_REPO_ID);
+
+                        PageList<Repo> ret = new PageList<Repo>(PageControl.getUnlimitedInstance());
+                        ret.add(repo);
+                        return ret;
+                    } else {
+                        return new PageList<Repo>(PageControl.getUnlimitedInstance());
+                    }
+                }
+            });
+        
+        when(contentManager.findPackagesWithLatestVersion(any(Subject.class), any(PackageCriteria.class))).then(
+            new Answer<List<PackageAndLatestVersionComposite>>() {
+                @Override
+                public List<PackageAndLatestVersionComposite> answer(InvocationOnMock invocation) throws Throwable {
+                    PackageCriteria crit = (PackageCriteria) invocation.getArguments()[1];
+
+                    //this is so wrong...
+                    Field f = PackageCriteria.class.getDeclaredField("filterName");
+                    f.setAccessible(true);
+                    String name = (String) f.get(crit);
+
+                    if (CORRECT_PACKAGE_NAME.equals(name)) {
+                        PackageAndLatestVersionComposite composite = new PackageAndLatestVersionComposite();
+
+                        composite
+                            .setGeneralPackage(new org.rhq.core.domain.content.Package(CORRECT_PACKAGE_NAME, null));
+
+                        PackageVersion pv = new PackageVersion();
+                        pv.setId(CORRECT_PACKAGE_VERSION_ID);
+
+                        composite.setLatestPackageVersion(pv);
+
+                        PageList<PackageAndLatestVersionComposite> ret = new PageList<PackageAndLatestVersionComposite>(
+                            PageControl.getUnlimitedInstance());
+                        ret.add(composite);
+                        return ret;
+                    } else {
+                        return new PageList<PackageAndLatestVersionComposite>(PageControl.getUnlimitedInstance());
+                    }
+                }
+            });
+
+        when(repoManager.getPackageVersionBytes(any(Subject.class), anyInt(), anyInt())).then(
+            new Answer<byte[]>() {
+                @Override
+                public byte[] answer(InvocationOnMock invocation) throws Throwable {
+                    int repoId = (Integer) invocation.getArguments()[1];
+                    int packageId = (Integer) invocation.getArguments()[2];
+
+                    if (repoId == CORRECT_REPO_ID && packageId == CORRECT_PACKAGE_VERSION_ID) {
+                        return SCRIPT_CONTENTS.getBytes(Charset.forName("UTF-8"));
+                    } else {
+                        //TODO throw exceptions as the original method does
+                        return null;
+                    }
+                }
+            });
+
+        RepoScriptSourceProvider provider = new RepoScriptSourceProvider();
+        provider.rhqFacadeChanged(new StandardBindings(null, rhqFacade));
+
+        URI uri = new URI("rhq://repositories/" + CORRECT_REPO_NAME + "/" + CORRECT_PACKAGE_NAME);
+
+        Reader rdr = provider.getScriptSource(uri);
+
+        StringBuilder bld = new StringBuilder();
+        int c;
+        while ((c = rdr.read()) != -1) {
+            bld.append((char) c);
+        }
+
+        Assert.assertEquals(bld.toString(), SCRIPT_CONTENTS, "Unexpected script contents.");
+    }
+}
diff --git a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/HelpCommand.java b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/HelpCommand.java
index 69b3c7a..a415f25 100644
--- a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/HelpCommand.java
+++ b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/HelpCommand.java
@@ -18,9 +18,9 @@
  */
 package org.rhq.enterprise.client.commands;
 
+import java.lang.annotation.Annotation;
 import java.lang.reflect.Method;
 import java.lang.reflect.Type;
-import java.lang.annotation.Annotation;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -28,12 +28,13 @@ import java.util.Comparator;
 import java.util.List;
 import java.util.Map;
 
+import javax.jws.WebParam;
+
+import org.rhq.bindings.client.RhqManager;
 import org.rhq.bindings.output.TabularWriter;
 import org.rhq.enterprise.client.ClientMain;
 import org.rhq.enterprise.client.utility.ReflectionUtility;
 
-import javax.jws.WebParam;
-
 /**
  * @author Greg Hinkle
  */
@@ -61,16 +62,16 @@ public class HelpCommand implements ClientCommand {
             tw.setHideRowCount(true);
             tw.print(data);
         } else if ("api".equals(args[1])) {
-            Map<String, Object> services = client.getRemoteClient().getScriptingAPI();
+            Map<RhqManager, Object> services = client.getRemoteClient().getScriptingAPI();
             if (args.length == 2) {
                 TabularWriter tw = new TabularWriter(client.getPrintWriter(), "API", "Package");
                 tw.setWidth(client.getConsoleWidth());
 
                 String[][] data = new String[services.size()][2];
                 int i = 0;
-                for (String apiName : services.keySet()) {
-                    data[i][0] = apiName;
-                    Object service = services.get(apiName);
+                for (RhqManager api : services.keySet()) {
+                    data[i][0] = api.name();
+                    Object service = services.get(api);
                     data[i][1] = service.getClass().getInterfaces()[0].getPackage().getName();
                     i++;
                 }
diff --git a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/ScriptCommand.java b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/ScriptCommand.java
index e80c346..a511310 100644
--- a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/ScriptCommand.java
+++ b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/ScriptCommand.java
@@ -27,7 +27,6 @@ import java.io.InputStreamReader;
 import java.io.Reader;
 import java.util.Arrays;
 
-import javax.script.ScriptContext;
 import javax.script.ScriptEngine;
 import javax.script.ScriptException;
 
@@ -38,7 +37,6 @@ import org.rhq.bindings.ScriptEngineFactory;
 import org.rhq.bindings.StandardBindings;
 import org.rhq.bindings.client.RhqManager;
 import org.rhq.bindings.output.TabularWriter;
-import org.rhq.bindings.util.PackageFinder;
 import org.rhq.enterprise.client.ClientMain;
 import org.rhq.enterprise.client.Controller;
 import org.rhq.enterprise.client.proxy.ConfigurationEditor;
@@ -49,6 +47,8 @@ import org.rhq.enterprise.client.script.CommandLineParseException;
 import org.rhq.enterprise.client.script.NamedScriptArg;
 import org.rhq.enterprise.client.script.ScriptArg;
 import org.rhq.enterprise.client.script.ScriptCmdLine;
+import org.rhq.scripting.ScriptSourceProvider;
+import org.rhq.scripting.ScriptSourceProviderFactory;
 
 /**
  * @author Greg Hinkle
@@ -185,7 +185,9 @@ public class ScriptCommand implements ClientCommand {
 
         ScriptEngine engine = client.getScriptEngine();
 
-        ScriptEngineFactory.injectStandardBindings(engine, bindings, false);
+        ScriptSourceProvider[] sourceProviders = ScriptSourceProviderFactory.get(null);
+
+        ScriptEngineFactory.injectStandardBindings(engine, bindings, false, sourceProviders);
 
         ScriptEngineFactory.bindIndirectionMethods(engine, "configurationEditor");
         ScriptEngineFactory.bindIndirectionMethods(engine, "rhq");
@@ -206,7 +208,7 @@ public class ScriptCommand implements ClientCommand {
 
             // update the engine with the new client bindings. Keep the existing engine bindings as they
             // may contain bindings outside this standard set (like any var created by the script or command line user)
-            ScriptEngineFactory.injectStandardBindings(engine, bindings, false);
+            ScriptEngineFactory.injectStandardBindings(engine, bindings, false, ScriptSourceProviderFactory.get(null));
         }
 
         return;
diff --git a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/script/SamplesScriptSourceProvider.java b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/script/SamplesScriptSourceProvider.java
new file mode 100644
index 0000000..ca328b1
--- /dev/null
+++ b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/script/SamplesScriptSourceProvider.java
@@ -0,0 +1,67 @@
+/*
+ * RHQ Management Platform
+ * Copyright 2012, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.client.script;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.net.URI;
+import java.nio.charset.Charset;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.rhq.bindings.script.BaseRhqSchemeScriptSourceProvider;
+
+/**
+ * @author Lukas Krejci
+ */
+public class SamplesScriptSourceProvider extends BaseRhqSchemeScriptSourceProvider {
+
+    private static final Log LOG = LogFactory.getLog(SamplesScriptSourceProvider.class);
+
+    private static final String PREFIX = "//samples/";
+
+    @Override
+    protected Reader doGetScriptSource(URI scriptUri) {
+        String path = scriptUri.getSchemeSpecificPart();
+
+        if (!path.startsWith(PREFIX)) {
+            return null;
+        }
+
+        path = path.substring(2); //remove the leading '//';
+
+        //here we suppose that the CLI was started using the rhq-cli.(sh|bat) script
+        //which sets the working directory to the root of the CLI deployment
+        File file = new File(path);
+
+        try {
+            return new InputStreamReader(new FileInputStream(file), Charset.forName("UTF-8"));
+        } catch (FileNotFoundException e) {
+            LOG.debug("Failed to locate the script at: " + scriptUri, e);
+            return null;
+        }
+    }
+
+}
diff --git a/modules/enterprise/remoting/cli/src/main/resources/META-INF/services/org.rhq.scripting.ScriptSourceProvider b/modules/enterprise/remoting/cli/src/main/resources/META-INF/services/org.rhq.scripting.ScriptSourceProvider
new file mode 100644
index 0000000..9722a1c
--- /dev/null
+++ b/modules/enterprise/remoting/cli/src/main/resources/META-INF/services/org.rhq.scripting.ScriptSourceProvider
@@ -0,0 +1 @@
+org.rhq.enterprise.client.script.SamplesScriptSourceProvider
diff --git a/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RemoteClient.java b/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RemoteClient.java
index 4ea3267..0fd4b92 100644
--- a/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RemoteClient.java
+++ b/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RemoteClient.java
@@ -62,7 +62,7 @@ public class RemoteClient implements RhqFacade {
     private final int port;
     private boolean loggedIn;
     private boolean connected;
-    private Map<String, Object> managers;
+    private Map<RhqManager, Object> managers;
     private Subject subject;
     private Client remotingClient;
     private String subsystem = null;
@@ -277,16 +277,16 @@ public class RemoteClient implements RhqFacade {
      *
      * @return Map K=manager name V=remote proxy
      */
-    public Map<String, Object> getScriptingAPI() {
+    public Map<RhqManager, Object> getScriptingAPI() {
         if (this.managers == null) {
 
-            this.managers = new HashMap<String, Object>();
+            this.managers = new HashMap<RhqManager, Object>();
 
             for (RhqManager manager : RhqManager.values()) {
                 if (manager.enabled()) {
                     try {
                         Object proxy = getProcessor(this, manager, true);
-                        this.managers.put(manager.name(), proxy);
+                        this.managers.put(manager, proxy);
                     } catch (Throwable e) {
                         LOG.error("Failed to load manager " + manager + " due to missing class.", e);
                     }
diff --git a/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RhqDownloadsScriptSourceProvider.java b/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RhqDownloadsScriptSourceProvider.java
new file mode 100644
index 0000000..663e1b3
--- /dev/null
+++ b/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RhqDownloadsScriptSourceProvider.java
@@ -0,0 +1,89 @@
+/*
+ * RHQ Management Platform
+ * Copyright 2012, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.clientapi;
+
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URL;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.rhq.bindings.StandardBindings;
+import org.rhq.bindings.client.RhqFacade;
+import org.rhq.bindings.script.BaseRhqSchemeScriptSourceProvider;
+
+/**
+ * @author Lukas Krejci
+ */
+public class RhqDownloadsScriptSourceProvider extends BaseRhqSchemeScriptSourceProvider implements
+    StandardBindings.RhqFacadeChangeListener {
+
+    private static final Log LOG = LogFactory.getLog(RhqDownloadsScriptSourceProvider.class);
+
+    private static final String PREFIX = "//downloads/";
+
+    private RemoteClient remoteClient;
+
+    @Override
+    public void rhqFacadeChanged(StandardBindings bindings) {
+        RhqFacade facade = bindings.getAssociatedRhqFacade();
+
+        if (facade instanceof RemoteClient) {
+            remoteClient = (RemoteClient) facade;
+        } else {
+            remoteClient = null;
+        }
+    }
+
+    @Override
+    protected Reader doGetScriptSource(URI scriptUri) {
+        if (remoteClient == null) {
+            return null;
+        }
+
+        String path = scriptUri.getSchemeSpecificPart();
+
+        if (!path.startsWith(PREFIX)) {
+            return null;
+        }
+
+        path.substring(1); //remove the leading '/'
+
+        String urlString = remoteClient.getTransport() + "://" + remoteClient.getHost() + ":" + remoteClient.getPort()
+            + path;
+
+        try {
+            URL downloadUrl = new URL(urlString);
+
+            return new InputStreamReader(downloadUrl.openStream());
+        } catch (MalformedURLException e) {
+            LOG.debug("Failed to download the script from the RHQ server using URL: " + urlString, e);
+        } catch (IOException e) {
+            LOG.debug("Failed to download the script from the RHQ server using URL: " + urlString, e);
+        }
+
+        return null;
+    }
+}
diff --git a/modules/enterprise/remoting/client-api/src/main/resources/META-INF/services/org.rhq.scripting.ScriptSourceProvider b/modules/enterprise/remoting/client-api/src/main/resources/META-INF/services/org.rhq.scripting.ScriptSourceProvider
new file mode 100644
index 0000000..4008d4a
--- /dev/null
+++ b/modules/enterprise/remoting/client-api/src/main/resources/META-INF/services/org.rhq.scripting.ScriptSourceProvider
@@ -0,0 +1 @@
+org.rhq.enterprise.clientapi.RhqDownloadsScriptSourceProvider
diff --git a/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptEngineInitializer.java b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptEngineInitializer.java
index 9365304..ffeffd7 100644
--- a/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptEngineInitializer.java
+++ b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptEngineInitializer.java
@@ -47,9 +47,19 @@ public interface ScriptEngineInitializer {
      * @return a newly instantiated script engine configured as above
      * @throws ScriptException
      */
-    ScriptEngine instantiate(Set<String> packages, ScriptSourceProvider scriptSourceProvider, PermissionCollection permissions) throws ScriptException;
+    ScriptEngine instantiate(Set<String> packages, PermissionCollection permissions) throws ScriptException;
     
     /**
+     * Installs given script source provider into the script engine.
+     * 
+     * @param scriptEngine
+     * @param scriptSourceProvider
+     * 
+     * @throws IllegalArgumentException if the script engine is not supported by this initializer
+     */
+    void installScriptSourceProvider(ScriptEngine scriptEngine, ScriptSourceProvider scriptSourceProvider);
+
+    /**
      * This function returns a definition string in the script engine's language
      * that provides an indirection to calling the method on the bound object.
      * 
diff --git a/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptEngineProvider.java b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptEngineProvider.java
index 2742970..067ed90 100644
--- a/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptEngineProvider.java
+++ b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptEngineProvider.java
@@ -25,7 +25,15 @@ import org.jetbrains.annotations.Nullable;
 /**
  * This is the service interface for scripting language implementations for RHQ
  * (loaded using the META-INF/services mechanism).
- *
+ * <p>
+ * Note that the API module provides no factory class that would load the ScriptEngineProvider 
+ * implementations present on the classpath. That is because for the script engine to be
+ * usable by RHQ, it needs to be initialized with a couple of dependencies that are not
+ * appropriate for the API module.
+ * <p>
+ * The factory is located in the <code>rhq-script-bindings</code> module as 
+ * <code>org.rhq.bindings.ScriptEngineFactory</code>.
+ * 
  * @author Lukas Krejci
  */
 public interface ScriptEngineProvider {
diff --git a/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptSourceProvider.java b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptSourceProvider.java
index 276e385..c91b706 100644
--- a/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptSourceProvider.java
+++ b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptSourceProvider.java
@@ -26,7 +26,10 @@ import java.net.URI;
  * Scripts in RHQ can be stored in various locations or maybe not even in the filesystem.
  * Implementations of this interface can be used to provide the contents of the scripts
  * based on URIs. 
- *
+ * <p>
+ * Implementations of this interface can be located using the {@link ScriptSourceProviderFactory}
+ * if they are registered in META-INF/services.
+ * 
  * @author Lukas Krejci
  */
 public interface ScriptSourceProvider {
diff --git a/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptSourceProviderFactory.java b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptSourceProviderFactory.java
new file mode 100644
index 0000000..3373792
--- /dev/null
+++ b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptSourceProviderFactory.java
@@ -0,0 +1,61 @@
+/*
+ * RHQ Management Platform
+ * Copyright 2012, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.scripting;
+
+import java.util.ArrayList;
+import java.util.ServiceLoader;
+
+/**
+ * A factory class for the ScriptSourceProvider implementations.
+ * 
+ * @author Lukas Krejci
+ */
+public final class ScriptSourceProviderFactory {
+
+    private ScriptSourceProviderFactory() {
+
+    }
+
+    /**
+     * Loads the set of the available {@link ScriptSourceProvider} implementations
+     * present on the classpath and registered in META-INF/services.
+     * 
+     * @param classLoader the classloader to be used to locate the impls or null if the
+     * context class loader of the current thread should be used.
+     * 
+     * @return the set of the script source providers available
+     */
+    public static ScriptSourceProvider[] get(ClassLoader classLoader) {
+        ArrayList<ScriptSourceProvider> ps = new ArrayList<ScriptSourceProvider>();
+
+        if (classLoader == null) {
+            classLoader = Thread.currentThread().getContextClassLoader();
+        }
+
+        ServiceLoader<ScriptSourceProvider> loader = ServiceLoader.load(ScriptSourceProvider.class, classLoader);
+
+        for (ScriptSourceProvider provider : loader) {
+            ps.add(provider);
+        }
+
+        return ps.toArray(new ScriptSourceProvider[ps.size()]);
+    }
+}
diff --git a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineInitializer.java b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineInitializer.java
index 771ec1f..f4e2292 100644
--- a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineInitializer.java
+++ b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineInitializer.java
@@ -52,11 +52,10 @@ public class JsEngineInitializer implements ScriptEngineInitializer {
     private ScriptEngineManager engineManager = new ScriptEngineManager();
 
     @Override
-    public ScriptEngine instantiate(final Set<String> packages, final ScriptSourceProvider scriptSourceProvider,
-        PermissionCollection permissions) throws ScriptException {
+    public ScriptEngine instantiate(final Set<String> packages, PermissionCollection permissions) throws ScriptException {
         
         if (permissions == null) {
-            return instantiateUnsecured(packages, scriptSourceProvider);
+            return instantiateUnsecured(packages);
         } else {
             try {
                 CodeSource cs = new CodeSource(null, (Certificate[]) null);
@@ -67,7 +66,7 @@ public class JsEngineInitializer implements ScriptEngineInitializer {
                 return AccessController.doPrivileged(new PrivilegedExceptionAction<ScriptEngine>() {
                     @Override
                     public ScriptEngine run() throws Exception {
-                        return instantiateUnsecured(packages, scriptSourceProvider);
+                        return instantiateUnsecured(packages);
                     }
                 }, acc);
             } catch (PrivilegedActionException e) {
@@ -81,6 +80,21 @@ public class JsEngineInitializer implements ScriptEngineInitializer {
     }
 
     @Override
+    public void installScriptSourceProvider(ScriptEngine scriptEngine, ScriptSourceProvider scriptSourceProvider) {
+        if (!(scriptEngine instanceof RhinoScriptEngine)) {
+            throw new IllegalArgumentException("Provided script engine cannot be handled by " + this.getClass()
+                + ". Expected " + RhinoScriptEngine.class + " but got "
+                + (scriptEngine == null ? "null" : scriptEngine.getClass().getName()));
+        }
+
+        RhinoScriptEngine eng = (RhinoScriptEngine) scriptEngine;
+
+        if (scriptSourceProvider != null) {
+            eng.setModuleSourceProvider(new ScriptSourceToModuleSourceProviderAdapter(scriptSourceProvider));
+        }
+    }
+
+    @Override
     public Set<String> generateIndirectionMethods(String boundObjectName, Set<Method> methods) {
         if (methods.size() == 0) {
             return Collections.emptySet();
@@ -132,7 +146,7 @@ public class JsEngineInitializer implements ScriptEngineInitializer {
         return errorMessage;
     }
 
-    private ScriptEngine instantiateUnsecured(Set<String> packages, ScriptSourceProvider scriptSourceProvider)
+    private ScriptEngine instantiateUnsecured(Set<String> packages)
         throws ScriptException {
         RhinoScriptEngine eng = (RhinoScriptEngine) engineManager.getEngineByName("rhino-nonjdk");
         
@@ -140,10 +154,6 @@ public class JsEngineInitializer implements ScriptEngineInitializer {
             throw new IllegalStateException("Failed to instantiate the 'rhino-nonjdk' script engine. This means that either the required library is missing from the classpath or that there are some security issues preventing it from being instantiated.");
         }
         
-        if (scriptSourceProvider != null) {
-            eng.setModuleSourceProvider(new ScriptSourceToModuleSourceProviderAdapter(scriptSourceProvider));
-        }
-
         for (String pkg : packages) {
             eng.eval("importPackage(" + pkg + ")");
         }
diff --git a/modules/enterprise/scripting/javascript/src/test/java/org/rhq/scripting/javascript/InitializerTest.java b/modules/enterprise/scripting/javascript/src/test/java/org/rhq/scripting/javascript/InitializerTest.java
index 3a50839..e71155b 100644
--- a/modules/enterprise/scripting/javascript/src/test/java/org/rhq/scripting/javascript/InitializerTest.java
+++ b/modules/enterprise/scripting/javascript/src/test/java/org/rhq/scripting/javascript/InitializerTest.java
@@ -89,7 +89,7 @@ public class InitializerTest {
         perms.add(new FilePermission("<<ALL FILES>>", "read"));
         perms.add(new PropertyPermission("*", "read"));
         
-        ScriptEngine eng = new JsEngineInitializer().instantiate(Collections.<String>emptySet(), null, perms);
+        ScriptEngine eng = new JsEngineInitializer().instantiate(Collections.<String>emptySet(), perms);
         
         try {
             eng.eval("java.lang.System.exit(1)");
@@ -103,7 +103,7 @@ public class InitializerTest {
         String script = "var m = require('rhq://test-module1.js'); m.func1();";
         
         //first let's try to find the scripts with the default source provider...
-        ScriptEngine eng = new JsEngineInitializer().instantiate(Collections.<String>emptySet(), null, null);
+        ScriptEngine eng = new JsEngineInitializer().instantiate(Collections.<String>emptySet(), null);
         try {
             eng.eval(script);
             fail("The module should not have been loaded using the default source provider.");
@@ -111,17 +111,18 @@ public class InitializerTest {
             //expected
         }
         
-        eng = new JsEngineInitializer().instantiate(Collections.<String>emptySet(), new ScriptSourceProvider() {            
+        eng = new JsEngineInitializer().instantiate(Collections.<String>emptySet(), null);
+        new JsEngineInitializer().installScriptSourceProvider(eng, new ScriptSourceProvider() {
             @Override
             public Reader getScriptSource(URI location) {
                 if (!"rhq".equals(location.getScheme())) {
                     return null;
                 }
                 String scriptName = location.getSchemeSpecificPart().substring(2); //remove the '//'
-                InputStream src =  getClass().getClassLoader().getResourceAsStream(scriptName);
+                InputStream src = getClass().getClassLoader().getResourceAsStream(scriptName);
                 return new InputStreamReader(src);
             }
-        }, null);
+        });
 
         try {
             eng.eval(script);
@@ -133,7 +134,7 @@ public class InitializerTest {
     public void indirectionMethodsValid() throws Exception {
         JsEngineInitializer initializer = new JsEngineInitializer();
         
-        ScriptEngine eng = initializer.instantiate(Collections.<String>emptySet(), null, null);
+        ScriptEngine eng = initializer.instantiate(Collections.<String>emptySet(), null);
         
         TestClass myObject = new TestClass();
                 
diff --git a/modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonScriptEngineInitializer.java b/modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonScriptEngineInitializer.java
index 9ee50b8..07ed8eb 100644
--- a/modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonScriptEngineInitializer.java
+++ b/modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonScriptEngineInitializer.java
@@ -43,8 +43,7 @@ public class PythonScriptEngineInitializer implements ScriptEngineInitializer {
     private ScriptEngineManager engineManager = new ScriptEngineManager();
 
     @Override
-    public ScriptEngine instantiate(Set<String> packages, ScriptSourceProvider scriptSourceProvider,
-        PermissionCollection permissions) throws ScriptException {
+    public ScriptEngine instantiate(Set<String> packages, PermissionCollection permissions) throws ScriptException {
 
         ScriptEngine eng = engineManager.getEngineByName("python");
 
@@ -52,23 +51,26 @@ public class PythonScriptEngineInitializer implements ScriptEngineInitializer {
             eng.eval("from " + pkg + " import *\n");
         }
 
-        //TODO add support for script source providers... possibly using http://www.python.org/dev/peps/pep-0302/
-        
         //fingers crossed we can secure jython like this
         return new SandboxedScriptEngine(eng, permissions);
     }
 
     @Override
+    public void installScriptSourceProvider(ScriptEngine scriptEngine, ScriptSourceProvider provider) {
+        //TODO add support for script source providers... possibly using http://www.python.org/dev/peps/pep-0302/        
+    }
+
+    @Override
     public Set<String> generateIndirectionMethods(String boundObjectName, Set<Method> overloadedMethods) {
         if (overloadedMethods == null || overloadedMethods.isEmpty()) {
             return Collections.emptySet();
         }
 
         Set<Integer> argCnts = new HashSet<Integer>();
-        for(Method m : overloadedMethods) {
+        for (Method m : overloadedMethods) {
             argCnts.add(m.getParameterTypes().length);
         }
-        
+
         String methodName = overloadedMethods.iterator().next().getName();
         StringBuilder functionBody = new StringBuilder();
 
@@ -76,18 +78,18 @@ public class PythonScriptEngineInitializer implements ScriptEngineInitializer {
         functionBody.append("\t").append("if len(kwargs) > 0:\n");
         functionBody.append("\t\t").append("raise ValueError(\"Named arguments not supported for Java methods\")\n");
         functionBody.append("\t").append("argCnt = len(args)\n");
-                
-        for(Integer argCnt : argCnts) {
+
+        for (Integer argCnt : argCnts) {
             functionBody.append("\t").append("if argCnt == ").append(argCnt).append(":\n");
             functionBody.append("\t\treturn ").append(boundObjectName).append(".").append(methodName).append("(");
             int last = argCnt - 1;
-            for(int i = 0; i < argCnt; ++i) {
+            for (int i = 0; i < argCnt; ++i) {
                 functionBody.append("args[").append(i).append("]");
                 if (i < last) {
                     functionBody.append(", ");
                 }
             }
-            functionBody.append(")\n");            
+            functionBody.append(")\n");
         }
 
         return Collections.singleton(functionBody.toString());
diff --git a/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClient.java b/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClient.java
index 384a6e0..7f8efad 100644
--- a/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClient.java
+++ b/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClient.java
@@ -44,7 +44,7 @@ public class LocalClient implements RhqFacade {
     private static final Log LOG = LogFactory.getLog(LocalClient.class);
 
     private Subject subject;
-    private Map<String, Object> managers;
+    private Map<RhqManager, Object> managers;
 
     public LocalClient(Subject subject) {
         this.subject = subject;
@@ -70,10 +70,10 @@ public class LocalClient implements RhqFacade {
     }
 
     @Override
-    public Map<String, Object> getScriptingAPI() {
+    public Map<RhqManager, Object> getScriptingAPI() {
         if (managers == null) {
 
-            managers = new HashMap<String, Object>();
+            managers = new HashMap<RhqManager, Object>();
 
             for (final RhqManager manager : RhqManager.values()) {
                 if (manager.enabled()) {
@@ -85,7 +85,7 @@ public class LocalClient implements RhqFacade {
                             }
                         });
 
-                        managers.put(manager.name(), proxy);
+                        managers.put(manager, proxy);
                     } catch (Throwable e) {
                         LOG.error("Failed to load manager " + manager + " due to missing class.", e);
                     }
diff --git a/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/RhqDownloadsScriptSourceProvider.java b/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/RhqDownloadsScriptSourceProvider.java
new file mode 100644
index 0000000..7b9232a
--- /dev/null
+++ b/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/RhqDownloadsScriptSourceProvider.java
@@ -0,0 +1,80 @@
+/*
+ * RHQ Management Platform
+ * Copyright 2012, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.client;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.net.URI;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.rhq.bindings.script.BaseRhqSchemeScriptSourceProvider;
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.common.ServerDetails;
+import org.rhq.enterprise.server.auth.SubjectManagerLocal;
+import org.rhq.enterprise.server.system.SystemManagerLocal;
+import org.rhq.enterprise.server.util.LookupUtil;
+
+/**
+ * @author Lukas Krejci
+ */
+public class RhqDownloadsScriptSourceProvider extends BaseRhqSchemeScriptSourceProvider {
+
+    private static final Log LOG = LogFactory.getLog(RhqDownloadsScriptSourceProvider.class);
+
+    private static final String PREFIX = "//downloads/";
+
+    private SystemManagerLocal systemManager = LookupUtil.getSystemManager();
+    private SubjectManagerLocal subjectManager = LookupUtil.getSubjectManager();
+
+    @Override
+    protected Reader doGetScriptSource(URI scriptUri) {
+        String path = scriptUri.getSchemeSpecificPart();
+
+        if (!path.startsWith(PREFIX)) {
+            return null;
+        }
+
+        path = path.substring(PREFIX.length());
+
+        Subject overlord = subjectManager.getOverlord();
+
+        ServerDetails serverDetails = systemManager.getServerDetails(overlord);
+
+        String serverHomeDir = serverDetails.getDetails().get(ServerDetails.Detail.SERVER_HOME_DIR);
+
+        File downloads = new File(serverHomeDir, "deploy/rhq.ear/rhq-downloads");
+
+        File file = new File(downloads, path);
+
+        try {
+            return new InputStreamReader(new FileInputStream(file));
+        } catch (FileNotFoundException e) {
+            LOG.debug("Failed to locate the download file: " + scriptUri, e);
+            return null;
+        }
+    }
+
+}
diff --git a/modules/enterprise/server/client-api/src/main/resources/META-INF/services/org.rhq.scripting.ScriptSourceProvider b/modules/enterprise/server/client-api/src/main/resources/META-INF/services/org.rhq.scripting.ScriptSourceProvider
new file mode 100644
index 0000000..7523c32
--- /dev/null
+++ b/modules/enterprise/server/client-api/src/main/resources/META-INF/services/org.rhq.scripting.ScriptSourceProvider
@@ -0,0 +1 @@
+org.rhq.enterprise.client.RhqDownloadsScriptSourceProvider
diff --git a/modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/test/LocalClientTest.java b/modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/test/LocalClientTest.java
index 2236923..61f9ea0 100644
--- a/modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/test/LocalClientTest.java
+++ b/modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/test/LocalClientTest.java
@@ -112,7 +112,7 @@ public class LocalClientTest extends JMockTest {
             LocalClient lc = new LocalClient(null);
             
             //this call creates the proxy and is theoretically prone to the context classloader
-            Object am = lc.getScriptingAPI().get("AlertManager");
+            Object am = lc.getScriptingAPI().get(RhqManager.AlertManager);
 
             //check that only the simplified method exists on the returned object
             try {
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentManagerLocal.java
index fc72896..abc8ba5 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentManagerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentManagerLocal.java
@@ -421,7 +421,7 @@ public interface ContentManagerLocal {
     InstalledPackage getBackingPackageForResource(Subject subject, int resourceId);
 
     /**
-     * @see {@link ContentManagerRemote#getPackageBytes(Subject, int, int)
+     * @see {@link ContentManagerRemote#getPackageBytes(Subject, int, int)}
      */
     byte[] getPackageBytes(Subject user, int resourceId, int installedPackageId);
 
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentManagerRemote.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentManagerRemote.java
index a75d78f..e2e37c5 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentManagerRemote.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentManagerRemote.java
@@ -292,5 +292,4 @@ public interface ContentManagerRemote {
     @WebMethod
     byte[] getPackageBytes(@WebParam(name = "subject") Subject user, @WebParam(name = "resourceId") int resourceId,
         @WebParam(name = "installedPackageId") int installedPackageId);
-
 }
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/RepoManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/RepoManagerBean.java
index 72d7bee..9bcf553 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/RepoManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/RepoManagerBean.java
@@ -18,6 +18,8 @@
  */
 package org.rhq.enterprise.server.content;
 
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
 import java.text.ParseException;
 import java.util.ArrayList;
 import java.util.Comparator;
@@ -990,6 +992,35 @@ public class RepoManagerBean implements RepoManagerLocal, RepoManagerRemote {
         repo.addRepoRelationship(repoRelationship);
     }
 
+    @Override
+    public byte[] getPackageVersionBytes(Subject subject, int repoId, int packageVersionId) {
+        if (!authzManager.canViewRepo(subject, repoId)) {
+            throw new PermissionException("User [" + subject + "] cannot access a repo with id " + repoId);
+        }
+
+        //check that the provided package version actually belongs to the repo
+        Repo repo = entityManager.find(Repo.class, repoId);
+
+        PackageVersion pv = entityManager.find(PackageVersion.class, packageVersionId);
+        if (pv == null || !pv.getRepos().contains(repo)) {
+            throw new IllegalArgumentException("The package version with id " + packageVersionId
+                + " does not belong to the repo with id " + repoId + " or does not exist.");
+        }
+
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        contentSourceManager.outputPackageVersionBits(pv, out);
+
+        byte[] ret = out.toByteArray();
+
+        try {
+            out.close();
+        } catch (IOException e) {
+            //this is not gonna happen with a byte array stream
+        }
+
+        return ret;
+    }
+
     private void validateFields(Repo repo) throws RepoException {
         if (repo.getName() == null || repo.getName().trim().equals("")) {
             throw new RepoException("Repo name is required");
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/RepoManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/RepoManagerLocal.java
index 51957bd..94c1159 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/RepoManagerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/RepoManagerLocal.java
@@ -18,7 +18,6 @@
  */
 package org.rhq.enterprise.server.content;
 
-import java.util.Comparator;
 import java.util.List;
 
 import javax.ejb.Local;
@@ -415,4 +414,6 @@ public interface RepoManagerLocal {
      * @return
      */
     List<SubscribedRepo> findSubscriptions(Subject subject, int resourceId);
+
+    byte[] getPackageVersionBytes(Subject user, int repoId, int packageVersionId);
 }
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/RepoManagerRemote.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/RepoManagerRemote.java
index d144443..45c0c5a 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/RepoManagerRemote.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/RepoManagerRemote.java
@@ -18,7 +18,6 @@
  */
 package org.rhq.enterprise.server.content;
 
-import java.util.Comparator;
 import java.util.List;
 
 import javax.ejb.Remote;
@@ -260,4 +259,17 @@ public interface RepoManagerRemote {
         @WebParam(name = "subject") Subject subject, //
         @WebParam(name = "repoIds") int[] repoIds) //
         throws Exception;
+
+    /**
+     * This method allows for downloading the bytes of an arbitrary package version. This call can be dangerous with 
+     * large packages because it will attempt to load the whole package in memory.
+     * 
+     * @param user
+     * @param repoId
+     * @param packageVersionId
+     * @return the bytes of the package version
+     */
+    @WebMethod
+    byte[] getPackageVersionBytes(@WebParam(name = "subject") Subject user, @WebParam(name = "repoId") int repoId,
+        @WebParam(name = "packageVersionId") int packageVersionId);
 }
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/webservices/WebservicesManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/webservices/WebservicesManagerBean.java
index 27cdabd..69d797a 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/webservices/WebservicesManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/webservices/WebservicesManagerBean.java
@@ -903,6 +903,10 @@ public class WebservicesManagerBean implements WebservicesRemote {
         return repoManager.synchronizeRepos(subject, repoIds);
     }
 
+    public byte[] getPackageVersionBytes(Subject user, int repoId, int packageVersionId) {
+        return repoManager.getPackageVersionBytes(user, repoId, packageVersionId);
+    }
+
     //REPOMANAGER: END ----------------------------------
 
     //RESOURCEFACTORYMANAGER: BEGIN ----------------------------------
diff --git a/modules/enterprise/server/plugins/alert-cli/src/main/java/org/rhq/enterprise/server/plugins/alertCli/CliSender.java b/modules/enterprise/server/plugins/alert-cli/src/main/java/org/rhq/enterprise/server/plugins/alertCli/CliSender.java
index 09dc8a5..8ca0b39 100644
--- a/modules/enterprise/server/plugins/alert-cli/src/main/java/org/rhq/enterprise/server/plugins/alertCli/CliSender.java
+++ b/modules/enterprise/server/plugins/alert-cli/src/main/java/org/rhq/enterprise/server/plugins/alertCli/CliSender.java
@@ -61,6 +61,8 @@ import org.rhq.enterprise.server.plugin.pc.alert.AlertSender;
 import org.rhq.enterprise.server.plugin.pc.alert.AlertSenderValidationResults;
 import org.rhq.enterprise.server.util.LookupUtil;
 import org.rhq.scripting.ScriptEngineInitializer;
+import org.rhq.scripting.ScriptSourceProvider;
+import org.rhq.scripting.ScriptSourceProviderFactory;
 
 /**
  * Uses CLI to perform the alert notification.
@@ -425,9 +427,10 @@ public class CliSender extends AlertSender<CliComponent> {
             if (engine == null) {
                 engine = ScriptEngineFactory.getSecuredScriptEngine(ENGINE_NAME,
                     new PackageFinder(Collections.<File> emptyList()), bindings, new StandardScriptPermissions());
-            } else {
-                ScriptEngineFactory.injectStandardBindings(engine, bindings, true);
             }
+            //TODO is this OK, or should we use a different classloader than the context classloader?
+            ScriptSourceProvider[] providers = ScriptSourceProviderFactory.get(null);
+            ScriptEngineFactory.injectStandardBindings(engine, bindings, true, providers);
 
             ++ENGINES_IN_USE;
 


commit e7b13bd50bbac52f88cdde48b28a90286740e896
Author: Mike Thompson <mithomps at redhat.com>
Date:   Tue Jul 3 11:43:44 2012 -0700

    On Resource Detail Configuration Tab - Move Save Button bar  down to bottom of screen (from top) to match other button bars.

diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/ResourceConfigurationEditView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/ResourceConfigurationEditView.java
index 6725e98..9d2d1a2 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/ResourceConfigurationEditView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/ResourceConfigurationEditView.java
@@ -80,6 +80,18 @@ public class ResourceConfigurationEditView extends LocatableVLayout implements P
     protected void onDraw() {
         super.onDraw();
 
+        //createButtonBar();
+
+        refresh();
+
+        if (!this.resourcePermission.isConfigureWrite()) {
+            Message message = new Message(MSG.view_configurationDetails_noPermission(), Message.Severity.Info, EnumSet
+                .of(Message.Option.Transient, Message.Option.Sticky));
+            CoreGUI.getMessageCenter().notify(message);
+        }
+    }
+
+    private ToolStrip createButtonBar() {
         this.buttonbar = new ToolStrip();
         buttonbar.setWidth100();
         buttonbar.setExtraSpace(10);
@@ -95,15 +107,7 @@ public class ResourceConfigurationEditView extends LocatableVLayout implements P
         buttonbar.addMember(saveButton);
         // The button bar will remain hidden until the configuration has been successfully loaded.
         buttonbar.setVisible(false);
-        addMember(buttonbar);
-
-        refresh();
-
-        if (!this.resourcePermission.isConfigureWrite()) {
-            Message message = new Message(MSG.view_configurationDetails_noPermission(), Message.Severity.Info, EnumSet
-                .of(Message.Option.Transient, Message.Option.Sticky));
-            CoreGUI.getMessageCenter().notify(message);
-        }
+        return buttonbar;
     }
 
     @Override
@@ -113,11 +117,12 @@ public class ResourceConfigurationEditView extends LocatableVLayout implements P
         }
 
         this.refreshing = true;
-        this.buttonbar.setVisible(false);
 
         if (editor != null) {
             editor.destroy();
             removeMember(editor);
+            buttonbar.destroy();
+            removeMember(buttonbar);
         }
         
         GWTServiceLookup.getConfigurationService().getLatestResourceConfigurationUpdate(resource.getId(),
@@ -155,6 +160,7 @@ public class ResourceConfigurationEditView extends LocatableVLayout implements P
                                         editor.addPropertyValueChangeListener(ResourceConfigurationEditView.this);
                                         editor.setReadOnly(!resourcePermission.isConfigureWrite());
                                         addMember(editor);
+                                        addMember(createButtonBar());
 
                                         saveButton.disable();
                                         buttonbar.setVisible(true);


commit 00db03b19d5a70e9798405b33f91ed150e38382e
Author: John Mazzitelli <mazz at redhat.com>
Date:   Tue Jul 3 13:06:41 2012 -0400

    [BZ 834019] unit test to make sure we push out the schedule properly for late-collected metrics

diff --git a/modules/core/plugin-container-itest/src/test/java/org/rhq/core/pc/measurement/LateMeasurementRescheduleTest.java b/modules/core/plugin-container-itest/src/test/java/org/rhq/core/pc/measurement/LateMeasurementRescheduleTest.java
index 518d5da..e7661ac 100644
--- a/modules/core/plugin-container-itest/src/test/java/org/rhq/core/pc/measurement/LateMeasurementRescheduleTest.java
+++ b/modules/core/plugin-container-itest/src/test/java/org/rhq/core/pc/measurement/LateMeasurementRescheduleTest.java
@@ -21,6 +21,7 @@ import org.rhq.core.pc.PluginContainer;
 import org.rhq.core.pc.inventory.ResourceContainer;
 import org.rhq.plugins.test.SingleResourceDiscoveryComponent;
 import org.rhq.plugins.test.measurement.BZ834019ResourceComponent;
+import org.rhq.plugins.test.measurement.BZ834019ResourceComponent.CollectedMetric;
 import org.rhq.test.arquillian.AfterDiscovery;
 import org.rhq.test.arquillian.BeforeDiscovery;
 import org.rhq.test.arquillian.FakeServerInventory;
@@ -31,20 +32,22 @@ import org.rhq.test.arquillian.RunDiscovery;
 import org.rhq.test.shrinkwrap.RhqAgentPluginArchive;
 
 /**
- * Test for BZ 834019.
+ * Test for BZ 834019. This test requires a long time to complete (about 2.5 minutes) because
+ * we have to wait for the minimum collection intervals (30s) to pass several times.
  */
 @RunDiscovery
 public class LateMeasurementRescheduleTest extends Arquillian {
 
-    @Deployment(name = "SingleMetricPlugin")
+    @Deployment(name = "TwoMetricPlugin")
     @TargetsContainer("connected-pc-with-metric-collection")
     public static RhqAgentPluginArchive getTestPlugin() {
-        RhqAgentPluginArchive pluginJar = ShrinkWrap
-            .create(RhqAgentPluginArchive.class, "single-metric-plugin-1.0.jar");
+        RhqAgentPluginArchive pluginJar = ShrinkWrap.create(RhqAgentPluginArchive.class, "bz834019-plugin-1.0.jar");
         HashMap<String, String> replacements = new HashMap<String, String>();
         replacements.put("@@@discovery@@@", SingleResourceDiscoveryComponent.class.getName());
         replacements.put("@@@class@@@", BZ834019ResourceComponent.class.getName());
-        return pluginJar.setPluginDescriptorFromTemplate("single-metric-rhq-plugin.xml", replacements).addClasses(
+        replacements.put("@@@metric1.interval@@@", "30000");
+        replacements.put("@@@metric2.interval@@@", "35000"); // this MUST be 35s - if you make it 30s, the collections won't be late!
+        return pluginJar.setPluginDescriptorFromTemplate("two-metric-rhq-plugin.xml", replacements).addClasses(
             SingleResourceDiscoveryComponent.class, BZ834019ResourceComponent.class);
     }
 
@@ -57,10 +60,10 @@ public class LateMeasurementRescheduleTest extends Arquillian {
     private FakeServerInventory fakeServerInventory;
     private FakeServerInventory.CompleteDiscoveryChecker discoveryCompleteChecker;
 
-    @ResourceContainers(plugin = "SingleMetricPlugin", resourceType = "SingleMetricServer")
+    @ResourceContainers(plugin = "TwoMetricPlugin", resourceType = "TwoMetricServer")
     private Set<ResourceContainer> containers;
 
-    @ResourceComponentInstances(plugin = "SingleMetricPlugin", resourceType = "SingleMetricServer")
+    @ResourceComponentInstances(plugin = "TwoMetricPlugin", resourceType = "TwoMetricServer")
     private Set<BZ834019ResourceComponent> components;
 
     @BeforeDiscovery(testMethods = "testBZ834019")
@@ -100,6 +103,73 @@ public class LateMeasurementRescheduleTest extends Arquillian {
 
         BZ834019ResourceComponent server = this.components.iterator().next();
 
-        // TODO do things to test BZ 834019
+        // do things to test BZ 834019. Here's what is happening:
+        // - server has metric1 and metric2 with intervals of 30s and 35s respectively
+        //   (MUST make sure metric2 is no less than 35s, else the collections won't be late!)
+        // - the resource component will sleep in its getValues for 91s - no metrics will be reported the first 91s
+        // - the PC will call getValues() in this sequence:
+        // ** metric1 - starting at time 0  (due to the sleep in our getValues, this won't compete until time 91)
+        // ** metric2 - starting at time 0  (completes at time 91)
+        // ** metric1 - starting at time 30 (completes at time 91)
+        // ** metric2 - starting at time 60 (completes at time 91)
+        // ** metric2 - starting at time 90 (completes at time 91)
+        // ** metric2 - starting at time 105 (completes at time 105)
+        // ** metric1 - starting at time 121 (completes at time 121)
+        // Now, I can't explain this behavior entirely, however, it appears that metric1 is considered late so it
+        // is pushed back by our fix. It is last collected at time 30, but doesn't finish timely. The next time it should
+        // be collected is time 60 but because it has been late, that collection is skipped and our fix will re-schedule it
+        // next at time (interval+31), which means: 60 + (interval+31) == 60 + (30+31) == 60+61 == 121.
+        // And you can see above, that is when the next request to collect metric1 is done.
+        // Without the fix, the next collection of metric1 would have been at around time 60 + (interval) == 60 + (30) == 90
+
+        // rather than just blindly sleeping, make this test complete as fast as possible by
+        // stop waiting as soon as we see metric1 having been collected at least 3 times.
+        CollectedMetric[] collectedMetrics = null;
+        boolean keepWaiting = true;
+        int waitCycles = 0;
+        while (keepWaiting) {
+            Thread.sleep(1000);
+            int numberOfTimesMetric1WasCollectedSoFar = 0;
+            collectedMetrics = server.collectedMetrics.toArray(new CollectedMetric[0]); // copy it fast, this is synchronized so our component's thread won't break us
+            for (CollectedMetric collectedMetric : collectedMetrics) {
+                if (collectedMetric.metricName.equals("metric1")) {
+                    numberOfTimesMetric1WasCollectedSoFar++;
+                }
+            }
+            if (numberOfTimesMetric1WasCollectedSoFar >= 3) {
+                keepWaiting = false;
+            }
+            if (waitCycles++ > 140) {
+                keepWaiting = false; // stop waiting but the test will probably fail because we should have had three metric1 collections by now
+            }
+        }
+
+        // round all the time values to the nearest second
+        for (CollectedMetric metric : collectedMetrics) {
+            metric.collectedTime = getRoundedSeconds(metric.collectedTime);
+            metric.finishedTime = getRoundedSeconds(metric.finishedTime);
+            System.out.println("BZ 834019 test metric=" + metric.metricName + "; start=" + metric.collectedTime
+                + "; stop=" + metric.finishedTime);
+        }
+
+        // now look at the timings and make sure we see metric1 pushed out into the future like our bug fix wants it to be
+        int collectionNumber = 0;
+        for (CollectedMetric metric : collectedMetrics) {
+            if ("metric1".equals(metric.metricName)) {
+                collectionNumber++; // this tracks that we are on the Nth time the metric was collected, we expect 3 total
+                if (collectionNumber == 1) {
+                    assert metric.collectedTime <= 3; // should be 0, but give it some leeway in case our test box is slow
+                } else if (collectionNumber == 2) {
+                    assert metric.collectedTime >= 29 && metric.collectedTime <= 32; // should be 30, but give it some leeway
+                } else if (collectionNumber == 3) {
+                    assert metric.collectedTime >= 119 && metric.collectedTime <= 123; // should be 121, but give it some leeway
+                }
+            }
+        }
+        assert collectionNumber >= 3 : "test should have collected metric1 at least 3 times: " + collectionNumber;
+    }
+
+    private long getRoundedSeconds(long millis) {
+        return (long) ((millis / 1000.0) + 0.5);
     }
 }
diff --git a/modules/core/plugin-container-itest/src/test/java/org/rhq/core/pc/measurement/ReadOnlyScheduleSetTest.java b/modules/core/plugin-container-itest/src/test/java/org/rhq/core/pc/measurement/ReadOnlyScheduleSetTest.java
index ed55d63..dedf968 100644
--- a/modules/core/plugin-container-itest/src/test/java/org/rhq/core/pc/measurement/ReadOnlyScheduleSetTest.java
+++ b/modules/core/plugin-container-itest/src/test/java/org/rhq/core/pc/measurement/ReadOnlyScheduleSetTest.java
@@ -44,6 +44,8 @@ public class ReadOnlyScheduleSetTest extends Arquillian {
         HashMap<String, String> replacements = new HashMap<String, String>();
         replacements.put("@@@discovery@@@", SingleResourceDiscoveryComponent.class.getName());
         replacements.put("@@@class@@@", BZ821058ResourceComponent.class.getName());
+        replacements.put("@@@metric1.interval@@@", "30000");
+        replacements.put("@@@metric2.interval@@@", "30000");
         return pluginJar.setPluginDescriptorFromTemplate("two-metric-rhq-plugin.xml", replacements).addClasses(
             SingleResourceDiscoveryComponent.class, BZ821058ResourceComponent.class);
     }
diff --git a/modules/core/plugin-container-itest/src/test/java/org/rhq/plugins/test/measurement/BZ834019ResourceComponent.java b/modules/core/plugin-container-itest/src/test/java/org/rhq/plugins/test/measurement/BZ834019ResourceComponent.java
index 6a3a93d..a6f7221 100644
--- a/modules/core/plugin-container-itest/src/test/java/org/rhq/plugins/test/measurement/BZ834019ResourceComponent.java
+++ b/modules/core/plugin-container-itest/src/test/java/org/rhq/plugins/test/measurement/BZ834019ResourceComponent.java
@@ -1,7 +1,10 @@
 package org.rhq.plugins.test.measurement;
 
+import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.Set;
+import java.util.Vector;
+import java.util.concurrent.CountDownLatch;
 
 import org.rhq.core.domain.measurement.AvailabilityType;
 import org.rhq.core.domain.measurement.MeasurementDataNumeric;
@@ -13,6 +16,16 @@ import org.rhq.core.pluginapi.measurement.MeasurementFacet;
 
 public class BZ834019ResourceComponent implements ResourceComponent<ResourceComponent<?>>, MeasurementFacet {
 
+    public class CollectedMetric {
+        public String metricName;
+        public long collectedTime; // the collected time as relative to initialCollectionTime
+        public long finishedTime; // the time when the getValues returned relative to initialCollectionTime
+    }
+
+    public CountDownLatch latch;
+    public long initialCollectionTime = 0L;
+    public Vector<CollectedMetric> collectedMetrics = new Vector<CollectedMetric>(); // we want synchronized Vector
+
     @Override
     public AvailabilityType getAvailability() {
         return AvailabilityType.UP;
@@ -28,11 +41,64 @@ public class BZ834019ResourceComponent implements ResourceComponent<ResourceComp
 
     @Override
     public void getValues(MeasurementReport report, Set<MeasurementScheduleRequest> metrics) throws Exception {
-        //  TODO: do things to test BZ 834019
+        boolean doSleep = false;
+        if (initialCollectionTime == 0L) {
+            initialCollectionTime = System.currentTimeMillis();
+            doSleep = true;
+            latch = new CountDownLatch(1); // so the rest of our collections will wait for our sleep to finish
+        }
+
+        ArrayList<CollectedMetric> thisCollection = new ArrayList<CollectedMetric>();
+
+        long now = System.currentTimeMillis() - initialCollectionTime;
         for (Iterator<MeasurementScheduleRequest> i = metrics.iterator(); i.hasNext();) {
             MeasurementScheduleRequest metric = i.next();
+            log("collecting metric " + (metric.getName() + " (interval=" + metric.getInterval() + ")"));
             report.addData(new MeasurementDataNumeric(metric, new Double(1.0)));
+
+            // remember what time we were called and which metric was asked to be collected
+            CollectedMetric collectedMetric = new CollectedMetric();
+            collectedMetric.collectedTime = now;
+            collectedMetric.metricName = metric.getName();
+            collectedMetrics.add(collectedMetric);
+            thisCollection.add(collectedMetric);
+        }
+
+        // delay the initial collection a long time to push back collection of future metrics - we must ignore all interrupts!
+        if (doSleep) {
+            log("before sleep");
+            for (int i = 0; i < 91; i++) {
+                try {
+                    Thread.sleep(1000);
+                } catch (Exception e) {
+                    log("ignoring interrupt at second #" + i);
+                }
+            }
+            log("after sleep");
+            latch.countDown();
+        } else {
+            // don't let interrupts abort our wait - always wait for the countdown latch to open up
+            boolean shouldWait = true;
+            while (shouldWait) {
+                try {
+                    log("before latch wait");
+                    latch.await();
+                    log("latch opened up");
+                    shouldWait = false;
+                } catch (Exception e) {
+                    log("latch wait interruptted, go back and wait...");
+                }
+            }
+        }
+
+        now = System.currentTimeMillis() - initialCollectionTime;
+        for (CollectedMetric collection : thisCollection) {
+            collection.finishedTime = now;
         }
         return;
     }
+
+    private void log(String msg) {
+        //System.out.println("!!!!!!!!!!! " + this.getClass().getSimpleName() + ": " + new Date() + ": " + msg);
+    }
 }
\ No newline at end of file
diff --git a/modules/core/plugin-container-itest/src/test/resources/two-metric-rhq-plugin.xml b/modules/core/plugin-container-itest/src/test/resources/two-metric-rhq-plugin.xml
index 4d9b7e1..8302160 100644
--- a/modules/core/plugin-container-itest/src/test/resources/two-metric-rhq-plugin.xml
+++ b/modules/core/plugin-container-itest/src/test/resources/two-metric-rhq-plugin.xml
@@ -16,12 +16,12 @@
               dataType="measurement"
               defaultOn="true"
               displayType="summary"
-              defaultInterval="30000" />
+              defaultInterval="@@@metric1.interval@@@" />
 
       <metric property="metric2"
               dataType="measurement"
               defaultOn="true"
               displayType="summary"
-              defaultInterval="30000" />
+              defaultInterval="@@@metric2.interval@@@" />
    </server>
 </plugin>


commit bbf48d7bddbd0361e7406d23762990fd840cd8da
Author: Heiko W. Rupp <hwr at redhat.com>
Date:   Tue Jul 3 12:48:30 2012 +0200

    BZ 834820 Eliminate call to isLast() which is problematic on Oracle

diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerBean.java
index 5987758..d602751 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/MetricHandlerBean.java
@@ -646,8 +646,13 @@ public class MetricHandlerBean  extends AbstractRestBean implements MetricHandle
                 PrintWriter pw = new PrintWriter(outputStream);
 
                 if (mediaType.equals(MediaType.APPLICATION_JSON_TYPE)) {
+                    boolean needsComma = false;
                     pw.println("[");
                     while (rs.next()) {
+                        if (needsComma) {
+                            pw.print(",\n");
+                        }
+                        needsComma = true;
                         pw.print("{");
                         pw.print("\"scheduleId\":");
                         pw.print(scheduleId);
@@ -658,8 +663,6 @@ public class MetricHandlerBean  extends AbstractRestBean implements MetricHandle
                         pw.print("\"value\":");
                         pw.print(rs.getDouble(2));
                         pw.print("}");
-                        if (!rs.isLast())
-                            pw.print(",\n");
                     }
                     pw.println("]");
                 }


commit 87f63d5522059ca035c0c1d1377aba569e552b22
Author: Mike Thompson <mithomps at redhat.com>
Date:   Mon Jul 2 13:19:44 2012 -0700

    [BZ 734490] AS7 plugin: resource config: 'Module Name' member props of 'Installed Extensions' map should be read-only

diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/ImageManager.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/ImageManager.java
index c7de21b..e50fe14 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/ImageManager.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/ImageManager.java
@@ -72,6 +72,13 @@ public class ImageManager {
     }
 
     /**
+     * Returns a generic add icon.
+     */
+    public static String getAddIcon() {
+        return "[SKIN]/actions/add.png";
+    }
+
+    /**
      * Returns a generic approve (aka "ok") icon.
      */
     public static String getApproveIcon() {
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/ConfigurationEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/ConfigurationEditor.java
index 4e3e9df..9932499 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/ConfigurationEditor.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/ConfigurationEditor.java
@@ -545,7 +545,6 @@ public class ConfigurationEditor extends LocatableVLayout {
         if (propertyMap instanceof Configuration) {
             this.topLevelPropertiesValuesManager.addMember(form);
         }
-        //form.setValidateOnExit(true);  // TODO: Remove this?
         form.setHiliteRequiredFields(true);
         form.setNumCols(4);
         form.setCellPadding(5);
@@ -1000,7 +999,7 @@ public class ConfigurationEditor extends LocatableVLayout {
 
             removeField.addRecordClickHandler(new RecordClickHandler() {
                 public void onRecordClick(final RecordClickEvent recordClickEvent) {
-                    Log.info("You want to delete: " + recordClickEvent.getRecordNum());
+                    Log.debug("You want to delete: " + recordClickEvent.getRecordNum());
                     SC.confirm(MSG.view_configEdit_confirm_2(), new BooleanCallback() {
                         public void execute(Boolean confirmed) {
                             if (confirmed) {
@@ -1074,20 +1073,15 @@ public class ConfigurationEditor extends LocatableVLayout {
     }
 
     private static boolean isAllReadOnly(List<PropertyDefinition> propertyDefinitions) {
-        // TODO (ips, 02/13/12): If we are going to do this correctly, we need to call isPropertyReadOnly() on each
-        //                       member property to determine whether that particular property is read-only or not,
-        //                       rather than relying solely on whether the member property definition is read-only; this
-        //                       is because, for a couple special cases, isPropertyReadOnly() returns false even when
-        //                       the prop def is read-only.
-        /*boolean allPropsDefsReadOnly = true;
+        boolean allPropsDefsReadOnly = true;
         for (PropertyDefinition subDef : propertyDefinitions) {
             if (!subDef.isReadOnly()) {
+                Log.debug("Found at least one non-readOnly property for: "+subDef.getName());
                 allPropsDefsReadOnly = false;
                 break;
             }
         }
-        return allPropsDefsReadOnly;*/
-        return false;
+        return allPropsDefsReadOnly;
     }
 
     private PropertyMapListGridRecord[] buildSummaryRecords(PropertyList propertyList,
@@ -1133,8 +1127,8 @@ public class ConfigurationEditor extends LocatableVLayout {
             vLayout.addMember(footer);
 
             final IButton deleteButton = new LocatableIButton(extendLocatorId("Delete"));
-            deleteButton.setIcon(Window.getImgURL("[SKIN]/actions/remove.png"));
-            deleteButton.setTooltip(MSG.view_configEdit_tooltip_1());
+            deleteButton.setIcon(Window.getImgURL(ImageManager.getRemoveIcon()));
+                    deleteButton.setTooltip(MSG.view_configEdit_tooltip_1());
             deleteButton.setDisabled(true);
             deleteButton.addClickHandler(new com.smartgwt.client.widgets.events.ClickHandler() {
                 public void onClick(ClickEvent clickEvent) {
@@ -1178,11 +1172,10 @@ public class ConfigurationEditor extends LocatableVLayout {
             });
 
             final IButton newButton = new LocatableIButton(vLayout.extendLocatorId("New"), MSG.common_button_new());
-            newButton.setIcon(Window.getImgURL("[SKIN]/actions/add.png"));
+            newButton.setIcon(Window.getImgURL(ImageManager.getAddIcon()));
             newButton.setTooltip(MSG.view_configEdit_tooltip_2());
             newButton.addClickHandler(new com.smartgwt.client.widgets.events.ClickHandler() {
                 public void onClick(ClickEvent clickEvent) {
-                    // TODO: selenium locators
                     final Window popup = new Window();
                     popup.setTitle(MSG.view_configEdit_addItem());
                     popup.setWidth(300);
@@ -1276,7 +1269,7 @@ public class ConfigurationEditor extends LocatableVLayout {
         return buildComplexPropertyField(vLayout);
     }
 
-    private LinkedHashMap<String, String> buildValueMap(PropertyList propertyList) {
+    private static LinkedHashMap<String, String> buildValueMap(PropertyList propertyList) {
         LinkedHashMap<String, String> memberValueToIndexMap = new LinkedHashMap<String, String>();
         List<Property> memberProperties = propertyList.getList();
         int index = 0;
@@ -1296,13 +1289,14 @@ public class ConfigurationEditor extends LocatableVLayout {
 
     protected FormItem buildSimpleField(final PropertyDefinitionSimple propertyDefinitionSimple,
         final PropertySimple propertySimple) {
-        Log.debug("Building simple field for " + propertySimple + "...");
 
         FormItem valueItem = null;
 
         boolean propertyIsReadOnly = isReadOnly(propertyDefinitionSimple, propertySimple);
+        Log.debug("Building simple field for " + propertySimple +"(read-only:"+propertyIsReadOnly+")...");
+
         // TODO (ips, 03/25/11): We eventually want to use StaticTextItems for read-only PASSWORD props too, but we have
-        //                       to wait until we implement masking/unmasking of PASSWORD props at the SLSB layer first.
+        // to wait until we implement masking/unmasking of PASSWORD props at the SLSB layer first.
         if (propertyIsReadOnly && propertyDefinitionSimple.getType() != PropertySimpleType.PASSWORD) {
             valueItem = new StaticTextItem();
         } else {
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/ResourceConfigurationEditView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/ResourceConfigurationEditView.java
index ddf9784..6725e98 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/ResourceConfigurationEditView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/ResourceConfigurationEditView.java
@@ -47,6 +47,7 @@ import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.ResourceD
 import org.rhq.enterprise.gui.coregui.client.inventory.resource.type.ResourceTypeRepository;
 import org.rhq.enterprise.gui.coregui.client.inventory.resource.type.ResourceTypeRepository.MetadataType;
 import org.rhq.enterprise.gui.coregui.client.inventory.resource.type.ResourceTypeRepository.TypeLoadedCallback;
+import org.rhq.enterprise.gui.coregui.client.util.Log;
 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.LocatableIButton;
@@ -190,7 +191,6 @@ public class ResourceConfigurationEditView extends LocatableVLayout implements P
                             .view_configurationDetails_messageDetailed(version, resource.getName()),
                             Message.Severity.Info);
                     } else {
-                        // TODO: i18n
                         message = new Message(MSG.view_configurationDetails_configNotUpdatedDueToNoChange(),
                             Message.Severity.Warning);
                     }


commit d12f2d22940245491344cc4238eb7651cf18d1a6
Author: Mike Thompson <mithomps at redhat.com>
Date:   Tue Jun 26 13:36:05 2012 -0700

    Minor: Change icon strings to IconEnum for better type safety.

diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/IconEnum.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/IconEnum.java
index 23bb13d..987dca6 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/IconEnum.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/IconEnum.java
@@ -18,6 +18,7 @@
  */
 package org.rhq.enterprise.gui.coregui.client;
 
+
 /**
  * Adding type information around Icons instead of having plain Strings.
  * Icons imply more than just a String type. There are attributes associated with icons
@@ -26,6 +27,7 @@ package org.rhq.enterprise.gui.coregui.client;
  * This provides more type safety than the ImageManager class that deals only with String type.
  * IDE's can quickly query on Icon Types and quickly see exactly where that image was used
  * and understand the full ramifications of changing an image.
+ * Helps provide consistency of images throughout the app.
  * By having the IconEnum represent the icon, we can defer the determination of the
  * size of the icon to the implementation while still defining an icon.
  * It is also very easy for a method signature to become ambiguous if the string is null.
@@ -58,6 +60,7 @@ public enum IconEnum {
     TAGS("global/Tag_16.png","global/Tag_24.png" ),
     REPORT("subsystems/report/Document_16.png","subsystems/report/Document_24.png" ),
     SUSPECT_METRICS("subsystems/monitor/Monitor_failed_16.png","subsystems/monitor/Monitor_failed_24.png","subsystems/monitor/Monitor_grey_16.png",null),
+    RECENT_MEASUREMENTS("subsystems/monitor/Monitor_16.png","subsystems/monitor/Monitor_24.png"),
     CONFIGURATION_HISTORY("subsystems/configure/Configure_16.png", "subsystems/configure/Configure_24.png","subsystems/configure/Configure_grey_16.png",null),
     RECENT_OPERATIONS("subsystems/control/Operation_16.png","subsystems/control/Operation_24.png", "subsystems/control/Operation_grey_16.png",null),
     RECENT_ALERTS("subsystems/alert/Alert_LOW_16.png"),
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/summary/AbstractActivityView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/summary/AbstractActivityView.java
index 8d9680a..758d8eb 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/summary/AbstractActivityView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/summary/AbstractActivityView.java
@@ -55,6 +55,7 @@ import org.rhq.core.domain.resource.group.GroupCategory;
 import org.rhq.core.domain.resource.group.ResourceGroup;
 import org.rhq.core.domain.resource.group.composite.ResourceGroupComposite;
 import org.rhq.core.domain.util.PageList;
+import org.rhq.enterprise.gui.coregui.client.IconEnum;
 import org.rhq.enterprise.gui.coregui.client.RefreshableView;
 import org.rhq.enterprise.gui.coregui.client.components.measurement.CustomConfigMeasurementRangeEditor;
 import org.rhq.enterprise.gui.coregui.client.dashboard.portlets.PortletConfigurationEditorComponent.Constant;
@@ -172,7 +173,7 @@ public abstract class AbstractActivityView extends LocatableVLayout implements R
         }
 
         //recentMetrics.xhtml
-        HLayout recentMetricsTitle = new TitleWithIcon("subsystems/monitor/Monitor_24.png", RECENT_MEASUREMENTS);
+        HLayout recentMetricsTitle = new TitleWithIcon(IconEnum.RECENT_MEASUREMENTS.getIcon24x24Path(), RECENT_MEASUREMENTS);
         if ((resource != null) || ((group != null) && (groupCategory.equals(GroupCategory.COMPATIBLE)))) {//resource,CompatibleGroup
             leftPane.addMember(recentMetricsTitle);
             leftPane.addMember(recentMeasurementsContent);
@@ -180,12 +181,12 @@ public abstract class AbstractActivityView extends LocatableVLayout implements R
             leftPane.addMember(divider1);
         }
         //recentAlerts.xhtml
-        HLayout recentAlertsTitle = new TitleWithIcon("subsystems/alert/Flag_blue_24.png", RECENT_ALERTS);
+        HLayout recentAlertsTitle = new TitleWithIcon(IconEnum.RECENT_ALERTS.getIcon24x24Path(), RECENT_ALERTS);
         leftPane.addMember(recentAlertsTitle);
         leftPane.addMember(recentAlertsContent);
         recentAlertsContent.setHeight(20);
         //recentOOBs.xhtml
-        HLayout recentOobsTitle = new TitleWithIcon("subsystems/monitor/Monitor_failed_24.png", RECENT_OOB);
+        HLayout recentOobsTitle = new TitleWithIcon(IconEnum.SUSPECT_METRICS.getIcon24x24Path(), RECENT_OOB);
         recentOobContent.setHeight(20);
         if ((resource != null) || ((group != null) && (groupCategory.equals(GroupCategory.COMPATIBLE)))) {//resource,CompatibleGroup
             leftPane.addMember(divider2);
@@ -199,7 +200,7 @@ public abstract class AbstractActivityView extends LocatableVLayout implements R
         rightPane.setAutoHeight();
         firstRightPanePortletLoaded = false;
         //recentConfigUpdates.xhtml
-        HLayout recentConfigUpdatesTitle = new TitleWithIcon("subsystems/configure/Configure_24.png",
+        HLayout recentConfigUpdatesTitle = new TitleWithIcon(IconEnum.CONFIGURE.getIcon24x24Path(),
             RECENT_CONFIGURATIONS);
         recentConfigurationContent.setHeight(20);
         if (((resource != null) && (resourceFacets.contains(ResourceTypeFacet.CONFIGURATION)))
@@ -210,7 +211,7 @@ public abstract class AbstractActivityView extends LocatableVLayout implements R
         }
 
         //recentOperations.xhtml
-        HLayout recentOperationsTitle = new TitleWithIcon("subsystems/control/Operation_24.png", RECENT_OPERATIONS);
+        HLayout recentOperationsTitle = new TitleWithIcon(IconEnum.RECENT_OPERATIONS.getIcon24x24Path(), RECENT_OPERATIONS);
         recentOperationsContent.setHeight(20);
         if (((resource != null) && (resourceFacets.contains(ResourceTypeFacet.OPERATION)))
             || (displayGroupOperations(groupCategory, facets))) {//resource
@@ -222,7 +223,7 @@ public abstract class AbstractActivityView extends LocatableVLayout implements R
             firstRightPanePortletLoaded = true;
         }
         //recentEventCounts.xhtml
-        HLayout recentEventsTitle = new TitleWithIcon("subsystems/event/Events_24.png", RECENT_EVENTS);
+        HLayout recentEventsTitle = new TitleWithIcon(IconEnum.EVENTS.getIcon24x24Path(), RECENT_EVENTS);
         recentEventsContent.setHeight(20);
         if (((resource != null) && (resourceFacets.contains(ResourceTypeFacet.EVENT)))
             || displayGroupEvents(groupCategory, facets)) {//resource
@@ -234,7 +235,7 @@ public abstract class AbstractActivityView extends LocatableVLayout implements R
             firstRightPanePortletLoaded = true;
         }
         //recentPackageHistory.xhtml
-        HLayout recentPkgHistoryTitle = new TitleWithIcon("subsystems/content/Package_24.png", RECENT_PKG_HISTORY);
+        HLayout recentPkgHistoryTitle = new TitleWithIcon(IconEnum.CONTENT.getIcon24x24Path(),RECENT_PKG_HISTORY);
         recentPkgHistoryContent.setHeight(20);
         if ((resource != null) || ((group != null) && (groupCategory.equals(GroupCategory.COMPATIBLE)))) {//resource,CompatibleGroup
             if (firstRightPanePortletLoaded) {
@@ -245,7 +246,7 @@ public abstract class AbstractActivityView extends LocatableVLayout implements R
         }
 
         //recent bundle deployments
-        recentBundleDeployTitle = new TitleWithIcon("subsystems/content/Content_24.png", RECENT_BUNDLE_DEPLOY);
+        recentBundleDeployTitle = new TitleWithIcon(IconEnum.CONTENT.getIcon24x24Path(), RECENT_BUNDLE_DEPLOY);
         recentBundleDeployTitle.setHeight(20);
         deployBundleViewIfApplicable(resource, group);
 
@@ -513,7 +514,7 @@ public abstract class AbstractActivityView extends LocatableVLayout implements R
 
     /** Takes the current value of the widget and persists it into the configuration object passed in.
     *
-    * @param configUpdateStatusSelector
+    * @param configStatusSelector
     * @param portletConfig
     * returns populated configuration object.
     */


commit cbb57a8b8b0a04eb680881f364598bb821cfb6c5
Author: John Mazzitelli <mazz at redhat.com>
Date:   Mon Jul 2 13:39:09 2012 -0400

    [BZ 821058] refactor the unit test to use the templatized descriptor stuff. we now have a reusable descriptor that defines a server with two metrics that this test is using

diff --git a/modules/core/plugin-container-itest/src/test/java/org/rhq/core/pc/measurement/ReadOnlyScheduleSetTest.java b/modules/core/plugin-container-itest/src/test/java/org/rhq/core/pc/measurement/ReadOnlyScheduleSetTest.java
index d94e32f..ed55d63 100644
--- a/modules/core/plugin-container-itest/src/test/java/org/rhq/core/pc/measurement/ReadOnlyScheduleSetTest.java
+++ b/modules/core/plugin-container-itest/src/test/java/org/rhq/core/pc/measurement/ReadOnlyScheduleSetTest.java
@@ -3,6 +3,7 @@ package org.rhq.core.pc.measurement;
 import static org.mockito.Matchers.any;
 import static org.mockito.Mockito.when;
 
+import java.util.HashMap;
 import java.util.Set;
 import java.util.concurrent.TimeUnit;
 
@@ -36,11 +37,14 @@ import org.rhq.test.shrinkwrap.RhqAgentPluginArchive;
 @RunDiscovery
 public class ReadOnlyScheduleSetTest extends Arquillian {
 
-    @Deployment(name = "bz821058Plugin")
+    @Deployment(name = "TwoMetricPlugin")
     @TargetsContainer("connected-pc-with-metric-collection")
     public static RhqAgentPluginArchive getTestPlugin() {
         RhqAgentPluginArchive pluginJar = ShrinkWrap.create(RhqAgentPluginArchive.class, "bz821058-plugin-1.0.jar");
-        return pluginJar.setPluginDescriptor("bz821058-rhq-plugin.xml").addClasses(
+        HashMap<String, String> replacements = new HashMap<String, String>();
+        replacements.put("@@@discovery@@@", SingleResourceDiscoveryComponent.class.getName());
+        replacements.put("@@@class@@@", BZ821058ResourceComponent.class.getName());
+        return pluginJar.setPluginDescriptorFromTemplate("two-metric-rhq-plugin.xml", replacements).addClasses(
             SingleResourceDiscoveryComponent.class, BZ821058ResourceComponent.class);
     }
 
@@ -53,10 +57,10 @@ public class ReadOnlyScheduleSetTest extends Arquillian {
     private FakeServerInventory fakeServerInventory;
     private FakeServerInventory.CompleteDiscoveryChecker discoveryCompleteChecker;
 
-    @ResourceContainers(plugin = "bz821058Plugin", resourceType = "BZ821058Server")
+    @ResourceContainers(plugin = "TwoMetricPlugin", resourceType = "TwoMetricServer")
     private Set<ResourceContainer> containers;
 
-    @ResourceComponentInstances(plugin = "bz821058Plugin", resourceType = "BZ821058Server")
+    @ResourceComponentInstances(plugin = "TwoMetricPlugin", resourceType = "TwoMetricServer")
     private Set<BZ821058ResourceComponent> components;
 
     @BeforeDiscovery(testMethods = "testBZ821058")
diff --git a/modules/core/plugin-container-itest/src/test/resources/bz821058-rhq-plugin.xml b/modules/core/plugin-container-itest/src/test/resources/bz821058-rhq-plugin.xml
deleted file mode 100644
index c6adda6..0000000
--- a/modules/core/plugin-container-itest/src/test/resources/bz821058-rhq-plugin.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<plugin name="bz821058Plugin"
-        displayName="Plugin to test BZ 821058"
-        description="This will help test that measurement facet is given a read-only schedule set."
-        version="1.0"
-        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xmlns="urn:xmlns:rhq-plugin"
-        xmlns:c="urn:xmlns:rhq-configuration">
-
-   <server name="BZ821058Server"
-           discovery="org.rhq.plugins.test.SingleResourceDiscoveryComponent"
-           class="org.rhq.plugins.test.measurement.BZ821058ResourceComponent">
-
-      <metric property="metric1"
-              dataType="measurement"
-              defaultOn="true"
-              displayType="summary"
-              defaultInterval="30000" />
-
-      <metric property="metric2"
-              dataType="measurement"
-              defaultOn="true"
-              displayType="summary"
-              defaultInterval="30000" />
-   </server>
-</plugin>
-        
diff --git a/modules/core/plugin-container-itest/src/test/resources/two-metric-rhq-plugin.xml b/modules/core/plugin-container-itest/src/test/resources/two-metric-rhq-plugin.xml
new file mode 100644
index 0000000..4d9b7e1
--- /dev/null
+++ b/modules/core/plugin-container-itest/src/test/resources/two-metric-rhq-plugin.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<plugin name="TwoMetricPlugin"
+        displayName="Plugin that has a single server with a two enabled metrics."
+        description="This will help test measurement collections by providing a server with a two enabled metrics."
+        version="1.0"
+        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xmlns="urn:xmlns:rhq-plugin"
+        xmlns:c="urn:xmlns:rhq-configuration">
+
+   <server name="TwoMetricServer"
+           discovery="@@@discovery@@@"
+           class="@@@class@@@">
+
+      <metric property="metric1"
+              dataType="measurement"
+              defaultOn="true"
+              displayType="summary"
+              defaultInterval="30000" />
+
+      <metric property="metric2"
+              dataType="measurement"
+              defaultOn="true"
+              displayType="summary"
+              defaultInterval="30000" />
+   </server>
+</plugin>


commit 25b62b50adc3b8631f68e52304df22d7e8d7959a
Author: John Sanda <jsanda at redhat.com>
Date:   Mon Jul 2 11:31:33 2012 -0400

    [BZ 826716] Improve error reporting in the UI

diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/resource/group/DuplicateExpressionTypeException.java b/modules/core/domain/src/main/java/org/rhq/core/domain/resource/group/DuplicateExpressionTypeException.java
new file mode 100644
index 0000000..4d51fc9
--- /dev/null
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/resource/group/DuplicateExpressionTypeException.java
@@ -0,0 +1,38 @@
+/*
+ *
+ *  * RHQ Management Platform
+ *  * Copyright (C) 2005-2012 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.domain.resource.group;
+
+/**
+ * @author John Sanda
+ */
+public class DuplicateExpressionTypeException extends InvalidExpressionException {
+
+    private static final long serialVersionUID = 1L;
+
+    private DuplicateExpressionTypeException() {
+    }
+
+    public DuplicateExpressionTypeException(String predicate) {
+        super("You cannot specify multiple " + predicate + " expressions.");
+    }
+
+}
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/resource/group/InvalidExpressionException.java b/modules/core/domain/src/main/java/org/rhq/core/domain/resource/group/InvalidExpressionException.java
new file mode 100644
index 0000000..600ba04
--- /dev/null
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/resource/group/InvalidExpressionException.java
@@ -0,0 +1,38 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2008 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.rhq.core.domain.resource.group;
+
+public class InvalidExpressionException extends Exception {
+    private static final long serialVersionUID = 1L;
+
+    public InvalidExpressionException() {
+    }
+
+    public InvalidExpressionException(String message) {
+        super(message);
+    }
+
+    public InvalidExpressionException(Throwable cause) {
+        super(cause);
+    }
+
+    public InvalidExpressionException(String message, Throwable cause) {
+        super(message, cause);
+    }
+}
\ No newline at end of file
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/ResourceGroupGWTService.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/ResourceGroupGWTService.java
index bd196fc..6cd1a43 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/ResourceGroupGWTService.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/ResourceGroupGWTService.java
@@ -27,6 +27,7 @@ import org.rhq.core.domain.resource.group.GroupDefinition;
 import org.rhq.core.domain.resource.group.ResourceGroup;
 import org.rhq.core.domain.resource.group.composite.ResourceGroupComposite;
 import org.rhq.core.domain.util.PageList;
+import org.rhq.core.domain.resource.group.DuplicateExpressionTypeException;
 
 /**
  * @author Greg Hinkle
@@ -64,9 +65,11 @@ public interface ResourceGroupGWTService extends RemoteService {
 
     void setAssignedResources(int groupId, int[] resourceIds, boolean setType) throws RuntimeException;
 
-    void recalculateGroupDefinitions(int[] groupDefinitionIds) throws RuntimeException;
+    void recalculateGroupDefinitions(int[] groupDefinitionIds)
+        throws DuplicateExpressionTypeException, RuntimeException;
 
-    void updateGroupDefinition(GroupDefinition groupDefinition) throws RuntimeException;
+    void updateGroupDefinition(GroupDefinition groupDefinition)
+        throws DuplicateExpressionTypeException, RuntimeException;
 
     void updateResourceGroup(ResourceGroup group) throws RuntimeException;
 
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/definitions/GroupDefinitionDataSource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/definitions/GroupDefinitionDataSource.java
index ff3cab2..74484dd 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/definitions/GroupDefinitionDataSource.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/definitions/GroupDefinitionDataSource.java
@@ -33,6 +33,7 @@ import com.smartgwt.client.rpc.RPCResponse;
 import com.smartgwt.client.widgets.grid.ListGridRecord;
 
 import org.rhq.core.domain.criteria.ResourceGroupDefinitionCriteria;
+import org.rhq.core.domain.resource.group.DuplicateExpressionTypeException;
 import org.rhq.core.domain.resource.group.GroupDefinition;
 import org.rhq.core.domain.util.PageList;
 import org.rhq.enterprise.gui.coregui.client.CoreGUI;
@@ -154,7 +155,11 @@ public class GroupDefinitionDataSource extends RPCDataSource<GroupDefinition, Re
             new AsyncCallback<Void>() {
                 @Override
                 public void onFailure(Throwable caught) {
-                    CoreGUI.getErrorHandler().handleError(MSG.view_dynagroup_saveFailure(name), caught);
+                    if (caught instanceof DuplicateExpressionTypeException) {
+                        CoreGUI.getMessageCenter().notify(new Message(caught.getMessage(), Message.Severity.Warning));
+                    } else {
+                        CoreGUI.getErrorHandler().handleError(MSG.view_dynagroup_saveFailure(name), caught);
+                    }
                 }
 
                 @Override
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/definitions/GroupDefinitionListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/definitions/GroupDefinitionListView.java
index 38b5165..0661533 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/definitions/GroupDefinitionListView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/definitions/GroupDefinitionListView.java
@@ -18,6 +18,9 @@
  */
 package org.rhq.enterprise.gui.coregui.client.inventory.groups.definitions;
 
+import java.util.Date;
+import java.util.Set;
+
 import com.google.gwt.user.client.History;
 import com.google.gwt.user.client.rpc.AsyncCallback;
 import com.smartgwt.client.types.ListGridFieldType;
@@ -26,20 +29,23 @@ import com.smartgwt.client.widgets.grid.CellFormatter;
 import com.smartgwt.client.widgets.grid.HoverCustomizer;
 import com.smartgwt.client.widgets.grid.ListGridField;
 import com.smartgwt.client.widgets.grid.ListGridRecord;
+
 import org.rhq.core.domain.authz.Permission;
 import org.rhq.enterprise.gui.coregui.client.CoreGUI;
 import org.rhq.enterprise.gui.coregui.client.PermissionsLoadedListener;
 import org.rhq.enterprise.gui.coregui.client.PermissionsLoader;
 import org.rhq.enterprise.gui.coregui.client.ViewPath;
-import org.rhq.enterprise.gui.coregui.client.components.table.*;
+import org.rhq.enterprise.gui.coregui.client.components.table.AbstractTableAction;
+import org.rhq.enterprise.gui.coregui.client.components.table.EscapedHtmlCellFormatter;
+import org.rhq.enterprise.gui.coregui.client.components.table.TableActionEnablement;
+import org.rhq.enterprise.gui.coregui.client.components.table.TableSection;
+import org.rhq.enterprise.gui.coregui.client.components.table.TimestampCellFormatter;
 import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
 import org.rhq.enterprise.gui.coregui.client.gwt.ResourceGroupGWTServiceAsync;
 import org.rhq.enterprise.gui.coregui.client.util.TableUtility;
 import org.rhq.enterprise.gui.coregui.client.util.message.Message;
 import org.rhq.enterprise.gui.coregui.client.util.message.Message.Severity;
-
-import java.util.Date;
-import java.util.Set;
+import org.rhq.core.domain.resource.group.DuplicateExpressionTypeException;
 
 /**
  * @author Greg Hinkle
@@ -156,7 +162,12 @@ public class GroupDefinitionListView extends TableSection<GroupDefinitionDataSou
 
                 resourceGroupManager.recalculateGroupDefinitions(groupDefinitionIds, new AsyncCallback<Void>() {
                     public void onFailure(Throwable caught) {
-                        CoreGUI.getErrorHandler().handleError(MSG.view_dynagroup_recalcFailureSelection(), caught);
+                        if (caught instanceof DuplicateExpressionTypeException) {
+                            CoreGUI.getMessageCenter().notify(new Message(caught.getMessage(),
+                                Message.Severity.Warning));
+                        } else {
+                            CoreGUI.getErrorHandler().handleError(MSG.view_dynagroup_recalcFailureSelection(), caught);
+                        }
                     }
 
                     public void onSuccess(Void result) {
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/definitions/SingleGroupDefinitionView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/definitions/SingleGroupDefinitionView.java
index f55c37a..c417426 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/definitions/SingleGroupDefinitionView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/definitions/SingleGroupDefinitionView.java
@@ -61,6 +61,7 @@ import com.smartgwt.client.widgets.layout.HLayout;
 
 import org.rhq.core.domain.authz.Permission;
 import org.rhq.core.domain.criteria.ResourceGroupDefinitionCriteria;
+import org.rhq.core.domain.resource.group.DuplicateExpressionTypeException;
 import org.rhq.core.domain.resource.group.GroupCategory;
 import org.rhq.core.domain.resource.group.GroupDefinition;
 import org.rhq.core.domain.util.PageList;
@@ -239,7 +240,11 @@ public class SingleGroupDefinitionView extends LocatableVLayout implements Bookm
             new AsyncCallback<Void>() {
                 @Override
                 public void onFailure(Throwable caught) {
-                    CoreGUI.getErrorHandler().handleError(MSG.view_dynagroup_recalcFailure(), caught);
+                    if (caught instanceof DuplicateExpressionTypeException) {
+                        CoreGUI.getMessageCenter().notify(new Message(caught.getMessage(), Message.Severity.Warning));
+                    } else {
+                        CoreGUI.getErrorHandler().handleError(MSG.view_dynagroup_recalcFailure(), caught);
+                    }
                 }
 
                 @Override
@@ -487,6 +492,7 @@ public class SingleGroupDefinitionView extends LocatableVLayout implements Bookm
                     public void onFailure(Throwable caught) {
                         CoreGUI.getErrorHandler().handleError(
                             MSG.view_dynagroup_loadDefinitionFailure(String.valueOf(groupDefinitionId)), caught);
+
                         History.back();
                     }
 
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/ResourceGroupGWTServiceImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/ResourceGroupGWTServiceImpl.java
index b098980..8c5c54d 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/ResourceGroupGWTServiceImpl.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/ResourceGroupGWTServiceImpl.java
@@ -29,6 +29,7 @@ import org.rhq.enterprise.gui.coregui.client.gwt.ResourceGroupGWTService;
 import org.rhq.enterprise.gui.coregui.server.util.SerialUtility;
 import org.rhq.enterprise.server.resource.group.ResourceGroupManagerLocal;
 import org.rhq.enterprise.server.resource.group.definition.GroupDefinitionManagerLocal;
+import org.rhq.core.domain.resource.group.DuplicateExpressionTypeException;
 import org.rhq.enterprise.server.util.LookupUtil;
 
 /**
@@ -146,20 +147,28 @@ public class ResourceGroupGWTServiceImpl extends AbstractGWTServiceImpl implemen
         }
     }
 
-    public void updateGroupDefinition(GroupDefinition groupDefinition) throws RuntimeException {
+    public void updateGroupDefinition(GroupDefinition groupDefinition)
+        throws DuplicateExpressionTypeException, RuntimeException {
         try {
             definitionManager.updateGroupDefinition(getSessionSubject(), groupDefinition);
         } catch (Throwable t) {
+            if (t instanceof DuplicateExpressionTypeException) {
+                throw (DuplicateExpressionTypeException) t;
+            }
             throw getExceptionToThrowToClient(t);
         }
     }
 
-    public void recalculateGroupDefinitions(int[] groupDefinitionIds) throws RuntimeException {
+    public void recalculateGroupDefinitions(int[] groupDefinitionIds)
+        throws DuplicateExpressionTypeException, RuntimeException {
         try {
             for (int nextGroupDefinitionId : groupDefinitionIds) {
                 definitionManager.calculateGroupMembership(getSessionSubject(), nextGroupDefinitionId);
             }
         } catch (Throwable t) {
+            if (t instanceof DuplicateExpressionTypeException) {
+                throw (DuplicateExpressionTypeException) t;
+            }
             throw getExceptionToThrowToClient(t);
         }
     }
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/definition/group/EditGroupDefinitionGeneralPropertiesUIBean.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/definition/group/EditGroupDefinitionGeneralPropertiesUIBean.java
index 262c173..b3a1edd 100644
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/definition/group/EditGroupDefinitionGeneralPropertiesUIBean.java
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/definition/group/EditGroupDefinitionGeneralPropertiesUIBean.java
@@ -31,7 +31,7 @@ import org.rhq.enterprise.gui.util.EnterpriseFacesContextUtility;
 import org.rhq.enterprise.server.resource.group.ResourceGroupUpdateException;
 import org.rhq.enterprise.server.resource.group.definition.GroupDefinitionManagerLocal;
 import org.rhq.enterprise.server.resource.group.definition.exception.GroupDefinitionException;
-import org.rhq.enterprise.server.resource.group.definition.framework.InvalidExpressionException;
+import org.rhq.core.domain.resource.group.InvalidExpressionException;
 import org.rhq.enterprise.server.util.LookupUtil;
 
 public class EditGroupDefinitionGeneralPropertiesUIBean {
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/GroupDefinitionManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/GroupDefinitionManagerBean.java
index 3776c70..190a169 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/GroupDefinitionManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/GroupDefinitionManagerBean.java
@@ -62,7 +62,7 @@ import org.rhq.enterprise.server.resource.group.definition.exception.GroupDefini
 import org.rhq.enterprise.server.resource.group.definition.exception.GroupDefinitionNotFoundException;
 import org.rhq.enterprise.server.resource.group.definition.exception.GroupDefinitionUpdateException;
 import org.rhq.enterprise.server.resource.group.definition.framework.ExpressionEvaluator;
-import org.rhq.enterprise.server.resource.group.definition.framework.InvalidExpressionException;
+import org.rhq.core.domain.resource.group.InvalidExpressionException;
 import org.rhq.enterprise.server.resource.group.definition.mbean.GroupDefinitionRecalculationThreadMonitor;
 import org.rhq.enterprise.server.resource.group.definition.mbean.GroupDefinitionRecalculationThreadMonitorMBean;
 import org.rhq.enterprise.server.util.CriteriaQueryGenerator;
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/GroupDefinitionManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/GroupDefinitionManagerLocal.java
index d83c77c..b1d0d1d 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/GroupDefinitionManagerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/GroupDefinitionManagerLocal.java
@@ -33,7 +33,7 @@ import org.rhq.enterprise.server.resource.group.definition.exception.GroupDefini
 import org.rhq.enterprise.server.resource.group.definition.exception.GroupDefinitionNotFoundException;
 import org.rhq.enterprise.server.resource.group.definition.exception.GroupDefinitionUpdateException;
 import org.rhq.enterprise.server.resource.group.definition.framework.ExpressionEvaluator;
-import org.rhq.enterprise.server.resource.group.definition.framework.InvalidExpressionException;
+import org.rhq.core.domain.resource.group.InvalidExpressionException;
 
 @Local
 public interface GroupDefinitionManagerLocal {
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/DuplicateExpressionTypeException.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/DuplicateExpressionTypeException.java
deleted file mode 100644
index 2b34b05..0000000
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/DuplicateExpressionTypeException.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- *
- *  * RHQ Management Platform
- *  * Copyright (C) 2005-2012 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.resource.group.definition.framework;
-
-/**
- * @author John Sanda
- */
-public class DuplicateExpressionTypeException extends InvalidExpressionException {
-
-    private static final long serialVersionUID = 1L;
-
-    private DuplicateExpressionTypeException() {
-    }
-
-    public DuplicateExpressionTypeException(String predicate) {
-        super("You cannot specify multiple " + predicate + " expressions.");
-    }
-
-}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/ExpressionEvaluator.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/ExpressionEvaluator.java
index 925d59d..7f42f55 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/ExpressionEvaluator.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/ExpressionEvaluator.java
@@ -28,7 +28,7 @@ import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import java.util.TreeSet;
+import java.util.TreeMap;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -39,6 +39,8 @@ import org.apache.commons.logging.LogFactory;
 
 import org.rhq.core.domain.measurement.AvailabilityType;
 import org.rhq.core.domain.resource.ResourceCategory;
+import org.rhq.core.domain.resource.group.DuplicateExpressionTypeException;
+import org.rhq.core.domain.resource.group.InvalidExpressionException;
 import org.rhq.enterprise.server.common.EntityManagerFacadeLocal;
 import org.rhq.enterprise.server.util.LookupUtil;
 import org.rhq.enterprise.server.util.QueryUtility;
@@ -93,7 +95,7 @@ public class ExpressionEvaluator implements Iterable<ExpressionEvaluator.Result>
 
     private EntityManagerFacadeLocal entityManagerFacade;
 
-    private Set<String> resourceExpressions = new TreeSet<String>();
+    private Map<String, String> resourceExpressions = new TreeMap<String, String>();
 
     public ExpressionEvaluator() {
         /*
@@ -129,69 +131,77 @@ public class ExpressionEvaluator implements Iterable<ExpressionEvaluator.Result>
          */
         whereStatics.add("res.inventoryStatus = org.rhq.core.domain.resource.InventoryStatus.COMMITTED");
 
-        resourceExpressions.add("res.id");
-        resourceExpressions.add("child.id");
-        resourceExpressions.add("res.parentResource.id");
-        resourceExpressions.add("res.parentResource.parentResource.id");
-        resourceExpressions.add("res.parentResource.parentResource.parentResource.id");
-        resourceExpressions.add("res.parentResource.parentResource.parentResource.parentResource.id");
-
-        resourceExpressions.add("res.name");
-        resourceExpressions.add("child.name");
-        resourceExpressions.add("res.parentResource.name");
-        resourceExpressions.add("res.parentResource.parentResource.name");
-        resourceExpressions.add("res.parentResource.parentResource.parentResource.name");
-        resourceExpressions.add("res.parentResource.parentResource.parentResource.parentResource.name");
-
-        resourceExpressions.add("res.version");
-        resourceExpressions.add("child.version");
-        resourceExpressions.add("res.parentResource.version");
-        resourceExpressions.add("res.parentResource.parentResource.version");
-        resourceExpressions.add("res.parentResource.parentResource.parentResource.version");
-        resourceExpressions.add("res.parentResource.parentResource.parentResource.parentResource.version");
-
-
-        resourceExpressions.add("res.resourceType.plugin");
-        resourceExpressions.add("res.resourceType.name");
-        resourceExpressions.add("child.resourceType.plugin");
-        resourceExpressions.add("child.resourceType.name");
-        resourceExpressions.add("res.parentResource.resourceType.plugin");
-        resourceExpressions.add("res.parentResource.resourceType.name");
-        resourceExpressions.add("res.parentResource.parentResource.resourceType.plugin");
-        resourceExpressions.add("res.parentResource.parentResource.resourceType.name");
-        resourceExpressions.add("res.parentResource.parentResource.parentResource.resourceType.plugin");
-        resourceExpressions.add("res.parentResource.parentResource.parentResource.resourceType.name");
-        resourceExpressions.add("res.parentResource.parentResource.parentResource.parentResource.resourceType.plugin");
-        resourceExpressions.add("res.parentResource.parentResource.parentResource.parentResource.resourceType.name");
-
-
-        resourceExpressions.add("res.resourceType.category");
-        resourceExpressions.add("child.resourceType.category");
-        resourceExpressions.add("res.parentResource.resourceType.category");
-        resourceExpressions.add("res.parentResource.parentResource.resourceType.category");
-        resourceExpressions.add("res.parentResource.parentResource.parentResource.resourceType.category");
-        resourceExpressions.add("res.parentResource.parentResource.parentResource.parentResource.resourceType.category");
-
-        resourceExpressions.add("avail.availabilityType");
-        resourceExpressions.add("child.avail.availabilityType");
-        resourceExpressions.add("res.parentResource.avail.availabilityType");
-        resourceExpressions.add("res.parentResource.parentResource.avail.availabilityType");
-        resourceExpressions.add("res.parentResource.parentResource.parentResource.avail.availabilityType");
-        resourceExpressions.add("res.parentResource.parentResource.parentResource.parentResource.avail.availabilityType");
-
-        resourceExpressions.add("trait.value");
-        resourceExpressions.add("child.trait.value");
-        resourceExpressions.add("res.parentResource.trait.value");
-        resourceExpressions.add("res.parentResource.parentResource.trait.value");
-        resourceExpressions.add("res.parentResource.parentResource.parentResource.trait.value");
-        resourceExpressions.add("res.parentResource.parentResource.parentResource.parentResource.trait.value");
-
-        resourceExpressions.add("simple.name");
-        resourceExpressions.add("child.simple.name");
-        resourceExpressions.add("res.parentResource.simple.name");
-        resourceExpressions.add("res.parentResource.parentResource.simple.name");
-        resourceExpressions.add("res.parentResource.parentResource.parentResource.simple.name");
-        resourceExpressions.add("res.parentResource.parentResource.parentResource.parentResource.simple.name");
+        resourceExpressions.put("res.id", "resource id");
+        resourceExpressions.put("child.id", "resource id");
+        resourceExpressions.put("res.parentResource.id", "resource id");
+        resourceExpressions.put("res.parentResource.parentResource.id", "resource id");
+        resourceExpressions.put("res.parentResource.parentResource.parentResource.id", "resource id");
+        resourceExpressions.put("res.parentResource.parentResource.parentResource.parentResource.id", "resource id");
+
+        resourceExpressions.put("res.name", "resource name");
+        resourceExpressions.put("child.name", "resource name");
+        resourceExpressions.put("res.parentResource.name", "resource name");
+        resourceExpressions.put("res.parentResource.parentResource.name", "resource name");
+        resourceExpressions.put("res.parentResource.parentResource.parentResource.name", "resource name");
+        resourceExpressions.put("res.parentResource.parentResource.parentResource.parentResource.name",
+            "resource name");
+
+        resourceExpressions.put("res.version", "resource version");
+        resourceExpressions.put("child.version", "resource version");
+        resourceExpressions.put("res.parentResource.version", "resource version");
+        resourceExpressions.put("res.parentResource.parentResource.version", "resource version");
+        resourceExpressions.put("res.parentResource.parentResource.parentResource.version", "resource version");
+        resourceExpressions.put("res.parentResource.parentResource.parentResource.parentResource.version",
+            "resource version");
+
+        resourceExpressions.put("res.resourceType.plugin", "resource type");
+        resourceExpressions.put("res.resourceType.name", "resource type");
+        resourceExpressions.put("child.resourceType.plugin", "resource type");
+        resourceExpressions.put("child.resourceType.name", "resource type");
+        resourceExpressions.put("res.parentResource.resourceType.plugin", "resource type");
+        resourceExpressions.put("res.parentResource.resourceType.name", "resource type");
+        resourceExpressions.put("res.parentResource.parentResource.resourceType.plugin", "resource type");
+        resourceExpressions.put("res.parentResource.parentResource.resourceType.name", "resource type");
+        resourceExpressions.put("res.parentResource.parentResource.parentResource.resourceType.plugin",
+            "resource type");
+        resourceExpressions.put("res.parentResource.parentResource.parentResource.resourceType.name", "resource type");
+        resourceExpressions.put("res.parentResource.parentResource.parentResource.parentResource.resourceType.plugin",
+            "resource type");
+        resourceExpressions.put("res.parentResource.parentResource.parentResource.parentResource.resourceType.name",
+            "resource type");
+
+        resourceExpressions.put("res.resourceType.category", "resource category");
+        resourceExpressions.put("child.resourceType.category", "resource category");
+        resourceExpressions.put("res.parentResource.resourceType.category", "resource category");
+        resourceExpressions.put("res.parentResource.parentResource.resourceType.category", "resource category");
+        resourceExpressions.put("res.parentResource.parentResource.parentResource.resourceType.category",
+            "resource category");
+        resourceExpressions.put("res.parentResource.parentResource.parentResource.parentResource.resourceType.category",
+            "resource category");
+
+        resourceExpressions.put("avail.availabilityType", "availability");
+        resourceExpressions.put("child.avail.availabilityType", "availability");
+        resourceExpressions.put("res.parentResource.avail.availabilityType", "availability");
+        resourceExpressions.put("res.parentResource.parentResource.avail.availabilityType", "availability");
+        resourceExpressions.put("res.parentResource.parentResource.parentResource.avail.availabilityType",
+            "availability");
+        resourceExpressions.put("res.parentResource.parentResource.parentResource.parentResource.avail.availabilityType",
+            "availability");
+
+        resourceExpressions.put("trait.value", "trait");
+        resourceExpressions.put("child.trait.value", "trait");
+        resourceExpressions.put("res.parentResource.trait.value", "trait");
+        resourceExpressions.put("res.parentResource.parentResource.trait.value", "trait");
+        resourceExpressions.put("res.parentResource.parentResource.parentResource.trait.value", "trait");
+        resourceExpressions.put("res.parentResource.parentResource.parentResource.parentResource.trait.value", "trait");
+
+        resourceExpressions.put("simple.name", "configuration");
+        resourceExpressions.put("child.simple.name", "configuration");
+        resourceExpressions.put("res.parentResource.simple.name", "configuration");
+        resourceExpressions.put("res.parentResource.parentResource.simple.name", "configuration");
+        resourceExpressions.put("res.parentResource.parentResource.parentResource.simple.name", "configuration");
+        resourceExpressions.put("res.parentResource.parentResource.parentResource.parentResource.simple.name",
+            "configuration");
     }
 
     public class Result {
@@ -231,7 +241,7 @@ public class ExpressionEvaluator implements Iterable<ExpressionEvaluator.Result>
      *
      * @return a reference to itself, so that method chaining can be used
      *
-     * @throws InvalidExpressionException if the expression can not be parsed for any reason, the message will try to
+     * @throws org.rhq.core.domain.resource.group.InvalidExpressionException if the expression can not be parsed for any reason, the message will try to
      *                                    get the details as to the parse failure
      */
     public ExpressionEvaluator addExpression(String expression) throws InvalidExpressionException {
@@ -779,8 +789,8 @@ public class ExpressionEvaluator implements Iterable<ExpressionEvaluator.Result>
                     + "] for predicate population");
             }
 
-            if (resourceExpressions.contains(predicateName) && whereConditions.containsKey(predicateName)) {
-                throw new DuplicateExpressionTypeException(predicateName);
+            if (resourceExpressions.containsKey(predicateName) && whereConditions.containsKey(predicateName)) {
+                throw new DuplicateExpressionTypeException(resourceExpressions.get(predicateName));
             }
 
             whereConditions.put(predicateName, argumentName);
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/InvalidExpressionException.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/InvalidExpressionException.java
deleted file mode 100644
index 06c7558..0000000
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/InvalidExpressionException.java
+++ /dev/null
@@ -1,38 +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.resource.group.definition.framework;
-
-public class InvalidExpressionException extends Exception {
-    private static final long serialVersionUID = 1L;
-
-    public InvalidExpressionException() {
-    }
-
-    public InvalidExpressionException(String message) {
-        super(message);
-    }
-
-    public InvalidExpressionException(Throwable cause) {
-        super(cause);
-    }
-
-    public InvalidExpressionException(String message, Throwable cause) {
-        super(message, cause);
-    }
-}
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/definition/framework/test/ExpressionEvaluatorTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/definition/framework/test/ExpressionEvaluatorTest.java
index 76c5824..a1c8a65 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/definition/framework/test/ExpressionEvaluatorTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/definition/framework/test/ExpressionEvaluatorTest.java
@@ -24,9 +24,9 @@ import java.util.List;
 
 import org.testng.annotations.Test;
 
-import org.rhq.enterprise.server.resource.group.definition.framework.DuplicateExpressionTypeException;
+import org.rhq.core.domain.resource.group.DuplicateExpressionTypeException;
 import org.rhq.enterprise.server.resource.group.definition.framework.ExpressionEvaluator;
-import org.rhq.enterprise.server.resource.group.definition.framework.InvalidExpressionException;
+import org.rhq.core.domain.resource.group.InvalidExpressionException;
 import org.rhq.enterprise.server.test.AbstractEJB3Test;
 import org.rhq.enterprise.server.util.QueryUtility;
 


commit c97c6b90b7cd8d54c3974b8bddc61fe808e2b72b
Author: John Sanda <jsanda at redhat.com>
Date:   Wed Jun 27 14:19:03 2012 -0400

    [BZ 826716] Adding tests for plugin and resource config expressions.

diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/ExpressionEvaluator.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/ExpressionEvaluator.java
index 32565b6..925d59d 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/ExpressionEvaluator.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/ExpressionEvaluator.java
@@ -178,6 +178,20 @@ public class ExpressionEvaluator implements Iterable<ExpressionEvaluator.Result>
         resourceExpressions.add("res.parentResource.parentResource.avail.availabilityType");
         resourceExpressions.add("res.parentResource.parentResource.parentResource.avail.availabilityType");
         resourceExpressions.add("res.parentResource.parentResource.parentResource.parentResource.avail.availabilityType");
+
+        resourceExpressions.add("trait.value");
+        resourceExpressions.add("child.trait.value");
+        resourceExpressions.add("res.parentResource.trait.value");
+        resourceExpressions.add("res.parentResource.parentResource.trait.value");
+        resourceExpressions.add("res.parentResource.parentResource.parentResource.trait.value");
+        resourceExpressions.add("res.parentResource.parentResource.parentResource.parentResource.trait.value");
+
+        resourceExpressions.add("simple.name");
+        resourceExpressions.add("child.simple.name");
+        resourceExpressions.add("res.parentResource.simple.name");
+        resourceExpressions.add("res.parentResource.parentResource.simple.name");
+        resourceExpressions.add("res.parentResource.parentResource.parentResource.simple.name");
+        resourceExpressions.add("res.parentResource.parentResource.parentResource.parentResource.simple.name");
     }
 
     public class Result {
@@ -549,10 +563,6 @@ public class ExpressionEvaluator implements Iterable<ExpressionEvaluator.Result>
                 addJoinCondition(JoinCondition.AVAILABILITY);
                 populatePredicateCollections(JoinCondition.AVAILABILITY.alias + ".availabilityType", type);
             } else if (context == ParseContext.Trait) {
-                if (whereConditions.containsKey(TRAIT_ALIAS + ".value")) {
-                    throw new InvalidExpressionException("Cannot have multiple trait expressions.");
-                }
-
                 // SELECT res.id FROM Resource res JOIN res.schedules sched, sched.definition def, MeasurementDataTrait trait
                 // WHERE def.name = :arg1 AND trait.value = :arg2 AND trait.schedule = sched AND trait.id.timestamp =
                 // (SELECT max(mdt.id.timestamp) FROM MeasurementDataTrait mdt WHERE sched.id = mdt.schedule.id)
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/definition/framework/test/ExpressionEvaluatorTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/definition/framework/test/ExpressionEvaluatorTest.java
index 78ee34f..76c5824 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/definition/framework/test/ExpressionEvaluatorTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/definition/framework/test/ExpressionEvaluatorTest.java
@@ -29,7 +29,6 @@ import org.rhq.enterprise.server.resource.group.definition.framework.ExpressionE
 import org.rhq.enterprise.server.resource.group.definition.framework.InvalidExpressionException;
 import org.rhq.enterprise.server.test.AbstractEJB3Test;
 import org.rhq.enterprise.server.util.QueryUtility;
-import org.rhq.test.TransactionCallback;
 
 public class ExpressionEvaluatorTest extends AbstractEJB3Test {
 
@@ -158,7 +157,7 @@ public class ExpressionEvaluatorTest extends AbstractEJB3Test {
             "   AND simple.name = simpleDef.name AND simpleDef.type != 'PASSWORD' " }, };
     }
 
-//    @Test(groups = "integration.session")
+    @Test(groups = "integration.session")
     public void testWellFormedExpressions() throws Exception {
 
         String[][] successTestCases = getSuccessTestCases();
@@ -215,7 +214,7 @@ public class ExpressionEvaluatorTest extends AbstractEJB3Test {
         }
     }
 
-//    @Test(groups = "integration.session")
+    @Test(groups = "integration.session")
     public void testTokenizer() {
 
         String[] input = { "resource.child.name", //
@@ -257,15 +256,6 @@ public class ExpressionEvaluatorTest extends AbstractEJB3Test {
         }
     }
 
-    private void executeAndRollback(TransactionCallback callback) throws Exception {
-        try {
-            getTransactionManager().begin();
-            callback.execute();
-        } finally {
-            getTransactionManager().rollback();
-        }
-    }
-
     private static interface ExpressionGenerator {
         String[] getExpressions();
     }
@@ -284,34 +274,86 @@ public class ExpressionEvaluatorTest extends AbstractEJB3Test {
         }
     }
 
-    @Test(expectedExceptions = InvalidExpressionException.class,
-        expectedExceptionsMessageRegExp = ".*Cannot have multiple trait expressions.*")
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
     public void doNotAllowMultipleResourceTraitExpressions() throws Exception {
-        executeAndRollback(new TransactionCallback() {
+        evaluateExpressions(new ExpressionGenerator() {
             @Override
-            public void execute() throws Exception {
-                ExpressionEvaluator evaluator = new ExpressionEvaluator();
-                evaluator.addExpression("resource.trait[agentHomeDirectory] = /var/rhq-agent");
-                evaluator.addExpression("resource.trait[reasonForLastRestart] = OOMError");
+            public String[] getExpressions() {
+                return new String[] {
+                    "resource.trait[agentHomeDirectory] = /var/rhq-agent",
+                    "resource.trait[reasonForLastRestart] = OOMError"
+                };
+            }
+        });
+    }
 
-                evaluator.execute();
-                evaluator.iterator().next();
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleChildResourceTraitExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[] {
+                    "resource.child.trait[agentHomeDirectory] = /var/rhq-agent",
+                    "resource.child.trait[reasonForLastRestart] = OOMError"
+                };
             }
         });
     }
 
-    @Test(expectedExceptions = InvalidExpressionException.class,
-        expectedExceptionsMessageRegExp = ".*Cannot have multiple trait expressions.*")
-    public void doNotAllowMultiplParentResourceTraitExpressions() throws Exception {
-        executeAndRollback(new TransactionCallback() {
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleParentResourceTraitExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
             @Override
-            public void execute() throws Exception {
-                ExpressionEvaluator evaluator = new ExpressionEvaluator();
-                evaluator.addExpression("resource.parent.trait[agentHomeDirectory] = /var/rhq-agent");
-                evaluator.addExpression("resource.parent.trait[reasonForLastRestart] = OOMError");
+            public String[] getExpressions() {
+                return new String[] {
+                    "resource.parent.trait[agentHomeDirectory] = /var/rhq-agent",
+                    "resource.parent.trait[reasonForLastRestart] = OOMError"
+                };
+            }
+        });
+    }
 
-                evaluator.execute();
-                evaluator.iterator().next();
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleGrandParentResourceTraitExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[] {
+                    "resource.grandParent.trait[agentHomeDirectory] = /var/rhq-agent",
+                    "resource.grandParent.trait[reasonForLastRestart] = OOMError"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleGreatGrandParentResourceTraitExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[] {
+                    "resource.greatGrandParent.trait[agentHomeDirectory] = /var/rhq-agent",
+                    "resource.greatGrandParent.trait[reasonForLastRestart] = OOMError"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleGreatGreatGrandParentResourceTraitExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[] {
+                    "resource.greatGreatGrandParent.trait[agentHomeDirectory] = /var/rhq-agent",
+                    "resource.greatGreatGrandParent.trait[reasonForLastRestart] = OOMError"
+                };
             }
         });
     }
@@ -748,6 +790,174 @@ public class ExpressionEvaluatorTest extends AbstractEJB3Test {
         });
     }
 
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleResourcePluginConfigExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[]{
+                    "resource.pluginConfiguration[x] = 1",
+                    "resource.pluginConfiguration[y] = 2"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleChildResourcePluginConfigExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[]{
+                    "resource.child.pluginConfiguration[x] = 1",
+                    "resource.child.pluginConfiguration[y] = 2"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleParentResourcePluginConfigExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[]{
+                    "resource.parent.pluginConfiguration[x] = 1",
+                    "resource.parent.pluginConfiguration[y] = 2"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleGrandParentResourcePluginConfigExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[]{
+                    "resource.grandParent.pluginConfiguration[x] = 1",
+                    "resource.grandParent.pluginConfiguration[y] = 2"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleGreatGrandParentResourcePluginConfigExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[]{
+                    "resource.greatGrandParent.pluginConfiguration[x] = 1",
+                    "resource.greatGrandParent.pluginConfiguration[y] = 2"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleGreatGreatGrandParentResourcePluginConfigExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[]{
+                    "resource.greatGreatGrandParent.pluginConfiguration[x] = 1",
+                    "resource.greatGreatGrandParent.pluginConfiguration[y] = 2"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleResourceConfigExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[]{
+                    "resource.resourceConfiguration[x] = 1",
+                    "resource.resourceConfiguration[y] = 2"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleChildResourceConfigExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[]{
+                    "resource.child.resourceConfiguration[x] = 1",
+                    "resource.child.resourceConfiguration[y] = 2"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleParentResourceConfigExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[]{
+                    "resource.parent.resourceConfiguration[x] = 1",
+                    "resource.parent.resourceConfiguration[y] = 2"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleGrandParentResourceConfigExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[]{
+                    "resource.grandParent.resourceConfiguration[x] = 1",
+                    "resource.grandParent.resourceConfiguration[y] = 2"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleGreatGrandParentResourceConfigExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[]{
+                    "resource.greatGrandParent.resourceConfiguration[x] = 1",
+                    "resource.greatGrandParent.resourceConfiguration[y] = 2"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleGreatGreatGrandParentResourceConfigExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[]{
+                    "resource.greatGreatGrandParent.resourceConfiguration[x] = 1",
+                    "resource.greatGreatGrandParent.resourceConfiguration[y] = 2"
+                };
+            }
+        });
+    }
+
     private String cleanUp(String result) {
         return result.replaceAll("\\s+", " ").trim();
     }


commit 95a0bf5b8be8a17638bd1b6fbf740e959e19af31
Author: John Sanda <jsanda at redhat.com>
Date:   Tue Jun 26 17:04:29 2012 -0400

    [BZ 667896] Adding more tests to verify we do not allow multiple expressions of the same type

diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/DuplicateExpressionTypeException.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/DuplicateExpressionTypeException.java
new file mode 100644
index 0000000..2b34b05
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/DuplicateExpressionTypeException.java
@@ -0,0 +1,38 @@
+/*
+ *
+ *  * RHQ Management Platform
+ *  * Copyright (C) 2005-2012 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.resource.group.definition.framework;
+
+/**
+ * @author John Sanda
+ */
+public class DuplicateExpressionTypeException extends InvalidExpressionException {
+
+    private static final long serialVersionUID = 1L;
+
+    private DuplicateExpressionTypeException() {
+    }
+
+    public DuplicateExpressionTypeException(String predicate) {
+        super("You cannot specify multiple " + predicate + " expressions.");
+    }
+
+}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/ExpressionEvaluator.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/ExpressionEvaluator.java
index 1f7e300..32565b6 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/ExpressionEvaluator.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/ExpressionEvaluator.java
@@ -28,6 +28,7 @@ import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.TreeSet;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -92,6 +93,8 @@ public class ExpressionEvaluator implements Iterable<ExpressionEvaluator.Result>
 
     private EntityManagerFacadeLocal entityManagerFacade;
 
+    private Set<String> resourceExpressions = new TreeSet<String>();
+
     public ExpressionEvaluator() {
         /*
          * used LinkedHashMap for whereConditions on purpose so that the iterator will return them in the same order
@@ -125,6 +128,56 @@ public class ExpressionEvaluator implements Iterable<ExpressionEvaluator.Result>
          * initialization for special handling that all dynagroups should get
          */
         whereStatics.add("res.inventoryStatus = org.rhq.core.domain.resource.InventoryStatus.COMMITTED");
+
+        resourceExpressions.add("res.id");
+        resourceExpressions.add("child.id");
+        resourceExpressions.add("res.parentResource.id");
+        resourceExpressions.add("res.parentResource.parentResource.id");
+        resourceExpressions.add("res.parentResource.parentResource.parentResource.id");
+        resourceExpressions.add("res.parentResource.parentResource.parentResource.parentResource.id");
+
+        resourceExpressions.add("res.name");
+        resourceExpressions.add("child.name");
+        resourceExpressions.add("res.parentResource.name");
+        resourceExpressions.add("res.parentResource.parentResource.name");
+        resourceExpressions.add("res.parentResource.parentResource.parentResource.name");
+        resourceExpressions.add("res.parentResource.parentResource.parentResource.parentResource.name");
+
+        resourceExpressions.add("res.version");
+        resourceExpressions.add("child.version");
+        resourceExpressions.add("res.parentResource.version");
+        resourceExpressions.add("res.parentResource.parentResource.version");
+        resourceExpressions.add("res.parentResource.parentResource.parentResource.version");
+        resourceExpressions.add("res.parentResource.parentResource.parentResource.parentResource.version");
+
+
+        resourceExpressions.add("res.resourceType.plugin");
+        resourceExpressions.add("res.resourceType.name");
+        resourceExpressions.add("child.resourceType.plugin");
+        resourceExpressions.add("child.resourceType.name");
+        resourceExpressions.add("res.parentResource.resourceType.plugin");
+        resourceExpressions.add("res.parentResource.resourceType.name");
+        resourceExpressions.add("res.parentResource.parentResource.resourceType.plugin");
+        resourceExpressions.add("res.parentResource.parentResource.resourceType.name");
+        resourceExpressions.add("res.parentResource.parentResource.parentResource.resourceType.plugin");
+        resourceExpressions.add("res.parentResource.parentResource.parentResource.resourceType.name");
+        resourceExpressions.add("res.parentResource.parentResource.parentResource.parentResource.resourceType.plugin");
+        resourceExpressions.add("res.parentResource.parentResource.parentResource.parentResource.resourceType.name");
+
+
+        resourceExpressions.add("res.resourceType.category");
+        resourceExpressions.add("child.resourceType.category");
+        resourceExpressions.add("res.parentResource.resourceType.category");
+        resourceExpressions.add("res.parentResource.parentResource.resourceType.category");
+        resourceExpressions.add("res.parentResource.parentResource.parentResource.resourceType.category");
+        resourceExpressions.add("res.parentResource.parentResource.parentResource.parentResource.resourceType.category");
+
+        resourceExpressions.add("avail.availabilityType");
+        resourceExpressions.add("child.avail.availabilityType");
+        resourceExpressions.add("res.parentResource.avail.availabilityType");
+        resourceExpressions.add("res.parentResource.parentResource.avail.availabilityType");
+        resourceExpressions.add("res.parentResource.parentResource.parentResource.avail.availabilityType");
+        resourceExpressions.add("res.parentResource.parentResource.parentResource.parentResource.avail.availabilityType");
     }
 
     public class Result {
@@ -716,6 +769,10 @@ public class ExpressionEvaluator implements Iterable<ExpressionEvaluator.Result>
                     + "] for predicate population");
             }
 
+            if (resourceExpressions.contains(predicateName) && whereConditions.containsKey(predicateName)) {
+                throw new DuplicateExpressionTypeException(predicateName);
+            }
+
             whereConditions.put(predicateName, argumentName);
             whereReplacements.put(argumentName, value);
 
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/definition/framework/test/ExpressionEvaluatorTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/definition/framework/test/ExpressionEvaluatorTest.java
index f0a64ff..78ee34f 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/definition/framework/test/ExpressionEvaluatorTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/definition/framework/test/ExpressionEvaluatorTest.java
@@ -24,10 +24,12 @@ import java.util.List;
 
 import org.testng.annotations.Test;
 
+import org.rhq.enterprise.server.resource.group.definition.framework.DuplicateExpressionTypeException;
 import org.rhq.enterprise.server.resource.group.definition.framework.ExpressionEvaluator;
 import org.rhq.enterprise.server.resource.group.definition.framework.InvalidExpressionException;
 import org.rhq.enterprise.server.test.AbstractEJB3Test;
 import org.rhq.enterprise.server.util.QueryUtility;
+import org.rhq.test.TransactionCallback;
 
 public class ExpressionEvaluatorTest extends AbstractEJB3Test {
 
@@ -255,24 +257,495 @@ public class ExpressionEvaluatorTest extends AbstractEJB3Test {
         }
     }
 
-    @Test(expectedExceptions = InvalidExpressionException.class)
-    public void throwExceptionWhenMultipleResourceTraitsSpecified() throws Exception {
-        ExpressionEvaluator evaluator = new ExpressionEvaluator();
-        evaluator.addExpression("resource.trait[agentHomeDirectory] = /var/rhq-agent");
-        evaluator.addExpression("resource.trait[reasonForLastRestart] = OOMError");
+    private void executeAndRollback(TransactionCallback callback) throws Exception {
+        try {
+            getTransactionManager().begin();
+            callback.execute();
+        } finally {
+            getTransactionManager().rollback();
+        }
+    }
 
-        evaluator.execute();
-        evaluator.iterator().next();
+    private static interface ExpressionGenerator {
+        String[] getExpressions();
     }
 
-    @Test(expectedExceptions = InvalidExpressionException.class)
-    public void throwExceptionWhenMultipleResourceParentTraitsSpecified() throws Exception {
-        ExpressionEvaluator evaluator = new ExpressionEvaluator();
-        evaluator.addExpression("resource.parent.trait[agentHomeDirectory] = /var/rhq-agent");
-        evaluator.addExpression("resource.parent.trait[reasonForLastRestart] = OOMError");
+    private void evaluateExpressions(ExpressionGenerator generator) throws Exception {
+        try {
+            getTransactionManager().begin();
+            ExpressionEvaluator evaluator = new ExpressionEvaluator();
+            for (String expression : generator.getExpressions()) {
+                evaluator.addExpression(expression);
+            }
+            evaluator.execute();
+            evaluator.iterator().next();
+        } finally {
+            getTransactionManager().rollback();
+        }
+    }
+
+    @Test(expectedExceptions = InvalidExpressionException.class,
+        expectedExceptionsMessageRegExp = ".*Cannot have multiple trait expressions.*")
+    public void doNotAllowMultipleResourceTraitExpressions() throws Exception {
+        executeAndRollback(new TransactionCallback() {
+            @Override
+            public void execute() throws Exception {
+                ExpressionEvaluator evaluator = new ExpressionEvaluator();
+                evaluator.addExpression("resource.trait[agentHomeDirectory] = /var/rhq-agent");
+                evaluator.addExpression("resource.trait[reasonForLastRestart] = OOMError");
+
+                evaluator.execute();
+                evaluator.iterator().next();
+            }
+        });
+    }
+
+    @Test(expectedExceptions = InvalidExpressionException.class,
+        expectedExceptionsMessageRegExp = ".*Cannot have multiple trait expressions.*")
+    public void doNotAllowMultiplParentResourceTraitExpressions() throws Exception {
+        executeAndRollback(new TransactionCallback() {
+            @Override
+            public void execute() throws Exception {
+                ExpressionEvaluator evaluator = new ExpressionEvaluator();
+                evaluator.addExpression("resource.parent.trait[agentHomeDirectory] = /var/rhq-agent");
+                evaluator.addExpression("resource.parent.trait[reasonForLastRestart] = OOMError");
+
+                evaluator.execute();
+                evaluator.iterator().next();
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleResourceIdExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[] {
+                    "resource.id = 5",
+                    "resource.id = 6"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleChildResourceIdExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[]{
+                    "resource.child.id = 5",
+                    "resource.child.id = 6"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleParentResourceIdExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[]{
+                    "resource.parent.id = 5",
+                    "resource.parent.id = 6"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = InvalidExpressionException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleGrandParentResourceIdExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[] {
+                    "resource.grandParent.id = 5",
+                    "resource.grandParent.id = 6"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleGreatGrandParentResourceIdExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[]{
+                    "resource.greatGrandParent.id = 5",
+                    "resource.greatGrandParent.id = 6"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleGreatGreatGrandParentResourceIdExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[]{
+                    "resource.greatGreatGrandParent.id = 5",
+                    "resource.greatGreatGrandParent.id = 6"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleResourceNameExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[]{
+                    "resource.name = foo",
+                    "resource.name = bar"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleChildResourceNameExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[]{
+                    "resource.child.name = foo",
+                    "resource.child.name = bar"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleParentResourceNameExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[]{
+                    "resource.parent.name = foo",
+                    "resource.parent.name = bar"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleGrandParentResourceNameExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[]{
+                    "resource.grandParent.name = foo",
+                    "resource.grandParent.name = bar"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleGreatGrandParentResourceNameExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[]{
+                    "resource.greatGrandParent.name = foo",
+                    "resource.greatGrandParent.name = bar"
+                };
+            }
+        });
+    }
 
-        evaluator.execute();
-        evaluator.iterator().next();
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleGreatGreatGrandParentResourceNameExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[]{
+                    "resource.greatGreatGrandParent.name = foo",
+                    "resource.greatGreatGrandParent.name = bar"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleResourceTypeExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[] {
+                    "resource.type.plugin = rhq-agent",
+                    "resource.type.name = RHQ Agent",
+                    "resource.type.plugin = rhq-server",
+                    "resource.type.name = RHQ Server"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleChildResourceTypeExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[] {
+                    "resource.child.type.plugin = rhq-agent",
+                    "resource.child.type.name = RHQ Agent",
+                    "resource.child.type.plugin = rhq-server",
+                    "resource.child.type.name = RHQ Server"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleParentResourceTypeExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[]{
+                    "resource.parent.type.plugin = rhq-agent",
+                    "resource.parent.type.name = RHQ Agent",
+                    "resource.parent.type.plugin = rhq-server",
+                    "resource.parent.type.name = RHQ Server"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleGrandParentResourceTypeExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[] {
+                    "resource.grandParent.type.plugin = rhq-agent",
+                    "resource.grandParent.type.name = RHQ Agent",
+                    "resource.grandParent.type.plugin = rhq-server",
+                    "resource.grandParent.type.name = RHQ Server"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleGreatGrandParentResourceTypeExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[] {
+                    "resource.greatGrandParent.type.plugin = rhq-agent",
+                    "resource.greatGrandParent.type.name = RHQ Agent",
+                    "resource.greatGrandParent.type.plugin = rhq-server",
+                    "resource.greatGrandParent.type.name = RHQ Server"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleGreatGreatGrandParentResourceTypeExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[] {
+                    "resource.greatGreatGrandParent.type.plugin = rhq-agent",
+                    "resource.greatGreatGrandParent.type.name = RHQ Agent",
+                    "resource.greatGreatGrandParent.type.plugin = rhq-server",
+                    "resource.greatGreatGrandParent.type.name = RHQ Server"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleResourceCategoryExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[]{
+                    "resource.type.category = PLATFORM",
+                    "resource.type.category = SERVER"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleChildResourceCategoryExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[]{
+                    "resource.child.type.category = PLATFORM",
+                    "resource.child.type.category = SERVER"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleParentResourceCategoryExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[]{
+                    "resource.parent.type.category = PLATFORM",
+                    "resource.parent.type.category = SERVER"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleGrandParentResourceCategoryExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[]{
+                    "resource.grandParent.type.category = PLATFORM",
+                    "resource.grandParent.type.category = SERVER"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleGreatGrandParentResourceCategoryExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[]{
+                    "resource.greatGrandParent.type.category = PLATFORM",
+                    "resource.greatGrandParent.type.category = SERVER"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleGreatGreatGrandParentResourceCategoryExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[] {
+                    "resource.greatGreatGrandParent.type.category = PLATFORM",
+                    "resource.greatGreatGrandParent.type.category = SERVER"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleResourceAvailabilityExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[] {
+                    "resource.availability = UP",
+                    "resource.availability = UNKNOWN"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleChildResourceAvailabilityExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[] {
+                    "resource.child.availability = UP",
+                    "resource.child.availability = UNKNOWN"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleParentResourceAvailabilityExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[] {
+                    "resource.parent.availability = UP",
+                    "resource.parent.availability = UNKNOWN"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleGrandParentResourceAvailabilityExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[] {
+                    "resource.grandParent.availability = UP",
+                    "resource.grandParent.availability = UNKNOWN"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleGreatGrandParentResourceAvailabilityExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[] {
+                    "resource.greatGrandParent.availability = UP",
+                    "resource.greatGrandParent.availability = UNKNOWN"
+                };
+            }
+        });
+    }
+
+    @Test(expectedExceptions = DuplicateExpressionTypeException.class,
+        expectedExceptionsMessageRegExp = "You cannot specify multiple.*")
+    public void doNotAllowMultipleGreatGreatGrandParentResourceAvailabilityExpressions() throws Exception {
+        evaluateExpressions(new ExpressionGenerator() {
+            @Override
+            public String[] getExpressions() {
+                return new String[] {
+                    "resource.greatGreatGrandParent.availability = UP",
+                    "resource.greatGreatGrandParent.availability = UNKNOWN"
+                };
+            }
+        });
     }
 
     private String cleanUp(String result) {


commit 3442a828acc2a6e82e6d845f852246d66b2f2053
Author: John Sanda <jsanda at redhat.com>
Date:   Fri Jun 22 21:33:59 2012 -0400

    [BZ 667896] Throw exception if multiple trait expressions specified

diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/ExpressionEvaluator.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/ExpressionEvaluator.java
index 480c97f..1f7e300 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/ExpressionEvaluator.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/definition/framework/ExpressionEvaluator.java
@@ -496,6 +496,10 @@ public class ExpressionEvaluator implements Iterable<ExpressionEvaluator.Result>
                 addJoinCondition(JoinCondition.AVAILABILITY);
                 populatePredicateCollections(JoinCondition.AVAILABILITY.alias + ".availabilityType", type);
             } else if (context == ParseContext.Trait) {
+                if (whereConditions.containsKey(TRAIT_ALIAS + ".value")) {
+                    throw new InvalidExpressionException("Cannot have multiple trait expressions.");
+                }
+
                 // SELECT res.id FROM Resource res JOIN res.schedules sched, sched.definition def, MeasurementDataTrait trait
                 // WHERE def.name = :arg1 AND trait.value = :arg2 AND trait.schedule = sched AND trait.id.timestamp =
                 // (SELECT max(mdt.id.timestamp) FROM MeasurementDataTrait mdt WHERE sched.id = mdt.schedule.id)
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/definition/framework/test/ExpressionEvaluatorTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/definition/framework/test/ExpressionEvaluatorTest.java
index fd3db2e..f0a64ff 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/definition/framework/test/ExpressionEvaluatorTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/group/definition/framework/test/ExpressionEvaluatorTest.java
@@ -25,6 +25,7 @@ import java.util.List;
 import org.testng.annotations.Test;
 
 import org.rhq.enterprise.server.resource.group.definition.framework.ExpressionEvaluator;
+import org.rhq.enterprise.server.resource.group.definition.framework.InvalidExpressionException;
 import org.rhq.enterprise.server.test.AbstractEJB3Test;
 import org.rhq.enterprise.server.util.QueryUtility;
 
@@ -155,7 +156,7 @@ public class ExpressionEvaluatorTest extends AbstractEJB3Test {
             "   AND simple.name = simpleDef.name AND simpleDef.type != 'PASSWORD' " }, };
     }
 
-    @Test(groups = "integration.session")
+//    @Test(groups = "integration.session")
     public void testWellFormedExpressions() throws Exception {
 
         String[][] successTestCases = getSuccessTestCases();
@@ -212,7 +213,7 @@ public class ExpressionEvaluatorTest extends AbstractEJB3Test {
         }
     }
 
-    @Test(groups = "integration.session")
+//    @Test(groups = "integration.session")
     public void testTokenizer() {
 
         String[] input = { "resource.child.name", //
@@ -254,6 +255,26 @@ public class ExpressionEvaluatorTest extends AbstractEJB3Test {
         }
     }
 
+    @Test(expectedExceptions = InvalidExpressionException.class)
+    public void throwExceptionWhenMultipleResourceTraitsSpecified() throws Exception {
+        ExpressionEvaluator evaluator = new ExpressionEvaluator();
+        evaluator.addExpression("resource.trait[agentHomeDirectory] = /var/rhq-agent");
+        evaluator.addExpression("resource.trait[reasonForLastRestart] = OOMError");
+
+        evaluator.execute();
+        evaluator.iterator().next();
+    }
+
+    @Test(expectedExceptions = InvalidExpressionException.class)
+    public void throwExceptionWhenMultipleResourceParentTraitsSpecified() throws Exception {
+        ExpressionEvaluator evaluator = new ExpressionEvaluator();
+        evaluator.addExpression("resource.parent.trait[agentHomeDirectory] = /var/rhq-agent");
+        evaluator.addExpression("resource.parent.trait[reasonForLastRestart] = OOMError");
+
+        evaluator.execute();
+        evaluator.iterator().next();
+    }
+
     private String cleanUp(String result) {
         return result.replaceAll("\\s+", " ").trim();
     }


commit 73da0abdb93a5925e79ea1d35a62d15557bd96e1
Merge: fbb4fd5 b48676a
Author: Lukas Krejci <lkrejci at redhat.com>
Date:   Mon Jul 2 14:47:36 2012 +0200

    Merge remote-tracking branch 'origin/master' into lkrejci/modular-scripting



commit fbb4fd565dec268144e29692bb8c20cc98e9c487
Author: Lukas Krejci <lkrejci at redhat.com>
Date:   Mon Jul 2 14:36:31 2012 +0200

    Javascript completor now correctly outputs the signatures of the methods.

diff --git a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/utility/CLIMetadataProvider.java b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/utility/CLIMetadataProvider.java
index ff98b5c..a8da737 100644
--- a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/utility/CLIMetadataProvider.java
+++ b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/utility/CLIMetadataProvider.java
@@ -22,6 +22,7 @@ package org.rhq.enterprise.client.utility;
 
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
 import java.lang.reflect.Type;
 
 import javax.jws.WebParam;
@@ -34,6 +35,26 @@ import org.rhq.scripting.MetadataProvider;
 public class CLIMetadataProvider implements MetadataProvider {
 
     @Override
+    public Method getUnproxiedMethod(Method method) {
+        if (Proxy.isProxyClass(method.getDeclaringClass())) {
+            //ok, don't look at the proxy class but at the interface that is actually defining this method
+            for (Class<?> iface : method.getDeclaringClass().getInterfaces()) {
+                try {
+                    Method ifaceMethod = iface.getMethod(method.getName(), method.getParameterTypes());
+                    return ifaceMethod;
+                } catch (NoSuchMethodException e) {
+                    //well, never mind, let's try the next interface
+                } catch (SecurityException e) {
+                    //whoa
+                    throw new IllegalStateException("Current code doesn't have reflection permissions.", e);
+                }
+            }
+        }
+
+        return method;
+    }
+
+    @Override
     public String getParameterName(Method method, int parameterIndex) {
         String name = null;
 
diff --git a/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/MetadataProvider.java b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/MetadataProvider.java
index 598d952..448da46 100644
--- a/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/MetadataProvider.java
+++ b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/MetadataProvider.java
@@ -37,6 +37,21 @@ import java.lang.reflect.Type;
 public interface MetadataProvider {
 
     /**
+     * Many of the objects that RHQ exposes in the scripting environment are implemented
+     * using proxies. But proxies don't seem to maintain the generic types on them.
+     * <p>
+     * This method tries to find out if given method comes from a proxy class and if it is,
+     * it tries to find the method in one of the interfaces that the proxy implements that
+     * corresponds to it. That method is going to have all the metadata - i.e. annotations,
+     * generics, etc.
+     * 
+     * @param method the method to inspect
+     * @return the method from one of the interfaces implemented by the given method's declaring class
+     * or the given method itself if it is not proxied.
+     */
+    Method getUnproxiedMethod(Method method);
+
+    /**
      * Tries to determine the name of a parameter on a method.
      * 
      * @param method the method
diff --git a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JavascriptCompletor.java b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JavascriptCompletor.java
index 36eb060..f90969a 100644
--- a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JavascriptCompletor.java
+++ b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JavascriptCompletor.java
@@ -276,6 +276,9 @@ public class JavascriptCompletor implements CodeCompletion {
                     maxReturnLength = sig[0].length();
             }
 
+            output.println();
+            output.println();
+
             for (String[] sig : signatures) {
                 for (i = 0; i < (maxReturnLength - sig[0].length()); i++) {
                     output.print(" ");
@@ -500,6 +503,7 @@ public class JavascriptCompletor implements CodeCompletion {
         StringBuilder buf = new StringBuilder();
         Type[] params = m.getGenericParameterTypes();
         int i = 0;
+        m = metadataProvider.getUnproxiedMethod(m);
 
         buf.append(metadataProvider.getTypeName(m.getGenericReturnType(), false));
         buf.append(" ");


commit fca41ffec5ff7d32735f4c25d033b240a6d1df4b
Author: Lukas Krejci <lkrejci at redhat.com>
Date:   Mon Jul 2 14:32:56 2012 +0200

    The CLI interactive console correctly handles the case where the completor outputs some additional text to the output.
    The output is flushed and the commandline is re-printed underneath it.

diff --git a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java
index 5d1af69..cfe1686 100644
--- a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java
+++ b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java
@@ -241,7 +241,7 @@ public class ClientMain {
             initCodeCompletion();
 
             consoleReader.addCompletor(new MultiCompletor(new Completor[] {
-                new CodeCompletionCompletorWrapper(codeCompletion, outputWriter), helpCompletor,
+                new CodeCompletionCompletorWrapper(codeCompletion, outputWriter, consoleReader), helpCompletor,
                 commandCompletor }));
                 
             // enable pagination
diff --git a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/utility/ChangeRegisteringPrintWriter.java b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/utility/ChangeRegisteringPrintWriter.java
new file mode 100644
index 0000000..dfc03b4
--- /dev/null
+++ b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/utility/ChangeRegisteringPrintWriter.java
@@ -0,0 +1,233 @@
+/*
+ * RHQ Management Platform
+ * Copyright 2012, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.client.utility;
+
+import java.io.PrintWriter;
+import java.io.Writer;
+import java.util.Locale;
+
+/**
+ * @author Lukas Krejci
+ *
+ */
+public class ChangeRegisteringPrintWriter extends PrintWriter {
+
+    private boolean changed;
+
+    public ChangeRegisteringPrintWriter(Writer out) {
+        super(out);
+    }
+
+    public boolean isChanged() {
+        return changed;
+    }
+
+    public void setChanged(boolean changed) {
+        this.changed = changed;
+    }
+
+    @Override
+    public PrintWriter append(char c) {
+        setChanged(true);
+        return super.append(c);
+    }
+
+    @Override
+    public void write(int c) {
+        setChanged(true);
+        super.write(c);
+    }
+
+    @Override
+    public void write(char[] buf, int off, int len) {
+        setChanged(true);
+        super.write(buf, off, len);
+    }
+
+    @Override
+    public void write(char[] buf) {
+        setChanged(true);
+        super.write(buf);
+    }
+
+    @Override
+    public void write(String s, int off, int len) {
+        setChanged(true);
+        super.write(s, off, len);
+    }
+
+    @Override
+    public void write(String s) {
+        setChanged(true);
+        super.write(s);
+    }
+
+    @Override
+    public void print(boolean b) {
+        setChanged(true);
+        super.print(b);
+    }
+
+    @Override
+    public void print(char c) {
+        setChanged(true);
+        super.print(c);
+    }
+
+    @Override
+    public void print(int i) {
+        setChanged(true);
+        super.print(i);
+    }
+
+    @Override
+    public void print(long l) {
+        setChanged(true);
+        super.print(l);
+    }
+
+    @Override
+    public void print(float f) {
+        setChanged(true);
+        super.print(f);
+    }
+
+    @Override
+    public void print(double d) {
+        setChanged(true);
+        super.print(d);
+    }
+
+    @Override
+    public void print(char[] s) {
+        setChanged(true);
+        super.print(s);
+    }
+
+    @Override
+    public void print(String s) {
+        setChanged(true);
+        super.print(s);
+    }
+
+    @Override
+    public void print(Object obj) {
+        setChanged(true);
+        super.print(obj);
+    }
+
+    @Override
+    public void println() {
+        setChanged(true);
+        super.println();
+    }
+
+    @Override
+    public void println(boolean x) {
+        setChanged(true);
+        super.println(x);
+    }
+
+    @Override
+    public void println(char x) {
+        setChanged(true);
+        super.println(x);
+    }
+
+    @Override
+    public void println(int x) {
+        setChanged(true);
+        super.println(x);
+    }
+
+    @Override
+    public void println(long x) {
+        setChanged(true);
+        super.println(x);
+    }
+
+    @Override
+    public void println(float x) {
+        setChanged(true);
+        super.println(x);
+    }
+
+    @Override
+    public void println(double x) {
+        setChanged(true);
+        super.println(x);
+    }
+
+    @Override
+    public void println(char[] x) {
+        setChanged(true);
+        super.println(x);
+    }
+
+    @Override
+    public void println(String x) {
+        setChanged(true);
+        super.println(x);
+    }
+
+    @Override
+    public void println(Object x) {
+        setChanged(true);
+        super.println(x);
+    }
+
+    @Override
+    public PrintWriter printf(String format, Object... args) {
+        setChanged(true);
+        return super.printf(format, args);
+    }
+
+    @Override
+    public PrintWriter printf(Locale l, String format, Object... args) {
+        setChanged(true);
+        return super.printf(l, format, args);
+    }
+
+    @Override
+    public PrintWriter format(String format, Object... args) {
+        setChanged(true);
+        return super.format(format, args);
+    }
+
+    @Override
+    public PrintWriter format(Locale l, String format, Object... args) {
+        setChanged(true);
+        return super.format(l, format, args);
+    }
+
+    @Override
+    public PrintWriter append(CharSequence csq) {
+        setChanged(true);
+        return super.append(csq);
+    }
+
+    @Override
+    public PrintWriter append(CharSequence csq, int start, int end) {
+        setChanged(true);
+        return super.append(csq, start, end);
+    }
+
+}
diff --git a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/utility/CodeCompletionCompletorWrapper.java b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/utility/CodeCompletionCompletorWrapper.java
index 8f2570c..4be3613 100644
--- a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/utility/CodeCompletionCompletorWrapper.java
+++ b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/utility/CodeCompletionCompletorWrapper.java
@@ -1,24 +1,48 @@
 package org.rhq.enterprise.client.utility;
 
+import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.List;
 
 import jline.Completor;
+import jline.ConsoleReader;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 
 import org.rhq.scripting.CodeCompletion;
 
 public class CodeCompletionCompletorWrapper implements Completor {
 
+    private static final Log LOG = LogFactory.getLog(CodeCompletionCompletorWrapper.class);
+
     private CodeCompletion completion;
-    private PrintWriter output;
+    private ChangeRegisteringPrintWriter output;
+    private ConsoleReader consoleReader;
 
-    public CodeCompletionCompletorWrapper(CodeCompletion completion, PrintWriter output) {
+    public CodeCompletionCompletorWrapper(CodeCompletion completion, PrintWriter output, ConsoleReader consoleReader) {
         this.completion = completion;
-        this.output = output;
+        this.output = new ChangeRegisteringPrintWriter(output);
+        this.consoleReader = consoleReader;
     }
 
     @Override
     public int complete(String buffer, int cursor, List candidates) {
-        return completion.complete(output, buffer, cursor, candidates);
+        String start = this.consoleReader.getCursorBuffer().getBuffer().toString();
+
+        output.setChanged(false);
+        int ret = completion.complete(output, buffer, cursor, candidates);
+
+        if (output.isChanged()) {
+            try {
+                output.flush();
+                consoleReader.printNewline();
+                consoleReader.drawLine();
+            } catch (IOException e) {
+                LOG.debug("Failed to draw a console reader line.", e);
+            }
+        }
+
+        return ret;
     }
 }


commit 1d1e61836632b35abe0a30b67b6b999cd4a84ef0
Author: Lukas Krejci <lkrejci at redhat.com>
Date:   Mon Jul 2 14:30:32 2012 +0200

    InterfaceSimplifier now mirrors the generic type signatures and annotations
    on all levels.
    The newly generated class preserves the generic type signatures and
    annotations on the class, method and method parameter levels.

diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/InterfaceSimplifier.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/InterfaceSimplifier.java
index d6835a0..dc29bc9 100644
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/InterfaceSimplifier.java
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/InterfaceSimplifier.java
@@ -18,13 +18,37 @@
  */
 package org.rhq.bindings.util;
 
+import java.util.ArrayList;
+import java.util.List;
+
 import javassist.CannotCompileException;
 import javassist.ClassPool;
 import javassist.CtClass;
 import javassist.CtMethod;
 import javassist.CtNewMethod;
+import javassist.Modifier;
 import javassist.NotFoundException;
+import javassist.bytecode.AnnotationsAttribute;
+import javassist.bytecode.ClassFile;
+import javassist.bytecode.ConstPool;
 import javassist.bytecode.ParameterAnnotationsAttribute;
+import javassist.bytecode.SignatureAttribute;
+import javassist.bytecode.annotation.Annotation;
+import javassist.bytecode.annotation.AnnotationMemberValue;
+import javassist.bytecode.annotation.ArrayMemberValue;
+import javassist.bytecode.annotation.BooleanMemberValue;
+import javassist.bytecode.annotation.ByteMemberValue;
+import javassist.bytecode.annotation.CharMemberValue;
+import javassist.bytecode.annotation.ClassMemberValue;
+import javassist.bytecode.annotation.DoubleMemberValue;
+import javassist.bytecode.annotation.EnumMemberValue;
+import javassist.bytecode.annotation.FloatMemberValue;
+import javassist.bytecode.annotation.IntegerMemberValue;
+import javassist.bytecode.annotation.LongMemberValue;
+import javassist.bytecode.annotation.MemberValue;
+import javassist.bytecode.annotation.MemberValueVisitor;
+import javassist.bytecode.annotation.ShortMemberValue;
+import javassist.bytecode.annotation.StringMemberValue;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -33,18 +57,18 @@ import org.rhq.core.domain.auth.Subject;
 
 /**
  * The scripts can use simplified interfaces that omit the first "Subject" argument
- * to most methods. This helper class prepares such simplified interfaces.
+ * to most methods from RHQ's remote API. This helper class prepares such simplified interfaces.
  * 
  * @author Greg Hinkle
  * @author Lukas Krejci
  */
 public class InterfaceSimplifier {
     private static final Log LOG = LogFactory.getLog(InterfaceSimplifier.class);
-    
+
     private InterfaceSimplifier() {
-        
+
     }
-    
+
     public static Class<?> simplify(Class<?> intf) {
         try {
             ClassPool classPool = ClassPool.getDefault();
@@ -52,65 +76,125 @@ public class InterfaceSimplifier {
             String simplifiedName = getSimplifiedName(intf);
             LOG.debug("Simplifying " + intf + " (simplified interface name: " + simplifiedName + ")...");
 
+            CtClass cached = null;
             try {
-                @SuppressWarnings("unused")
-                CtClass cached = classPool.get(simplifiedName);
+                cached = classPool.get(simplifiedName);
                 return Class.forName(simplifiedName, false, classPool.getClassLoader());
-
             } catch (NotFoundException e) {
                 // ok... load it
             } catch (ClassNotFoundException e) {
                 LOG.debug("Class [" + simplifiedName + "] not found - cause: " + e, e);
+                if (cached != null) {
+                    // strange - we found the class definition in the class pool, which means we must have touched it 
+                    // before but Class.forName failed to find the class in the class pool's class loader.
+                    return cached.toClass();
+                }
             }
 
             CtClass originalClass = classPool.get(intf.getName());
+            ClassFile originalClassFile = originalClass.getClassFile();
 
             CtClass newClass = classPool.makeInterface(simplifiedName);
 
             newClass.defrost();
 
+            ClassFile newClassFile = newClass.getClassFile();
+
+            //we'll be adding new constants to the class file (for generics and annotations)
+            ConstPool constPool = newClassFile.getConstPool();
+
+            //copy the annotations on the class
+            AnnotationsAttribute annotations = (AnnotationsAttribute) originalClassFile
+                .getAttribute(AnnotationsAttribute.visibleTag);
+            AnnotationsAttribute newAnnotations = copyAnnotations(annotations, constPool);
+            if (newAnnotations != null) {
+                newClassFile.addAttribute(newAnnotations);
+            }
+
+            //copy the generic signature of the class
+            SignatureAttribute signature = (SignatureAttribute) originalClassFile.getAttribute(SignatureAttribute.tag);
+            if (signature != null) {
+                newClassFile.addAttribute(new SignatureAttribute(constPool, signature.getSignature()));
+            }
+
+            //now copy over the methods
             CtMethod[] methods = originalClass.getMethods();
 
             for (CtMethod originalMethod : methods) {
 
+                //we are only simplifying interfaces here, but the CtClass.getMethods() also returns concrete methods
+                //inherited from Object. Let's just skip those - we don't need to worry about them...
+                if (!Modifier.isAbstract(originalMethod.getModifiers())) {
+                    continue;
+                }
+
                 CtClass[] params = originalMethod.getParameterTypes();
-                if (params.length > 0 && params[0].getName().equals(Subject.class.getName())) {
 
+                //capture all the runtime visible method annotations on the original method
+                annotations = (AnnotationsAttribute) originalMethod.getMethodInfo().getAttribute(
+                    AnnotationsAttribute.visibleTag);
+
+                //capture all the runtime visible parameter annotations on the original method
+                ParameterAnnotationsAttribute parameterAnnotations = (ParameterAnnotationsAttribute) originalMethod
+                    .getMethodInfo().getAttribute(ParameterAnnotationsAttribute.visibleTag);
+
+                //capture the generic signature of the original method.
+                signature = (SignatureAttribute) originalMethod.getMethodInfo().getAttribute(
+                    SignatureAttribute.tag);
+
+                boolean simplify = params.length > 0 && params[0].getName().equals(Subject.class.getName());
+
+                if (simplify) {
+                    //generate new params, leaving out the first parameter (the subject)
                     CtClass[] simpleParams = new CtClass[params.length - 1];
 
                     System.arraycopy(params, 1, simpleParams, 0, params.length - 1);
-                    newClass.defrost();
+                    params = simpleParams;
+                }
 
-                    CtMethod newMethod = CtNewMethod.abstractMethod(originalMethod.getReturnType(), originalMethod
-.getName(), simpleParams, null, newClass);
+                //generate the new method with possibly modified parameters
+                CtMethod newMethod = CtNewMethod.abstractMethod(originalMethod.getReturnType(),
+                    originalMethod.getName(), params, originalMethod.getExceptionTypes(), newClass);
 
-                    ParameterAnnotationsAttribute originalAnnotationsAttribute = (ParameterAnnotationsAttribute) originalMethod
-                        .getMethodInfo().getAttribute(ParameterAnnotationsAttribute.visibleTag);
+                //copy over the method annotations
+                annotations = copyAnnotations(annotations, constPool);
 
-                    // If there are any parameter annotations, copy the one's we're keeping
-                    if (originalAnnotationsAttribute != null) {
+                if (simplify) {
+                    if (signature != null) {
+                        //fun, we need to modify the signature, too, because we have left out the parameter
+                        MethodSignature sig = MethodSignature.parse(signature.getSignature());
 
-                        javassist.bytecode.annotation.Annotation[][] originalAnnotations = originalAnnotationsAttribute
-                            .getAnnotations();
-                        javassist.bytecode.annotation.Annotation[][] newAnnotations = new javassist.bytecode.annotation.Annotation[originalAnnotations.length - 1][];
+                        sig.paramTypes.remove(0);
 
-                        for (int i = 1; i < originalAnnotations.length; i++) {
-                            newAnnotations[i - 1] = new javassist.bytecode.annotation.Annotation[originalAnnotations[i].length];
-                            System.arraycopy(originalAnnotations[i], 0, newAnnotations[i - 1], 0,
-                                originalAnnotations[i].length);
-                        }
+                        signature = new SignatureAttribute(constPool, sig.toString());
+                    }
 
-                        ParameterAnnotationsAttribute newAnnotationsAttribute = new ParameterAnnotationsAttribute(
-                            newMethod.getMethodInfo().getConstPool(), ParameterAnnotationsAttribute.visibleTag);
+                    //next, we need to copy the parameter annotations
+                    parameterAnnotations = copyParameterAnnotations(parameterAnnotations, constPool, 1);
+                } else {
+                    //just copy the sig and parameter annotations verbatim
+                    if (signature != null) {
+                        signature = new SignatureAttribute(constPool, signature.getSignature());
+                    }
 
-                        newAnnotationsAttribute.setAnnotations(newAnnotations);
+                    parameterAnnotations = copyParameterAnnotations(parameterAnnotations, constPool, 0);
+                }
 
-                        newMethod.getMethodInfo().addAttribute(newAnnotationsAttribute);
+                if (parameterAnnotations != null) {
+                    newMethod.getMethodInfo().addAttribute(parameterAnnotations);
+                }
 
-                    }
+                if (signature != null) {
+                    newMethod.getMethodInfo().addAttribute(signature);
+                }
 
-                    newClass.addMethod(newMethod);
+                if (annotations != null) {
+                    newMethod.getMethodInfo().addAttribute(annotations);
                 }
+
+                //it is important to add the method directly to the classfile, not the class
+                //because otherwise the generics info wouldn't survive
+                newClassFile.addMethod(newMethod.getMethodInfo());
             }
 
             return newClass.toClass();
@@ -127,9 +211,266 @@ public class InterfaceSimplifier {
         String fullName = interfaceClass.getName();
         String simpleName = interfaceClass.getSimpleName();
         Package pkg = interfaceClass.getPackage();
-        String packageName = (pkg != null) ? pkg.getName() :
-                fullName.substring(0, fullName.length() - (simpleName.length() + 1));
+        String packageName = (pkg != null) ? pkg.getName() : fullName.substring(0,
+            fullName.length() - (simpleName.length() + 1));
         return packageName + ".wrapped." + simpleName + "Simple";
     }
 
+    /**
+     * Copies the provided annotation into the provided const pool.
+     * 
+     * @param annotation
+     * @param constPool
+     * @return
+     * @throws NotFoundException
+     */
+    private static Annotation cloneAnnotation(Annotation annotation, final ConstPool constPool)
+        throws NotFoundException {
+
+        Annotation ret = new Annotation(annotation.getTypeName(), constPool);
+
+        for (Object m : annotation.getMemberNames()) {
+            final String memberName = (String) m;
+
+            MemberValue origValue = annotation.getMemberValue(memberName);
+            final MemberValue[] newValue = new MemberValue[1];
+
+            origValue.accept(new ArrayIndexAssigningVisitor(newValue, 0, constPool));
+
+            ret.addMemberValue(memberName, newValue[0]);
+        }
+
+        return ret;
+    }
+
+    private static AnnotationsAttribute copyAnnotations(AnnotationsAttribute annotations, ConstPool constPool)
+        throws NotFoundException {
+        if (annotations != null) {
+            Annotation[] origAnnotations = annotations.getAnnotations();
+            Annotation[] newClassAnnotations = new Annotation[origAnnotations.length];
+            for (int i = 0; i < newClassAnnotations.length; ++i) {
+                newClassAnnotations[i] = cloneAnnotation(origAnnotations[i], constPool);
+            }
+
+            AnnotationsAttribute newAnnotations = new AnnotationsAttribute(constPool, AnnotationsAttribute.visibleTag);
+            newAnnotations.setAnnotations(newClassAnnotations);
+
+            return newAnnotations;
+        }
+
+        return null;
+    }
+
+    private static ParameterAnnotationsAttribute copyParameterAnnotations(
+        ParameterAnnotationsAttribute parameterAnnotations, ConstPool constPool, int fromIndex)
+        throws NotFoundException {
+
+        if (parameterAnnotations != null) {
+            Annotation[][] originalAnnotations = parameterAnnotations.getAnnotations();
+
+            //return early if there are no annotations to copy
+            if (originalAnnotations.length - fromIndex <= 0) {
+                return null;
+            }
+
+            Annotation[][] newParameterAnnotations = new Annotation[originalAnnotations.length - fromIndex][];
+
+            for (int i = fromIndex; i < originalAnnotations.length; i++) {
+                newParameterAnnotations[i - fromIndex] = new Annotation[originalAnnotations[i].length];
+                for (int j = 0; j < originalAnnotations[i].length; ++j) {
+                    Annotation origAnnotation = originalAnnotations[i][j];
+
+                    newParameterAnnotations[i - fromIndex][j] = cloneAnnotation(origAnnotation, constPool);
+                }
+            }
+
+            ParameterAnnotationsAttribute newAnnotationsAttribute = new ParameterAnnotationsAttribute(constPool,
+                ParameterAnnotationsAttribute.visibleTag);
+
+            newAnnotationsAttribute.setAnnotations(newParameterAnnotations);
+
+            return newAnnotationsAttribute;
+        }
+
+        return null;
+    }
+
+    private static class ArrayIndexAssigningVisitor implements MemberValueVisitor {
+        private MemberValue[] array;
+        private int index;
+        private ConstPool constPool;
+
+        public ArrayIndexAssigningVisitor(MemberValue[] array, int index, ConstPool constPool) {
+            this.array = array;
+            this.index = index;
+            this.constPool = constPool;
+        }
+
+        @Override
+        public void visitStringMemberValue(StringMemberValue node) {
+            array[index] = new StringMemberValue(node.getValue(), constPool);
+        }
+
+        @Override
+        public void visitShortMemberValue(ShortMemberValue node) {
+            array[index] = new ShortMemberValue(node.getValue(), constPool);
+        }
+
+        @Override
+        public void visitLongMemberValue(LongMemberValue node) {
+            array[index] = new LongMemberValue(node.getValue(), constPool);
+        }
+
+        @Override
+        public void visitIntegerMemberValue(IntegerMemberValue node) {
+            array[index] = new IntegerMemberValue(constPool, node.getValue());
+        }
+
+        @Override
+        public void visitFloatMemberValue(FloatMemberValue node) {
+            array[index] = new FloatMemberValue(node.getValue(), constPool);
+        }
+
+        @Override
+        public void visitEnumMemberValue(EnumMemberValue node) {
+            EnumMemberValue val = new EnumMemberValue(constPool);
+            val.setType(node.getType());
+            val.setValue(node.getValue());
+            array[index] = val;
+        }
+
+        @Override
+        public void visitDoubleMemberValue(DoubleMemberValue node) {
+            array[index] = new DoubleMemberValue(node.getValue(), constPool);
+        }
+
+        @Override
+        public void visitClassMemberValue(ClassMemberValue node) {
+            array[index] = new ClassMemberValue(node.getValue(), constPool);
+        }
+
+        @Override
+        public void visitCharMemberValue(CharMemberValue node) {
+            array[index] = new CharMemberValue(node.getValue(), constPool);
+        }
+
+        @Override
+        public void visitByteMemberValue(ByteMemberValue node) {
+            array[index] = new ByteMemberValue(node.getValue(), constPool);
+        }
+
+        @Override
+        public void visitBooleanMemberValue(BooleanMemberValue node) {
+            array[index] = new BooleanMemberValue(node.getValue(), constPool);
+        }
+
+        @Override
+        public void visitArrayMemberValue(ArrayMemberValue node) {
+            ArrayMemberValue val = new ArrayMemberValue(node.getType(), constPool);
+            MemberValue[] newVals = new MemberValue[node.getValue().length];
+            for (int i = 0; i < node.getValue().length; ++i) {
+                node.getValue()[i].accept(new ArrayIndexAssigningVisitor(newVals, i, constPool));
+            }
+
+            val.setValue(newVals);
+            array[index] = val;
+        }
+
+        @Override
+        public void visitAnnotationMemberValue(AnnotationMemberValue node) {
+            array[index] = new AnnotationMemberValue(node.getValue(), constPool);
+        }
+    }
+
+    //a quick and dirty method signature parser
+    //see http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.3.4
+    private static class MethodSignature {
+        public String returnType;
+        public List<String> paramTypes = new ArrayList<String>();
+        public String typeParameters;
+        public String exceptionTypes;
+        
+        public static MethodSignature parse(String signature) {
+            int startParams = signature.indexOf('(') + 1;
+            int endParams = signature.indexOf(')');
+            int startExceptions = signature.indexOf('^');
+
+            MethodSignature sig = new MethodSignature();
+            sig.typeParameters = signature.substring(0, startParams - 1);
+            if (startExceptions == -1) {
+                sig.returnType = signature.substring(endParams + 1);
+                sig.exceptionTypes = "";
+            } else {
+                sig.returnType = signature.substring(endParams + 1, startExceptions);
+                sig.exceptionTypes = signature.substring(startExceptions);
+            }
+
+            int idx = startParams;
+            while (idx < endParams) {
+                int end = findEndOfTypeSignature(idx, signature);
+                sig.paramTypes.add(signature.substring(idx, end));
+                idx = end;
+            }
+
+            return sig;
+        }
+
+        private static int findEndOfTypeSignature(int idx, String signature) {
+            int c = signature.charAt(idx);
+
+            switch (c) {
+            case 'L':
+                return findEndOfClassSignature(idx, signature);
+            case '[':
+                return findEndOfTypeSignature(idx + 1, signature);
+            case 'T':
+                return signature.indexOf(';', idx + 1) + 1;
+            default:
+                return idx + 1;
+            }
+        }
+
+        private static int findEndOfClassSignature(int indexOfL, String signature) {
+            int idx = indexOfL + 1;
+
+            int genericDeclDepth = 0;
+
+            while (idx < signature.length()) {
+                boolean sigComplete = false;
+
+                char c = signature.charAt(idx++);
+                switch (c) {
+                case '<':
+                    genericDeclDepth++;
+                    break;
+                case '>':
+                    genericDeclDepth--;
+                    break;
+                case ';':
+                    sigComplete = genericDeclDepth == 0;
+                    break;
+                }
+
+                if (sigComplete) {
+                    break;
+                }
+            }
+
+            return idx;
+        }
+
+        @Override
+        public String toString() {
+            StringBuilder bld = new StringBuilder(typeParameters);
+            bld.append("(");
+            for (String p : paramTypes) {
+                bld.append(p);
+            }
+            bld.append(")");
+            bld.append(returnType);
+            bld.append(exceptionTypes);
+
+            return bld.toString();
+        }
+    }
 }
diff --git a/modules/enterprise/binding/src/test/java/org/rhq/bindings/util/InterfaceSimplifierTest.java b/modules/enterprise/binding/src/test/java/org/rhq/bindings/util/InterfaceSimplifierTest.java
new file mode 100644
index 0000000..4312153
--- /dev/null
+++ b/modules/enterprise/binding/src/test/java/org/rhq/bindings/util/InterfaceSimplifierTest.java
@@ -0,0 +1,317 @@
+/*
+ * RHQ Management Platform
+ * Copyright 2012, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.bindings.util;
+
+import java.io.IOException;
+import java.lang.annotation.Annotation;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.util.Arrays;
+import java.util.List;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.auth.Subject;
+
+/**
+ * @author Lukas Krejci
+ */
+ at Test
+public class InterfaceSimplifierTest {
+
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target({ ElementType.TYPE, ElementType.PARAMETER, ElementType.METHOD })
+    public static @interface MyAnnotation {
+        int value() default 1;
+
+        String parameter();
+    }
+
+    public static interface NoSimplifications {
+        void voidMethodWithNoExceptions();
+
+        void voidMethodWithExceptions() throws IOException, InterruptedException;
+
+        int intMethod();
+
+        Object objectMethod();
+
+        Object objectMethodWithParams(int p1, Object p2);
+
+        Object objectMethodWithParamsAndExceptions(int p1, Object p2) throws IOException, InterruptedException;
+    }
+
+    public static interface Simplifications {
+        void voidMethodWithNoExceptions(Subject s);
+
+        void voidMethodWithExceptions(Subject s) throws IOException, InterruptedException;
+
+        int intMethod(Subject s);
+
+        Object objectMethod(Subject s);
+
+        Object objectMethodWithParams(Subject s, int p1, Object p2);
+
+        Object objectMethodWithParamsAndExceptions(Subject s, int p1, Object p2) throws IOException,
+            InterruptedException;
+    }
+
+    public static interface Generics<C extends Type> {
+        void genericParameters(List<String> p, int p2);
+
+        <T extends Type> T typeParameters(T p, int p2);
+
+        <T extends Type> T typeParametersSimplified(Subject s, T p, int p2);
+
+        <T extends C> T classTypeParameters(T p, int p2);
+    }
+
+
+    @MyAnnotation(parameter = "CLASS")
+    public static interface Annotations {
+
+        @MyAnnotation(value = 2, parameter = "a")
+        int method(@MyAnnotation(parameter = "b") int p) throws IOException;
+
+        @MyAnnotation(value = 2, parameter = "c")
+        int methodSimplified(@MyAnnotation(parameter = "disappear") Subject s, @MyAnnotation(parameter = "d") int p)
+            throws IOException;
+    }
+
+    public void testNoSimplifications() throws Exception {
+        Class<?> iface = InterfaceSimplifier.simplify(NoSimplifications.class);
+
+        Method voidMethodWithNoExceptions = iface.getMethod("voidMethodWithNoExceptions");
+        Assert.assertEquals(voidMethodWithNoExceptions.getReturnType(), void.class);
+        
+        Method voidMethodWithExceptions = iface.getMethod("voidMethodWithExceptions");
+        List<Class<?>> exceptions = Arrays.asList(voidMethodWithExceptions.getExceptionTypes());
+        Assert.assertTrue(exceptions.contains(IOException.class),
+            "The 'voidMethodWithExceptions doesn't seem to declare throws IOException");
+        Assert.assertTrue(exceptions.contains(InterruptedException.class),
+            "The 'voidMethodWithExceptions doesn't seem to declare throws InterruptedException");
+        
+        Method intMethod = iface.getMethod("intMethod");
+        Assert.assertEquals(intMethod.getReturnType(), int.class);
+
+        Method objectMethod = iface.getMethod("objectMethod");
+        Assert.assertEquals(objectMethod.getReturnType(), Object.class);
+
+        Method objectMethodWithParams = iface.getMethod("objectMethodWithParams", int.class, Object.class);
+        Assert.assertEquals(objectMethodWithParams.getReturnType(), Object.class);
+
+        Method objectMethodWithParamsAndExceptions = iface.getMethod("objectMethodWithParamsAndExceptions", int.class,
+            Object.class);
+        Assert.assertEquals(objectMethodWithParamsAndExceptions.getReturnType(), Object.class);
+        exceptions = Arrays.asList(objectMethodWithParamsAndExceptions.getExceptionTypes());
+        Assert.assertTrue(exceptions.contains(IOException.class),
+            "The 'objectMethodWithParamsAndExceptions doesn't seem to declare throws IOException");
+        Assert.assertTrue(exceptions.contains(InterruptedException.class),
+            "The 'objectMethodWithParamsAndExceptions doesn't seem to declare throws InterruptedException");
+    }
+
+    public void testSimplifications() throws Exception {
+        Class<?> iface = InterfaceSimplifier.simplify(Simplifications.class);
+
+        //These tests are exactly the same as for the NoSimplifications class, because
+        //the simplifier should leave out all the subject parameters in the Simplifications
+        //class' methods.
+
+        Method voidMethodWithNoExceptions = iface.getMethod("voidMethodWithNoExceptions");
+        Assert.assertEquals(voidMethodWithNoExceptions.getReturnType(), void.class);
+
+        Method voidMethodWithExceptions = iface.getMethod("voidMethodWithExceptions");
+        List<Class<?>> exceptions = Arrays.asList(voidMethodWithExceptions.getExceptionTypes());
+        Assert.assertTrue(exceptions.contains(IOException.class),
+            "The 'voidMethodWithExceptions doesn't seem to declare throws IOException");
+        Assert.assertTrue(exceptions.contains(InterruptedException.class),
+            "The 'voidMethodWithExceptions doesn't seem to declare throws InterruptedException");
+
+        Method intMethod = iface.getMethod("intMethod");
+        Assert.assertEquals(intMethod.getReturnType(), int.class);
+
+        Method objectMethod = iface.getMethod("objectMethod");
+        Assert.assertEquals(objectMethod.getReturnType(), Object.class);
+
+        Method objectMethodWithParams = iface.getMethod("objectMethodWithParams", int.class, Object.class);
+        Assert.assertEquals(objectMethodWithParams.getReturnType(), Object.class);
+
+        Method objectMethodWithParamsAndExceptions = iface.getMethod("objectMethodWithParamsAndExceptions", int.class,
+            Object.class);
+        Assert.assertEquals(objectMethodWithParamsAndExceptions.getReturnType(), Object.class);
+        exceptions = Arrays.asList(objectMethodWithParamsAndExceptions.getExceptionTypes());
+        Assert.assertTrue(exceptions.contains(IOException.class),
+            "The 'objectMethodWithParamsAndExceptions doesn't seem to declare throws IOException");
+        Assert.assertTrue(exceptions.contains(InterruptedException.class),
+            "The 'objectMethodWithParamsAndExceptions doesn't seem to declare throws InterruptedException");
+    }
+
+    public <T> void testGenerics() throws Exception {
+        @SuppressWarnings("unchecked")
+        Class<T> iface = (Class<T>) InterfaceSimplifier.simplify(Generics.class);
+
+        TypeVariable<Class<T>>[] classTypeParameters = iface.getTypeParameters();
+        Assert.assertEquals(classTypeParameters.length, 1, "There should be 1 type parameter on the class Generics.");
+        TypeVariable<?> typeVariable = classTypeParameters[0];
+        Assert.assertEquals(typeVariable.getName(), "C", "Unexpected type parameter name on 'Generics' class.");
+        Type[] bounds = typeVariable.getBounds();
+        Assert.assertEquals(bounds.length, 1, "The type parameter on the class 'Generics' should have 1 upper bound.");
+        Assert.assertEquals(bounds[0], Type.class,
+            "The type parameter on the class 'Generics' should have the upper bound of the Type class.");
+        
+        Method genericParameters = iface.getMethod("genericParameters", List.class, int.class);
+        Assert.assertEquals(genericParameters.getReturnType(), void.class);
+        
+        Type firstParamType = genericParameters.getGenericParameterTypes()[0];
+        Assert.assertTrue(firstParamType instanceof ParameterizedType,
+            "The first parameter of the 'genericParameters' should be parameterized.");
+        Assert.assertEquals(((ParameterizedType) firstParamType).getRawType(), List.class,
+            "The first parameter of the 'genericParameters' method should be a List.");
+        Assert.assertEquals(((ParameterizedType) firstParamType).getActualTypeArguments()[0], String.class,
+            "The first parameter of the 'genericParamters' method should be a List<String>");
+
+        Method typeParameters = iface.getMethod("typeParameters", Type.class, int.class);
+        Assert.assertEquals(typeParameters.getReturnType(), Type.class);
+
+        TypeVariable<Method>[] typeVariables = typeParameters.getTypeParameters();
+        Assert.assertEquals(typeVariables.length, 1,
+            "There should be 1 type parameter on the the 'typeParameters' method.");
+        typeVariable = typeVariables[0];
+        Assert.assertEquals(typeVariable.getName(), "T", "Unexpected type parameter name on 'typeParameters' method.");
+        bounds = typeVariable.getBounds();
+        Assert.assertEquals(bounds.length, 1, "The type parameter on the method 'typeParameters' should have 1 upper bound.");
+        Assert.assertEquals(bounds[0], Type.class,
+            "The type parameter on the method 'typeParameters' should have the upper bound of the Type class.");
+
+        Type returnType = typeParameters.getGenericReturnType();
+        Assert.assertTrue(returnType instanceof TypeVariable,
+            "The generic return type of the 'typeParameters' class should be a type variable.");
+        typeVariable = (TypeVariable<?>) returnType;
+        Assert.assertEquals(typeVariable.getName(), "T",
+            "Unexpected type parameter at the return type of the 'typeParameters' method.");
+
+        Method typeParametersSimplified = iface.getMethod("typeParametersSimplified", Type.class, int.class);
+        Assert.assertEquals(typeParameters.getReturnType(), Type.class);
+
+        typeVariables = typeParametersSimplified.getTypeParameters();
+        Assert.assertEquals(typeVariables.length, 1,
+            "There should be 1 type parameter on the the 'typeParametersSimplified' method.");
+        typeVariable = typeVariables[0];
+        Assert.assertEquals(typeVariable.getName(), "T",
+            "Unexpected type parameter name on 'typeParametersSimplified' method.");
+        bounds = typeVariable.getBounds();
+        Assert.assertEquals(bounds.length, 1,
+            "The type parameter on the method 'typeParametersSimplified' should have 1 upper bound.");
+        Assert
+            .assertEquals(bounds[0], Type.class,
+                "The type parameter on the method 'typeParametersSimplified' should have the upper bound of the Type class.");
+
+        returnType = typeParametersSimplified.getGenericReturnType();
+        Assert.assertTrue(returnType instanceof TypeVariable,
+            "The generic return type of the 'typeParametersSimplified' class should be a type variable.");
+        typeVariable = (TypeVariable<?>) returnType;
+        Assert.assertEquals(typeVariable.getName(), "T",
+            "Unexpected type parameter at the return type of the 'typeParametersSimplified' method.");
+    }
+    
+    public void testAnnotations() throws Exception {
+        Class<?> iface = InterfaceSimplifier.simplify(Annotations.class);
+
+        Annotation[] annotations = iface.getAnnotations();
+        Assert.assertEquals(annotations.length, 1, "UNexpected number of annotations on the 'Annotations' class.");
+        Annotation annotation = annotations[0];
+        Assert.assertEquals(annotation.annotationType(), MyAnnotation.class,
+            "Unexpected annotation type on the class 'Annotations");
+        Assert.assertEquals(((MyAnnotation) annotation).value(), 1,
+            "Unexpected value of the 'value' attribute on the annotation on the 'Annotations' class.");
+        Assert.assertEquals(((MyAnnotation) annotation).parameter(), "CLASS",
+            "Unexpected value of the 'parameter' attribute on the annotation on the 'Annotations' class.");
+
+        Method method = iface.getMethod("method", int.class);
+        annotations = method.getAnnotations();
+        Assert.assertEquals(annotations.length, 1, "Unexpected number of annotations on the 'method' method.");
+
+        annotation = annotations[0];
+        Assert.assertEquals(annotation.annotationType(), MyAnnotation.class,
+            "Unexpected annotation type on the method 'method");
+
+        Assert.assertEquals(((MyAnnotation) annotation).value(), 2,
+            "Unexpected value of the 'value' attribute on the annotation on the 'method' method.");
+        Assert.assertEquals(((MyAnnotation) annotation).parameter(), "a",
+            "Unexpected value of the 'parameter' attribute on the annotation on the 'method' method.");
+
+        Annotation[][] parameterAnnotations = method.getParameterAnnotations();
+
+        Assert
+            .assertEquals(parameterAnnotations.length, 1,
+                "Method 'Annotations.method(int)' has 1 parameter with annotations but we got a different number of parameters.");
+
+        Assert.assertEquals(parameterAnnotations[0].length, 1,
+            "The parameter of 'Annotations.method(int)' method has an annotation but we couldn't detect any.");
+
+        annotation = parameterAnnotations[0][0];
+        Assert.assertEquals(annotation.annotationType(), MyAnnotation.class,
+            "Unexpected annotation type on the parameter 'p' of 'Annotations.method(int)'");
+        Assert.assertEquals(((MyAnnotation) annotation).value(), 1,
+            "Unexpected value of the 'value' of the annotation on the parameter p of 'Annotations.method(int)'.");
+        Assert.assertEquals(((MyAnnotation) annotation).parameter(), "b",
+            "Unexpected value of the 'parameter' of the annotation on the parameter p of 'Annotations.method(int)'.");
+
+        method = iface.getMethod("methodSimplified", int.class);
+        annotations = method.getAnnotations();
+        Assert
+            .assertEquals(annotations.length, 1, "Unexpected number of annotations on the 'methodSimplified' method.");
+
+        annotation = annotations[0];
+        Assert.assertEquals(annotation.annotationType(), MyAnnotation.class,
+            "Unexpected annotation type on the method 'methodSimplified");
+
+        Assert.assertEquals(((MyAnnotation) annotation).value(), 2,
+            "Unexpected value of the 'value' attribute on the annotation on the 'methodSimplified' method.");
+        Assert.assertEquals(((MyAnnotation) annotation).parameter(), "c",
+            "Unexpected value of the 'parameter' attribute on the annotation on the 'methodSimplified' method.");
+
+        parameterAnnotations = method.getParameterAnnotations();
+
+        Assert
+            .assertEquals(parameterAnnotations.length, 1,
+                "Method 'Annotations.methodSimplified(int)' has 1 parameter with annotations but we got a different number of parameters.");
+
+        Assert.assertEquals(parameterAnnotations[0].length, 1,
+                "The parameter of 'Annotations.methodSimplified(int)' method has an annotation but we couldn't detect any.");
+
+        annotation = parameterAnnotations[0][0];
+        Assert.assertEquals(annotation.annotationType(), MyAnnotation.class,
+            "Unexpected annotation type on the parameter 'p' of 'Annotations.methodSimplified(int)'");
+        Assert.assertEquals(((MyAnnotation) annotation).value(), 1,
+                "Unexpected value of the 'value' of the annotation on the parameter p of 'Annotations.methodSimplified(int)'.");
+        Assert
+            .assertEquals(((MyAnnotation) annotation).parameter(), "d",
+                "Unexpected value of the 'parameter' of the annotation on the parameter p of 'Annotations.methodSimplified(int)'.");
+    }
+}


commit b48676a8552e723f2fce366b00d438dbf2484693
Merge: 5e823b9 00c0ee0
Author: John Mazzitelli <mazz at redhat.com>
Date:   Fri Jun 29 17:48:02 2012 -0400

    Merge branch 'master' of ssh://git.fedorahosted.org/git/rhq/rhq.git



commit 5e823b969b8cc830432cfc2e055ed3292464c4d8
Author: John Mazzitelli <mazz at redhat.com>
Date:   Fri Jun 29 17:47:26 2012 -0400

    [BZ 834019] enhancement to the arquillian stuff so we can have code that can templatize reusable plugin descriptors. this also has a reusable discovery component. This includes LateMeasurementRescheduleTest that will hopefully, eventually test this BZ but the actual test method is essentially a stub right now

diff --git a/modules/core/arquillian-integration/archive/pom.xml b/modules/core/arquillian-integration/archive/pom.xml
index f92cc5e..edf6add 100644
--- a/modules/core/arquillian-integration/archive/pom.xml
+++ b/modules/core/arquillian-integration/archive/pom.xml
@@ -25,6 +25,12 @@
 
         <dependency>
             <groupId>org.rhq</groupId>
+            <artifactId>rhq-core-util</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.rhq</groupId>
             <artifactId>rhq-core-client-api</artifactId>
             <version>${project.version}</version>
         </dependency>
diff --git a/modules/core/arquillian-integration/archive/src/main/java/org/rhq/test/shrinkwrap/RhqAgentPluginArchiveImpl.java b/modules/core/arquillian-integration/archive/src/main/java/org/rhq/test/shrinkwrap/RhqAgentPluginArchiveImpl.java
index ed19397..3d31785 100644
--- a/modules/core/arquillian-integration/archive/src/main/java/org/rhq/test/shrinkwrap/RhqAgentPluginArchiveImpl.java
+++ b/modules/core/arquillian-integration/archive/src/main/java/org/rhq/test/shrinkwrap/RhqAgentPluginArchiveImpl.java
@@ -3,7 +3,9 @@
  */
 package org.rhq.test.shrinkwrap;
 
+import java.io.ByteArrayInputStream;
 import java.io.File;
+import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URL;
@@ -41,6 +43,7 @@ import org.jboss.shrinkwrap.impl.base.container.ContainerBase;
 import org.jboss.shrinkwrap.impl.base.path.BasicPath;
 
 import org.rhq.core.clientapi.agent.metadata.PluginDependencyGraph;
+import org.rhq.core.util.stream.StreamUtil;
 
 /**
  * @author Lukas Krejci
@@ -122,6 +125,31 @@ public class RhqAgentPluginArchiveImpl extends ContainerBase<RhqAgentPluginArchi
     }
 
     @Override
+    public RhqAgentPluginArchive setPluginDescriptorFromTemplate(String resourceName,
+        Map<String, String> replacementValues) throws IllegalArgumentException {
+
+        Validate.notNull(resourceName, "resourceName should be specified");
+        Validate.notNull(replacementValues, "replacementValues should be specified");
+
+        // get the template text and replace all tokens with their replacement values
+        String templateXml = new String(StreamUtil.slurp(new ClassLoaderAsset(resourceName).openStream()));
+        for (Map.Entry<String, String> entry : replacementValues.entrySet()) {
+            templateXml = templateXml.replace(entry.getKey(), entry.getValue());
+        }
+
+        // Make a new descriptor file with the new template content (with variables replaced) in a tmp directory.
+        File newDescriptorFile;
+        try {
+            newDescriptorFile = File.createTempFile(resourceName.replace(".xml", ""), ".xml");
+            StreamUtil.copy(new ByteArrayInputStream(templateXml.getBytes()), new FileOutputStream(newDescriptorFile));
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+
+        return setPluginDescriptor(newDescriptorFile);
+    }
+
+    @Override
     public RhqAgentPluginArchive setPluginDescriptor(String resourceName) throws IllegalArgumentException {
         Validate.notNull(resourceName, "ResourceName should be specified");
         return setPluginDescriptor(new ClassLoaderAsset(resourceName));
diff --git a/modules/core/arquillian-integration/archive/src/main/java/org/rhq/test/shrinkwrap/RhqAgentPluginDescriptorContainer.java b/modules/core/arquillian-integration/archive/src/main/java/org/rhq/test/shrinkwrap/RhqAgentPluginDescriptorContainer.java
index 309b341..ff5bdf1 100644
--- a/modules/core/arquillian-integration/archive/src/main/java/org/rhq/test/shrinkwrap/RhqAgentPluginDescriptorContainer.java
+++ b/modules/core/arquillian-integration/archive/src/main/java/org/rhq/test/shrinkwrap/RhqAgentPluginDescriptorContainer.java
@@ -7,6 +7,7 @@ import java.io.File;
 import java.net.URL;
 import java.util.Collection;
 import java.util.List;
+import java.util.Map;
 
 import org.jboss.shrinkwrap.api.Archive;
 import org.jboss.shrinkwrap.api.ArchivePath;
@@ -36,6 +37,21 @@ public interface RhqAgentPluginDescriptorContainer<T extends Archive<T>> {
     ArchivePath getRequiredPluginsPath();
     
     /**
+     * Sets the plugin descriptor using the plugin descriptor template resource, making
+     * a copy of that resource and replacing templatized variables in that file with
+     * replacement values that are passed into this method.
+     * The {@link ClassLoader} is used to obtain the plugin descriptor template resource, but
+     * it is assumed to be a file on the file system.
+     *
+     * @param resourceName the name of the plugin descriptor template resource as accessible by the class loader
+     * @param replacementValues map with keys of template replacement variable names with their replacement values 
+     * @return the archive itself
+     * @throws IllegalArgumentException if resourceName or replacementValues is null
+     */
+    T setPluginDescriptorFromTemplate(String resourceName, Map<String, String> replacementValues)
+        throws IllegalArgumentException;
+
+    /**
      * Sets the plugin descriptor using the resource name. The {@link ClassLoader} is
      * used to obtain the resource.
      * 
diff --git a/modules/core/plugin-container-itest/src/test/java/org/rhq/core/pc/measurement/LateMeasurementRescheduleTest.java b/modules/core/plugin-container-itest/src/test/java/org/rhq/core/pc/measurement/LateMeasurementRescheduleTest.java
new file mode 100644
index 0000000..518d5da
--- /dev/null
+++ b/modules/core/plugin-container-itest/src/test/java/org/rhq/core/pc/measurement/LateMeasurementRescheduleTest.java
@@ -0,0 +1,105 @@
+package org.rhq.core.pc.measurement;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.when;
+
+import java.util.HashMap;
+import java.util.Set;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.container.test.api.TargetsContainer;
+import org.jboss.arquillian.test.api.ArquillianResource;
+import org.jboss.arquillian.testng.Arquillian;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+
+import org.rhq.core.clientapi.server.discovery.InventoryReport;
+import org.rhq.core.domain.resource.InventoryStatus;
+import org.rhq.core.pc.PluginContainer;
+import org.rhq.core.pc.inventory.ResourceContainer;
+import org.rhq.plugins.test.SingleResourceDiscoveryComponent;
+import org.rhq.plugins.test.measurement.BZ834019ResourceComponent;
+import org.rhq.test.arquillian.AfterDiscovery;
+import org.rhq.test.arquillian.BeforeDiscovery;
+import org.rhq.test.arquillian.FakeServerInventory;
+import org.rhq.test.arquillian.MockingServerServices;
+import org.rhq.test.arquillian.ResourceComponentInstances;
+import org.rhq.test.arquillian.ResourceContainers;
+import org.rhq.test.arquillian.RunDiscovery;
+import org.rhq.test.shrinkwrap.RhqAgentPluginArchive;
+
+/**
+ * Test for BZ 834019.
+ */
+ at RunDiscovery
+public class LateMeasurementRescheduleTest extends Arquillian {
+
+    @Deployment(name = "SingleMetricPlugin")
+    @TargetsContainer("connected-pc-with-metric-collection")
+    public static RhqAgentPluginArchive getTestPlugin() {
+        RhqAgentPluginArchive pluginJar = ShrinkWrap
+            .create(RhqAgentPluginArchive.class, "single-metric-plugin-1.0.jar");
+        HashMap<String, String> replacements = new HashMap<String, String>();
+        replacements.put("@@@discovery@@@", SingleResourceDiscoveryComponent.class.getName());
+        replacements.put("@@@class@@@", BZ834019ResourceComponent.class.getName());
+        return pluginJar.setPluginDescriptorFromTemplate("single-metric-rhq-plugin.xml", replacements).addClasses(
+            SingleResourceDiscoveryComponent.class, BZ834019ResourceComponent.class);
+    }
+
+    @ArquillianResource
+    private PluginContainer pluginContainer;
+
+    @ArquillianResource
+    public MockingServerServices serverServices;
+
+    private FakeServerInventory fakeServerInventory;
+    private FakeServerInventory.CompleteDiscoveryChecker discoveryCompleteChecker;
+
+    @ResourceContainers(plugin = "SingleMetricPlugin", resourceType = "SingleMetricServer")
+    private Set<ResourceContainer> containers;
+
+    @ResourceComponentInstances(plugin = "SingleMetricPlugin", resourceType = "SingleMetricServer")
+    private Set<BZ834019ResourceComponent> components;
+
+    @BeforeDiscovery(testMethods = "testBZ834019")
+    public void resetServerServices() throws Exception {
+        serverServices.resetMocks();
+        fakeServerInventory = new FakeServerInventory();
+        discoveryCompleteChecker = fakeServerInventory.createAsyncDiscoveryCompletionChecker(1);
+
+        // autoimport everything
+        when(serverServices.getDiscoveryServerService().mergeInventoryReport(any(InventoryReport.class))).then(
+            fakeServerInventory.mergeInventoryReport(InventoryStatus.COMMITTED));
+
+        // set up the metric schedules using the metric metadata to determine default intervals and enablement
+        when(serverServices.getDiscoveryServerService().postProcessNewlyCommittedResources(any(Set.class))).then(
+            fakeServerInventory.postProcessNewlyCommittedResources());
+    }
+
+    @AfterDiscovery
+    public void waitForAsyncDiscoveries() throws Exception {
+        if (discoveryCompleteChecker != null) {
+            discoveryCompleteChecker.waitForDiscoveryComplete(10000);
+        }
+    }
+
+    @Test(groups = "pc.itest.bz834019", priority = 20)
+    public void testBZ834019() throws Exception {
+        Assert.assertNotNull(pluginContainer);
+        Assert.assertTrue(pluginContainer.isStarted());
+
+        // make sure we have the resource container
+        Assert.assertEquals(containers.size(), 1, "missing container");
+
+        // make sure we have the resource component
+        Assert.assertEquals(components.size(), 1, "missing component");
+
+        assert containers.iterator().next().getResource().getInventoryStatus() == InventoryStatus.COMMITTED;
+
+        BZ834019ResourceComponent server = this.components.iterator().next();
+
+        // TODO do things to test BZ 834019
+    }
+}
diff --git a/modules/core/plugin-container-itest/src/test/java/org/rhq/core/pc/measurement/ReadOnlyScheduleSetTest.java b/modules/core/plugin-container-itest/src/test/java/org/rhq/core/pc/measurement/ReadOnlyScheduleSetTest.java
index 8435114..d94e32f 100644
--- a/modules/core/plugin-container-itest/src/test/java/org/rhq/core/pc/measurement/ReadOnlyScheduleSetTest.java
+++ b/modules/core/plugin-container-itest/src/test/java/org/rhq/core/pc/measurement/ReadOnlyScheduleSetTest.java
@@ -19,7 +19,7 @@ import org.rhq.core.clientapi.server.discovery.InventoryReport;
 import org.rhq.core.domain.resource.InventoryStatus;
 import org.rhq.core.pc.PluginContainer;
 import org.rhq.core.pc.inventory.ResourceContainer;
-import org.rhq.plugins.test.measurement.BZ821058DiscoveryComponent;
+import org.rhq.plugins.test.SingleResourceDiscoveryComponent;
 import org.rhq.plugins.test.measurement.BZ821058ResourceComponent;
 import org.rhq.test.arquillian.AfterDiscovery;
 import org.rhq.test.arquillian.BeforeDiscovery;
@@ -40,8 +40,8 @@ public class ReadOnlyScheduleSetTest extends Arquillian {
     @TargetsContainer("connected-pc-with-metric-collection")
     public static RhqAgentPluginArchive getTestPlugin() {
         RhqAgentPluginArchive pluginJar = ShrinkWrap.create(RhqAgentPluginArchive.class, "bz821058-plugin-1.0.jar");
-        return pluginJar.setPluginDescriptor("bz821058-rhq-plugin.xml").addClasses(BZ821058DiscoveryComponent.class,
-            BZ821058ResourceComponent.class);
+        return pluginJar.setPluginDescriptor("bz821058-rhq-plugin.xml").addClasses(
+            SingleResourceDiscoveryComponent.class, BZ821058ResourceComponent.class);
     }
 
     @ArquillianResource
diff --git a/modules/core/plugin-container-itest/src/test/java/org/rhq/plugins/test/SingleResourceDiscoveryComponent.java b/modules/core/plugin-container-itest/src/test/java/org/rhq/plugins/test/SingleResourceDiscoveryComponent.java
new file mode 100644
index 0000000..fde1f91
--- /dev/null
+++ b/modules/core/plugin-container-itest/src/test/java/org/rhq/plugins/test/SingleResourceDiscoveryComponent.java
@@ -0,0 +1,30 @@
+package org.rhq.plugins.test;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.core.pluginapi.inventory.DiscoveredResourceDetails;
+import org.rhq.core.pluginapi.inventory.InvalidPluginConfigurationException;
+import org.rhq.core.pluginapi.inventory.ResourceComponent;
+import org.rhq.core.pluginapi.inventory.ResourceDiscoveryComponent;
+import org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext;
+
+public class SingleResourceDiscoveryComponent implements ResourceDiscoveryComponent<ResourceComponent<?>> {
+    @Override
+    public Set<DiscoveredResourceDetails> discoverResources(ResourceDiscoveryContext<ResourceComponent<?>> context)
+        throws InvalidPluginConfigurationException, Exception {
+
+        HashSet<DiscoveredResourceDetails> details = new HashSet<DiscoveredResourceDetails>(1);
+        ResourceType rt = context.getResourceType();
+        String key = "SingleResourceKey";
+        String name = "SingleResourceName";
+        String version = "1";
+        Configuration pc = context.getDefaultPluginConfiguration();
+        DiscoveredResourceDetails resource = new DiscoveredResourceDetails(rt, key, name, version, null, pc, null);
+        details.add(resource);
+
+        return details;
+    }
+}
\ No newline at end of file
diff --git a/modules/core/plugin-container-itest/src/test/java/org/rhq/plugins/test/measurement/BZ821058DiscoveryComponent.java b/modules/core/plugin-container-itest/src/test/java/org/rhq/plugins/test/measurement/BZ821058DiscoveryComponent.java
deleted file mode 100644
index b9f49a4..0000000
--- a/modules/core/plugin-container-itest/src/test/java/org/rhq/plugins/test/measurement/BZ821058DiscoveryComponent.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2012 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.plugins.test.measurement;
-
-import java.util.HashSet;
-import java.util.Set;
-
-import org.rhq.core.domain.configuration.Configuration;
-import org.rhq.core.domain.resource.ResourceType;
-import org.rhq.core.pluginapi.inventory.DiscoveredResourceDetails;
-import org.rhq.core.pluginapi.inventory.InvalidPluginConfigurationException;
-import org.rhq.core.pluginapi.inventory.ResourceComponent;
-import org.rhq.core.pluginapi.inventory.ResourceDiscoveryComponent;
-import org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext;
-
-public class BZ821058DiscoveryComponent implements ResourceDiscoveryComponent<ResourceComponent<?>> {
-
-    @Override
-    public Set<DiscoveredResourceDetails> discoverResources(ResourceDiscoveryContext<ResourceComponent<?>> context)
-        throws InvalidPluginConfigurationException, Exception {
-
-        HashSet<DiscoveredResourceDetails> details = new HashSet<DiscoveredResourceDetails>(1);
-        ResourceType rt = context.getResourceType();
-        String key = "bz821058";
-        String name = "bz821058";
-        String version = "1";
-        Configuration pc = context.getDefaultPluginConfiguration();
-        DiscoveredResourceDetails resource = new DiscoveredResourceDetails(rt, key, name, version, null, pc, null);
-        details.add(resource);
-
-        return details;
-    }
-
-}
diff --git a/modules/core/plugin-container-itest/src/test/java/org/rhq/plugins/test/measurement/BZ834019ResourceComponent.java b/modules/core/plugin-container-itest/src/test/java/org/rhq/plugins/test/measurement/BZ834019ResourceComponent.java
new file mode 100644
index 0000000..6a3a93d
--- /dev/null
+++ b/modules/core/plugin-container-itest/src/test/java/org/rhq/plugins/test/measurement/BZ834019ResourceComponent.java
@@ -0,0 +1,38 @@
+package org.rhq.plugins.test.measurement;
+
+import java.util.Iterator;
+import java.util.Set;
+
+import org.rhq.core.domain.measurement.AvailabilityType;
+import org.rhq.core.domain.measurement.MeasurementDataNumeric;
+import org.rhq.core.domain.measurement.MeasurementReport;
+import org.rhq.core.domain.measurement.MeasurementScheduleRequest;
+import org.rhq.core.pluginapi.inventory.ResourceComponent;
+import org.rhq.core.pluginapi.inventory.ResourceContext;
+import org.rhq.core.pluginapi.measurement.MeasurementFacet;
+
+public class BZ834019ResourceComponent implements ResourceComponent<ResourceComponent<?>>, MeasurementFacet {
+
+    @Override
+    public AvailabilityType getAvailability() {
+        return AvailabilityType.UP;
+    }
+
+    @Override
+    public void start(ResourceContext<ResourceComponent<?>> context) throws Exception {
+    }
+
+    @Override
+    public void stop() {
+    }
+
+    @Override
+    public void getValues(MeasurementReport report, Set<MeasurementScheduleRequest> metrics) throws Exception {
+        //  TODO: do things to test BZ 834019
+        for (Iterator<MeasurementScheduleRequest> i = metrics.iterator(); i.hasNext();) {
+            MeasurementScheduleRequest metric = i.next();
+            report.addData(new MeasurementDataNumeric(metric, new Double(1.0)));
+        }
+        return;
+    }
+}
\ No newline at end of file
diff --git a/modules/core/plugin-container-itest/src/test/resources/arquillian.xml b/modules/core/plugin-container-itest/src/test/resources/arquillian.xml
index 92968b2..964e07e 100644
--- a/modules/core/plugin-container-itest/src/test/resources/arquillian.xml
+++ b/modules/core/plugin-container-itest/src/test/resources/arquillian.xml
@@ -10,6 +10,7 @@
         <property name="insideAgent">true</property>
         <property name="startManagementBean">false</property>
         <property name="measurementCollectionInitialDelay">10</property> <!-- start collecting metrics after 10s -->
+        <property name="measurementCollectionThreadPoolSize">1</property> <!-- make testing easier by only having one thread collect -->
       </configuration>
     </container>
 
diff --git a/modules/core/plugin-container-itest/src/test/resources/bz821058-rhq-plugin.xml b/modules/core/plugin-container-itest/src/test/resources/bz821058-rhq-plugin.xml
index 730a656..c6adda6 100644
--- a/modules/core/plugin-container-itest/src/test/resources/bz821058-rhq-plugin.xml
+++ b/modules/core/plugin-container-itest/src/test/resources/bz821058-rhq-plugin.xml
@@ -3,15 +3,14 @@
 <plugin name="bz821058Plugin"
         displayName="Plugin to test BZ 821058"
         description="This will help test that measurement facet is given a read-only schedule set."
-        package="org.rhq.plugins.test.measurement"
         version="1.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="urn:xmlns:rhq-plugin"
         xmlns:c="urn:xmlns:rhq-configuration">
 
    <server name="BZ821058Server"
-           discovery="BZ821058DiscoveryComponent"
-           class="BZ821058ResourceComponent">
+           discovery="org.rhq.plugins.test.SingleResourceDiscoveryComponent"
+           class="org.rhq.plugins.test.measurement.BZ821058ResourceComponent">
 
       <metric property="metric1"
               dataType="measurement"
diff --git a/modules/core/plugin-container-itest/src/test/resources/single-metric-rhq-plugin.xml b/modules/core/plugin-container-itest/src/test/resources/single-metric-rhq-plugin.xml
new file mode 100644
index 0000000..d67fafd
--- /dev/null
+++ b/modules/core/plugin-container-itest/src/test/resources/single-metric-rhq-plugin.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<plugin name="SingleMetricPlugin"
+        displayName="Plugin that has a single server with a single enabled metric."
+        description="This will help test measurement collections by providing a server with an enabled metric."
+        version="1.0"
+        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xmlns="urn:xmlns:rhq-plugin"
+        xmlns:c="urn:xmlns:rhq-configuration">
+
+   <server name="SingleMetricServer"
+           discovery="@@@discovery@@@"
+           class="@@@class@@@">
+      <metric property="metric1"
+              dataType="measurement"
+              defaultOn="true"
+              displayType="summary"
+              defaultInterval="30000" />
+   </server>
+</plugin>
+        


commit cd6c2fa4ce4f128f80145438499dbfc1223fac42
Author: John Mazzitelli <mazz at redhat.com>
Date:   Fri Jun 29 17:45:46 2012 -0400

    [BZ 834019] the actual code fix to push out the new rescheduled metric - will later be checking in test code to help test this

diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/measurement/MeasurementCollectorRunner.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/measurement/MeasurementCollectorRunner.java
index ac13b06..e9303b4 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/measurement/MeasurementCollectorRunner.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/measurement/MeasurementCollectorRunner.java
@@ -88,7 +88,7 @@ public class MeasurementCollectorRunner implements Callable<MeasurementReport>,
                         }
                     }
 
-                    this.measurementManager.reschedule(requests);
+                    this.measurementManager.reschedule(requests, 31000L); // BZ 834019 - go to the next collection interval plus 31s to skew it
                     return report;
                 }
 
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/measurement/MeasurementManager.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/measurement/MeasurementManager.java
index dc7d0ca..33895aa 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/measurement/MeasurementManager.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/measurement/MeasurementManager.java
@@ -526,11 +526,31 @@ public class MeasurementManager extends AgentService implements MeasurementAgent
         return nextScheduledSet;
     }
 
+    /**
+     * Reschedules the given measurement schedules so the next collection occurs in the future.
+     * The next collection will be pushed out by the number of seconds of the schedule's collection
+     * interval.
+     *
+     * @param scheduledMeasurementInfos the schedules to reschedule
+     */
     public synchronized void reschedule(Set<ScheduledMeasurementInfo> scheduledMeasurementInfos) {
+        reschedule(scheduledMeasurementInfos, 0);
+    }
+
+    /**
+     * Reschedules the given measurement schedules so the next collection occurs in the future.
+     * The next collection will be pushed out by the number of seconds of the schedule's collection
+     * interval plus (or minus) the given adjustment (which is provided in milliseconds).
+     *
+     * @param scheduledMeasurementInfos the schedules to reschedule
+     * @param adjustment the number of milliseconds to adjust the next collection time. If 0, the
+     *                   next collection time will be the number of seconds in the future as indicated
+     *                   by the schedule's interval.
+     */
+    public synchronized void reschedule(Set<ScheduledMeasurementInfo> scheduledMeasurementInfos, long adjustment) {
         for (ScheduledMeasurementInfo scheduledMeasurement : scheduledMeasurementInfos) {
-            // Iterate to next collection time
             scheduledMeasurement.setNextCollection(scheduledMeasurement.getNextCollection()
-                + scheduledMeasurement.getInterval());
+                + scheduledMeasurement.getInterval() + adjustment);
             this.scheduledRequests.offer(scheduledMeasurement);
         }
     }


commit 00c0ee04c4f78b893cbd2b727c587ae76d1cc2f0
Author: Simeon Pinder <spinder at redhat.com>
Date:   Fri Jun 29 17:35:18 2012 -0400

     i)fix problem in resource key ii)up the discovery lag for loadUpdateTemplatedResourceConfiguration to try to fix invalid resource ids

diff --git a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/domain/SecurityModuleOptionsTest.java b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/domain/SecurityModuleOptionsTest.java
index 05ca0eb..7be0689 100644
--- a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/domain/SecurityModuleOptionsTest.java
+++ b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/domain/SecurityModuleOptionsTest.java
@@ -491,7 +491,7 @@ public class SecurityModuleOptionsTest extends AbstractJBossAS7PluginTest {
             ResourceType hostControllerType = new ResourceType("JBossAS7 Host Controller", PLUGIN_NAME,
                 ResourceCategory.SERVER, null);
             Resource hostController = getResourceByTypeAndKey(platform, hostControllerType,
-                "/tmp/jboss-as-6.0.0.GA/domain");
+                "/tmp/jboss-as-6.0.0/domain");
             //profile=full-ha
             ResourceType profileType = new ResourceType("Profile", PLUGIN_NAME, ResourceCategory.SERVICE, null);
             String key = PROFILE;
diff --git a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/TemplatedResourcesTest.java b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/TemplatedResourcesTest.java
index fe05def..908faff 100644
--- a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/TemplatedResourcesTest.java
+++ b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/TemplatedResourcesTest.java
@@ -58,7 +58,7 @@ public class TemplatedResourcesTest extends AbstractJBossAS7PluginTest {
         assertNotNull(platform);
         assertEquals(platform.getInventoryStatus(), InventoryStatus.COMMITTED);
 
-        Thread.sleep(20 * 1000L);
+        Thread.sleep(40 * 1000L);
     }
 
     @Test(priority = 11)


commit 7281ff782f83461ae81560adf82b83d3e08bf1db
Author: Simeon Pinder <spinder at redhat.com>
Date:   Fri Jun 29 11:14:18 2012 -0400

     -moved domain test into domain group and package
     -added longer sleep to TemplatedResource test to attempt to fix test run failures.

diff --git a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/domain/SecurityModuleOptionsTest.java b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/domain/SecurityModuleOptionsTest.java
new file mode 100644
index 0000000..05ca0eb
--- /dev/null
+++ b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/domain/SecurityModuleOptionsTest.java
@@ -0,0 +1,675 @@
+/*
+ * 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 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.modules.plugins.jbossas7.itest.domain;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Set;
+
+import org.codehaus.jackson.JsonGenerationException;
+import org.codehaus.jackson.JsonNode;
+import org.codehaus.jackson.JsonProcessingException;
+import org.codehaus.jackson.map.DeserializationConfig;
+import org.codehaus.jackson.map.JsonMappingException;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.testng.annotations.Test;
+
+import org.rhq.core.clientapi.agent.inventory.CreateResourceRequest;
+import org.rhq.core.clientapi.agent.inventory.CreateResourceResponse;
+import org.rhq.core.clientapi.agent.inventory.DeleteResourceRequest;
+import org.rhq.core.clientapi.agent.inventory.DeleteResourceResponse;
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.Property;
+import org.rhq.core.domain.configuration.PropertyMap;
+import org.rhq.core.domain.configuration.PropertySimple;
+import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
+import org.rhq.core.domain.resource.CreateResourceStatus;
+import org.rhq.core.domain.resource.DeleteResourceStatus;
+import org.rhq.core.domain.resource.InventoryStatus;
+import org.rhq.core.domain.resource.Resource;
+import org.rhq.core.domain.resource.ResourceCategory;
+import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.core.pc.configuration.ConfigurationManager;
+import org.rhq.core.pc.inventory.InventoryManager;
+import org.rhq.modules.plugins.jbossas7.ASConnection;
+import org.rhq.modules.plugins.jbossas7.ModuleOptionsComponent;
+import org.rhq.modules.plugins.jbossas7.ModuleOptionsComponent.Value;
+import org.rhq.modules.plugins.jbossas7.itest.AbstractJBossAS7PluginTest;
+import org.rhq.modules.plugins.jbossas7.itest.standalone.StandaloneServerComponentTest;
+import org.rhq.modules.plugins.jbossas7.json.Address;
+import org.rhq.modules.plugins.jbossas7.json.Operation;
+import org.rhq.modules.plugins.jbossas7.json.Result;
+import org.rhq.test.arquillian.RunDiscovery;
+
+/**
+ * Test exercising the subsystem=security/SecurityDomain/[Authentication(Classic|Jaspi), 
+ * Authorization, Mapping, Audit, Acl, 
+ *      Identity-Trust]
+ * @author Simeon Pinder
+ */
+ at Test(groups = { "integration", "pc", "domain" }, singleThreaded = true)
+public class SecurityModuleOptionsTest extends AbstractJBossAS7PluginTest {
+
+    private static ASConnection con = null;
+    private static ObjectMapper mapper = null;
+
+    private static String TEST_DOMAIN = "testDomain";
+    private static String SECURITY_RESOURCE_TYPE = "Security";
+    private static String SECURITY_RESOURCE_KEY = "subsystem=security";
+    private static String SECURITY_DOMAIN_RESOURCE_KEY = "security-domain";
+    private static String PROFILE = "profile=full-ha";
+    private static String SECURITY_DOMAIN_RESOURCE_TYPE = "Security Domain";
+    private static String AUTH_CLASSIC_RESOURCE_TYPE = "Authentication (Classic)";
+    private static String AUTH_CLASSIC_RESOURCE_KEY = "authentication=classic";
+
+    private static Resource securityResource = null;
+
+    protected static String DC_HOST = System.getProperty("jboss.domain.bindAddress");
+    protected static int DC_HTTP_PORT = Integer.valueOf(System.getProperty("jboss.domain.httpManagementPort"));
+    protected static String DC_USER = AbstractJBossAS7PluginTest.MANAGEMENT_USERNAME;
+    protected static String DC_PASS = AbstractJBossAS7PluginTest.MANAGEMENT_PASSWORD;
+
+    ASConnection getASConnection() {
+        ASConnection connection = new ASConnection(DC_HOST, DC_HTTP_PORT, DC_USER, DC_PASS);
+        return connection;
+    }
+
+    public static final ResourceType RESOURCE_TYPE = new ResourceType(SECURITY_RESOURCE_TYPE, PLUGIN_NAME,
+        ResourceCategory.SERVICE, null);
+    private static final String RESOURCE_KEY = SECURITY_RESOURCE_KEY;
+    private static Resource testSecurityDomain = null;
+    private String testSecurityDomainKey = null;
+    private ConfigurationManager testConfigurationManager = null;
+
+    //Define some shared and reusable content
+    static HashMap<String, String> jsonMap = new HashMap<String, String>();
+    static {
+        jsonMap
+            .put(
+                "login-modules",
+                "[{\"flag\":\"required\", \"code\":\"Ldap\", \"module-options\":{\"bindDn\":\"uid=ldapSecureUser,ou=People,dc=redat,dc=com\", \"bindPw\":\"test126\", \"allowEmptyPasswords\":\"true\"}}]");
+        jsonMap
+            .put(
+                "policy-modules",
+                "[{\"flag\":\"requisite\", \"code\":\"LdapExtended\", \"module-options\":{\"policy\":\"module\", \"policy1\":\"module1\"}}]");
+        jsonMap
+            .put("mapping-modules",
+                "[{\"code\":\"Test\", \"type\":\"attribute\", \"module-options\":{\"mapping\":\"module\", \"mapping1\":\"module1\"}}]");
+        jsonMap.put("provider-modules",
+            "[{\"code\":\"Providers\", \"module-options\":{\"provider\":\"module\", \"provider1\":\"module1\"}}]");
+        jsonMap
+            .put("acl-modules",
+                "[{\"flag\":\"sufficient\", \"code\":\"ACL\", \"module-options\":{\"acl\":\"module\", \"acl1\":\"module1\"}}]");
+        jsonMap
+            .put("trust-modules",
+                "[{\"flag\":\"optional\", \"code\":\"TRUST\", \"module-options\":{\"trust\":\"module\", \"trust1\":\"module1\"}}]");
+    }
+
+    /* This first discovery is only so that we can leverage existing code to install the management user needed
+     * in next test.
+     */
+    @Test(priority = 10, groups = "discovery")
+    @RunDiscovery(discoverServices = true, discoverServers = true)
+    public void firstDiscovery() throws Exception {
+        Resource platform = this.pluginContainer.getInventoryManager().getPlatform();
+        assertNotNull(platform);
+        assertEquals(platform.getInventoryStatus(), InventoryStatus.COMMITTED);
+
+        //now install mgmt users.
+        System.out.println("------ * Duplicating discovery for SecurityModule testing....");
+        installManagementUsers();
+    }
+
+    /** This method mass loads all the supported Module Option Types(Excluding authentication=jaspi, cannot co-exist with 
+     * authentication=classic) into a single SecurityDomain.  This is done as
+     * -i)creating all of the related hierarchy of types needed to exercise N Module Options Types and their associated 
+     *     Module Options instances would take too long to setup(N creates would signal N discovery runs before test could complete).
+     * -ii)setting the priority of this method lower than the discovery method means that we'll get all the same types in much 
+     *     less time.
+     *     
+     * @throws Exception
+     */
+    @Test(priority = 11)
+    public void loadStandardModuleOptionTypes() throws Exception {
+        mapper = new ObjectMapper();
+        mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+
+        //Adjust discovery depth to support deeper hierarchy depth of Module Option elements
+        setMaxDiscoveryDepthOverride(12);
+
+        //create new Security Domain
+        Address destination = new Address(PROFILE);
+        destination.addSegment(SECURITY_RESOURCE_KEY);
+        String securityDomainId = TEST_DOMAIN + "2";
+        destination.addSegment(SECURITY_DOMAIN_RESOURCE_KEY + "=" + securityDomainId);
+
+        ASConnection connection = getASConnection();
+        Result result = new Result();
+        Operation op = null;
+        //delete old one if present to setup clean slate
+        op = new Operation("remove", destination);
+        result = connection.execute(op);
+
+        //build/rebuild hierarchy
+        op = new Operation("add", destination);
+        result = connection.execute(op);
+        assert result.getOutcome().equals("success") : "Add of Security Domain has failed: "
+            + result.getFailureDescription();
+
+        //Ex. profile=standalone-ha,subsystem=security,security-domain
+        String addressPrefix = PROFILE + "," + SECURITY_RESOURCE_KEY + "," + SECURITY_DOMAIN_RESOURCE_KEY;
+
+        //loop over standard types and add base details for all of them to security domain
+        String address = "";
+        for (String attribute : jsonMap.keySet()) {
+            if (attribute.equals("policy-modules")) {
+                address = addressPrefix + "=" + securityDomainId + ",authorization=classic";
+            } else if (attribute.equals("acl-modules")) {
+                address = addressPrefix + "=" + securityDomainId + ",acl=classic";
+            } else if (attribute.equals("mapping-modules")) {
+                address = addressPrefix + "=" + securityDomainId + ",mapping=classic";
+            } else if (attribute.equals("trust-modules")) {
+                address = addressPrefix + "=" + securityDomainId + ",identity-trust=classic";
+            } else if (attribute.equals("provider-modules")) {
+                address = addressPrefix + "=" + securityDomainId + ",audit=classic";
+            } else if (attribute.equals("login-modules")) {
+                address = addressPrefix + "=" + securityDomainId + ",authentication=classic";
+            } else {
+                assert false : "An unknown attribute '" + attribute
+                    + "' was found. Is there a new type to be supported?";
+            }
+            //build the operation to add the component
+            ////Load json map into ModuleOptionType
+            List<Value> moduleTypeValue = new ArrayList<Value>();
+            try {
+                // loading jsonMap contents for Ex. 'login-module'
+                JsonNode node = mapper.readTree(jsonMap.get(attribute));
+                Object obj = mapper.treeToValue(node, Object.class);
+                result.setResult(obj);
+                result.setOutcome("success");
+            } catch (JsonProcessingException e) {
+                e.printStackTrace();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+
+            //populate the Value component complete with module Options.
+            moduleTypeValue = ModuleOptionsComponent.populateSecurityDomainModuleOptions(result,
+                ModuleOptionsComponent.loadModuleOptionType(attribute));
+            op = ModuleOptionsComponent.createAddModuleOptionTypeOperation(new Address(address), attribute,
+                moduleTypeValue);
+            //submit the command
+            result = connection.execute(op);
+        }
+    }
+
+    /** Runs the second discovery run to load all the new types added.
+     * 
+     * @throws Exception
+     */
+    @Test(priority = 12, groups = "discovery")
+    @RunDiscovery(discoverServices = true, discoverServers = true)
+    public void secondDiscovery() throws Exception {
+        Resource platform = this.pluginContainer.getInventoryManager().getPlatform();
+        assertNotNull(platform);
+        assertEquals(platform.getInventoryStatus(), InventoryStatus.COMMITTED);
+
+        //Have thread sleep longer to discover deeper resource types.
+        //spinder 6/29/12: up this number if the resources are not being discovered.
+        Thread.sleep(180 * 1000L); // delay so that PC gets a chance to scan for resources
+    }
+
+    /** This test method exercises a number of things:
+     *  - that the security-domain children loaded have been created successfully
+     *  - that all of the supported Module Option Type children(excluding 'authentication=jaspi') have been 
+     *    discovered as AS7 types successfully.
+     *  - that the correct child attribute was specified for each type //Ex. acl=classic -> acl-modules
+     *  - 
+     * 
+     * @throws Exception
+     */
+    @Test(priority = 13)
+    public void testDiscoveredSecurityNodes() throws Exception {
+        //lazy-load configurationManager
+        if (testConfigurationManager == null) {
+            testConfigurationManager = this.pluginContainer.getConfigurationManager();
+            testConfigurationManager = pluginContainer.getConfigurationManager();
+            testConfigurationManager.initialize();
+            Thread.sleep(20 * 1000L);
+        }
+        //iterate through list of nodes and make sure they've all been discovered
+        ////Ex. profile=full-ha,subsystem=security,security-domain=testDomain2,acl=classic
+        String attribute = null;
+        for (String jsonKey : jsonMap.keySet()) {
+            //Ex. policy-modules
+            attribute = jsonKey;
+            //spinder 6/26/12: Temporarily disable until figure out why NPE happens only for this type?
+            if (attribute.equals(ModuleOptionsComponent.ModuleOptionType.Authentication.getAttribute())) {
+                break;//
+            }
+            //Ex. name=acl-modules
+            //check the configuration for the Module Option Type Ex. 'Acl (Profile)' Resource. Should be able to verify components
+            Resource moduleOptionsTypeResource = getModuleOptionTypeResource(attribute);
+            //assert non-zero id returned
+            assert moduleOptionsTypeResource.getId() > 0 : "The resource was not properly initialized. Expected id >0 but got:"
+                + moduleOptionsTypeResource.getId();
+
+            //Now request the resource complete with resource config
+            Configuration loadedConfiguration = testConfigurationManager
+                .loadResourceConfiguration(moduleOptionsTypeResource.getId());
+            String code = null;
+            String type = null;
+            String flag = null;
+            //populate the associated attributes if it's supported.
+            for (String key : loadedConfiguration.getAllProperties().keySet()) {
+                Property property = loadedConfiguration.getAllProperties().get(key);
+                if (key.equals("code")) {
+                    code = ((PropertySimple) property).getStringValue();
+                } else if (key.equals("flag")) {
+                    flag = ((PropertySimple) property).getStringValue();
+                } else {//Ex. type.
+                    type = ((PropertySimple) property).getStringValue();
+                }
+            }
+
+            //retrieve module options as well.
+            String jsonContent = jsonMap.get(attribute);
+            Result result = new Result();
+            try {
+                // loading jsonMap contents for Ex. 'login-module'
+                JsonNode node = mapper.readTree(jsonContent);
+                Object obj = mapper.treeToValue(node, Object.class);
+                result.setResult(obj);
+                result.setOutcome("success");
+            } catch (JsonProcessingException e) {
+                e.printStackTrace();
+                assert false;
+            } catch (IOException e) {
+                e.printStackTrace();
+                assert false;
+            }
+
+            //populate the Value component complete with module Options.
+            List<Value> moduleTypeValue = ModuleOptionsComponent.populateSecurityDomainModuleOptions(result,
+                ModuleOptionsComponent.loadModuleOptionType(attribute));
+            Value moduleOptionType = moduleTypeValue.get(0);
+            //Ex. retrieve the acl-modules component and assert values.
+            //always test 'code'
+            assert moduleOptionType.getCode().equals(code) : "Module Option 'code' value is not correct. Expected '"
+                + code + "' but was '" + moduleOptionType.getCode() + "'";
+            if (attribute.equals(ModuleOptionsComponent.ModuleOptionType.Mapping.getAttribute())) {
+                assert moduleOptionType.getType().equals(type) : "Mapping Module 'type' value is not correct. Expected '"
+                    + type + "' but was '" + moduleOptionType.getType() + "'";
+            } else if (!attribute.equals(ModuleOptionsComponent.ModuleOptionType.Audit.getAttribute())) {//Audit has no second parameter
+                assert moduleOptionType.getFlag().equals(flag) : "Provider Module 'flag' value is not correct. Expected '"
+                    + flag + "' but was '" + moduleOptionType.getFlag() + "'";
+            }
+
+            //Retrieve Module Options and test
+            //Ex. Module Options  for (Acl Modules - Profile)
+            Resource moduleOptionsResource = getModuleOptionsResource(moduleOptionsTypeResource, attribute);
+            //assert non-zero id returned
+            assert moduleOptionsResource.getId() > 0 : "The resource was not properly initialized. Expected id > 0 but got:"
+                + moduleOptionsResource.getId();
+            //fetch configuration for module options
+            //Now request the resource complete with resource config
+            Configuration loadedOptionsConfiguration = testConfigurationManager
+                .loadResourceConfiguration(moduleOptionsResource.getId());
+            for (String key : loadedOptionsConfiguration.getAllProperties().keySet()) {
+                //retrieve the open map of Module Options 
+                PropertyMap map = ((PropertyMap) loadedOptionsConfiguration.getAllProperties().get(key));
+                LinkedHashMap<String, Object> options = moduleOptionType.getOptions();
+                for (String optionKey : map.getMap().keySet()) {
+                    PropertySimple property = (PropertySimple) map.getMap().get(optionKey);
+                    //test the key
+                    assert options.containsKey(optionKey) : "Unable to find expected option key '" + optionKey
+                        + "'. Check hierarchy.";
+                    //now the value.
+                    String value = String.valueOf(options.get(optionKey));
+                    assert value.equals(property.getStringValue()) : "Unable to find expected Module Option mapping.  Key '"
+                        + optionKey
+                        + "' did not map to expected value '"
+                        + value
+                        + "' but was '"
+                        + property.getStringValue() + "'.";
+                }
+            }
+        }
+    }
+
+    @Test(priority = 14)
+    public void testCreateSecurityDomain() throws Exception {
+        //get the root security resource
+        securityResource = getResource();
+
+        //plugin config
+        Configuration createPlugConfig = new Configuration();
+        createPlugConfig.put(new PropertySimple("path", SECURITY_DOMAIN_RESOURCE_KEY += "=" + TEST_DOMAIN));
+
+        //resource config
+        Configuration createResConfig = new Configuration();
+        createResConfig.put(new PropertySimple("name", TEST_DOMAIN));
+
+        CreateResourceRequest request = new CreateResourceRequest();
+        request.setParentResourceId(securityResource.getId());
+        request.setPluginConfiguration(createPlugConfig);
+        request.setPluginName(PLUGIN_NAME);
+        request.setResourceConfiguration(createResConfig);
+        request.setResourceName(TEST_DOMAIN);
+        request.setResourceTypeName(SECURITY_DOMAIN_RESOURCE_TYPE);
+
+        CreateResourceResponse response = pluginContainer.getResourceFactoryManager().executeCreateResourceImmediately(
+            request);
+
+        assert response.getStatus() == CreateResourceStatus.SUCCESS : "The Security Domain creation failed with an error mesasge: "
+            + response.getErrorMessage();
+    }
+
+    @Test(priority = 15)
+    public void testAuthenticationClassic() throws Exception {
+        //get the root security resource
+        securityResource = getResource();
+
+        //find TEST_DOMAIN 'security-domain'
+        Resource securityDomain = null;
+        Set<Resource> childResources = securityResource.getChildResources();
+        for (Resource r : childResources) {
+            if (r.getName().indexOf(TEST_DOMAIN) > -1) {
+                securityDomain = r;
+            }
+        }
+
+        //plugin config
+        Configuration createPlugConfig = new Configuration();
+        createPlugConfig.put(new PropertySimple("path", AUTH_CLASSIC_RESOURCE_KEY));
+
+        //resource config
+        Configuration createResConfig = new Configuration();
+        createResConfig.put(new PropertySimple("code", "Ldap"));
+        createResConfig.put(new PropertySimple("flag", "requisite"));
+
+        CreateResourceRequest request = new CreateResourceRequest();
+        request.setParentResourceId(securityDomain.getId());
+        request.setPluginConfiguration(createPlugConfig);
+        request.setPluginName(PLUGIN_NAME);
+        request.setResourceConfiguration(createResConfig);
+        request.setResourceName("Test - notUsed.");
+
+        request.setResourceTypeName(AUTH_CLASSIC_RESOURCE_TYPE);
+
+        CreateResourceResponse response = pluginContainer.getResourceFactoryManager().executeCreateResourceImmediately(
+            request);
+
+        assert response.getStatus() == CreateResourceStatus.SUCCESS : "The 'Authentication (Classic)' node creation failed with an error mesasge: "
+            + response.getErrorMessage();
+    }
+
+    @Test(priority = 16)
+    public void testDeleteSecurityDomain() throws Exception {
+        //get the root security resource
+        securityResource = getResource();
+        Resource found = null;
+        Set<Resource> childResources = securityResource.getChildResources();
+        for (Resource r : childResources) {
+            if (r.getName().indexOf(TEST_DOMAIN) > -1) {
+                found = r;
+            }
+        }
+
+        //plugin config
+        Configuration deletePlugConfig = new Configuration();
+        deletePlugConfig.put(new PropertySimple("path", SECURITY_DOMAIN_RESOURCE_KEY += "=" + TEST_DOMAIN));
+
+        //resource config
+        Configuration deleteResConfig = new Configuration();
+        deleteResConfig.put(new PropertySimple("name", TEST_DOMAIN));
+
+        DeleteResourceRequest request = new DeleteResourceRequest();
+        if (found != null) {
+            request.setResourceId(found.getId());
+        }
+        DeleteResourceResponse response = pluginContainer.getResourceFactoryManager().executeDeleteResourceImmediately(
+            request);
+
+        assert response.getStatus() == DeleteResourceStatus.SUCCESS : "The Security Domain deletion failed with an error mesasge: "
+            + response.getErrorMessage();
+    }
+
+    //    public static void main(String[] args) {
+    //        SecurityModuleOptionsTest setup = new SecurityModuleOptionsTest();
+    //        try {
+    //            setup.loadStandardModuleOptionTypes();
+    //        } catch (Exception e) {
+    //            e.printStackTrace();
+    //        }
+    //    }
+
+    private Resource getResource() {
+
+        InventoryManager im = pluginContainer.getInventoryManager();
+        Resource platform = im.getPlatform();
+        Resource server = getResourceByTypeAndKey(platform, StandaloneServerComponentTest.RESOURCE_TYPE,
+            StandaloneServerComponentTest.RESOURCE_KEY);
+        Resource bindings = getResourceByTypeAndKey(server, RESOURCE_TYPE, RESOURCE_KEY);
+        return bindings;
+    }
+
+    /** Automates hierarchy creation for Module Option type resources and their parents
+     * 
+     * @param optionAttributeType
+     * @return
+     */
+    private Resource getModuleOptionTypeResource(String optionAttributeType) {
+        Resource moduleOptionResource = null;
+        String securityDomainId = SECURITY_DOMAIN_RESOURCE_KEY + "=" + TEST_DOMAIN + "2";
+        if (testSecurityDomain == null) {
+            InventoryManager im = pluginContainer.getInventoryManager();
+            Resource platform = im.getPlatform();
+            //host controller
+            ResourceType hostControllerType = new ResourceType("JBossAS7 Host Controller", PLUGIN_NAME,
+                ResourceCategory.SERVER, null);
+            Resource hostController = getResourceByTypeAndKey(platform, hostControllerType,
+                "/tmp/jboss-as-6.0.0.GA/domain");
+            //profile=full-ha
+            ResourceType profileType = new ResourceType("Profile", PLUGIN_NAME, ResourceCategory.SERVICE, null);
+            String key = PROFILE;
+            Resource profile = getResourceByTypeAndKey(hostController, profileType, key);
+
+            //Security (Profile)
+            ResourceType securityType = new ResourceType("Security (Profile)", PLUGIN_NAME, ResourceCategory.SERVICE,
+                null);
+            key += "," + SECURITY_RESOURCE_KEY;
+            Resource security = getResourceByTypeAndKey(profile, securityType, key);
+
+            //Security Domain (Profile)
+            ResourceType domainType = new ResourceType("Security Domain (Profile)", PLUGIN_NAME,
+                ResourceCategory.SERVICE, null);
+            key += "," + securityDomainId;
+            testSecurityDomainKey = key;
+            testSecurityDomain = getResourceByTypeAndKey(security, domainType, key);
+        }
+
+        //acl=classic
+        String descriptorName = "";
+        String moduleAttribute = "";
+        //acl
+        if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.Acl.getAttribute())) {
+            descriptorName = "ACL (Profile)";
+            moduleAttribute = "acl=classic";
+        } else if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.Audit.getAttribute())) {
+            descriptorName = "Audit (Profile)";
+            moduleAttribute = "audit=classic";
+        } else if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.Authentication.getAttribute())) {
+            descriptorName = "Authentication (Classic - Profile)";
+            moduleAttribute = "authentication=classic";
+        } else if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.Authorization.getAttribute())) {
+            descriptorName = "Authorization (Profile)";
+            moduleAttribute = "authorization=classic";
+        } else if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.IdentityTrust.getAttribute())) {
+            descriptorName = "Identity Trust (Profile)";
+            moduleAttribute = "identity-trust=classic";
+        } else if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.Mapping.getAttribute())) {
+            descriptorName = "Mapping (Profile)";
+            moduleAttribute = "mapping=classic";
+        }
+        //Build the right Module Option Type. Ex. ACL (Profile), etc.
+        ResourceType moduleOptionType = new ResourceType(descriptorName, PLUGIN_NAME, ResourceCategory.SERVICE, null);
+        ConfigurationDefinition cdef = new ConfigurationDefinition(descriptorName, null);
+        moduleOptionType.setResourceConfigurationDefinition(cdef);
+        //Ex. profile=full-ha,subsystem=security,security-domain=testDomain2,identity-trust=classic
+        String moduleOptionTypeKey = testSecurityDomainKey += "," + moduleAttribute;
+
+        if (!testSecurityDomainKey.endsWith(securityDomainId)) {
+            moduleOptionTypeKey = testSecurityDomainKey.substring(0, testSecurityDomainKey.indexOf(securityDomainId)
+                + securityDomainId.length())
+                + "," + moduleAttribute;
+        }
+
+        moduleOptionResource = getResourceByTypeAndKey(testSecurityDomain, moduleOptionType, moduleOptionTypeKey);
+
+        return moduleOptionResource;
+    }
+
+    /** Automates hierarchy creation for Module Option type resources and their parents
+     * 
+     * @param optionAttributeType
+     * @return
+     */
+    private Resource getModuleOptionsResource(Resource parent, String optionAttributeType) {
+        Resource moduleOptionsResource = null;
+        String descriptorName = "";
+        String moduleAttribute = "";
+        String moduleOptionsDescriptor = "";
+        if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.Acl.getAttribute())) {
+            //            descriptorName = "ACL Modules (Profile)";
+            descriptorName = "Acl Modules (Profile)";
+            moduleAttribute = "acl=classic";
+            moduleOptionsDescriptor = "Module Options (Acl - Profile)";
+        } else if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.Audit.getAttribute())) {
+            descriptorName = "Provider Modules (Profile)";
+            moduleAttribute = "audit=classic";
+            moduleOptionsDescriptor = "Module Options (Provider Modules - Profile)";
+        } else if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.Authentication.getAttribute())) {
+            descriptorName = "Login Modules (Classic - Profile)";
+            moduleAttribute = "authentication=classic";
+            moduleOptionsDescriptor = "Module Options (Classic - Profile)";
+        } else if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.Authorization.getAttribute())) {
+            descriptorName = "Authorization Modules (Profile)";
+            moduleAttribute = "authorization=classic";
+            moduleOptionsDescriptor = "Module Options (Authorization - Profile)";
+        } else if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.IdentityTrust.getAttribute())) {
+            descriptorName = "Identity Trust Modules (Profile)";
+            moduleAttribute = "identity-trust=classic";
+            moduleOptionsDescriptor = "Module Options (Identity Trust - Profile)";
+        } else if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.Mapping.getAttribute())) {
+            descriptorName = "Mapping Modules (Profile)";
+            moduleAttribute = "mapping=classic";
+            moduleOptionsDescriptor = "Module Options (Mapping - Profile)";
+        }
+        //Build the right Module Option Type. Ex. ACL Modules (Profile), etc.
+        ResourceType modulesType = new ResourceType(descriptorName, PLUGIN_NAME, ResourceCategory.SERVICE, null);
+        //Ex. profile=full-ha,subsystem=security,security-domain=testDomain2,acl=classic,acl-modules:0
+        String sharedRoot = "profile=full-ha,subsystem=security,security-domain=testDomain2";
+        String moduleOptionTypeKey = sharedRoot += "," + moduleAttribute + ","
+            + optionAttributeType + ":0";
+        //Ex. Module Options Type children [ACL Modules (Profile),etc.]
+        Resource modulesInstance = getResourceByTypeAndKey(parent, modulesType, moduleOptionTypeKey);
+
+        //Module Options
+        ResourceType moduleOptionsType = new ResourceType(moduleOptionsDescriptor, PLUGIN_NAME,
+            ResourceCategory.SERVICE, null);
+        moduleOptionsResource = getResourceByTypeAndKey(modulesInstance, moduleOptionsType, moduleOptionTypeKey
+            + ",module-options");
+
+        return moduleOptionsResource;
+    }
+
+    private Resource getResource(Resource parentResource, String pluginDescriptorTypeName, String resourceKey) {
+        Resource resource = null;
+        if (((parentResource != null) & (pluginDescriptorTypeName != null) & (resourceKey != null))
+            & (((!pluginDescriptorTypeName.isEmpty()) & (!resourceKey.isEmpty())))) {
+            ResourceType resourceType = buildResourceType(pluginDescriptorTypeName);
+            resource = getResourceByTypeAndKey(parentResource, resourceType, resourceKey);
+        }
+        return resource;
+    }
+
+    private ResourceType buildResourceType(String pluginTypeName) {
+        ResourceType created = null;
+        if ((pluginTypeName != null) && (!pluginTypeName.isEmpty())) {
+            created = new ResourceType(pluginTypeName, PLUGIN_NAME, ResourceCategory.SERVICE, null);
+        }
+        return created;
+    }
+
+    /** For each operation 
+     *   - will write verbose json and operation details to system.out if verboseOutput = true;
+     *   - will execute the operation against running server if execute = true.
+     * 
+     * @param op
+     * @param execute
+     * @param verboseOutput
+     * @return
+     */
+    public static Result exerciseOperation(Operation op, boolean execute, boolean verboseOutput) {
+        //display operation as AS7 plugin will build it
+        if (verboseOutput) {
+            System.out.println("\tOperation is:" + op);
+        }
+
+        String jsonToSend = "";
+        try {
+            jsonToSend = mapper.defaultPrettyPrintingWriter().writeValueAsString(op);
+        } catch (JsonGenerationException e) {
+            e.printStackTrace();
+        } catch (JsonMappingException e) {
+            e.printStackTrace();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        //As generated by jackson mapper
+        if (verboseOutput) {
+            System.out.println("@@@@ OUTBOUND JSON#\n" + jsonToSend + "#");
+        }
+
+        //Execute the operation
+        Result result = new Result();
+        if (execute) {
+            result = con.execute(op);
+        } else {
+            if (verboseOutput) {
+                System.out.println("**** NOTE: Execution disabled . NOT exercising write-attribute operation. **** ");
+            }
+        }
+        if (verboseOutput) {
+            //result wrapper details 
+            System.out.println("\tResult:" + result);
+            //detailed results
+            System.out.println("\tValue:" + result.getResult());
+            System.out.println("-----------------------------------------------------\n");
+        }
+        return result;
+    }
+}
diff --git a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/SecurityModuleOptionsTest.java b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/SecurityModuleOptionsTest.java
deleted file mode 100644
index 452fdfb..0000000
--- a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/SecurityModuleOptionsTest.java
+++ /dev/null
@@ -1,674 +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 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.modules.plugins.jbossas7.itest.standalone;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Set;
-
-import org.codehaus.jackson.JsonGenerationException;
-import org.codehaus.jackson.JsonNode;
-import org.codehaus.jackson.JsonProcessingException;
-import org.codehaus.jackson.map.DeserializationConfig;
-import org.codehaus.jackson.map.JsonMappingException;
-import org.codehaus.jackson.map.ObjectMapper;
-import org.testng.annotations.Test;
-
-import org.rhq.core.clientapi.agent.inventory.CreateResourceRequest;
-import org.rhq.core.clientapi.agent.inventory.CreateResourceResponse;
-import org.rhq.core.clientapi.agent.inventory.DeleteResourceRequest;
-import org.rhq.core.clientapi.agent.inventory.DeleteResourceResponse;
-import org.rhq.core.domain.configuration.Configuration;
-import org.rhq.core.domain.configuration.Property;
-import org.rhq.core.domain.configuration.PropertyMap;
-import org.rhq.core.domain.configuration.PropertySimple;
-import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
-import org.rhq.core.domain.resource.CreateResourceStatus;
-import org.rhq.core.domain.resource.DeleteResourceStatus;
-import org.rhq.core.domain.resource.InventoryStatus;
-import org.rhq.core.domain.resource.Resource;
-import org.rhq.core.domain.resource.ResourceCategory;
-import org.rhq.core.domain.resource.ResourceType;
-import org.rhq.core.pc.configuration.ConfigurationManager;
-import org.rhq.core.pc.inventory.InventoryManager;
-import org.rhq.modules.plugins.jbossas7.ASConnection;
-import org.rhq.modules.plugins.jbossas7.ModuleOptionsComponent;
-import org.rhq.modules.plugins.jbossas7.ModuleOptionsComponent.Value;
-import org.rhq.modules.plugins.jbossas7.itest.AbstractJBossAS7PluginTest;
-import org.rhq.modules.plugins.jbossas7.json.Address;
-import org.rhq.modules.plugins.jbossas7.json.Operation;
-import org.rhq.modules.plugins.jbossas7.json.Result;
-import org.rhq.test.arquillian.RunDiscovery;
-
-/**
- * Test exercising the subsystem=security/SecurityDomain/[Authentication(Classic|Jaspi), 
- * Authorization, Mapping, Audit, Acl, 
- *      Identity-Trust]
- * @author Simeon Pinder
- */
- at Test(groups = { "integration", "pc", "standalone" }, singleThreaded = true)
-public class SecurityModuleOptionsTest extends AbstractJBossAS7PluginTest {
-
-    private static ASConnection con = null;
-    private static ObjectMapper mapper = null;
-
-    private static String TEST_DOMAIN = "testDomain";
-    private static String SECURITY_RESOURCE_TYPE = "Security";
-    private static String SECURITY_RESOURCE_KEY = "subsystem=security";
-    private static String SECURITY_DOMAIN_RESOURCE_KEY = "security-domain";
-    private static String PROFILE = "profile=full-ha";
-    private static String SECURITY_DOMAIN_RESOURCE_TYPE = "Security Domain";
-    private static String AUTH_CLASSIC_RESOURCE_TYPE = "Authentication (Classic)";
-    private static String AUTH_CLASSIC_RESOURCE_KEY = "authentication=classic";
-
-    private static Resource securityResource = null;
-
-    protected static String DC_HOST = System.getProperty("jboss.domain.bindAddress");
-    protected static int DC_HTTP_PORT = Integer.valueOf(System.getProperty("jboss.domain.httpManagementPort"));
-    protected static String DC_USER = AbstractJBossAS7PluginTest.MANAGEMENT_USERNAME;
-    protected static String DC_PASS = AbstractJBossAS7PluginTest.MANAGEMENT_PASSWORD;
-
-    ASConnection getASConnection() {
-        ASConnection connection = new ASConnection(DC_HOST, DC_HTTP_PORT, DC_USER, DC_PASS);
-        return connection;
-    }
-
-    public static final ResourceType RESOURCE_TYPE = new ResourceType(SECURITY_RESOURCE_TYPE, PLUGIN_NAME,
-        ResourceCategory.SERVICE, null);
-    private static final String RESOURCE_KEY = SECURITY_RESOURCE_KEY;
-    private static Resource testSecurityDomain = null;
-    private String testSecurityDomainKey = null;
-    private ConfigurationManager testConfigurationManager = null;
-
-    //Define some shared and reusable content
-    static HashMap<String, String> jsonMap = new HashMap<String, String>();
-    static {
-        jsonMap
-            .put(
-                "login-modules",
-                "[{\"flag\":\"required\", \"code\":\"Ldap\", \"module-options\":{\"bindDn\":\"uid=ldapSecureUser,ou=People,dc=redat,dc=com\", \"bindPw\":\"test126\", \"allowEmptyPasswords\":\"true\"}}]");
-        jsonMap
-            .put(
-                "policy-modules",
-                "[{\"flag\":\"requisite\", \"code\":\"LdapExtended\", \"module-options\":{\"policy\":\"module\", \"policy1\":\"module1\"}}]");
-        jsonMap
-            .put("mapping-modules",
-                "[{\"code\":\"Test\", \"type\":\"attribute\", \"module-options\":{\"mapping\":\"module\", \"mapping1\":\"module1\"}}]");
-        jsonMap.put("provider-modules",
-            "[{\"code\":\"Providers\", \"module-options\":{\"provider\":\"module\", \"provider1\":\"module1\"}}]");
-        jsonMap
-            .put("acl-modules",
-                "[{\"flag\":\"sufficient\", \"code\":\"ACL\", \"module-options\":{\"acl\":\"module\", \"acl1\":\"module1\"}}]");
-        jsonMap
-            .put("trust-modules",
-                "[{\"flag\":\"optional\", \"code\":\"TRUST\", \"module-options\":{\"trust\":\"module\", \"trust1\":\"module1\"}}]");
-    }
-
-    /* This first discovery is only so that we can leverage existing code to install the management user needed
-     * in next test.
-     */
-    @Test(priority = 10, groups = "discovery")
-    @RunDiscovery(discoverServices = true, discoverServers = true)
-    public void firstDiscovery() throws Exception {
-        Resource platform = this.pluginContainer.getInventoryManager().getPlatform();
-        assertNotNull(platform);
-        assertEquals(platform.getInventoryStatus(), InventoryStatus.COMMITTED);
-
-        //now install mgmt users.
-        System.out.println("------ * Duplicating discovery for SecurityModule testing....");
-        installManagementUsers();
-    }
-
-    /** This method mass loads all the supported Module Option Types(Excluding authentication=jaspi, cannot co-exist with 
-     * authentication=classic) into a single SecurityDomain.  This is done as
-     * -i)creating all of the related hierarchy of types needed to exercise N Module Options Types and their associated 
-     *     Module Options instances would take too long to setup(N creates would signal N discovery runs before test could complete).
-     * -ii)setting the priority of this method lower than the discovery method means that we'll get all the same types in much 
-     *     less time.
-     *     
-     * @throws Exception
-     */
-    @Test(priority = 11)
-    public void loadStandardModuleOptionTypes() throws Exception {
-        mapper = new ObjectMapper();
-        mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
-
-        //Adjust discovery depth to support deeper hierarchy depth of Module Option elements
-        setMaxDiscoveryDepthOverride(12);
-
-        //create new Security Domain
-        Address destination = new Address(PROFILE);
-        destination.addSegment(SECURITY_RESOURCE_KEY);
-        String securityDomainId = TEST_DOMAIN + "2";
-        destination.addSegment(SECURITY_DOMAIN_RESOURCE_KEY + "=" + securityDomainId);
-
-        ASConnection connection = getASConnection();
-        Result result = new Result();
-        Operation op = null;
-        //delete old one if present to setup clean slate
-        op = new Operation("remove", destination);
-        result = connection.execute(op);
-
-        //build/rebuild hierarchy
-        op = new Operation("add", destination);
-        result = connection.execute(op);
-        assert result.getOutcome().equals("success") : "Add of Security Domain has failed: "
-            + result.getFailureDescription();
-
-        //Ex. profile=standalone-ha,subsystem=security,security-domain
-        String addressPrefix = PROFILE + "," + SECURITY_RESOURCE_KEY + "," + SECURITY_DOMAIN_RESOURCE_KEY;
-
-        //loop over standard types and add base details for all of them to security domain
-        String address = "";
-        for (String attribute : jsonMap.keySet()) {
-            if (attribute.equals("policy-modules")) {
-                address = addressPrefix + "=" + securityDomainId + ",authorization=classic";
-            } else if (attribute.equals("acl-modules")) {
-                address = addressPrefix + "=" + securityDomainId + ",acl=classic";
-            } else if (attribute.equals("mapping-modules")) {
-                address = addressPrefix + "=" + securityDomainId + ",mapping=classic";
-            } else if (attribute.equals("trust-modules")) {
-                address = addressPrefix + "=" + securityDomainId + ",identity-trust=classic";
-            } else if (attribute.equals("provider-modules")) {
-                address = addressPrefix + "=" + securityDomainId + ",audit=classic";
-            } else if (attribute.equals("login-modules")) {
-                address = addressPrefix + "=" + securityDomainId + ",authentication=classic";
-            } else {
-                assert false : "An unknown attribute '" + attribute
-                    + "' was found. Is there a new type to be supported?";
-            }
-            //build the operation to add the component
-            ////Load json map into ModuleOptionType
-            List<Value> moduleTypeValue = new ArrayList<Value>();
-            try {
-                // loading jsonMap contents for Ex. 'login-module'
-                JsonNode node = mapper.readTree(jsonMap.get(attribute));
-                Object obj = mapper.treeToValue(node, Object.class);
-                result.setResult(obj);
-                result.setOutcome("success");
-            } catch (JsonProcessingException e) {
-                e.printStackTrace();
-            } catch (IOException e) {
-                e.printStackTrace();
-            }
-
-            //populate the Value component complete with module Options.
-            moduleTypeValue = ModuleOptionsComponent.populateSecurityDomainModuleOptions(result,
-                ModuleOptionsComponent.loadModuleOptionType(attribute));
-            op = ModuleOptionsComponent.createAddModuleOptionTypeOperation(new Address(address), attribute,
-                moduleTypeValue);
-            //submit the command
-            result = connection.execute(op);
-        }
-    }
-
-    /** Runs the second discovery run to load all the new types added.
-     * 
-     * @throws Exception
-     */
-    @Test(priority = 12, groups = "discovery")
-    @RunDiscovery(discoverServices = true, discoverServers = true)
-    public void secondDiscovery() throws Exception {
-        Resource platform = this.pluginContainer.getInventoryManager().getPlatform();
-        assertNotNull(platform);
-        assertEquals(platform.getInventoryStatus(), InventoryStatus.COMMITTED);
-
-        //Have thread sleep longer to discover deeper resource types.
-        //spinder 6/29/12: up this number if the resources are not being discovered.
-        Thread.sleep(180 * 1000L); // delay so that PC gets a chance to scan for resources
-    }
-
-    /** This test method exercises a number of things:
-     *  - that the security-domain children loaded have been created successfully
-     *  - that all of the supported Module Option Type children(excluding 'authentication=jaspi') have been 
-     *    discovered as AS7 types successfully.
-     *  - that the correct child attribute was specified for each type //Ex. acl=classic -> acl-modules
-     *  - 
-     * 
-     * @throws Exception
-     */
-    @Test(priority = 13)
-    public void testDiscoveredSecurityNodes() throws Exception {
-        //lazy-load configurationManager
-        if (testConfigurationManager == null) {
-            testConfigurationManager = this.pluginContainer.getConfigurationManager();
-            testConfigurationManager = pluginContainer.getConfigurationManager();
-            testConfigurationManager.initialize();
-            Thread.sleep(20 * 1000L);
-        }
-        //iterate through list of nodes and make sure they've all been discovered
-        ////Ex. profile=full-ha,subsystem=security,security-domain=testDomain2,acl=classic
-        String attribute = null;
-        for (String jsonKey : jsonMap.keySet()) {
-            //Ex. policy-modules
-            attribute = jsonKey;
-            //spinder 6/26/12: Temporarily disable until figure out why NPE happens only for this type?
-            if (attribute.equals(ModuleOptionsComponent.ModuleOptionType.Authentication.getAttribute())) {
-                break;//
-            }
-            //Ex. name=acl-modules
-            //check the configuration for the Module Option Type Ex. 'Acl (Profile)' Resource. Should be able to verify components
-            Resource moduleOptionsTypeResource = getModuleOptionTypeResource(attribute);
-            //assert non-zero id returned
-            assert moduleOptionsTypeResource.getId() > 0 : "The resource was not properly initialized. Expected id >0 but got:"
-                + moduleOptionsTypeResource.getId();
-
-            //Now request the resource complete with resource config
-            Configuration loadedConfiguration = testConfigurationManager
-                .loadResourceConfiguration(moduleOptionsTypeResource.getId());
-            String code = null;
-            String type = null;
-            String flag = null;
-            //populate the associated attributes if it's supported.
-            for (String key : loadedConfiguration.getAllProperties().keySet()) {
-                Property property = loadedConfiguration.getAllProperties().get(key);
-                if (key.equals("code")) {
-                    code = ((PropertySimple) property).getStringValue();
-                } else if (key.equals("flag")) {
-                    flag = ((PropertySimple) property).getStringValue();
-                } else {//Ex. type.
-                    type = ((PropertySimple) property).getStringValue();
-                }
-            }
-
-            //retrieve module options as well.
-            String jsonContent = jsonMap.get(attribute);
-            Result result = new Result();
-            try {
-                // loading jsonMap contents for Ex. 'login-module'
-                JsonNode node = mapper.readTree(jsonContent);
-                Object obj = mapper.treeToValue(node, Object.class);
-                result.setResult(obj);
-                result.setOutcome("success");
-            } catch (JsonProcessingException e) {
-                e.printStackTrace();
-                assert false;
-            } catch (IOException e) {
-                e.printStackTrace();
-                assert false;
-            }
-
-            //populate the Value component complete with module Options.
-            List<Value> moduleTypeValue = ModuleOptionsComponent.populateSecurityDomainModuleOptions(result,
-                ModuleOptionsComponent.loadModuleOptionType(attribute));
-            Value moduleOptionType = moduleTypeValue.get(0);
-            //Ex. retrieve the acl-modules component and assert values.
-            //always test 'code'
-            assert moduleOptionType.getCode().equals(code) : "Module Option 'code' value is not correct. Expected '"
-                + code + "' but was '" + moduleOptionType.getCode() + "'";
-            if (attribute.equals(ModuleOptionsComponent.ModuleOptionType.Mapping.getAttribute())) {
-                assert moduleOptionType.getType().equals(type) : "Mapping Module 'type' value is not correct. Expected '"
-                    + type + "' but was '" + moduleOptionType.getType() + "'";
-            } else if (!attribute.equals(ModuleOptionsComponent.ModuleOptionType.Audit.getAttribute())) {//Audit has no second parameter
-                assert moduleOptionType.getFlag().equals(flag) : "Provider Module 'flag' value is not correct. Expected '"
-                    + flag + "' but was '" + moduleOptionType.getFlag() + "'";
-            }
-
-            //Retrieve Module Options and test
-            //Ex. Module Options  for (Acl Modules - Profile)
-            Resource moduleOptionsResource = getModuleOptionsResource(moduleOptionsTypeResource, attribute);
-            //assert non-zero id returned
-            assert moduleOptionsResource.getId() > 0 : "The resource was not properly initialized. Expected id > 0 but got:"
-                + moduleOptionsResource.getId();
-            //fetch configuration for module options
-            //Now request the resource complete with resource config
-            Configuration loadedOptionsConfiguration = testConfigurationManager
-                .loadResourceConfiguration(moduleOptionsResource.getId());
-            for (String key : loadedOptionsConfiguration.getAllProperties().keySet()) {
-                //retrieve the open map of Module Options 
-                PropertyMap map = ((PropertyMap) loadedOptionsConfiguration.getAllProperties().get(key));
-                LinkedHashMap<String, Object> options = moduleOptionType.getOptions();
-                for (String optionKey : map.getMap().keySet()) {
-                    PropertySimple property = (PropertySimple) map.getMap().get(optionKey);
-                    //test the key
-                    assert options.containsKey(optionKey) : "Unable to find expected option key '" + optionKey
-                        + "'. Check hierarchy.";
-                    //now the value.
-                    String value = String.valueOf(options.get(optionKey));
-                    assert value.equals(property.getStringValue()) : "Unable to find expected Module Option mapping.  Key '"
-                        + optionKey
-                        + "' did not map to expected value '"
-                        + value
-                        + "' but was '"
-                        + property.getStringValue() + "'.";
-                }
-            }
-        }
-    }
-
-    @Test(priority = 14)
-    public void testCreateSecurityDomain() throws Exception {
-        //get the root security resource
-        securityResource = getResource();
-
-        //plugin config
-        Configuration createPlugConfig = new Configuration();
-        createPlugConfig.put(new PropertySimple("path", SECURITY_DOMAIN_RESOURCE_KEY += "=" + TEST_DOMAIN));
-
-        //resource config
-        Configuration createResConfig = new Configuration();
-        createResConfig.put(new PropertySimple("name", TEST_DOMAIN));
-
-        CreateResourceRequest request = new CreateResourceRequest();
-        request.setParentResourceId(securityResource.getId());
-        request.setPluginConfiguration(createPlugConfig);
-        request.setPluginName(PLUGIN_NAME);
-        request.setResourceConfiguration(createResConfig);
-        request.setResourceName(TEST_DOMAIN);
-        request.setResourceTypeName(SECURITY_DOMAIN_RESOURCE_TYPE);
-
-        CreateResourceResponse response = pluginContainer.getResourceFactoryManager().executeCreateResourceImmediately(
-            request);
-
-        assert response.getStatus() == CreateResourceStatus.SUCCESS : "The Security Domain creation failed with an error mesasge: "
-            + response.getErrorMessage();
-    }
-
-    @Test(priority = 15)
-    public void testAuthenticationClassic() throws Exception {
-        //get the root security resource
-        securityResource = getResource();
-
-        //find TEST_DOMAIN 'security-domain'
-        Resource securityDomain = null;
-        Set<Resource> childResources = securityResource.getChildResources();
-        for (Resource r : childResources) {
-            if (r.getName().indexOf(TEST_DOMAIN) > -1) {
-                securityDomain = r;
-            }
-        }
-
-        //plugin config
-        Configuration createPlugConfig = new Configuration();
-        createPlugConfig.put(new PropertySimple("path", AUTH_CLASSIC_RESOURCE_KEY));
-
-        //resource config
-        Configuration createResConfig = new Configuration();
-        createResConfig.put(new PropertySimple("code", "Ldap"));
-        createResConfig.put(new PropertySimple("flag", "requisite"));
-
-        CreateResourceRequest request = new CreateResourceRequest();
-        request.setParentResourceId(securityDomain.getId());
-        request.setPluginConfiguration(createPlugConfig);
-        request.setPluginName(PLUGIN_NAME);
-        request.setResourceConfiguration(createResConfig);
-        request.setResourceName("Test - notUsed.");
-
-        request.setResourceTypeName(AUTH_CLASSIC_RESOURCE_TYPE);
-
-        CreateResourceResponse response = pluginContainer.getResourceFactoryManager().executeCreateResourceImmediately(
-            request);
-
-        assert response.getStatus() == CreateResourceStatus.SUCCESS : "The 'Authentication (Classic)' node creation failed with an error mesasge: "
-            + response.getErrorMessage();
-    }
-
-    @Test(priority = 16)
-    public void testDeleteSecurityDomain() throws Exception {
-        //get the root security resource
-        securityResource = getResource();
-        Resource found = null;
-        Set<Resource> childResources = securityResource.getChildResources();
-        for (Resource r : childResources) {
-            if (r.getName().indexOf(TEST_DOMAIN) > -1) {
-                found = r;
-            }
-        }
-
-        //plugin config
-        Configuration deletePlugConfig = new Configuration();
-        deletePlugConfig.put(new PropertySimple("path", SECURITY_DOMAIN_RESOURCE_KEY += "=" + TEST_DOMAIN));
-
-        //resource config
-        Configuration deleteResConfig = new Configuration();
-        deleteResConfig.put(new PropertySimple("name", TEST_DOMAIN));
-
-        DeleteResourceRequest request = new DeleteResourceRequest();
-        if (found != null) {
-            request.setResourceId(found.getId());
-        }
-        DeleteResourceResponse response = pluginContainer.getResourceFactoryManager().executeDeleteResourceImmediately(
-            request);
-
-        assert response.getStatus() == DeleteResourceStatus.SUCCESS : "The Security Domain deletion failed with an error mesasge: "
-            + response.getErrorMessage();
-    }
-
-    //    public static void main(String[] args) {
-    //        SecurityModuleOptionsTest setup = new SecurityModuleOptionsTest();
-    //        try {
-    //            setup.loadStandardModuleOptionTypes();
-    //        } catch (Exception e) {
-    //            e.printStackTrace();
-    //        }
-    //    }
-
-    private Resource getResource() {
-
-        InventoryManager im = pluginContainer.getInventoryManager();
-        Resource platform = im.getPlatform();
-        Resource server = getResourceByTypeAndKey(platform, StandaloneServerComponentTest.RESOURCE_TYPE,
-            StandaloneServerComponentTest.RESOURCE_KEY);
-        Resource bindings = getResourceByTypeAndKey(server, RESOURCE_TYPE, RESOURCE_KEY);
-        return bindings;
-    }
-
-    /** Automates hierarchy creation for Module Option type resources and their parents
-     * 
-     * @param optionAttributeType
-     * @return
-     */
-    private Resource getModuleOptionTypeResource(String optionAttributeType) {
-        Resource moduleOptionResource = null;
-        String securityDomainId = SECURITY_DOMAIN_RESOURCE_KEY + "=" + TEST_DOMAIN + "2";
-        if (testSecurityDomain == null) {
-            InventoryManager im = pluginContainer.getInventoryManager();
-            Resource platform = im.getPlatform();
-            //host controller
-            ResourceType hostControllerType = new ResourceType("JBossAS7 Host Controller", PLUGIN_NAME,
-                ResourceCategory.SERVER, null);
-            Resource hostController = getResourceByTypeAndKey(platform, hostControllerType,
-                "/tmp/jboss-as-6.0.0.GA/domain");
-            //profile=full-ha
-            ResourceType profileType = new ResourceType("Profile", PLUGIN_NAME, ResourceCategory.SERVICE, null);
-            String key = PROFILE;
-            Resource profile = getResourceByTypeAndKey(hostController, profileType, key);
-
-            //Security (Profile)
-            ResourceType securityType = new ResourceType("Security (Profile)", PLUGIN_NAME, ResourceCategory.SERVICE,
-                null);
-            key += "," + SECURITY_RESOURCE_KEY;
-            Resource security = getResourceByTypeAndKey(profile, securityType, key);
-
-            //Security Domain (Profile)
-            ResourceType domainType = new ResourceType("Security Domain (Profile)", PLUGIN_NAME,
-                ResourceCategory.SERVICE, null);
-            key += "," + securityDomainId;
-            testSecurityDomainKey = key;
-            testSecurityDomain = getResourceByTypeAndKey(security, domainType, key);
-        }
-
-        //acl=classic
-        String descriptorName = "";
-        String moduleAttribute = "";
-        //acl
-        if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.Acl.getAttribute())) {
-            descriptorName = "ACL (Profile)";
-            moduleAttribute = "acl=classic";
-        } else if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.Audit.getAttribute())) {
-            descriptorName = "Audit (Profile)";
-            moduleAttribute = "audit=classic";
-        } else if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.Authentication.getAttribute())) {
-            descriptorName = "Authentication (Classic - Profile)";
-            moduleAttribute = "authentication=classic";
-        } else if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.Authorization.getAttribute())) {
-            descriptorName = "Authorization (Profile)";
-            moduleAttribute = "authorization=classic";
-        } else if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.IdentityTrust.getAttribute())) {
-            descriptorName = "Identity Trust (Profile)";
-            moduleAttribute = "identity-trust=classic";
-        } else if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.Mapping.getAttribute())) {
-            descriptorName = "Mapping (Profile)";
-            moduleAttribute = "mapping=classic";
-        }
-        //Build the right Module Option Type. Ex. ACL (Profile), etc.
-        ResourceType moduleOptionType = new ResourceType(descriptorName, PLUGIN_NAME, ResourceCategory.SERVICE, null);
-        ConfigurationDefinition cdef = new ConfigurationDefinition(descriptorName, null);
-        moduleOptionType.setResourceConfigurationDefinition(cdef);
-        //Ex. profile=full-ha,subsystem=security,security-domain=testDomain2,identity-trust=classic
-        String moduleOptionTypeKey = testSecurityDomainKey += "," + moduleAttribute;
-
-        if (!testSecurityDomainKey.endsWith(securityDomainId)) {
-            moduleOptionTypeKey = testSecurityDomainKey.substring(0, testSecurityDomainKey.indexOf(securityDomainId)
-                + securityDomainId.length())
-                + "," + moduleAttribute;
-        }
-
-        moduleOptionResource = getResourceByTypeAndKey(testSecurityDomain, moduleOptionType, moduleOptionTypeKey);
-
-        return moduleOptionResource;
-    }
-
-    /** Automates hierarchy creation for Module Option type resources and their parents
-     * 
-     * @param optionAttributeType
-     * @return
-     */
-    private Resource getModuleOptionsResource(Resource parent, String optionAttributeType) {
-        Resource moduleOptionsResource = null;
-        String descriptorName = "";
-        String moduleAttribute = "";
-        String moduleOptionsDescriptor = "";
-        if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.Acl.getAttribute())) {
-            //            descriptorName = "ACL Modules (Profile)";
-            descriptorName = "Acl Modules (Profile)";
-            moduleAttribute = "acl=classic";
-            moduleOptionsDescriptor = "Module Options (Acl - Profile)";
-        } else if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.Audit.getAttribute())) {
-            descriptorName = "Provider Modules (Profile)";
-            moduleAttribute = "audit=classic";
-            moduleOptionsDescriptor = "Module Options (Provider Modules - Profile)";
-        } else if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.Authentication.getAttribute())) {
-            descriptorName = "Login Modules (Classic - Profile)";
-            moduleAttribute = "authentication=classic";
-            moduleOptionsDescriptor = "Module Options (Classic - Profile)";
-        } else if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.Authorization.getAttribute())) {
-            descriptorName = "Authorization Modules (Profile)";
-            moduleAttribute = "authorization=classic";
-            moduleOptionsDescriptor = "Module Options (Authorization - Profile)";
-        } else if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.IdentityTrust.getAttribute())) {
-            descriptorName = "Identity Trust Modules (Profile)";
-            moduleAttribute = "identity-trust=classic";
-            moduleOptionsDescriptor = "Module Options (Identity Trust - Profile)";
-        } else if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.Mapping.getAttribute())) {
-            descriptorName = "Mapping Modules (Profile)";
-            moduleAttribute = "mapping=classic";
-            moduleOptionsDescriptor = "Module Options (Mapping - Profile)";
-        }
-        //Build the right Module Option Type. Ex. ACL Modules (Profile), etc.
-        ResourceType modulesType = new ResourceType(descriptorName, PLUGIN_NAME, ResourceCategory.SERVICE, null);
-        //Ex. profile=full-ha,subsystem=security,security-domain=testDomain2,acl=classic,acl-modules:0
-        String sharedRoot = "profile=full-ha,subsystem=security,security-domain=testDomain2";
-        String moduleOptionTypeKey = sharedRoot += "," + moduleAttribute + ","
-            + optionAttributeType + ":0";
-        //Ex. Module Options Type children [ACL Modules (Profile),etc.]
-        Resource modulesInstance = getResourceByTypeAndKey(parent, modulesType, moduleOptionTypeKey);
-
-        //Module Options
-        ResourceType moduleOptionsType = new ResourceType(moduleOptionsDescriptor, PLUGIN_NAME,
-            ResourceCategory.SERVICE, null);
-        moduleOptionsResource = getResourceByTypeAndKey(modulesInstance, moduleOptionsType, moduleOptionTypeKey
-            + ",module-options");
-
-        return moduleOptionsResource;
-    }
-
-    private Resource getResource(Resource parentResource, String pluginDescriptorTypeName, String resourceKey) {
-        Resource resource = null;
-        if (((parentResource != null) & (pluginDescriptorTypeName != null) & (resourceKey != null))
-            & (((!pluginDescriptorTypeName.isEmpty()) & (!resourceKey.isEmpty())))) {
-            ResourceType resourceType = buildResourceType(pluginDescriptorTypeName);
-            resource = getResourceByTypeAndKey(parentResource, resourceType, resourceKey);
-        }
-        return resource;
-    }
-
-    private ResourceType buildResourceType(String pluginTypeName) {
-        ResourceType created = null;
-        if ((pluginTypeName != null) && (!pluginTypeName.isEmpty())) {
-            created = new ResourceType(pluginTypeName, PLUGIN_NAME, ResourceCategory.SERVICE, null);
-        }
-        return created;
-    }
-
-    /** For each operation 
-     *   - will write verbose json and operation details to system.out if verboseOutput = true;
-     *   - will execute the operation against running server if execute = true.
-     * 
-     * @param op
-     * @param execute
-     * @param verboseOutput
-     * @return
-     */
-    public static Result exerciseOperation(Operation op, boolean execute, boolean verboseOutput) {
-        //display operation as AS7 plugin will build it
-        if (verboseOutput) {
-            System.out.println("\tOperation is:" + op);
-        }
-
-        String jsonToSend = "";
-        try {
-            jsonToSend = mapper.defaultPrettyPrintingWriter().writeValueAsString(op);
-        } catch (JsonGenerationException e) {
-            e.printStackTrace();
-        } catch (JsonMappingException e) {
-            e.printStackTrace();
-        } catch (IOException e) {
-            e.printStackTrace();
-        }
-        //As generated by jackson mapper
-        if (verboseOutput) {
-            System.out.println("@@@@ OUTBOUND JSON#\n" + jsonToSend + "#");
-        }
-
-        //Execute the operation
-        Result result = new Result();
-        if (execute) {
-            result = con.execute(op);
-        } else {
-            if (verboseOutput) {
-                System.out.println("**** NOTE: Execution disabled . NOT exercising write-attribute operation. **** ");
-            }
-        }
-        if (verboseOutput) {
-            //result wrapper details 
-            System.out.println("\tResult:" + result);
-            //detailed results
-            System.out.println("\tValue:" + result.getResult());
-            System.out.println("-----------------------------------------------------\n");
-        }
-        return result;
-    }
-}
diff --git a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/TemplatedResourcesTest.java b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/TemplatedResourcesTest.java
index 5d64977..fe05def 100644
--- a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/TemplatedResourcesTest.java
+++ b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/TemplatedResourcesTest.java
@@ -73,7 +73,7 @@ public class TemplatedResourcesTest extends AbstractJBossAS7PluginTest {
             StandaloneServerComponentTest.RESOURCE_KEY);
         inventoryManager.activateResource(server, platformContainer, false);
 
-        Thread.sleep(20 * 1000L);
+        Thread.sleep(30 * 1000L);
 
         for (ResourceData resourceData : testResourceData) {
             ResourceType resourceType = new ResourceType(resourceData.resourceTypeName, PLUGIN_NAME,
@@ -100,6 +100,7 @@ public class TemplatedResourcesTest extends AbstractJBossAS7PluginTest {
             for (Resource resourceUnderTest : foundResources) {
                 log.info(foundResources);
 
+                assert resourceUnderTest.getId() > 0 : "Resource not properly initialized. Id = 0. Try extending sleep after discovery.";
                 Configuration resourceUnderTestConfig = configurationManager
                     .loadResourceConfiguration(resourceUnderTest.getId());
 


commit 89fa0d623ae733febad51a61774782447bb07c41
Author: Simeon Pinder <spinder at redhat.com>
Date:   Fri Jun 29 09:30:20 2012 -0400

     Fix problem with test Resource discovery and cleaned up names and properties.

diff --git a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/SecurityModuleOptionsTest.java b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/SecurityModuleOptionsTest.java
index e3f88af..452fdfb 100644
--- a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/SecurityModuleOptionsTest.java
+++ b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/SecurityModuleOptionsTest.java
@@ -24,12 +24,15 @@ import static org.testng.Assert.assertNotNull;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Set;
 
+import org.codehaus.jackson.JsonGenerationException;
 import org.codehaus.jackson.JsonNode;
 import org.codehaus.jackson.JsonProcessingException;
 import org.codehaus.jackson.map.DeserializationConfig;
+import org.codehaus.jackson.map.JsonMappingException;
 import org.codehaus.jackson.map.ObjectMapper;
 import org.testng.annotations.Test;
 
@@ -39,6 +42,7 @@ import org.rhq.core.clientapi.agent.inventory.DeleteResourceRequest;
 import org.rhq.core.clientapi.agent.inventory.DeleteResourceResponse;
 import org.rhq.core.domain.configuration.Configuration;
 import org.rhq.core.domain.configuration.Property;
+import org.rhq.core.domain.configuration.PropertyMap;
 import org.rhq.core.domain.configuration.PropertySimple;
 import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
 import org.rhq.core.domain.resource.CreateResourceStatus;
@@ -67,27 +71,24 @@ import org.rhq.test.arquillian.RunDiscovery;
 @Test(groups = { "integration", "pc", "standalone" }, singleThreaded = true)
 public class SecurityModuleOptionsTest extends AbstractJBossAS7PluginTest {
 
-    private static String user = "rhqadmin";
-    private static String pass = "as7";
-    private static String host = "localhost";
     private static ASConnection con = null;
     private static ObjectMapper mapper = null;
-    private ModuleOptionsComponent moc = null;
 
     private static String TEST_DOMAIN = "testDomain";
-    private static Resource securityResource = null;
     private static String SECURITY_RESOURCE_TYPE = "Security";
     private static String SECURITY_RESOURCE_KEY = "subsystem=security";
-    private static String SECURITY_DOMAIN_RESOURCE_TYPE = "Security Domain";
     private static String SECURITY_DOMAIN_RESOURCE_KEY = "security-domain";
+    private static String PROFILE = "profile=full-ha";
+    private static String SECURITY_DOMAIN_RESOURCE_TYPE = "Security Domain";
     private static String AUTH_CLASSIC_RESOURCE_TYPE = "Authentication (Classic)";
     private static String AUTH_CLASSIC_RESOURCE_KEY = "authentication=classic";
-    private static String PROFILE = "profile=full-ha";
 
-    protected static final String DC_HOST = System.getProperty("jboss.domain.bindAddress");
-    protected static final int DC_HTTP_PORT = Integer.valueOf(System.getProperty("jboss.domain.httpManagementPort"));
-    protected static final String DC_USER = AbstractJBossAS7PluginTest.MANAGEMENT_USERNAME;
-    protected static final String DC_PASS = AbstractJBossAS7PluginTest.MANAGEMENT_PASSWORD;
+    private static Resource securityResource = null;
+
+    protected static String DC_HOST = System.getProperty("jboss.domain.bindAddress");
+    protected static int DC_HTTP_PORT = Integer.valueOf(System.getProperty("jboss.domain.httpManagementPort"));
+    protected static String DC_USER = AbstractJBossAS7PluginTest.MANAGEMENT_USERNAME;
+    protected static String DC_PASS = AbstractJBossAS7PluginTest.MANAGEMENT_PASSWORD;
 
     ASConnection getASConnection() {
         ASConnection connection = new ASConnection(DC_HOST, DC_HTTP_PORT, DC_USER, DC_PASS);
@@ -125,6 +126,21 @@ public class SecurityModuleOptionsTest extends AbstractJBossAS7PluginTest {
                 "[{\"flag\":\"optional\", \"code\":\"TRUST\", \"module-options\":{\"trust\":\"module\", \"trust1\":\"module1\"}}]");
     }
 
+    /* This first discovery is only so that we can leverage existing code to install the management user needed
+     * in next test.
+     */
+    @Test(priority = 10, groups = "discovery")
+    @RunDiscovery(discoverServices = true, discoverServers = true)
+    public void firstDiscovery() throws Exception {
+        Resource platform = this.pluginContainer.getInventoryManager().getPlatform();
+        assertNotNull(platform);
+        assertEquals(platform.getInventoryStatus(), InventoryStatus.COMMITTED);
+
+        //now install mgmt users.
+        System.out.println("------ * Duplicating discovery for SecurityModule testing....");
+        installManagementUsers();
+    }
+
     /** This method mass loads all the supported Module Option Types(Excluding authentication=jaspi, cannot co-exist with 
      * authentication=classic) into a single SecurityDomain.  This is done as
      * -i)creating all of the related hierarchy of types needed to exercise N Module Options Types and their associated 
@@ -134,13 +150,13 @@ public class SecurityModuleOptionsTest extends AbstractJBossAS7PluginTest {
      *     
      * @throws Exception
      */
-    @Test(priority = 10)
-    public void testLoadStandardModuleOptionTypes() throws Exception {
+    @Test(priority = 11)
+    public void loadStandardModuleOptionTypes() throws Exception {
         mapper = new ObjectMapper();
         mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
 
         //Adjust discovery depth to support deeper hierarchy depth of Module Option elements
-        setMaxDiscoveryDepthOverride(10);
+        setMaxDiscoveryDepthOverride(12);
 
         //create new Security Domain
         Address destination = new Address(PROFILE);
@@ -150,13 +166,16 @@ public class SecurityModuleOptionsTest extends AbstractJBossAS7PluginTest {
 
         ASConnection connection = getASConnection();
         Result result = new Result();
+        Operation op = null;
         //delete old one if present to setup clean slate
-        Operation op = new Operation("remove", destination);
+        op = new Operation("remove", destination);
         result = connection.execute(op);
 
         //build/rebuild hierarchy
         op = new Operation("add", destination);
         result = connection.execute(op);
+        assert result.getOutcome().equals("success") : "Add of Security Domain has failed: "
+            + result.getFailureDescription();
 
         //Ex. profile=standalone-ha,subsystem=security,security-domain
         String addressPrefix = PROFILE + "," + SECURITY_RESOURCE_KEY + "," + SECURITY_DOMAIN_RESOURCE_KEY;
@@ -205,15 +224,20 @@ public class SecurityModuleOptionsTest extends AbstractJBossAS7PluginTest {
         }
     }
 
-    @Test(priority = 11, groups = "discovery")
+    /** Runs the second discovery run to load all the new types added.
+     * 
+     * @throws Exception
+     */
+    @Test(priority = 12, groups = "discovery")
     @RunDiscovery(discoverServices = true, discoverServers = true)
-    public void initialDiscovery() throws Exception {
+    public void secondDiscovery() throws Exception {
         Resource platform = this.pluginContainer.getInventoryManager().getPlatform();
         assertNotNull(platform);
         assertEquals(platform.getInventoryStatus(), InventoryStatus.COMMITTED);
 
-        //Have thread sleep longer to discover deeper resource types. 
-        Thread.sleep(120 * 1000L); // delay so that PC gets a chance to scan for resources
+        //Have thread sleep longer to discover deeper resource types.
+        //spinder 6/29/12: up this number if the resources are not being discovered.
+        Thread.sleep(180 * 1000L); // delay so that PC gets a chance to scan for resources
     }
 
     /** This test method exercises a number of things:
@@ -225,7 +249,7 @@ public class SecurityModuleOptionsTest extends AbstractJBossAS7PluginTest {
      * 
      * @throws Exception
      */
-    @Test(priority = 12)
+    @Test(priority = 13)
     public void testDiscoveredSecurityNodes() throws Exception {
         //lazy-load configurationManager
         if (testConfigurationManager == null) {
@@ -246,13 +270,14 @@ public class SecurityModuleOptionsTest extends AbstractJBossAS7PluginTest {
             }
             //Ex. name=acl-modules
             //check the configuration for the Module Option Type Ex. 'Acl (Profile)' Resource. Should be able to verify components
-            Resource aclResource = getModuleOptionResourceResource(attribute);
+            Resource moduleOptionsTypeResource = getModuleOptionTypeResource(attribute);
             //assert non-zero id returned
-            assert aclResource.getId() > 0 : "The resource was not properly initialized. Expected id >0 but got:"
-                + aclResource.getId();
+            assert moduleOptionsTypeResource.getId() > 0 : "The resource was not properly initialized. Expected id >0 but got:"
+                + moduleOptionsTypeResource.getId();
 
             //Now request the resource complete with resource config
-            Configuration loadedConfiguration = testConfigurationManager.loadResourceConfiguration(aclResource.getId());
+            Configuration loadedConfiguration = testConfigurationManager
+                .loadResourceConfiguration(moduleOptionsTypeResource.getId());
             String code = null;
             String type = null;
             String flag = null;
@@ -300,11 +325,40 @@ public class SecurityModuleOptionsTest extends AbstractJBossAS7PluginTest {
                 assert moduleOptionType.getFlag().equals(flag) : "Provider Module 'flag' value is not correct. Expected '"
                     + flag + "' but was '" + moduleOptionType.getFlag() + "'";
             }
+
+            //Retrieve Module Options and test
+            //Ex. Module Options  for (Acl Modules - Profile)
+            Resource moduleOptionsResource = getModuleOptionsResource(moduleOptionsTypeResource, attribute);
+            //assert non-zero id returned
+            assert moduleOptionsResource.getId() > 0 : "The resource was not properly initialized. Expected id > 0 but got:"
+                + moduleOptionsResource.getId();
+            //fetch configuration for module options
+            //Now request the resource complete with resource config
+            Configuration loadedOptionsConfiguration = testConfigurationManager
+                .loadResourceConfiguration(moduleOptionsResource.getId());
+            for (String key : loadedOptionsConfiguration.getAllProperties().keySet()) {
+                //retrieve the open map of Module Options 
+                PropertyMap map = ((PropertyMap) loadedOptionsConfiguration.getAllProperties().get(key));
+                LinkedHashMap<String, Object> options = moduleOptionType.getOptions();
+                for (String optionKey : map.getMap().keySet()) {
+                    PropertySimple property = (PropertySimple) map.getMap().get(optionKey);
+                    //test the key
+                    assert options.containsKey(optionKey) : "Unable to find expected option key '" + optionKey
+                        + "'. Check hierarchy.";
+                    //now the value.
+                    String value = String.valueOf(options.get(optionKey));
+                    assert value.equals(property.getStringValue()) : "Unable to find expected Module Option mapping.  Key '"
+                        + optionKey
+                        + "' did not map to expected value '"
+                        + value
+                        + "' but was '"
+                        + property.getStringValue() + "'.";
+                }
+            }
         }
-        //TODO spinder 6-26-12: retrieve the Module Options and test them too.
     }
 
-    @Test(priority = 13)
+    @Test(priority = 14)
     public void testCreateSecurityDomain() throws Exception {
         //get the root security resource
         securityResource = getResource();
@@ -332,7 +386,7 @@ public class SecurityModuleOptionsTest extends AbstractJBossAS7PluginTest {
             + response.getErrorMessage();
     }
 
-    @Test(priority = 14)
+    @Test(priority = 15)
     public void testAuthenticationClassic() throws Exception {
         //get the root security resource
         securityResource = getResource();
@@ -371,7 +425,7 @@ public class SecurityModuleOptionsTest extends AbstractJBossAS7PluginTest {
             + response.getErrorMessage();
     }
 
-    @Test(priority = 15)
+    @Test(priority = 16)
     public void testDeleteSecurityDomain() throws Exception {
         //get the root security resource
         securityResource = getResource();
@@ -405,7 +459,7 @@ public class SecurityModuleOptionsTest extends AbstractJBossAS7PluginTest {
     //    public static void main(String[] args) {
     //        SecurityModuleOptionsTest setup = new SecurityModuleOptionsTest();
     //        try {
-    //            setup.testLoadStandardModuleOptionTypes();
+    //            setup.loadStandardModuleOptionTypes();
     //        } catch (Exception e) {
     //            e.printStackTrace();
     //        }
@@ -421,12 +475,12 @@ public class SecurityModuleOptionsTest extends AbstractJBossAS7PluginTest {
         return bindings;
     }
 
-    /** Automates
+    /** Automates hierarchy creation for Module Option type resources and their parents
      * 
      * @param optionAttributeType
      * @return
      */
-    private Resource getModuleOptionResourceResource(String optionAttributeType) {
+    private Resource getModuleOptionTypeResource(String optionAttributeType) {
         Resource moduleOptionResource = null;
         String securityDomainId = SECURITY_DOMAIN_RESOURCE_KEY + "=" + TEST_DOMAIN + "2";
         if (testSecurityDomain == null) {
@@ -497,6 +551,60 @@ public class SecurityModuleOptionsTest extends AbstractJBossAS7PluginTest {
         return moduleOptionResource;
     }
 
+    /** Automates hierarchy creation for Module Option type resources and their parents
+     * 
+     * @param optionAttributeType
+     * @return
+     */
+    private Resource getModuleOptionsResource(Resource parent, String optionAttributeType) {
+        Resource moduleOptionsResource = null;
+        String descriptorName = "";
+        String moduleAttribute = "";
+        String moduleOptionsDescriptor = "";
+        if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.Acl.getAttribute())) {
+            //            descriptorName = "ACL Modules (Profile)";
+            descriptorName = "Acl Modules (Profile)";
+            moduleAttribute = "acl=classic";
+            moduleOptionsDescriptor = "Module Options (Acl - Profile)";
+        } else if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.Audit.getAttribute())) {
+            descriptorName = "Provider Modules (Profile)";
+            moduleAttribute = "audit=classic";
+            moduleOptionsDescriptor = "Module Options (Provider Modules - Profile)";
+        } else if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.Authentication.getAttribute())) {
+            descriptorName = "Login Modules (Classic - Profile)";
+            moduleAttribute = "authentication=classic";
+            moduleOptionsDescriptor = "Module Options (Classic - Profile)";
+        } else if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.Authorization.getAttribute())) {
+            descriptorName = "Authorization Modules (Profile)";
+            moduleAttribute = "authorization=classic";
+            moduleOptionsDescriptor = "Module Options (Authorization - Profile)";
+        } else if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.IdentityTrust.getAttribute())) {
+            descriptorName = "Identity Trust Modules (Profile)";
+            moduleAttribute = "identity-trust=classic";
+            moduleOptionsDescriptor = "Module Options (Identity Trust - Profile)";
+        } else if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.Mapping.getAttribute())) {
+            descriptorName = "Mapping Modules (Profile)";
+            moduleAttribute = "mapping=classic";
+            moduleOptionsDescriptor = "Module Options (Mapping - Profile)";
+        }
+        //Build the right Module Option Type. Ex. ACL Modules (Profile), etc.
+        ResourceType modulesType = new ResourceType(descriptorName, PLUGIN_NAME, ResourceCategory.SERVICE, null);
+        //Ex. profile=full-ha,subsystem=security,security-domain=testDomain2,acl=classic,acl-modules:0
+        String sharedRoot = "profile=full-ha,subsystem=security,security-domain=testDomain2";
+        String moduleOptionTypeKey = sharedRoot += "," + moduleAttribute + ","
+            + optionAttributeType + ":0";
+        //Ex. Module Options Type children [ACL Modules (Profile),etc.]
+        Resource modulesInstance = getResourceByTypeAndKey(parent, modulesType, moduleOptionTypeKey);
+
+        //Module Options
+        ResourceType moduleOptionsType = new ResourceType(moduleOptionsDescriptor, PLUGIN_NAME,
+            ResourceCategory.SERVICE, null);
+        moduleOptionsResource = getResourceByTypeAndKey(modulesInstance, moduleOptionsType, moduleOptionTypeKey
+            + ",module-options");
+
+        return moduleOptionsResource;
+    }
+
     private Resource getResource(Resource parentResource, String pluginDescriptorTypeName, String resourceKey) {
         Resource resource = null;
         if (((parentResource != null) & (pluginDescriptorTypeName != null) & (resourceKey != null))
@@ -515,288 +623,52 @@ public class SecurityModuleOptionsTest extends AbstractJBossAS7PluginTest {
         return created;
     }
 
-    //##################################################################
-    //    /**The test reads the existing property values, deserializes them and writes the same 
-    //     * contents back out to a running instance for all known ModuleOptionTypes.
-    //     * 
-    //     * @throws Exception
-    //     */
-    //    public void testPopulateModuleOptionsAndTypes() throws Exception {
-    //
-    //        //as7 node details.
-    //        String securityDomainId = "testDomain";
-    //        //TODO: spinder 6-6-12: this cannot run as a standalone itest until JIRA https://issues.jboss.org/browse/AS7-4951
-    //        //      is addressed as there is no way to automate setup of the information being tested.
-    //        String address = "subsystem=security,security-domain=" + securityDomainId + ",authentication=classic";
-    //        boolean verboseOutput = true;
-    //        boolean executeOperation = true;
-    //        for (ModuleOptionType t : ModuleOptionType.values()) {
-    //            String attribute = t.getAttribute();
-    //            if (verboseOutput) {
-    //                System.out.println("======= Running with ModuleOptionType:" + t + " attribute:" + attribute + ":");
-    //            }
-    //            if (attribute.equals("policy-modules")) {
-    //                address = "subsystem=security,security-domain=" + securityDomainId + ",authorization=classic";
-    //            } else if (attribute.equals("acl-modules")) {
-    //                address = "subsystem=security,security-domain=" + securityDomainId + ",acl=classic";
-    //            } else if (attribute.equals("mapping-modules")) {
-    //                address = "subsystem=security,security-domain=" + securityDomainId + ",mapping=classic";
-    //            } else if (attribute.equals("trust-modules")) {
-    //                address = "subsystem=security,security-domain=" + securityDomainId + ",identity-trust=classic";
-    //            } else if (attribute.equals("provider-modules")) {
-    //                address = "subsystem=security,security-domain=" + securityDomainId + ",audit=classic";
-    //            } else if (attribute.equals("login-modules")) {
-    //                address = "subsystem=security,security-domain=" + securityDomainId + ",authentication=classic";
-    //            } else {
-    //                assert false : "An unknown attribute '" + attribute
-    //                    + "' was found. Is there a new type to be supported?";
-    //            }
-    //
-    //            //test operation- read property always available.
-    //            Operation op = null;
-    //
-    //            //read the login-modules attribute
-    //            op = new ReadAttribute(new Address(address), attribute);
-    //            Result result = exerciseOperation(op, true, verboseOutput);
-    //            assert result.isSuccess() == true : "The operation '" + op + "' failed to read the resource."
-    //                + result.getFailureDescription();
-    //            //extract current results
-    //            Object rawResult = result.getResult();
-    //            assert rawResult != null : "Read of attribute'" + attribute + "' from address '" + address
-    //                + "' has returned no value. Are those values in the model?";
-    //
-    //            List<Value> list2 = new ArrayList<Value>();
-    //            //populate the Value component complete with module Options.
-    //            list2 = moc.populateSecurityDomainModuleOptions(result,
-    //                ModuleOptionsComponent.loadModuleOptionType(attribute));
-    //            if (verboseOutput) {
-    //                if (rawResult != null) {
-    //                    System.out.println("Raw Result is:" + rawResult + " and of type:" + rawResult.getClass());
-    //                } else {
-    //                    System.out.println("Read of attribute'" + attribute + "' from address '" + address
-    //                        + "' has returned no value. Are those values in the model?");
-    //                }
-    //            }
-    //            //write the login-modules attribute
-    //            op = new WriteAttribute(new Address(address));
-    //            op.addAdditionalProperty("name", attribute);//attribute to execute on
-    //            op.addAdditionalProperty("value", list2);
-    //
-    //            //Now test the operation
-    //            result = exerciseOperation(op, executeOperation, verboseOutput);
-    //            assert ((result.isSuccess() == true) || (result.getOutcome() == null)) : "The operation '" + op
-    //                + "' failed to write the resource.." + result.getFailureDescription();
-    //
-    //            //read the login-modules attribute
-    //            op = new ReadAttribute(new Address(address), attribute);
-    //            result = exerciseOperation(op, true, verboseOutput);
-    //            assert (result.isSuccess() == true) : "The operation '" + op + "' failed to read the resource."
-    //                + result.getFailureDescription();
-    //        }
-    //        if (verboseOutput) {
-    //            System.out.println("Successfully detected,read and wrote out attribute values for:");
-    //            for (ModuleOptionType type : ModuleOptionType.values()) {
-    //                System.out.println("\n" + type.ordinal() + " " + type.name());
-    //            }
-    //        }
-    //    }
-    //
-    //    /**Attempts to create a new Authentication node(authentication=classic) with a
-    //     * 'login-modules' attribute complete with 'code':'Ldap' and 'flag':'required' 
-    //     *  and some sample 'module-options' values.
-    //     *  
-    //     */
-    //    @Test(enabled = true)
-    //    public void testCreateSecurityDomainChildLoginModules() {
-    //        boolean execute = true;
-    //        boolean verboseOutput = false;
-    //        String address = "subsystem=security,security-domain=testDomain3,authentication=classic";
-    //        String attribute = ModuleOptionType.Authentication.getAttribute();
-    //
-    //        //test operation- read property always available.
-    //        Operation op = null;
-    //
-    //        //read the login-modules attribute
-    //        op = new ReadAttribute(new Address(address), attribute);
-    //        Result result = exerciseOperation(op, execute, verboseOutput);
-    //        assert result.isSuccess() == true : "The operation '" + op + "' failed to read the resource."
-    //            + result.getFailureDescription();
-    //
-    //        //extract current results
-    //        Object rawResult = result.getResult();
-    //
-    //        //#### Have to create new content for the new node.
-    //        List<Value> moduleTypeValue = new ArrayList<Value>();
-    //        try {
-    //            // loading 'login-module'
-    //            JsonNode node = mapper.readTree(jsonMap.get(attribute));
-    //            result.setResult(mapper.treeToValue(node, Object.class));
-    //        } catch (JsonProcessingException e) {
-    //            e.printStackTrace();
-    //        } catch (IOException e) {
-    //            e.printStackTrace();
-    //        }
-    //
-    //        //populate the Value component complete with module Options.
-    //        moduleTypeValue = ModuleOptionsComponent.populateSecurityDomainModuleOptions(result,
-    //            ModuleOptionsComponent.loadModuleOptionType(attribute));
-    //
-    //        //add the login-modules attribute
-    //        op = ModuleOptionsComponent
-    //            .createAddModuleOptionTypeOperation(new Address(address), attribute, moduleTypeValue);
-    //
-    //        result = exerciseOperation(op, execute, verboseOutput);
-    //        assert ((result.isSuccess() == true) || (result.getOutcome() == null)) : "The operation '" + op
-    //            + "' failed to write the resource.." + result.getFailureDescription();
-    //
-    //        //read the login-modules attribute
-    //        op = new ReadAttribute(new Address(address), attribute);
-    //        result = exerciseOperation(op, execute, verboseOutput);
-    //        assert result.isSuccess() == true : "The operation '" + op + "' failed to read the resource."
-    //            + result.getFailureDescription();
-    //
-    //        //exercise values retrieved from read
-    //        List<Value> serverResponse = ModuleOptionsComponent.populateSecurityDomainModuleOptions(result,
-    //            ModuleOptionsComponent.loadModuleOptionType(attribute));
-    //        Value serverState = serverResponse.get(0);
-    //        assert serverState.getFlag().equals("required") : "Incorrect state retrieved for 'flag'. Expected 'required'.";
-    //        assert serverState.getCode().equals("Ldap") : "Incorrect state retrieved for 'code'. Expected 'Ldap'.";
-    //        LinkedHashMap<String, Object> options = serverState.getOptions();
-    //        assert options.size() == 3 : "Invalid number of module options returned. Expected 3.";
-    //        int found = 0;
-    //        for (String key : options.keySet()) {
-    //            if (key.equals("bindPw")) {
-    //                assert "test126".equals(options.get(key)) : "Module option value not correct for key '" + key + "'.";
-    //                found++;
-    //            } else if (key.equals("bindDn")) {
-    //                assert "uid=ldapSecureUser,ou=People,dc=redat,dc=com".equals(options.get(key)) : "Module option value not correct for key '"
-    //                    + key + "'.";
-    //                found++;
-    //            } else if (key.equals("allowEmptyPasswords")) {
-    //                assert "true".equals(options.get(key)) : "Module option value not correct for key '" + key + "'.";
-    //                found++;
-    //            }
-    //        }
-    //        assert found == 3 : "All module options were not loaded.";
-    //
-    //        //remove the original node to reset for next run.
-    //        op = new Remove(new Address(address));
-    //        result = exerciseOperation(op, execute, verboseOutput);
-    //        assert result.isSuccess() == true : "The operation '" + op + "' failed to remove the resource."
-    //            + result.getFailureDescription();
-    //    }
-    //
-    //    /** For each operation 
-    //     *   - will write verbose json and operation details to system.out if verboseOutput = true;
-    //     *   - will execute the operation against running server if execute = true.
-    //     * 
-    //     * @param op
-    //     * @param execute
-    //     * @param verboseOutput
-    //     * @return
-    //     */
-    //    public static Result exerciseOperation(Operation op, boolean execute, boolean verboseOutput) {
-    //        //display operation as AS7 plugin will build it
-    //        if (verboseOutput) {
-    //            System.out.println("\tOperation is:" + op);
-    //        }
-    //
-    //        String jsonToSend = "";
-    //        try {
-    //            jsonToSend = mapper.defaultPrettyPrintingWriter().writeValueAsString(op);
-    //        } catch (JsonGenerationException e) {
-    //            e.printStackTrace();
-    //        } catch (JsonMappingException e) {
-    //            e.printStackTrace();
-    //        } catch (IOException e) {
-    //            e.printStackTrace();
-    //        }
-    //        //As generated by jackson mapper
-    //        if (verboseOutput) {
-    //            System.out.println("@@@@ OUTBOUND JSON#\n" + jsonToSend + "#");
-    //        }
-    //
-    //        //Execute the operation
-    //        Result result = new Result();
-    //        if (execute) {
-    //            result = con.execute(op);
-    //        } else {
-    //            if (verboseOutput) {
-    //                System.out.println("**** NOTE: Execution disabled . NOT exercising write-attribute operation. **** ");
-    //            }
-    //        }
-    //        if (verboseOutput) {
-    //            //result wrapper details 
-    //            System.out.println("\tResult:" + result);
-    //            //detailed results
-    //            System.out.println("\tValue:" + result.getResult());
-    //            System.out.println("-----------------------------------------------------\n");
-    //        }
-    //        return result;
-    //    }
-    //
-    //    @Test(priority = 10, groups = "discovery")
-    //    public void initialSetup() throws Exception {
-    //        String securityDomainId = TEST_DOMAIN + "1";
-    //        Result result = null;
-    //        Operation op = null;
-    //
-    //        //create the initial securityDomain
-    //        op = new Operation("add", new Address("subsystem=security,security-domain=" + securityDomainId));
-    //        ASConnection connection = getASConnection();
-    //        con = connection;
-    //        mapper = new ObjectMapper();
-    //        mapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true);
-    //
-    //        moc = new ModuleOptionsComponent();
-    //        result = connection.execute(op);
-    //        System.out.println("#### Op is:" + op);
-    //        System.out.println("#### Result is:" + result);
-    //
-    //        //iterate over jsonMap
-    //        for (String key : jsonMap.keySet()) {
-    //            String attribute = key;
-    //            String address = "";
-    //            if (attribute.equals("policy-modules")) {
-    //                address = "subsystem=security,security-domain=" + securityDomainId + ",authorization=classic";
-    //            } else if (attribute.equals("acl-modules")) {
-    //                address = "subsystem=security,security-domain=" + securityDomainId + ",acl=classic";
-    //            } else if (attribute.equals("mapping-modules")) {
-    //                address = "subsystem=security,security-domain=" + securityDomainId + ",mapping=classic";
-    //            } else if (attribute.equals("trust-modules")) {
-    //                address = "subsystem=security,security-domain=" + securityDomainId + ",identity-trust=classic";
-    //            } else if (attribute.equals("provider-modules")) {
-    //                address = "subsystem=security,security-domain=" + securityDomainId + ",audit=classic";
-    //            } else if (attribute.equals("login-modules")) {
-    //                address = "subsystem=security,security-domain=" + securityDomainId + ",authentication=classic";
-    //            } else {
-    //                assert false : "An unknown attribute '" + attribute
-    //                    + "' was found. Is there a new type to be supported?";
-    //            }
-    //            //#### Have to create new content for the new node.
-    //            List<Value> moduleTypeValue = new ArrayList<Value>();
-    //
-    //            try {
-    //                // loading 'login-module'
-    //                JsonNode node = mapper.readTree(jsonMap.get(attribute));
-    //                result.setResult(mapper.treeToValue(node, Object.class));
-    //            } catch (JsonProcessingException e) {
-    //                e.printStackTrace();
-    //            } catch (IOException e) {
-    //                e.printStackTrace();
-    //            }
-    //
-    //            //populate the Value component complete with module Options.
-    //            moduleTypeValue = ModuleOptionsComponent.populateSecurityDomainModuleOptions(result,
-    //                ModuleOptionsComponent.loadModuleOptionType(attribute));
-    //
-    //            //add the login-modules attribute
-    //            op = ModuleOptionsComponent.createAddModuleOptionTypeOperation(new Address(address), attribute,
-    //                moduleTypeValue);
-    //
-    //            result = exerciseOperation(op, true, true);
-    //            assert ((result.isSuccess() == true) || (result.getOutcome() == null)) : "The operation '" + op
-    //                + "' failed to write the resource.." + result.getFailureDescription();
-    //        }
-    //    }
+    /** For each operation 
+     *   - will write verbose json and operation details to system.out if verboseOutput = true;
+     *   - will execute the operation against running server if execute = true.
+     * 
+     * @param op
+     * @param execute
+     * @param verboseOutput
+     * @return
+     */
+    public static Result exerciseOperation(Operation op, boolean execute, boolean verboseOutput) {
+        //display operation as AS7 plugin will build it
+        if (verboseOutput) {
+            System.out.println("\tOperation is:" + op);
+        }
+
+        String jsonToSend = "";
+        try {
+            jsonToSend = mapper.defaultPrettyPrintingWriter().writeValueAsString(op);
+        } catch (JsonGenerationException e) {
+            e.printStackTrace();
+        } catch (JsonMappingException e) {
+            e.printStackTrace();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        //As generated by jackson mapper
+        if (verboseOutput) {
+            System.out.println("@@@@ OUTBOUND JSON#\n" + jsonToSend + "#");
+        }
+
+        //Execute the operation
+        Result result = new Result();
+        if (execute) {
+            result = con.execute(op);
+        } else {
+            if (verboseOutput) {
+                System.out.println("**** NOTE: Execution disabled . NOT exercising write-attribute operation. **** ");
+            }
+        }
+        if (verboseOutput) {
+            //result wrapper details 
+            System.out.println("\tResult:" + result);
+            //detailed results
+            System.out.println("\tValue:" + result.getResult());
+            System.out.println("-----------------------------------------------------\n");
+        }
+        return result;
+    }
 }


commit 8e3709f8d7a7ffce5b44322a656836be13a7a652
Author: Jay Shaughnessy <jshaughn at redhat.com>
Date:   Wed Jun 27 13:24:00 2012 -0400

    [Bug 835113 - EJB2 MDBs are DOWN in JON UI]
    Restructure getAvailability() and getManagedComponent() to remove
    ambiguity in UNKNOWN runState handling as well as provide consistent
    Exception throwing/handling, and ManagedComponent refresh.  Simplify the
    override point for getManagedComponent.
    
    Remove Ejb2BeanComponent's special-handling for UNKNOWN runState, previously committed for
    this fix, in favor of the new base handling.

diff --git a/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/Ejb2BeanComponent.java b/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/Ejb2BeanComponent.java
index c4ae68f..95ba080 100644
--- a/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/Ejb2BeanComponent.java
+++ b/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/Ejb2BeanComponent.java
@@ -27,9 +27,7 @@ import java.util.Set;
 import org.jboss.deployers.spi.management.ManagementView;
 import org.jboss.managed.api.ComponentType;
 import org.jboss.managed.api.ManagedComponent;
-import org.jboss.managed.api.RunState;
 
-import org.rhq.core.domain.measurement.AvailabilityType;
 import org.rhq.plugins.jbossas5.util.Ejb2BeanUtils;
 
 /**
@@ -40,27 +38,15 @@ import org.rhq.plugins.jbossas5.util.Ejb2BeanUtils;
 public class Ejb2BeanComponent extends AbstractEjbBeanComponent {
     private static final ComponentType MDB_COMPONENT_TYPE = new ComponentType("EJB", "MDB");
 
+
     @Override
-    protected AvailabilityType getAvailabilityForRunState(RunState runState) {
-        AvailabilityType avail;
-        if (MDB_COMPONENT_TYPE.equals(getComponentType())) {
-            // This is a workaround for if BZ 835113.
-            avail = (runState == RunState.RUNNING || runState == RunState.UNKNOWN) ?
-                    AvailabilityType.UP : AvailabilityType.DOWN;
-        } else {
-            avail = super.getAvailabilityForRunState(runState);
+    protected ManagedComponent getManagedComponent(ManagementView mv) throws Exception {
+        if (null == mv) {
+            throw new IllegalArgumentException("managementView can not be null");
         }
-        return avail;
-    }
 
-    @Override
-    protected ManagedComponent getManagedComponent() {
         if (MDB_COMPONENT_TYPE.equals(getComponentType())) {
             try {
-                //we need to reload the management view here, because the MDBs might have changed since
-                //the last call, because the @object-id is part of their names.
-                ManagementView mv = getConnection().getManagementView();
-
                 Set<ManagedComponent> mdbs = mv.getComponentsForType(MDB_COMPONENT_TYPE);
 
                 for (ManagedComponent mdb : mdbs) {
@@ -73,7 +59,7 @@ public class Ejb2BeanComponent extends AbstractEjbBeanComponent {
                 throw new IllegalStateException(e);
             }
         } else {
-            return super.getManagedComponent();
+            return super.getManagedComponent(mv);
         }
 
         return null;
diff --git a/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/ManagedComponentComponent.java b/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/ManagedComponentComponent.java
index a44cfc8..da0b24b 100644
--- a/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/ManagedComponentComponent.java
+++ b/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/ManagedComponentComponent.java
@@ -104,19 +104,21 @@ public class ManagedComponentComponent extends AbstractManagedComponent implemen
      */
     private static final long AVAIL_REFRESH_INTERVAL = 1000 * 60 * 15; // 15 minutes
 
+    private long availRefreshInterval = AVAIL_REFRESH_INTERVAL;
+
     /**
      * The ManagedComponent is fetched from the server in {@link #getManagedComponent} throughout
      * the life cycle of this resource component. For example during metrics collections
-     * when getValues is invoked, getManagedComponent is called. Any time getManagedComponent
+     * when getValues() is invoked, getManagedComponent() is called. Any time getManagedComponent()
      * is called the lastComponentRefresh timestamp is updated. This timestamp is used in
      * {@link #getAvailability} to determine whether or not a component is needed to
      * perform an availability check.
      */
     private long lastComponentRefresh = 0L;
 
-    private long availRefreshInterval = AVAIL_REFRESH_INTERVAL;
-
-    private RunState runState = RunState.UNKNOWN;
+    // The last known runState for the component.  This is used to determine the result of getAvailability(). We
+    // do *not* cache the entire ManagedComponent because it is potentially a huge object that would eat too much memory.
+    private RunState runState;
 
     private String componentName;
     private ComponentType componentType;
@@ -124,20 +126,19 @@ public class ManagedComponentComponent extends AbstractManagedComponent implemen
     // ResourceComponent Implementation  --------------------------------------------
 
     public AvailabilityType getAvailability() {
-        if (lastComponentRefresh == 0) {
-            // The managed component has not been refreshed at all yet.
-            getManagedComponent();
-        } else {
-            long timeSinceComponentRefresh = System.currentTimeMillis() - lastComponentRefresh;
-            if (timeSinceComponentRefresh > availRefreshInterval) {
-                if (log.isDebugEnabled()) {
-                    log.debug("The availability refresh interval for [resourceKey: "
-                        + getResourceContext().getResourceKey() + ", type: " + componentType + ", name: " + componentName
-                        + "] has been exceeded by " + (timeSinceComponentRefresh - availRefreshInterval)
-                        + " ms. Reloading managed component...");
-                }
-                getManagedComponent();
+        long timeSinceComponentRefresh = System.currentTimeMillis() - lastComponentRefresh;
+        boolean refresh = timeSinceComponentRefresh > availRefreshInterval;
+
+        if (refresh) {
+            if (lastComponentRefresh > 0L && log.isDebugEnabled()) {
+                log.debug("The availability refresh interval for [resourceKey: "
+                    + getResourceContext().getResourceKey() + ", type: " + componentType + ", name: " + componentName
+                    + "] has been exceeded by " + (timeSinceComponentRefresh - availRefreshInterval)
+                    + " ms. Reloading managed component...");
             }
+
+            ManagedComponent managedComponent = getManagedComponent();
+            runState = managedComponent.getRunState();
         }
 
         return getAvailabilityForRunState(runState);
@@ -146,11 +147,14 @@ public class ManagedComponentComponent extends AbstractManagedComponent implemen
     protected AvailabilityType getAvailabilityForRunState(RunState runState) {
         if (runState == RunState.RUNNING) {
             return AvailabilityType.UP;
+
         } else {
             if (log.isDebugEnabled()) {
-                log.debug(componentType + " component '" + componentName + "' was not running - state was [" + runState
-                        + "].");
+                log.debug("Returning DOWN avail for " + componentType + " component '" + componentName
+                    + "' with runState [" + runState
+                    + "].");
             }
+
             return AvailabilityType.DOWN;
         }
     }
@@ -438,29 +442,58 @@ public class ManagedComponentComponent extends AbstractManagedComponent implemen
         return componentName;
     }
 
+    /**
+     * This method should most likely not be overridden. Instead, override {@link #getManagedComponent(ManagementView)}.
+     * <br/><br/>
+     * IMPORTANT!!! The returned ManagedComponent SHOULD NOT be cached in the instance. It is potentially a memory hog.
+     * 
+     * @return The ManagedComponent
+     * @throws RuntimeException if fetching the ManagementView or getting the component fails
+     * @throws IllegalStateException if the managedComponent is null/not found
+     */
+    @NotNull
     protected ManagedComponent getManagedComponent() {
         ManagedComponent managedComponent;
+
         try {
             ManagementView managementView = getConnection().getManagementView();
-            managedComponent = managementView.getComponent(this.componentName, this.componentType);
+            managedComponent = getManagedComponent(managementView);
         } catch (Exception e) {
-            runState = RunState.UNKNOWN;
             throw new RuntimeException("Failed to load [" + this.componentType + "] ManagedComponent ["
                 + this.componentName + "].", e);
         }
+
+        // Even if not found, update the refresh time. It will avoid too many costly, and potentially fruitless, fetches 
+        lastComponentRefresh = System.currentTimeMillis();
+
         if (managedComponent == null) {
-            runState = RunState.UNKNOWN;
             throw new IllegalStateException("Failed to find [" + this.componentType + "] ManagedComponent named ["
                 + this.componentName + "].");
         }
+
         if (log.isTraceEnabled()) {
             log.trace("Retrieved " + toString(managedComponent) + ".");
         }
-        lastComponentRefresh = System.currentTimeMillis();
-        runState = managedComponent.getRunState();
+
         return managedComponent;
     }
 
+    /**
+     * This is an override point. When actually fetching the managed component, this entry point should not be
+     * used. Instead, access should be via {@link #getManagedComponent()}. 
+     *
+     * @param managementView
+     * @return the ManagedComponent. Null if not found.
+     * @Throws Exception if there is a problem getting the component.
+     */
+    protected ManagedComponent getManagedComponent(ManagementView managementView) throws Exception {
+        if (null == managementView) {
+            throw new IllegalArgumentException("managementView can not be null");
+        }
+
+        return managementView.getComponent(this.componentName, this.componentType);
+    }
+
     @NotNull
     private OperationDefinition getOperationDefinition(String operationName) {
         ResourceType resourceType = getResourceContext().getResourceType();


commit 4699b70c9bde96b1c95c89e7e9b32e6ff73ad860
Author: Jirka Kremser <jkremser at redhat.com>
Date:   Wed Jun 27 15:55:28 2012 +0200

    formatting only

diff --git a/modules/core/client-api/pom.xml b/modules/core/client-api/pom.xml
index 834ad85..6f6a937 100644
--- a/modules/core/client-api/pom.xml
+++ b/modules/core/client-api/pom.xml
@@ -1,285 +1,288 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 
-   <modelVersion>4.0.0</modelVersion>
+  <modelVersion>4.0.0</modelVersion>
 
-   <parent>
-      <groupId>org.rhq</groupId>
-      <artifactId>rhq-core-parent</artifactId>
-      <version>4.5.0-SNAPSHOT</version>
-   </parent>
+  <parent>
+    <groupId>org.rhq</groupId>
+    <artifactId>rhq-core-parent</artifactId>
+    <version>4.5.0-SNAPSHOT</version>
+  </parent>
 
-   <groupId>org.rhq</groupId>
-   <artifactId>rhq-core-client-api</artifactId>
-   <packaging>jar</packaging>
+  <groupId>org.rhq</groupId>
+  <artifactId>rhq-core-client-api</artifactId>
+  <packaging>jar</packaging>
 
-   <name>RHQ Client API</name>
-   <description>Server and Client APIs for invoking operations on the RHQ plugin container</description>
+  <name>RHQ Client API</name>
+  <description>Server and Client APIs for invoking operations on the RHQ plugin container</description>
 
-   <dependencies>
+  <dependencies>
 
-      <dependency>
-         <groupId>${rhq.groupId}</groupId>
-         <artifactId>rhq-core-domain</artifactId>
-         <version>${project.version}</version>
-         <scope>provided</scope>
-      </dependency>
+    <dependency>
+      <groupId>${rhq.groupId}</groupId>
+      <artifactId>rhq-core-domain</artifactId>
+      <version>${project.version}</version>
+      <scope>provided</scope>
+    </dependency>
 
-      <dependency>
-         <groupId>${rhq.groupId}</groupId>
-         <artifactId>rhq-core-comm-api</artifactId>
-         <version>${project.version}</version>
-         <scope>provided</scope>
-      </dependency>
+    <dependency>
+      <groupId>${rhq.groupId}</groupId>
+      <artifactId>rhq-core-comm-api</artifactId>
+      <version>${project.version}</version>
+      <scope>provided</scope>
+    </dependency>
 
-       <dependency>
-          <groupId>${rhq.groupId}</groupId>
-          <artifactId>rhq-common-drift</artifactId>
-          <version>${project.version}</version>
-      </dependency>
+    <dependency>
+      <groupId>${rhq.groupId}</groupId>
+      <artifactId>rhq-common-drift</artifactId>
+      <version>${project.version}</version>
+    </dependency>
 
       <!-- TODO: This is a fix for the Javac bug requiring annotations to be
                  available when compiling dependent classes; it is fixed in JDK 6. -->
 
-      <dependency>
-         <groupId>jboss.jboss-embeddable-ejb3</groupId>
-         <artifactId>hibernate-all</artifactId>
-         <version>1.0.0.Alpha9</version>
-         <scope>provided</scope>
+    <dependency>
+      <groupId>jboss.jboss-embeddable-ejb3</groupId>
+      <artifactId>hibernate-all</artifactId>
+      <version>1.0.0.Alpha9</version>
+      <scope>provided</scope>
          <!-- set scope to 'provided', so Hibernate annotations can be used in the entities -->
-      </dependency>
+    </dependency>
 
-      <dependency>
-         <groupId>jboss.jboss-embeddable-ejb3</groupId>
-         <artifactId>jboss-ejb3-all</artifactId>
-         <version>1.0.0.Alpha9</version>
-         <scope>provided</scope>
-      </dependency>
+    <dependency>
+      <groupId>jboss.jboss-embeddable-ejb3</groupId>
+      <artifactId>jboss-ejb3-all</artifactId>
+      <version>1.0.0.Alpha9</version>
+      <scope>provided</scope>
+    </dependency>
 
-      <dependency>
-         <groupId>javax.xml.bind</groupId>
-         <artifactId>jaxb-api</artifactId>
+    <dependency>
+      <groupId>javax.xml.bind</groupId>
+      <artifactId>jaxb-api</artifactId>
          <!-- NOTE: The version is defined in the root POM's dependencyManagement section. -->
-      </dependency>
+    </dependency>
 
-      <dependency>
-         <groupId>com.sun.xml.bind</groupId>
-         <artifactId>jaxb-impl</artifactId>
+    <dependency>
+      <groupId>com.sun.xml.bind</groupId>
+      <artifactId>jaxb-impl</artifactId>
          <!-- NOTE: The version is defined in the root POM's dependencyManagement section. -->
          <!--<scope>test</scope>  not sure about this -->
-      </dependency>
+    </dependency>
 
-      <dependency>
-         <groupId>commons-jxpath</groupId>
-         <artifactId>commons-jxpath</artifactId>
-         <version>1.3</version>
-         <scope>test</scope>
-      </dependency>
+    <dependency>
+      <groupId>commons-jxpath</groupId>
+      <artifactId>commons-jxpath</artifactId>
+      <version>1.3</version>
+      <scope>test</scope>
+    </dependency>
 
-   </dependencies>
+  </dependencies>
 
-   <build>
-      <plugins>
-         <plugin>
-            <groupId>com.sun.tools.xjc.maven2</groupId>
-            <artifactId>maven-jaxb-plugin</artifactId>
-            <version>1.1</version>
-            <executions>
-               <execution>
-                  <goals>
-                     <goal>generate</goal>
-                  </goals>
-               </execution>
-            </executions>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>com.sun.tools.xjc.maven2</groupId>
+        <artifactId>maven-jaxb-plugin</artifactId>
+        <version>1.1</version>
+        <executions>
+          <execution>
+            <goals>
+              <goal>generate</goal>
+            </goals>
+          </execution>
+        </executions>
+        <configuration>
+          <generateDirectory>${basedir}/target/generated-sources/xjc</generateDirectory>
+        </configuration>
+      </plugin>
+
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <configuration>
+          <source>1.6</source>
+        </configuration>
+      </plugin>
+
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jar-plugin</artifactId>
+        <executions>
+          <execution>
+            <phase>package</phase>
+            <goals>
+              <goal>test-jar</goal>
+            </goals>
             <configuration>
-              <generateDirectory>${basedir}/target/generated-sources/xjc</generateDirectory>
+              <includes>
+                <include>org/rhq/core/clientapi/shared/**</include>
+              </includes>
             </configuration>
-         </plugin>
+          </execution>
+        </executions>
+      </plugin>
 
-         <plugin>
-            <groupId>org.apache.maven.plugins</groupId>
-            <artifactId>maven-compiler-plugin</artifactId>
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>build-helper-maven-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>add-xjc-source</id>
+            <phase>generate-sources</phase>
+            <goals>
+              <goal>add-source</goal>
+            </goals>
             <configuration>
-               <source>1.6</source>
+              <sources>
+                <source>${basedir}/target/generated-sources/xjc</source>
+              </sources>
             </configuration>
-         </plugin>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
 
-         <plugin>
-             <groupId>org.apache.maven.plugins</groupId>
-             <artifactId>maven-jar-plugin</artifactId>
-             <executions>
-                <execution>
-                   <phase>package</phase>
-                   <goals>
-                      <goal>test-jar</goal>
-                   </goals>
-                   <configuration>
-                      <includes>
-                         <include>org/rhq/core/clientapi/shared/**</include>
-                      </includes>
-                   </configuration>
-                </execution>
-             </executions>
-          </plugin>
+  <profiles>
+
+    <profile>
+      <id>dev</id>
+
+      <properties>
+        <rhq.rootDir>../../..</rhq.rootDir>
+        <rhq.containerDir>${rhq.rootDir}/${rhq.defaultDevContainerPath}</rhq.containerDir>
+        <rhq.deploymentDir>${rhq.containerDir}/jbossas/server/default/deploy/${rhq.earName}/lib</rhq.deploymentDir>
+      </properties>
+
+      <build>
+        <plugins>
 
           <plugin>
-            <groupId>org.codehaus.mojo</groupId>
-            <artifactId>build-helper-maven-plugin</artifactId>
+            <artifactId>maven-antrun-plugin</artifactId>
             <executions>
+
               <execution>
-                <id>add-xjc-source</id>
-                <phase>generate-sources</phase>
+                <id>deploy</id>
+                <phase>compile</phase>
+                <configuration>
+                  <target>
+                    <mkdir dir="${rhq.deploymentDir}"/>
+                    <property name="deployment.file" location="${rhq.deploymentDir}/${project.build.finalName}.jar"/>
+                    <echo>*** Updating ${deployment.file}...</echo>
+                    <jar destfile="${deployment.file}" basedir="${project.build.outputDirectory}"/>
+                  </target>
+                </configuration>
                 <goals>
-                  <goal>add-source</goal>
+                  <goal>run</goal>
                 </goals>
+              </execution>
+
+              <execution>
+                <id>undeploy</id>
+                <phase>clean</phase>
                 <configuration>
-                  <sources>
-                    <source>${basedir}/target/generated-sources/xjc</source>
-                  </sources>
+                  <target>
+                    <property name="deployment.file" location="${rhq.deploymentDir}/${project.build.finalName}.jar"/>
+                    <echo>*** Deleting ${deployment.file}...</echo>
+                    <delete file="${deployment.file}"/>
+                  </target>
                 </configuration>
+                <goals>
+                  <goal>run</goal>
+                </goals>
               </execution>
+
             </executions>
           </plugin>
-      </plugins>
-   </build>
-
-   <profiles>
 
-      <profile>
-         <id>dev</id>
-
-         <properties>
-            <rhq.rootDir>../../..</rhq.rootDir>
-            <rhq.containerDir>${rhq.rootDir}/${rhq.defaultDevContainerPath}</rhq.containerDir>
-            <rhq.deploymentDir>${rhq.containerDir}/jbossas/server/default/deploy/${rhq.earName}/lib</rhq.deploymentDir>
-         </properties>
-
-         <build>
-            <plugins>
-
-               <plugin>
-                 <artifactId>maven-antrun-plugin</artifactId>
-                 <executions>
-
-                     <execution>
-                        <id>deploy</id>
-                        <phase>compile</phase>
-                        <configuration>
-                          <target>
-                            <mkdir dir="${rhq.deploymentDir}" />
-                            <property name="deployment.file" location="${rhq.deploymentDir}/${project.build.finalName}.jar" />
-                            <echo>*** Updating ${deployment.file}...</echo>
-                            <jar destfile="${deployment.file}" basedir="${project.build.outputDirectory}" />
-                          </target>
-                        </configuration>
-                        <goals>
-                          <goal>run</goal>
-                        </goals>
-                     </execution>
-
-                     <execution>
-                        <id>undeploy</id>
-                        <phase>clean</phase>
-                        <configuration>
-                          <target>
-                            <property name="deployment.file" location="${rhq.deploymentDir}/${project.build.finalName}.jar" />
-                            <echo>*** Deleting ${deployment.file}...</echo>
-                            <delete file="${deployment.file}" />
-                          </target>
-                        </configuration>
-                        <goals>
-                          <goal>run</goal>
-                        </goals>
-                     </execution>
-
-                   </executions>
-               </plugin>
-
-            </plugins>
-         </build>
-      </profile>
+        </plugins>
+      </build>
+    </profile>
     <profile>
       <id>cobertura</id>
       <activation>
         <activeByDefault>false</activeByDefault>
       </activation>
-        <build>
-         <plugins>
-           <plugin>
-             <artifactId>maven-antrun-plugin</artifactId>
-              <dependencies>
-               <dependency>
-                 <groupId>net.sourceforge.cobertura</groupId>
-                 <artifactId>cobertura</artifactId>
-                 <version>${cobertura.version}</version>
-               </dependency>
-             </dependencies>
-             <executions>
+      <build>
+        <plugins>
+          <plugin>
+            <artifactId>maven-antrun-plugin</artifactId>
+            <dependencies>
+              <dependency>
+                <groupId>net.sourceforge.cobertura</groupId>
+                <artifactId>cobertura</artifactId>
+                <version>${cobertura.version}</version>
+              </dependency>
+            </dependencies>
+            <executions>
               <execution>
-               <id>cobertura-instrument</id>
-               <phase>process-test-classes</phase>
-                 <configuration>
-                   <target>
+                <id>cobertura-instrument</id>
+                <phase>process-test-classes</phase>
+                <configuration>
+                  <target>
                    <!-- prepare directory structure for cobertura-->
-                   <mkdir dir="target/cobertura" />
-                   <mkdir dir="target/cobertura/backup" />
+                    <mkdir dir="target/cobertura"/>
+                    <mkdir dir="target/cobertura/backup"/>
                    <!-- backup all classes so that we can instrument the original classes-->
-                   <copy toDir="target/cobertura/backup" verbose="true" overwrite="true">
+                    <copy toDir="target/cobertura/backup" verbose="true" overwrite="true">
                       <fileset dir="target/classes">
-                         <include name="**/*.class" />
+                        <include name="**/*.class"/>
                       </fileset>
-                   </copy>
+                    </copy>
                    <!-- create a properties file and save there location of cobertura data file-->
-                   <touch file="target/classes/cobertura.properties" />
-                   <echo file="target/classes/cobertura.properties">net.sourceforge.cobertura.datafile=${project.build.directory}/cobertura/cobertura.ser</echo>
-                   <taskdef classpathref="maven.plugin.classpath" resource="tasks.properties" />
+                    <touch file="target/classes/cobertura.properties"/>
+                    <echo file="target/classes/cobertura.properties">net.sourceforge.cobertura.datafile=${project.build.directory}/cobertura/cobertura.ser</echo>
+                    <taskdef classpathref="maven.plugin.classpath" resource="tasks.properties"/>
                    <!-- instrument all classes in target/classes directory -->
-                   <cobertura-instrument datafile="${project.build.directory}/cobertura/cobertura.ser" todir="${project.build.directory}/classes">
-                     <fileset dir="${project.build.directory}/classes">
-                        <include name="**/*.class" />
+                    <cobertura-instrument datafile="${project.build.directory}/cobertura/cobertura.ser"
+                      todir="${project.build.directory}/classes">
+                      <fileset dir="${project.build.directory}/classes">
+                        <include name="**/*.class"/>
                       </fileset>
                     </cobertura-instrument>
-                   </target>
-                 </configuration>
-               <goals>
-                 <goal>run</goal>
-               </goals>
+                  </target>
+                </configuration>
+                <goals>
+                  <goal>run</goal>
+                </goals>
               </execution>
               <execution>
-               <id>cobertura-report</id>
-               <phase>prepare-package</phase>
-                 <configuration>
-                   <target>
-                     <taskdef classpathref="maven.plugin.classpath" resource="tasks.properties" />
+                <id>cobertura-report</id>
+                <phase>prepare-package</phase>
+                <configuration>
+                  <target>
+                    <taskdef classpathref="maven.plugin.classpath" resource="tasks.properties"/>
                      <!-- prepare directory structure for cobertura-->
-                     <mkdir dir="target/cobertura" />
-                     <mkdir dir="target/site/cobertura" />
+                    <mkdir dir="target/cobertura"/>
+                    <mkdir dir="target/site/cobertura"/>
                      <!-- restore classes from backup folder to classes folder -->
-                     <copy toDir="target/classes" verbose="true" overwrite="true">
+                    <copy toDir="target/classes" verbose="true" overwrite="true">
                       <fileset dir="target/cobertura/backup">
-                         <include name="**/*.class" />
+                        <include name="**/*.class"/>
                       </fileset>
-                     </copy>
+                    </copy>
                      <!-- delete backup folder-->
-                     <delete dir="target/cobertura/backup" />
+                    <delete dir="target/cobertura/backup"/>
                      <!-- create a code coverage report -->
-                     <cobertura-report format="html" datafile="${project.build.directory}/cobertura/cobertura.ser" destdir="${project.build.directory}/site/cobertura">
+                    <cobertura-report format="html" datafile="${project.build.directory}/cobertura/cobertura.ser"
+                      destdir="${project.build.directory}/site/cobertura">
                       <fileset dir="${basedir}/src/main/java">
-                         <include name="**/*.java" />
+                        <include name="**/*.java"/>
                       </fileset>
-                     </cobertura-report>
+                    </cobertura-report>
                      <!-- delete cobertura.properties file -->
-                     <delete file="target/classes/cobertura.properties" />
-                   </target>
-                 </configuration>
-               <goals>
-                 <goal>run</goal>
-               </goals>
-               </execution>
+                    <delete file="target/classes/cobertura.properties"/>
+                  </target>
+                </configuration>
+                <goals>
+                  <goal>run</goal>
+                </goals>
+              </execution>
             </executions>
-           </plugin>
-          </plugins>
-       </build>
-     </profile>
-   </profiles>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+  </profiles>
 
 </project>
diff --git a/modules/enterprise/gui/coregui/pom.xml b/modules/enterprise/gui/coregui/pom.xml
index 29662c8..e3aca30 100644
--- a/modules/enterprise/gui/coregui/pom.xml
+++ b/modules/enterprise/gui/coregui/pom.xml
@@ -1,33 +1,34 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 
-    <modelVersion>4.0.0</modelVersion>
-
-    <parent>
-        <groupId>org.rhq</groupId>
-        <artifactId>rhq-parent</artifactId>
-        <version>4.5.0-SNAPSHOT</version>
-        <relativePath>../../../../pom.xml</relativePath>
-    </parent>
+  <modelVersion>4.0.0</modelVersion>
 
+  <parent>
     <groupId>org.rhq</groupId>
-    <artifactId>rhq-coregui</artifactId>
-    <packaging>war</packaging>
+    <artifactId>rhq-parent</artifactId>
+    <version>4.5.0-SNAPSHOT</version>
+    <relativePath>../../../../pom.xml</relativePath>
+  </parent>
+
+  <groupId>org.rhq</groupId>
+  <artifactId>rhq-coregui</artifactId>
+  <packaging>war</packaging>
 
-    <name>RHQ Enterprise Core GUI</name>
-    <description>the RHQ Enterprise Core GUI webapp</description>
+  <name>RHQ Enterprise Core GUI</name>
+  <description>the RHQ Enterprise Core GUI webapp</description>
 
-    <properties>
+  <properties>
         <!-- dependency versions -->
-        <gwt.version>2.4.0</gwt.version>
-        <smartgwt.version>3.0</smartgwt.version>
+    <gwt.version>2.4.0</gwt.version>
+    <smartgwt.version>3.0</smartgwt.version>
 
         <!--  If this is too much memory to allocate to your gwt:debug process then override this property in
               in your settings.xml -->
-        <gwt-plugin.extraJvmArgs>-Xms512M -Xmx512M -XX:PermSize=128M -XX:MaxPermSize=256M</gwt-plugin.extraJvmArgs>
-        <gwt-plugin.localWorkers>4</gwt-plugin.localWorkers>
+    <gwt-plugin.extraJvmArgs>-Xms512M -Xmx512M -XX:PermSize=128M -XX:MaxPermSize=256M</gwt-plugin.extraJvmArgs>
+    <gwt-plugin.localWorkers>4</gwt-plugin.localWorkers>
 
-        <coreGuiParams />
-        <coreGuiRunTarget>'http://localhost:7080/coregui/CoreGUI.html${coreGuiParams}'</coreGuiRunTarget>
+    <coreGuiParams/>
+    <coreGuiRunTarget>'http://localhost:7080/coregui/CoreGUI.html${coreGuiParams}'</coreGuiRunTarget>
 
         <!--
          This property is substituted, by the resource plugin during the resources phase, as the
@@ -52,201 +53,201 @@
          Multiple agents can be specified as a comma-delimited list, as demonstrated by the default
          value below.
         -->
-        <gwt.userAgent>ie8,ie9,gecko1_8,safari,opera</gwt.userAgent>
+    <gwt.userAgent>ie8,ie9,gecko1_8,safari,opera</gwt.userAgent>
 
         <!-- Change this to "true" via the mvn command line or your ~/.m2/settings.xml to speed
              up gwt compilation. -->
-        <gwt.draftCompile>false</gwt.draftCompile>
+    <gwt.draftCompile>false</gwt.draftCompile>
 
         <!-- Change this to "true" via the mvn command line or your ~/.m2/settings.xml to generate report -->
-        <gwt.soyc>false</gwt.soyc>
+    <gwt.soyc>false</gwt.soyc>
 
         <!-- Change this to "DETAILED" via the mvn command line or your ~/.m2/settings.xml to
              make sure GWT-generated JavaScript code is not obfuscated. -->
-        <gwt.style>PRETTY</gwt.style>
+    <gwt.style>PRETTY</gwt.style>
 
         <!-- Comma-separated list of the locales that should be included during GWT compilation. The specified locales
              should each have two corresponding message bundle properties files under
              src/main/resources/org/rhq/enterprise/gui/coregui/client/. For example, the "ja" locale has
              Messages_ja.properties and MessageConstants_ja.properties. -->
-        <gwt.locale>en,de,ja,pt,zh,ru,cs</gwt.locale>
+    <gwt.locale>en,de,ja,pt,zh,ru,cs</gwt.locale>
 
         <!-- The locale that GWT should fallback to if the user specified an unsupported locale via the 'locale' query
              string parameter. -->
-        <gwt.fallback.locale>en</gwt.fallback.locale>
- 
-        <enable.tags>true</enable.tags>
-    </properties>
+    <gwt.fallback.locale>en</gwt.fallback.locale>
+
+    <enable.tags>true</enable.tags>
+  </properties>
 
-    <dependencies>
+  <dependencies>
 
         <!-- ============= Internal Deps ============= -->
 
-        <dependency>
-            <groupId>org.rhq</groupId>
-            <artifactId>rhq-core-domain</artifactId>
-            <version>${project.version}</version>
-            <scope>provided</scope>
+    <dependency>
+      <groupId>org.rhq</groupId>
+      <artifactId>rhq-core-domain</artifactId>
+      <version>${project.version}</version>
+      <scope>provided</scope>
             <!-- by rhq.ear (as ejb-jar) -->
-        </dependency>
+    </dependency>
 
-        <dependency>
-            <groupId>org.rhq</groupId>
-            <artifactId>rhq-enterprise-server</artifactId>
-            <version>${project.version}</version>
-            <scope>provided</scope>
+    <dependency>
+      <groupId>org.rhq</groupId>
+      <artifactId>rhq-enterprise-server</artifactId>
+      <version>${project.version}</version>
+      <scope>provided</scope>
             <!-- by rhq.ear (as ejb-jar) -->
-        </dependency>
+    </dependency>
 
-        <dependency>
-            <groupId>org.rhq</groupId>
-            <artifactId>rhq-core-util</artifactId>
-            <version>${project.version}</version>
-            <scope>provided</scope>
+    <dependency>
+      <groupId>org.rhq</groupId>
+      <artifactId>rhq-core-util</artifactId>
+      <version>${project.version}</version>
+      <scope>provided</scope>
             <!-- by rhq.ear -->
-        </dependency>
+    </dependency>
 
 
         <!-- =============== 3rd Party Deps =============== -->
 
-        <dependency>
-            <groupId>com.google.gwt</groupId>
-            <artifactId>gwt-servlet</artifactId>
-            <version>${gwt.version}</version>
-            <scope>compile</scope>
-        </dependency>
-        <dependency>
-            <groupId>com.google.gwt</groupId>
-            <artifactId>gwt-user</artifactId>
-            <version>${gwt.version}</version>
-            <scope>provided</scope>
-        </dependency>
+    <dependency>
+      <groupId>com.google.gwt</groupId>
+      <artifactId>gwt-servlet</artifactId>
+      <version>${gwt.version}</version>
+      <scope>compile</scope>
+    </dependency>
+    <dependency>
+      <groupId>com.google.gwt</groupId>
+      <artifactId>gwt-user</artifactId>
+      <version>${gwt.version}</version>
+      <scope>provided</scope>
+    </dependency>
         <!-- This is so we can compile custom GWT Generators to be called during gwt compilation.
              Is is not needed at runtime and so is not included in the WAR. -->
-        <dependency>
-            <groupId>com.google.gwt</groupId>
-            <artifactId>gwt-dev</artifactId>
-            <version>${gwt.version}</version>
-            <scope>provided</scope>
-        </dependency>
+    <dependency>
+      <groupId>com.google.gwt</groupId>
+      <artifactId>gwt-dev</artifactId>
+      <version>${gwt.version}</version>
+      <scope>provided</scope>
+    </dependency>
 
 
-        <dependency>
-            <groupId>com.smartgwt</groupId>
-            <artifactId>smartgwt</artifactId>
-            <version>${smartgwt.version}</version>
-        </dependency>
+    <dependency>
+      <groupId>com.smartgwt</groupId>
+      <artifactId>smartgwt</artifactId>
+      <version>${smartgwt.version}</version>
+    </dependency>
 
 
         <!-- the GWT graphing library (note, this provides jquery 1.3.2. If we get rid of GFlot we will need
              to provide jquery explcitly for jquery.sparkline support. See CoreGUI.gwt.xml for the jquery.sparkline
              declaration and coregui/webapp/js for the lib inclusion.) -->
-        <dependency>
-            <groupId>ca.nanometrics</groupId>
-            <artifactId>gflot</artifactId>
-            <version>1.0.0</version>
-        </dependency>
+    <dependency>
+      <groupId>ca.nanometrics</groupId>
+      <artifactId>gflot</artifactId>
+      <version>1.0.0</version>
+    </dependency>
 
 
         <!-- for file uploads -->
-        <dependency>
-            <groupId>commons-fileupload</groupId>
-            <artifactId>commons-fileupload</artifactId>
-            <version>1.2</version>
-        </dependency>
-
-        <dependency>
-            <groupId>commons-io</groupId>
-            <artifactId>commons-io</artifactId>
-            <version>1.3.1</version>
-        </dependency>
-
-        <dependency>
-            <groupId>commons-logging</groupId>
-            <artifactId>commons-logging</artifactId>
-            <version>1.0.4</version>
-            <scope>provided</scope>
+    <dependency>
+      <groupId>commons-fileupload</groupId>
+      <artifactId>commons-fileupload</artifactId>
+      <version>1.2</version>
+    </dependency>
+
+    <dependency>
+      <groupId>commons-io</groupId>
+      <artifactId>commons-io</artifactId>
+      <version>1.3.1</version>
+    </dependency>
+
+    <dependency>
+      <groupId>commons-logging</groupId>
+      <artifactId>commons-logging</artifactId>
+      <version>1.0.4</version>
+      <scope>provided</scope>
             <!-- by JBossAS -->
-        </dependency>
+    </dependency>
 
-        <dependency>
-            <groupId>org.opensymphony.quartz</groupId>
-            <artifactId>quartz</artifactId>
+    <dependency>
+      <groupId>org.opensymphony.quartz</groupId>
+      <artifactId>quartz</artifactId>
             <!-- NOTE: The version is defined in the root POM's dependencyManagement section. -->
-            <scope>provided</scope>
+      <scope>provided</scope>
             <!-- by JBossAS itself, which the container buildNodes has packaged with 1.6.5 -->
-        </dependency>
+    </dependency>
 
         <!-- needed for referenced domain entities that use Hibernate annotations (due to JDK5 bug) -->
-        <dependency>
-            <groupId>hibernate-annotations</groupId>
-            <artifactId>hibernate-annotations</artifactId>
+    <dependency>
+      <groupId>hibernate-annotations</groupId>
+      <artifactId>hibernate-annotations</artifactId>
             <!-- NOTE: The version is defined in the root POM's dependencyManagement section. -->
-            <scope>provided</scope>
+      <scope>provided</scope>
             <!-- by JBossAS -->
-        </dependency>
+    </dependency>
 
         <!-- transitive dependency needed for JspC -->
-        <dependency>
-            <groupId>javax.servlet</groupId>
-            <artifactId>servlet-api</artifactId>
-            <version>2.4</version>
-            <scope>provided</scope>
+    <dependency>
+      <groupId>javax.servlet</groupId>
+      <artifactId>servlet-api</artifactId>
+      <version>2.4</version>
+      <scope>provided</scope>
             <!-- by JBossAS -->
-        </dependency>
+    </dependency>
 
         <!-- needed for referenced domain entities that use JPA annotations (due to JDK5 bug) -->
-        <dependency>
-            <groupId>javax.persistence</groupId>
-            <artifactId>persistence-api</artifactId>
-            <version>1.0</version>
-            <scope>provided</scope>
+    <dependency>
+      <groupId>javax.persistence</groupId>
+      <artifactId>persistence-api</artifactId>
+      <version>1.0</version>
+      <scope>provided</scope>
             <!-- by JBossAS -->
-        </dependency>
+    </dependency>
 
         <!-- needed for EJB3 annotations (e.g. ApplicationException) -->
-        <dependency>
-            <groupId>jboss</groupId>
-            <artifactId>jboss-ejb3x</artifactId>
+    <dependency>
+      <groupId>jboss</groupId>
+      <artifactId>jboss-ejb3x</artifactId>
             <!-- NOTE: The version is defined in the root POM's dependencyManagement section. -->
-            <scope>provided</scope>
+      <scope>provided</scope>
             <!-- by JBossAS -->
-        </dependency>
+    </dependency>
 
         <!-- Needed due to JDK 1.5 bug. -->
-        <dependency>
-            <groupId>jboss</groupId>
-            <artifactId>jboss-annotations-ejb3</artifactId>
+    <dependency>
+      <groupId>jboss</groupId>
+      <artifactId>jboss-annotations-ejb3</artifactId>
             <!-- NOTE: The version is defined in the root POM's dependencyManagement section. -->
-            <scope>provided</scope>
+      <scope>provided</scope>
             <!-- by JBossAS -->
-        </dependency>
+    </dependency>
 
-        <dependency>
-           <groupId>jboss.jbossws</groupId>
-           <artifactId>jboss-jaxws</artifactId>
-           <version>3.0.1-native-2.0.4.GA</version>
-           <scope>provided</scope> <!-- by JBossAS -->
-        </dependency>
+    <dependency>
+      <groupId>jboss.jbossws</groupId>
+      <artifactId>jboss-jaxws</artifactId>
+      <version>3.0.1-native-2.0.4.GA</version>
+      <scope>provided</scope> <!-- by JBossAS -->
+    </dependency>
 
-        <dependency>
-            <groupId>org.jboss.resteasy</groupId>
-            <artifactId>resteasy-jaxrs</artifactId>
-            <version>${resteasy.version}</version>
-            <scope>provided</scope>
-        </dependency>
+    <dependency>
+      <groupId>org.jboss.resteasy</groupId>
+      <artifactId>resteasy-jaxrs</artifactId>
+      <version>${resteasy.version}</version>
+      <scope>provided</scope>
+    </dependency>
 
-    </dependencies>
+  </dependencies>
 
 
-    <build>
-        <finalName>coregui</finalName>
+  <build>
+    <finalName>coregui</finalName>
 
-        <resources>
-            <resource>
-                <targetPath>${project.build.directory}/generated-sources/gwt</targetPath>
-                <directory>src/main/resources</directory>
-                <filtering>true</filtering>
+    <resources>
+      <resource>
+        <targetPath>${project.build.directory}/generated-sources/gwt</targetPath>
+        <directory>src/main/resources</directory>
+        <filtering>true</filtering>
                 <!-- 
                   Do NOT include java files here, because otherwise the java files from
                   resources would end up in WEB-INF/classes which definitely not something
@@ -259,110 +260,110 @@
                   need to replace the ${...} place-holders with the build-provided values
                   in there.
                 -->
-                <includes>
-                  <include>**/*.gwt.xml</include>
-                  <include>**/*.properties</include>
-                </includes>
-            </resource>
-            <resource>
-                <directory>src/main/java</directory>
-                <includes>
-                    <include>**/*.java</include>
-                </includes>
-            </resource>
-        </resources>
-
-
-        <plugins>
-
-            <plugin>
-                <groupId>org.codehaus.mojo</groupId>
-                <artifactId>gwt-maven-plugin</artifactId>
-                <version>2.4.0</version>
-                <configuration>
-                    <noServer>true</noServer>
-                    <inplace>false</inplace>
+        <includes>
+          <include>**/*.gwt.xml</include>
+          <include>**/*.properties</include>
+        </includes>
+      </resource>
+      <resource>
+        <directory>src/main/java</directory>
+        <includes>
+          <include>**/*.java</include>
+        </includes>
+      </resource>
+    </resources>
+
+
+    <plugins>
+
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>gwt-maven-plugin</artifactId>
+        <version>2.4.0</version>
+        <configuration>
+          <noServer>true</noServer>
+          <inplace>false</inplace>
                     <!-- <logLevel>INFO' -bindAddress 0.0.0.0 -logLevel 'INFO</logLevel> -->
-                    <logLevel>INFO</logLevel>
-                    <runTarget>${coreGuiRunTarget}</runTarget>
-                    <extraJvmArgs>${gwt-plugin.extraJvmArgs}</extraJvmArgs>
-                    <localWorkers>${gwt-plugin.localWorkers}</localWorkers>
-                    <draftCompile>${gwt.draftCompile}</draftCompile>
-                    <soyc>${gwt.soyc}</soyc>                    
-                    <buildOutputDirectory>target/gwtclasses</buildOutputDirectory>
-                    <hostedWebapp>target/hostedWar</hostedWebapp>
-                    <debugSuspend>false</debugSuspend>
-                    <servicePattern>**/gwt/*GWTService.java</servicePattern>
-                    <i18nMessagesBundle>org.rhq.enterprise.gui.coregui.client.Messages</i18nMessagesBundle>
-                    <i18nConstantsWithLookupBundle>org.rhq.enterprise.gui.coregui.client.MessageConstants</i18nConstantsWithLookupBundle>
-                    <compileSourcesArtifact>org.rhq:rhq-core-domain</compileSourcesArtifact>
-                    <style>${gwt.style}</style>
-                    <strict>true</strict>
+          <logLevel>INFO</logLevel>
+          <runTarget>${coreGuiRunTarget}</runTarget>
+          <extraJvmArgs>${gwt-plugin.extraJvmArgs}</extraJvmArgs>
+          <localWorkers>${gwt-plugin.localWorkers}</localWorkers>
+          <draftCompile>${gwt.draftCompile}</draftCompile>
+          <soyc>${gwt.soyc}</soyc>
+          <buildOutputDirectory>target/gwtclasses</buildOutputDirectory>
+          <hostedWebapp>target/hostedWar</hostedWebapp>
+          <debugSuspend>false</debugSuspend>
+          <servicePattern>**/gwt/*GWTService.java</servicePattern>
+          <i18nMessagesBundle>org.rhq.enterprise.gui.coregui.client.Messages</i18nMessagesBundle>
+          <i18nConstantsWithLookupBundle>org.rhq.enterprise.gui.coregui.client.MessageConstants</i18nConstantsWithLookupBundle>
+          <compileSourcesArtifact>org.rhq:rhq-core-domain</compileSourcesArtifact>
+          <style>${gwt.style}</style>
+          <strict>true</strict>
                     <!-- compiles gwt artifacts like symbolMap outside of war so it doesnt get packaged -->
-                    <deploy>${project.build.directory}/gwt-deploy</deploy>
-                </configuration>
-
-                <executions>
-                    <execution>
-                        <id>gwt-goals</id>
-                        <goals>
-                            <goal>compile</goal>
-                            <goal>generateAsync</goal>
-                            <goal>i18n</goal>
-                        </goals>
-                    </execution>
-                    <execution>
+          <deploy>${project.build.directory}/gwt-deploy</deploy>
+        </configuration>
+
+        <executions>
+          <execution>
+            <id>gwt-goals</id>
+            <goals>
+              <goal>compile</goal>
+              <goal>generateAsync</goal>
+              <goal>i18n</goal>
+            </goals>
+          </execution>
+          <execution>
                         <!-- This id is what does the trick, don't change it. For this to work maven 2.2.0 and later is needed. -->
-                        <id>default-cli</id>
-                        <goals>
-                            <goal>debug</goal>
-                        </goals>
-                        <configuration>
-                            <module>org.rhq.enterprise.gui.coregui.CoreGUI</module>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
-
-            <plugin>
-                <artifactId>maven-war-plugin</artifactId>
-                <configuration>
-                    <archive>
-                        <manifest>
-                            <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
-                            <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
-                        </manifest>
-                        <manifestEntries>
-                            <Build-Number>${buildNumber}</Build-Number>
-                        </manifestEntries>
-                    </archive>
-                    <webResources>
-                        <resource>
-                            <filtering>false</filtering>
-                            <directory>${basedir}/src/main/webapp</directory>
-                        </resource>
-                    </webResources>
-                </configuration>
-            </plugin>
-
-            <plugin>
-                <groupId>org.codehaus.mojo</groupId>
-                <artifactId>build-helper-maven-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <id>add-gwt-source</id>
-                        <phase>generate-sources</phase>
-                        <goals>
-                            <goal>add-source</goal>
-                        </goals>
-                        <configuration>
-                            <sources>
-                                <source>${basedir}/target/generated-sources/gwt</source>
-                            </sources>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
+            <id>default-cli</id>
+            <goals>
+              <goal>debug</goal>
+            </goals>
+            <configuration>
+              <module>org.rhq.enterprise.gui.coregui.CoreGUI</module>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+
+      <plugin>
+        <artifactId>maven-war-plugin</artifactId>
+        <configuration>
+          <archive>
+            <manifest>
+              <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
+              <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
+            </manifest>
+            <manifestEntries>
+              <Build-Number>${buildNumber}</Build-Number>
+            </manifestEntries>
+          </archive>
+          <webResources>
+            <resource>
+              <filtering>false</filtering>
+              <directory>${basedir}/src/main/webapp</directory>
+            </resource>
+          </webResources>
+        </configuration>
+      </plugin>
+
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>build-helper-maven-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>add-gwt-source</id>
+            <phase>generate-sources</phase>
+            <goals>
+              <goal>add-source</goal>
+            </goals>
+            <configuration>
+              <sources>
+                <source>${basedir}/target/generated-sources/gwt</source>
+              </sources>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
 
             <!--
                <plugin>
@@ -406,36 +407,36 @@
                   </executions>
                </plugin>
             -->
-        </plugins>
+    </plugins>
 
-    </build>
+  </build>
 
 
-    <profiles>
-        <profile>
-            <id>dev</id>
+  <profiles>
+    <profile>
+      <id>dev</id>
 
-            <properties>
-                <rhq.rootDir>../../../..</rhq.rootDir>
-                <rhq.containerDir>${rhq.rootDir}/${rhq.defaultDevContainerPath}</rhq.containerDir>
-                <rhq.deploymentName>${project.build.finalName}.war</rhq.deploymentName>
-                <rhq.deploymentDir>
-                    ${rhq.containerDir}/jbossas/server/default/deploy/${rhq.earName}/${rhq.deploymentName}
+      <properties>
+        <rhq.rootDir>../../../..</rhq.rootDir>
+        <rhq.containerDir>${rhq.rootDir}/${rhq.defaultDevContainerPath}</rhq.containerDir>
+        <rhq.deploymentName>${project.build.finalName}.war</rhq.deploymentName>
+        <rhq.deploymentDir>
+          ${rhq.containerDir}/jbossas/server/default/deploy/${rhq.earName}/${rhq.deploymentName}
                 </rhq.deploymentDir>
-            </properties>
+      </properties>
 
-            <build>
-                <plugins>
+      <build>
+        <plugins>
 
-                    <plugin>
-                        <artifactId>maven-antrun-plugin</artifactId>
-                        <executions>
+          <plugin>
+            <artifactId>maven-antrun-plugin</artifactId>
+            <executions>
 
-                            <execution>
-                                <id>deploy-classes</id>
-                                <phase>compile</phase>
-                                <configuration>
-                                    <target>
+              <execution>
+                <id>deploy-classes</id>
+                <phase>compile</phase>
+                <configuration>
+                  <target>
                                         <!--
                                         <property name="classes.dir" location="${rhq.deploymentDir}/WEB-INF/classes" />
                                         <echo>*** Copying updated files from target/${project.buildNodes.finalName}/WEB-INF/classes to ${classes.dir}...</echo>
@@ -443,126 +444,126 @@
                                            <fileset dir="war/WEB-INF/classes" />
                                         </copy>
                                         -->
-                                        <property name="deployment.dir" location="${rhq.deploymentDir}" />
-                                        <echo>*** Copying updated files from
-                                            src${file.separator}main${file.separator}webapp${file.separator} to
-                                            ${deployment.dir}${file.separator}...
+                    <property name="deployment.dir" location="${rhq.deploymentDir}"/>
+                    <echo>*** Copying updated files from
+                      src${file.separator}main${file.separator}webapp${file.separator} to
+                      ${deployment.dir}${file.separator}...
                                         </echo>
-                                        <copy todir="${deployment.dir}" verbose="${rhq.verbose}">
-                                            <fileset dir="${basedir}/src/main/webapp" />
-                                        </copy>
-                                    </target>
-                                </configuration>
-                                <goals>
-                                    <goal>run</goal>
-                                </goals>
-                            </execution>
-
-                            <execution>
-                                <id>deploy</id>
-                                <phase>package</phase>
-                                <configuration>
-                                    <target>
-                                        <property name="deployment.dir" location="${rhq.deploymentDir}" />
-                                        <echo>*** Copying updated files from
-                                            target${file.separator}${project.build.finalName}${file.separator} to
-                                            ${deployment.dir}${file.separator}...
+                    <copy todir="${deployment.dir}" verbose="${rhq.verbose}">
+                      <fileset dir="${basedir}/src/main/webapp"/>
+                    </copy>
+                  </target>
+                </configuration>
+                <goals>
+                  <goal>run</goal>
+                </goals>
+              </execution>
+
+              <execution>
+                <id>deploy</id>
+                <phase>package</phase>
+                <configuration>
+                  <target>
+                    <property name="deployment.dir" location="${rhq.deploymentDir}"/>
+                    <echo>*** Copying updated files from
+                      target${file.separator}${project.build.finalName}${file.separator} to
+                      ${deployment.dir}${file.separator}...
                                         </echo>
-                                        <copy todir="${deployment.dir}" verbose="${rhq.verbose}">
-                                            <fileset dir="${basedir}/target/${project.build.finalName}" />
-                                        </copy>
-                                    </target>
-                                </configuration>
-                                <goals>
-                                    <goal>run</goal>
-                                </goals>
-                            </execution>
-
-                            <execution>
-                                <id>undeploy</id>
-                                <phase>clean</phase>
-                                <configuration>
-                                    <target>
-                                        <property name="deployment.dir" location="${rhq.deploymentDir}" />
-                                        <echo>*** Deleting ${deployment.dir}${file.separator}...</echo>
-                                        <delete dir="${deployment.dir}" />
-                                    </target>
-                                </configuration>
-                                <goals>
-                                    <goal>run</goal>
-                                </goals>
-                            </execution>
-
-                        </executions>
-                    </plugin>
-
-                </plugins>
-            </build>
-        </profile>
+                    <copy todir="${deployment.dir}" verbose="${rhq.verbose}">
+                      <fileset dir="${basedir}/target/${project.build.finalName}"/>
+                    </copy>
+                  </target>
+                </configuration>
+                <goals>
+                  <goal>run</goal>
+                </goals>
+              </execution>
+
+              <execution>
+                <id>undeploy</id>
+                <phase>clean</phase>
+                <configuration>
+                  <target>
+                    <property name="deployment.dir" location="${rhq.deploymentDir}"/>
+                    <echo>*** Deleting ${deployment.dir}${file.separator}...</echo>
+                    <delete dir="${deployment.dir}"/>
+                  </target>
+                </configuration>
+                <goals>
+                  <goal>run</goal>
+                </goals>
+              </execution>
+
+            </executions>
+          </plugin>
+
+        </plugins>
+      </build>
+    </profile>
 
         <!--  Change the runTarget to not have single quotes. The quotes work for linux but not win -->
-        <profile>
-            <id>windows</id>
-            <activation>
-               <os>
-                  <family>Windows</family>
-               </os>
-            </activation>
-            <properties>
-               <coreGuiRunTarget>http://localhost:7080/coregui/CoreGUI.html${coreGuiParams}</coreGuiRunTarget>
-            </properties>
-        </profile>
-
-        <profile>
-            <id>msg</id>
-            <build>
-                <plugins>
-                  <plugin>
-                    <artifactId>maven-compiler-plugin</artifactId>
-                    <configuration>
-                       <includes>
-                           <include>org/rhq/enterprise/gui/coregui/client/Messages*.java</include>
-                       </includes>
-                    </configuration>
-                  </plugin>
-                </plugins>
-              </build>
-        </profile>
-
-      <profile>
-        <id>disable-tags</id>
-        <activation>       
-          <property>
-            <name>brew</name>            
-          </property>
-        </activation>       
-        <properties>
-          <enable.tags>false</enable.tags>
-        </properties>
-      </profile>
-
-    </profiles>
-
-
-    <repositories>
-        <repository>
-            <id>smartgwt</id>
-            <name>SmartGWT Releases</name>
-            <url>http://www.smartclient.com/maven2/</url>
-            <snapshots>
-               <enabled>false</enabled>
-            </snapshots>
-        </repository>
-
-        <repository>
-            <id>codehaus</id>
-            <name>Codehaus Releases</name>
-            <url>http://repository.codehaus.org/</url>
-            <snapshots>
-               <enabled>false</enabled>
-            </snapshots>
-        </repository>
-
-    </repositories>
+    <profile>
+      <id>windows</id>
+      <activation>
+        <os>
+          <family>Windows</family>
+        </os>
+      </activation>
+      <properties>
+        <coreGuiRunTarget>http://localhost:7080/coregui/CoreGUI.html${coreGuiParams}</coreGuiRunTarget>
+      </properties>
+    </profile>
+
+    <profile>
+      <id>msg</id>
+      <build>
+        <plugins>
+          <plugin>
+            <artifactId>maven-compiler-plugin</artifactId>
+            <configuration>
+              <includes>
+                <include>org/rhq/enterprise/gui/coregui/client/Messages*.java</include>
+              </includes>
+            </configuration>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+
+    <profile>
+      <id>disable-tags</id>
+      <activation>
+        <property>
+          <name>brew</name>
+        </property>
+      </activation>
+      <properties>
+        <enable.tags>false</enable.tags>
+      </properties>
+    </profile>
+
+  </profiles>
+
+
+  <repositories>
+    <repository>
+      <id>smartgwt</id>
+      <name>SmartGWT Releases</name>
+      <url>http://www.smartclient.com/maven2/</url>
+      <snapshots>
+        <enabled>false</enabled>
+      </snapshots>
+    </repository>
+
+    <repository>
+      <id>codehaus</id>
+      <name>Codehaus Releases</name>
+      <url>http://repository.codehaus.org/</url>
+      <snapshots>
+        <enabled>false</enabled>
+      </snapshots>
+    </repository>
+
+  </repositories>
 
 </project>
diff --git a/modules/enterprise/server/jar/pom.xml b/modules/enterprise/server/jar/pom.xml
index bf10fc1..aa0aad3 100644
--- a/modules/enterprise/server/jar/pom.xml
+++ b/modules/enterprise/server/jar/pom.xml
@@ -1,95 +1,96 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 
-   <modelVersion>4.0.0</modelVersion>
+  <modelVersion>4.0.0</modelVersion>
 
-   <parent>
-      <groupId>org.rhq</groupId>
-      <artifactId>rhq-parent</artifactId>
-      <version>4.5.0-SNAPSHOT</version>
-      <relativePath>../../../../pom.xml</relativePath>
-   </parent>
+  <parent>
+    <groupId>org.rhq</groupId>
+    <artifactId>rhq-parent</artifactId>
+    <version>4.5.0-SNAPSHOT</version>
+    <relativePath>../../../../pom.xml</relativePath>
+  </parent>
 
-   <artifactId>rhq-enterprise-server</artifactId>
-   <packaging>ejb</packaging>
+  <artifactId>rhq-enterprise-server</artifactId>
+  <packaging>ejb</packaging>
 
-   <name>RHQ Enterprise Server JAR</name>
-   <description>RHQ enterprise server main JAR</description>
+  <name>RHQ Enterprise Server JAR</name>
+  <description>RHQ enterprise server main JAR</description>
 
-   <properties>
-      <rhq.server.datasource>java:/RHQDS</rhq.server.datasource>
-      <rhq.server.ds-mapping>PostgreSQL</rhq.server.ds-mapping>
+  <properties>
+    <rhq.server.datasource>java:/RHQDS</rhq.server.datasource>
+    <rhq.server.ds-mapping>PostgreSQL</rhq.server.ds-mapping>
 
       <!-- dependency versions -->
-      <jboss-embeddable-ejb3.version>1.0.0.Alpha9</jboss-embeddable-ejb3.version>
+    <jboss-embeddable-ejb3.version>1.0.0.Alpha9</jboss-embeddable-ejb3.version>
 
-      <clean.db>true</clean.db>
-   </properties>
+    <clean.db>true</clean.db>
+  </properties>
 
-   <dependencies>
+  <dependencies>
 
       <!-- Internal Deps -->
 
-      <dependency>
-         <groupId>org.rhq</groupId>
-         <artifactId>rhq-enterprise-comm</artifactId>
-         <version>${project.version}</version>
-      </dependency>
-
-      <dependency>
-         <groupId>org.rhq</groupId>
-         <artifactId>rhq-enterprise-server-xml-schemas</artifactId>
-         <version>${project.version}</version>
-      </dependency>
-
-      <dependency>
-         <groupId>org.rhq</groupId>
-         <artifactId>rhq-core-domain</artifactId>
-         <version>${project.version}</version>
-         <scope>provided</scope> <!-- by ear -->
-      </dependency>
-
-      <dependency>
-         <groupId>org.rhq</groupId>
-         <artifactId>rhq-core-client-api</artifactId>
-         <version>${project.version}</version>
-      </dependency>
-
-      <dependency>
-         <groupId>org.rhq</groupId>
-         <artifactId>rhq-core-dbutils</artifactId>
-         <version>${project.version}</version>
-         <exclusions>
-            <exclusion>
-              <groupId>ant</groupId>
-              <artifactId>ant</artifactId>
-            </exclusion>
-         </exclusions>
-      </dependency>
-
-      <dependency>
-         <groupId>org.rhq</groupId>
-         <artifactId>safe-invoker</artifactId>
-         <version>${project.version}</version>
-      </dependency>
-
-      <dependency>
-         <groupId>org.rhq</groupId>
-         <artifactId>rhq-common-drift</artifactId>
-         <version>${project.version}</version>
-      </dependency>
-
-      <dependency>
-         <groupId>${project.groupId}</groupId>
-         <artifactId>rhq-container-lib</artifactId>
-         <version>${project.version}</version>
-         <scope>provided</scope>
-      </dependency>
-
-       <dependency>
-           <groupId>com.googlecode.java-diff-utils</groupId>
-           <artifactId>diffutils</artifactId>
-           <version>1.2.1</version>
-       </dependency>
+    <dependency>
+      <groupId>org.rhq</groupId>
+      <artifactId>rhq-enterprise-comm</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.rhq</groupId>
+      <artifactId>rhq-enterprise-server-xml-schemas</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.rhq</groupId>
+      <artifactId>rhq-core-domain</artifactId>
+      <version>${project.version}</version>
+      <scope>provided</scope> <!-- by ear -->
+    </dependency>
+
+    <dependency>
+      <groupId>org.rhq</groupId>
+      <artifactId>rhq-core-client-api</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.rhq</groupId>
+      <artifactId>rhq-core-dbutils</artifactId>
+      <version>${project.version}</version>
+      <exclusions>
+        <exclusion>
+          <groupId>ant</groupId>
+          <artifactId>ant</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+
+    <dependency>
+      <groupId>org.rhq</groupId>
+      <artifactId>safe-invoker</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.rhq</groupId>
+      <artifactId>rhq-common-drift</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>rhq-container-lib</artifactId>
+      <version>${project.version}</version>
+      <scope>provided</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>com.googlecode.java-diff-utils</groupId>
+      <artifactId>diffutils</artifactId>
+      <version>1.2.1</version>
+    </dependency>
 
 
       <!--================ Test Deps ================-->
@@ -99,1103 +100,1114 @@
            need the embeddable-ejb3 jar above the standard ejb3 jars because we need the embeddble packages
            loaded when testing.  -->
 
-      <dependency>
-         <groupId>org.rhq</groupId>
-         <artifactId>test-utils</artifactId>
-         <version>${project.version}</version>
-         <scope>test</scope>
-         <exclusions>
-            <exclusion>
-               <groupId>org.testng</groupId>
-               <artifactId>testng</artifactId>
-            </exclusion>
-         </exclusions>
-      </dependency>
-
-      <dependency>
-         <groupId>org.rhq</groupId>
-         <artifactId>rhq-core-domain</artifactId>
-         <version>${project.version}</version>
-         <type>test-jar</type>
-         <scope>test</scope>
-      </dependency>
-
-      <dependency>
-         <groupId>${project.groupId}</groupId>
-         <artifactId>rhq-core-client-api</artifactId>
-         <version>${project.version}</version>
-         <type>test-jar</type>
-         <scope>test</scope>
-      </dependency>
-
-      <dependency>
-        <groupId>org.rhq.helpers</groupId>
-        <artifactId>perftest-support</artifactId>
-        <version>${project.version}</version>
-        <scope>test</scope>
-        <exclusions>
-          <exclusion>
-            <groupId>ant</groupId>
-            <artifactId>ant</artifactId>
-          </exclusion>
-          <exclusion>
-            <groupId>ant</groupId>
-            <artifactId>ant-launcher</artifactId>
-          </exclusion>
-        </exclusions>
-      </dependency>
-
-      <dependency>
-         <groupId>jboss.jboss-embeddable-ejb3</groupId>
-         <artifactId>jboss-ejb3-all</artifactId>
-         <version>${jboss-embeddable-ejb3.version}</version>
-         <scope>test</scope>
-      </dependency>
+    <dependency>
+      <groupId>org.rhq</groupId>
+      <artifactId>test-utils</artifactId>
+      <version>${project.version}</version>
+      <scope>test</scope>
+      <exclusions>
+        <exclusion>
+          <groupId>org.testng</groupId>
+          <artifactId>testng</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+
+    <dependency>
+      <groupId>org.rhq</groupId>
+      <artifactId>rhq-core-domain</artifactId>
+      <version>${project.version}</version>
+      <type>test-jar</type>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>rhq-core-client-api</artifactId>
+      <version>${project.version}</version>
+      <type>test-jar</type>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.rhq.helpers</groupId>
+      <artifactId>perftest-support</artifactId>
+      <version>${project.version}</version>
+      <scope>test</scope>
+      <exclusions>
+        <exclusion>
+          <groupId>ant</groupId>
+          <artifactId>ant</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>ant</groupId>
+          <artifactId>ant-launcher</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+
+    <dependency>
+      <groupId>jboss.jboss-embeddable-ejb3</groupId>
+      <artifactId>jboss-ejb3-all</artifactId>
+      <version>${jboss-embeddable-ejb3.version}</version>
+      <scope>test</scope>
+    </dependency>
 
       <!-- NOTE: The remaining test deps correspond to the classes contained in hibernate-all.jar and thirdparty-all.jar. -->
 
-      <dependency>
-         <groupId>antlr</groupId>
-         <artifactId>antlr</artifactId>
-         <version>2.7.7</version>
-         <scope>test</scope>
-      </dependency>
+    <dependency>
+      <groupId>antlr</groupId>
+      <artifactId>antlr</artifactId>
+      <version>2.7.7</version>
+      <scope>test</scope>
+    </dependency>
 
-      <dependency>
-         <groupId>javassist</groupId>
-         <artifactId>javassist</artifactId>
+    <dependency>
+      <groupId>javassist</groupId>
+      <artifactId>javassist</artifactId>
          <!-- NOTE: The version is defined in the root POM's dependencyManagement section. -->
-         <scope>test</scope>
-      </dependency>
-
-      <dependency>
-         <groupId>trove</groupId>
-         <artifactId>trove</artifactId>
-         <version>1.0.2</version>
-         <scope>test</scope>
-      </dependency>
-
-      <dependency>
-         <groupId>xerces</groupId>
-         <artifactId>xercesImpl</artifactId>
-         <version>${xercesImpl.version}</version>
-         <scope>test</scope>
-      </dependency>
-
-       <dependency>
-           <groupId>net.sf.opencsv</groupId>
-           <artifactId>opencsv</artifactId>
-           <version>1.8</version>
-           <scope>test</scope>
-       </dependency>
-
-       <dependency>
-           <groupId>commons-jxpath</groupId>
-           <artifactId>commons-jxpath</artifactId>
-           <version>1.3</version>
-           <scope>test</scope>
-       </dependency>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>trove</groupId>
+      <artifactId>trove</artifactId>
+      <version>1.0.2</version>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>xerces</groupId>
+      <artifactId>xercesImpl</artifactId>
+      <version>${xercesImpl.version}</version>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>net.sf.opencsv</groupId>
+      <artifactId>opencsv</artifactId>
+      <version>1.8</version>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>commons-jxpath</groupId>
+      <artifactId>commons-jxpath</artifactId>
+      <version>1.3</version>
+      <scope>test</scope>
+    </dependency>
 
 
       <!-- 3rd Party Deps -->
 
-      <dependency>
-         <groupId>org.antlr</groupId>
-         <artifactId>antlr</artifactId>
-         <version>3.2</version>
-      </dependency>
+    <dependency>
+      <groupId>org.antlr</groupId>
+      <artifactId>antlr</artifactId>
+      <version>3.2</version>
+    </dependency>
 
       <!-- Required by a couple APL and Lather classes - TODO: Remove this once APL and Lather have been excised. -->
-      <dependency>
-         <groupId>commons-beanutils</groupId>
-         <artifactId>commons-beanutils</artifactId>
-         <version>1.6.1</version>
-      </dependency>
+    <dependency>
+      <groupId>commons-beanutils</groupId>
+      <artifactId>commons-beanutils</artifactId>
+      <version>1.6.1</version>
+    </dependency>
 
       <!-- Required by a couple APL classes - TODO: Remove this once APL has been removed. -->
       <!-- also required by EJB3 Embedded (test scope) -->
-      <dependency>
-         <groupId>commons-collections</groupId>
-         <artifactId>commons-collections</artifactId>
-         <version>3.2</version>
-      </dependency>
-
-      <dependency>
-         <groupId>commons-httpclient</groupId>
-         <artifactId>commons-httpclient</artifactId>
-         <version>3.0.1</version>
-      </dependency>
-
-      <dependency>
-        <groupId>commons-lang</groupId>
-         <artifactId>commons-lang</artifactId>
-         <version>2.4</version>
-      </dependency>
+    <dependency>
+      <groupId>commons-collections</groupId>
+      <artifactId>commons-collections</artifactId>
+      <version>3.2</version>
+    </dependency>
+
+    <dependency>
+      <groupId>commons-httpclient</groupId>
+      <artifactId>commons-httpclient</artifactId>
+      <version>3.0.1</version>
+    </dependency>
+
+    <dependency>
+      <groupId>commons-lang</groupId>
+      <artifactId>commons-lang</artifactId>
+      <version>2.4</version>
+    </dependency>
 
       <!-- Required by a couple APL classes - TODO: Remove this once APL has been removed. -->
-      <dependency>
-         <groupId>commons-validator</groupId>
-         <artifactId>commons-validator</artifactId>
-         <version>1.1.4</version>
-      </dependency>
+    <dependency>
+      <groupId>commons-validator</groupId>
+      <artifactId>commons-validator</artifactId>
+      <version>1.1.4</version>
+    </dependency>
 
       <!-- required by RHQ server classes, as well as EJB3 Embedded -->
-      <dependency>
-         <groupId>dom4j</groupId>
-         <artifactId>dom4j</artifactId>
-         <version>1.6.1-jboss</version>
-         <scope>runtime</scope>
-      </dependency>
-
-      <dependency>
-         <groupId>gnu-getopt</groupId>
-         <artifactId>getopt</artifactId>
+    <dependency>
+      <groupId>dom4j</groupId>
+      <artifactId>dom4j</artifactId>
+      <version>1.6.1-jboss</version>
+      <scope>runtime</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>gnu-getopt</groupId>
+      <artifactId>getopt</artifactId>
          <!-- NOTE: The version is defined in the root POM's dependencyManagement section. -->
-      </dependency>
+    </dependency>
 
-      <dependency>
-         <groupId>hibernate</groupId>
-         <artifactId>hibernate3</artifactId>
+    <dependency>
+      <groupId>hibernate</groupId>
+      <artifactId>hibernate3</artifactId>
          <!-- NOTE: The version is defined in the root POM's dependencyManagement section. -->
-         <scope>provided</scope> <!-- by JBossAS -->
-      </dependency>
+      <scope>provided</scope> <!-- by JBossAS -->
+    </dependency>
 
-      <dependency>
-         <groupId>hibernate-annotations</groupId>
-         <artifactId>hibernate-annotations</artifactId>
+    <dependency>
+      <groupId>hibernate-annotations</groupId>
+      <artifactId>hibernate-annotations</artifactId>
          <!-- NOTE: The version is defined in the root POM's dependencyManagement section. -->
-         <scope>provided</scope> <!-- by JBossAS -->
-      </dependency>
+      <scope>provided</scope> <!-- by JBossAS -->
+    </dependency>
 
-      <dependency>
-         <groupId>hibernate-entitymanager</groupId>
-         <artifactId>hibernate-entitymanager</artifactId>
+    <dependency>
+      <groupId>hibernate-entitymanager</groupId>
+      <artifactId>hibernate-entitymanager</artifactId>
          <!-- NOTE: The version is defined in the root POM's dependencyManagement section. -->
-         <scope>provided</scope> <!-- by JBossAS -->
-      </dependency>
+      <scope>provided</scope> <!-- by JBossAS -->
+    </dependency>
 
-      <dependency>
-         <groupId>i18nlog</groupId>
-         <artifactId>i18nlog</artifactId>
-      </dependency>
+    <dependency>
+      <groupId>i18nlog</groupId>
+      <artifactId>i18nlog</artifactId>
+    </dependency>
 
-      <dependency>
-         <groupId>org.apache.geronimo.specs</groupId>
-         <artifactId>geronimo-javamail_1.3.1_spec</artifactId>
+    <dependency>
+      <groupId>org.apache.geronimo.specs</groupId>
+      <artifactId>geronimo-javamail_1.3.1_spec</artifactId>
          <!-- The Sun javamail jar isn't available from a public repo due to licensing issues,
               so use the Geronimo one instead. -->
-         <version>1.3</version>
-         <scope>provided</scope> <!-- by JBossAS -->
-      </dependency>
-
-      <dependency>
-         <groupId>javax.persistence</groupId>
-         <artifactId>persistence-api</artifactId>
-         <version>1.0</version>
-         <scope>provided</scope> <!-- by JBossAS -->
-      </dependency>
-
-      <dependency>
-         <groupId>javax.servlet</groupId>
-         <artifactId>servlet-api</artifactId>
-         <version>2.4</version>
-         <scope>provided</scope> <!-- by JBossAS -->
-      </dependency>
-
-      <dependency>
-         <groupId>javax.servlet</groupId>
-         <artifactId>jsp-api</artifactId>
-         <version>2.0</version>
-         <scope>provided</scope> <!-- by JBossAS -->
-      </dependency>
-
-      <dependency>
-         <groupId>jboss</groupId>
-         <artifactId>jboss-annotations-ejb3</artifactId>
+      <version>1.3</version>
+      <scope>provided</scope> <!-- by JBossAS -->
+    </dependency>
+
+    <dependency>
+      <groupId>javax.persistence</groupId>
+      <artifactId>persistence-api</artifactId>
+      <version>1.0</version>
+      <scope>provided</scope> <!-- by JBossAS -->
+    </dependency>
+
+    <dependency>
+      <groupId>javax.servlet</groupId>
+      <artifactId>servlet-api</artifactId>
+      <version>2.4</version>
+      <scope>provided</scope> <!-- by JBossAS -->
+    </dependency>
+
+    <dependency>
+      <groupId>javax.servlet</groupId>
+      <artifactId>jsp-api</artifactId>
+      <version>2.0</version>
+      <scope>provided</scope> <!-- by JBossAS -->
+    </dependency>
+
+    <dependency>
+      <groupId>jboss</groupId>
+      <artifactId>jboss-annotations-ejb3</artifactId>
          <!-- NOTE: The version is defined in the root POM's dependencyManagement section. -->
-         <scope>provided</scope> <!-- by JBossAS -->
-      </dependency>
+      <scope>provided</scope> <!-- by JBossAS -->
+    </dependency>
 
-      <dependency>
-         <groupId>jboss</groupId>
-         <artifactId>jboss-cache</artifactId>
+    <dependency>
+      <groupId>jboss</groupId>
+      <artifactId>jboss-cache</artifactId>
          <!-- NOTE: The version is defined in the root POM's dependencyManagement section. -->
-         <scope>compile</scope>
-      </dependency>
+      <scope>compile</scope>
+    </dependency>
 
-      <dependency>
-         <groupId>jboss</groupId>
-         <artifactId>jboss-common</artifactId>
+    <dependency>
+      <groupId>jboss</groupId>
+      <artifactId>jboss-common</artifactId>
          <!-- NOTE: The version is defined in the root POM's dependencyManagement section. -->
-         <scope>provided</scope> <!-- by JBossAS -->
-      </dependency>
+      <scope>provided</scope> <!-- by JBossAS -->
+    </dependency>
 
-      <dependency>
-         <groupId>jboss</groupId>
-         <artifactId>jboss-ejb3x</artifactId>
+    <dependency>
+      <groupId>jboss</groupId>
+      <artifactId>jboss-ejb3x</artifactId>
          <!-- NOTE: The version is defined in the root POM's dependencyManagement section. -->
-         <scope>provided</scope> <!-- by JBossAS -->
-      </dependency>
+      <scope>provided</scope> <!-- by JBossAS -->
+    </dependency>
 
       <!-- includes the org.jboss.ejb3.StrictMaxPool class, which is needed by the PoolClass annotation used on some
            of our SLSB's -->
-      <dependency>
-         <groupId>jboss</groupId>
-         <artifactId>jboss-ejb3</artifactId>
+    <dependency>
+      <groupId>jboss</groupId>
+      <artifactId>jboss-ejb3</artifactId>
          <!-- NOTE: The version is defined in the root POM's dependencyManagement section. -->
-         <scope>provided</scope> <!-- by JBossAS -->
-      </dependency>
+      <scope>provided</scope> <!-- by JBossAS -->
+    </dependency>
 
-      <dependency>
-         <groupId>jboss</groupId>
-         <artifactId>jboss-j2ee</artifactId>
+    <dependency>
+      <groupId>jboss</groupId>
+      <artifactId>jboss-j2ee</artifactId>
          <!-- NOTE: The version is defined in the root POM's dependencyManagement section. -->
-         <scope>provided</scope> <!-- by JBossAS -->
-      </dependency>
+      <scope>provided</scope> <!-- by JBossAS -->
+    </dependency>
 
-      <dependency>
-         <groupId>jboss</groupId>
-         <artifactId>jboss-jmx</artifactId>
+    <dependency>
+      <groupId>jboss</groupId>
+      <artifactId>jboss-jmx</artifactId>
          <!-- NOTE: The version is defined in the root POM's dependencyManagement section. -->
-         <scope>provided</scope> <!-- by JBossAS -->
-      </dependency>
+      <scope>provided</scope> <!-- by JBossAS -->
+    </dependency>
 
-      <dependency>
-         <groupId>jboss</groupId>
-         <artifactId>jboss-system</artifactId>
+    <dependency>
+      <groupId>jboss</groupId>
+      <artifactId>jboss-system</artifactId>
          <!-- NOTE: The version is defined in the root POM's dependencyManagement section. -->
-         <scope>provided</scope> <!-- by JBossAS -->
-      </dependency>
+      <scope>provided</scope> <!-- by JBossAS -->
+    </dependency>
 
-      <dependency>
-         <groupId>jboss</groupId>
-         <artifactId>jbosssx</artifactId>
+    <dependency>
+      <groupId>jboss</groupId>
+      <artifactId>jbosssx</artifactId>
          <!-- NOTE: The version is defined in the root POM's dependencyManagement section. -->
-         <scope>provided</scope> <!-- by JBossAS -->
-      </dependency>
+      <scope>provided</scope> <!-- by JBossAS -->
+    </dependency>
 
-      <dependency>
-         <groupId>jboss</groupId>
-         <artifactId>jbpm</artifactId>
-         <version>3.1.1</version>
-      </dependency>
+    <dependency>
+      <groupId>jboss</groupId>
+      <artifactId>jbpm</artifactId>
+      <version>3.1.1</version>
+    </dependency>
 
       <!-- for the transaction interrupt EJB3 interceptor -->
-      <dependency>
-         <groupId>org.jboss.transaction</groupId>
-         <artifactId>jboss-jta</artifactId>
+    <dependency>
+      <groupId>org.jboss.transaction</groupId>
+      <artifactId>jboss-jta</artifactId>
          <!-- NOTE: The version is defined in the root POM's dependencyManagement section. -->
-         <scope>provided</scope> <!-- by JBossAS -->
-      </dependency>
+      <scope>provided</scope> <!-- by JBossAS -->
+    </dependency>
 
       <!-- TODO: remove this - tests should all be moved under the test source tree -->
-      <dependency>
-         <groupId>junit</groupId>
-         <artifactId>junit</artifactId>
-         <version>3.8.1</version>
-      </dependency>
-
-      <dependency>
-         <groupId>org.opensymphony.quartz</groupId>
-         <artifactId>quartz</artifactId>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>3.8.1</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.opensymphony.quartz</groupId>
+      <artifactId>quartz</artifactId>
          <!-- NOTE: The version is defined in the root POM's dependencyManagement section. -->
-         <scope>provided</scope> <!-- by JBossAS itself, which the container build has packaged with 1.6.5 -->
-      </dependency>
+      <scope>provided</scope> <!-- by JBossAS itself, which the container build has packaged with 1.6.5 -->
+    </dependency>
 
-      <dependency>
-         <groupId>org.opensymphony.quartz</groupId>
-         <artifactId>quartz-oracle</artifactId>
+    <dependency>
+      <groupId>org.opensymphony.quartz</groupId>
+      <artifactId>quartz-oracle</artifactId>
          <!-- NOTE: The version is defined in the root POM's dependencyManagement section. -->
-         <scope>provided</scope> <!-- by JBossAS itself, which the container build has packaged with 1.6.5 -->
-      </dependency>
-
-      <dependency>
-         <groupId>org.easymock</groupId>
-         <artifactId>easymockclassextension</artifactId>
-         <version>2.2</version>
-         <scope>test</scope>
+      <scope>provided</scope> <!-- by JBossAS itself, which the container build has packaged with 1.6.5 -->
+    </dependency>
+
+    <dependency>
+      <groupId>org.easymock</groupId>
+      <artifactId>easymockclassextension</artifactId>
+      <version>2.2</version>
+      <scope>test</scope>
          <!-- somehow this is needed otherwise the hibernate stuff doesn't initialize in our tests -->
-      </dependency>
+    </dependency>
 
-      <dependency>
-         <groupId>org.snmp4j</groupId>
-         <artifactId>snmp4j</artifactId>
-         <version>1.8.2</version>
-      </dependency>
+    <dependency>
+      <groupId>org.snmp4j</groupId>
+      <artifactId>snmp4j</artifactId>
+      <version>1.8.2</version>
+    </dependency>
 
       <!-- required by RHQ server classes, as well as EJB3 Embedded -->
-      <dependency>
-         <groupId>oswego-concurrent</groupId>
-         <artifactId>concurrent</artifactId>
-         <version>1.3.4</version>
-      </dependency>
+    <dependency>
+      <groupId>oswego-concurrent</groupId>
+      <artifactId>concurrent</artifactId>
+      <version>1.3.4</version>
+    </dependency>
 
       <!-- TODO: Why is this needed? -->
-      <dependency>
-         <groupId>postgresql</groupId>
-         <artifactId>postgresql</artifactId>
+    <dependency>
+      <groupId>postgresql</groupId>
+      <artifactId>postgresql</artifactId>
          <!--<scope>test</scope>-->
-      </dependency>
-
-      <dependency>
-         <groupId>rss4j</groupId>
-         <artifactId>rss4j</artifactId>
-         <version>0.92-on.2</version>
-      </dependency>
-
-      <dependency>
-         <groupId>tomcat</groupId>
-         <artifactId>catalina</artifactId>
-         <version>5.5.20</version>
-         <scope>provided</scope>
-      </dependency>
-
-      <dependency>
-         <groupId>tomcat</groupId>
-         <artifactId>tomcat-jk</artifactId>
-         <version>4.1.31</version>
-         <scope>provided</scope>
-      </dependency>
+    </dependency>
+
+    <dependency>
+      <groupId>rss4j</groupId>
+      <artifactId>rss4j</artifactId>
+      <version>0.92-on.2</version>
+    </dependency>
+
+    <dependency>
+      <groupId>tomcat</groupId>
+      <artifactId>catalina</artifactId>
+      <version>5.5.20</version>
+      <scope>provided</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>tomcat</groupId>
+      <artifactId>tomcat-jk</artifactId>
+      <version>4.1.31</version>
+      <scope>provided</scope>
+    </dependency>
 
       <!-- Needed by com.jboss.jbossnetwork.apl.actions.xml.XPathProcessor; TODO: Remove once APL has been excised. -->
-      <dependency>
-         <groupId>xalan</groupId>
-         <artifactId>xalan</artifactId>
-         <version>2.5.1</version>
-         <scope>provided</scope>
-      </dependency>
-
-       <dependency>
-           <groupId>com.jcraft</groupId>
-           <artifactId>jsch</artifactId>
-           <version>0.1.29</version>
-       </dependency>
-
-       <dependency>
-           <groupId>org.jboss.resteasy</groupId>
-           <artifactId>resteasy-jaxrs</artifactId>
-           <version>${resteasy.version}</version>
-           <scope>provided</scope> <!-- by container -->
-       </dependency>
-       <dependency>
-           <groupId>org.jboss.resteasy</groupId>
-           <artifactId>resteasy-jackson-provider</artifactId>
-           <version>${resteasy.version}</version>
-           <scope>provided</scope> <!-- by container -->
-       </dependency>
-       <dependency>
-           <groupId>org.jboss.resteasy</groupId>
-           <artifactId>resteasy-links</artifactId>
-           <version>${resteasy.version}</version>
-           <scope>provided</scope> <!-- by container -->
-       </dependency>
-       <dependency>
-             <groupId>org.jboss.resteasy</groupId>
-             <artifactId>resteasy-yaml-provider</artifactId>
-             <version>${resteasy.version}</version>
-           <scope>provided</scope>
-       </dependency>
-       <dependency>
-           <groupId>org.jboss.resteasy</groupId>
-           <artifactId>resteasy-jaxb-provider</artifactId>
-           <version>${resteasy.version}</version>
-           <scope>provided</scope>
-           <exclusions>
-               <exclusion>
-                   <groupId>com.sun.xml.bind</groupId>
-                   <artifactId>jaxb-impl</artifactId>
-               </exclusion>
-               <exclusion>
-                   <groupId>com.sun.xml.stream</groupId>
-                   <artifactId>sjsxp</artifactId>
-               </exclusion>
-           </exclusions>
-       </dependency>
-     <dependency>
-       <groupId>com.wordnik</groupId>
-       <artifactId>swagger-annotations_2.9.1</artifactId>
-       <version>1.1-SNAPSHOT</version>
-     </dependency>
-     <dependency>
-       <groupId>org.rhq.helpers</groupId>
-       <artifactId>rest-docs-generator</artifactId>
-       <version>${project.version}</version>
-       <scope>compile</scope>
-     </dependency>
-
-       <dependency>
-           <groupId>org.yaml</groupId>
-           <artifactId>snakeyaml</artifactId>
-           <version>1.8</version>
-       </dependency>
-       <dependency>
-           <groupId>org.jboss.el</groupId>
-           <artifactId>jboss-el</artifactId>
-           <version>2.0.1.GA</version>
-           <scope>provided</scope>
-       </dependency>
-       <dependency>
-           <groupId>org.freemarker</groupId>
-           <artifactId>freemarker</artifactId>
-           <version>2.3.18</version>
-           <scope>provided</scope>
-       </dependency>
-
-       <dependency>
-          <groupId>org.powermock</groupId>
-          <artifactId>powermock-module-testng</artifactId>
-          <version>${powermock.version}</version>
-          <scope>test</scope>
-       </dependency>
-
-       <dependency>
-           <groupId>org.powermock</groupId>
-           <artifactId>powermock-api-mockito</artifactId>
-           <version>${powermock.version}</version>
-           <scope>test</scope>
-       </dependency>
-
-       <dependency>
-           <groupId>org.liquibase</groupId>
-           <artifactId>liquibase-core</artifactId>
-           <version>2.0.3</version>
-           <scope>test</scope>
-       </dependency>
-
-   </dependencies>
-
-   <build>
-      <finalName>${project.artifactId}</finalName>
-
-      <resources>
+    <dependency>
+      <groupId>xalan</groupId>
+      <artifactId>xalan</artifactId>
+      <version>2.5.1</version>
+      <scope>provided</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>com.jcraft</groupId>
+      <artifactId>jsch</artifactId>
+      <version>0.1.29</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.jboss.resteasy</groupId>
+      <artifactId>resteasy-jaxrs</artifactId>
+      <version>${resteasy.version}</version>
+      <scope>provided</scope> <!-- by container -->
+    </dependency>
+    <dependency>
+      <groupId>org.jboss.resteasy</groupId>
+      <artifactId>resteasy-jackson-provider</artifactId>
+      <version>${resteasy.version}</version>
+      <scope>provided</scope> <!-- by container -->
+    </dependency>
+    <dependency>
+      <groupId>org.jboss.resteasy</groupId>
+      <artifactId>resteasy-links</artifactId>
+      <version>${resteasy.version}</version>
+      <scope>provided</scope> <!-- by container -->
+    </dependency>
+    <dependency>
+      <groupId>org.jboss.resteasy</groupId>
+      <artifactId>resteasy-yaml-provider</artifactId>
+      <version>${resteasy.version}</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.jboss.resteasy</groupId>
+      <artifactId>resteasy-jaxb-provider</artifactId>
+      <version>${resteasy.version}</version>
+      <scope>provided</scope>
+      <exclusions>
+        <exclusion>
+          <groupId>com.sun.xml.bind</groupId>
+          <artifactId>jaxb-impl</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>com.sun.xml.stream</groupId>
+          <artifactId>sjsxp</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+    <dependency>
+      <groupId>com.wordnik</groupId>
+      <artifactId>swagger-annotations_2.9.1</artifactId>
+      <version>1.1-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.rhq.helpers</groupId>
+      <artifactId>rest-docs-generator</artifactId>
+      <version>${project.version}</version>
+      <scope>compile</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.yaml</groupId>
+      <artifactId>snakeyaml</artifactId>
+      <version>1.8</version>
+    </dependency>
+    <dependency>
+      <groupId>org.jboss.el</groupId>
+      <artifactId>jboss-el</artifactId>
+      <version>2.0.1.GA</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.freemarker</groupId>
+      <artifactId>freemarker</artifactId>
+      <version>2.3.18</version>
+      <scope>provided</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.powermock</groupId>
+      <artifactId>powermock-module-testng</artifactId>
+      <version>${powermock.version}</version>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.powermock</groupId>
+      <artifactId>powermock-api-mockito</artifactId>
+      <version>${powermock.version}</version>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.liquibase</groupId>
+      <artifactId>liquibase-core</artifactId>
+      <version>2.0.3</version>
+      <scope>test</scope>
+    </dependency>
+
+  </dependencies>
+
+  <build>
+    <finalName>${project.artifactId}</finalName>
+
+    <resources>
          <!-- Redefine which directories to treat like resources (which are filtered). -->
-         <resource>
-           <directory>src/main/filtered-sources/java</directory>
-           <filtering>true</filtering>
-           <targetPath>../filtered-sources/java</targetPath>
-         </resource>
-         <resource>
-            <directory>src/main/resources</directory>
-            <filtering>true</filtering>
-         </resource>
-      </resources>
-
-      <testResources>
-         <testResource>
-            <directory>src/test/resources</directory>
-            <filtering>true</filtering>
-         </testResource>
-      </testResources>
-
-      <plugins>
-        <plugin>
-           <groupId>org.apache.maven.plugins</groupId>
-           <artifactId>maven-ejb-plugin</artifactId>
-           <version>2.3</version>
-           <configuration>
-              <generateClient>true</generateClient>
-           </configuration>
-         </plugin>
-
-         <plugin>
-            <groupId>org.apache.maven.plugins</groupId>
-            <artifactId>maven-jar-plugin</artifactId>
-            <executions>
-               <execution>
-                  <phase>package</phase>
-                  <goals>
-                     <goal>test-jar</goal>
-                  </goals>
-               </execution>
-            </executions>
-         </plugin>
-
-         <plugin>
-            <artifactId>maven-antrun-plugin</artifactId>
-            <executions>
-
-               <execution>
-                  <phase>process-classes</phase>
-                  <configuration>
-                     <target>
+      <resource>
+        <directory>src/main/filtered-sources/java</directory>
+        <filtering>true</filtering>
+        <targetPath>../filtered-sources/java</targetPath>
+      </resource>
+      <resource>
+        <directory>src/main/resources</directory>
+        <filtering>true</filtering>
+      </resource>
+    </resources>
+
+    <testResources>
+      <testResource>
+        <directory>src/test/resources</directory>
+        <filtering>true</filtering>
+      </testResource>
+    </testResources>
+
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-ejb-plugin</artifactId>
+        <version>2.3</version>
+        <configuration>
+          <generateClient>true</generateClient>
+        </configuration>
+      </plugin>
+
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jar-plugin</artifactId>
+        <executions>
+          <execution>
+            <phase>package</phase>
+            <goals>
+              <goal>test-jar</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+
+      <plugin>
+        <artifactId>maven-antrun-plugin</artifactId>
+        <executions>
+
+          <execution>
+            <phase>process-classes</phase>
+            <configuration>
+              <target>
                         <!-- generate the I18N resource bundles -->
-                        <taskdef name="i18n" classpathref="maven.runtime.classpath" classname="mazz.i18n.ant.I18NAntTask" />
+                <taskdef name="i18n" classpathref="maven.runtime.classpath" classname="mazz.i18n.ant.I18NAntTask"/>
 
-                        <i18n outputdir="${project.build.outputDirectory}" defaultlocale="en" verbose="false" append="false" verify="true">
-                           <classpath refid="maven.runtime.classpath" />
-                           <classfileset dir="${project.build.outputDirectory}">
-                              <include name="**/ServerI18NResourceKeys.class" />
-                              <include name="**/AlertI18NResourceKeys.class" />
-                           </classfileset>
-                        </i18n>
+                <i18n outputdir="${project.build.outputDirectory}" defaultlocale="en" verbose="false" append="false"
+                  verify="true">
+                  <classpath refid="maven.runtime.classpath"/>
+                  <classfileset dir="${project.build.outputDirectory}">
+                    <include name="**/ServerI18NResourceKeys.class"/>
+                    <include name="**/AlertI18NResourceKeys.class"/>
+                  </classfileset>
+                </i18n>
 
                         <!-- create our rhq-server-version.properties file that goes in our jar -->
-                        <tstamp>
-                           <format property="build.time" pattern="dd.MMM.yyyy HH.mm.ss z" />
-                        </tstamp>
-
-                        <echo file="${project.build.outputDirectory}/rhq-server-version.properties" append="false">Product-Name=${rhq.product.name}
-Product-Version=${project.version}
-Module-Name=${project.name}
-Module-Version=${project.version}
-Build-Number=${buildNumber}
-Build-Date=${build.time}
-Build-Jdk-Vendor=${java.vendor}
-Build-Jdk=${java.version}
-Build-OS-Name=${os.name}
-Build-OS-Version=${os.version}
+                <tstamp>
+                  <format property="build.time" pattern="dd.MMM.yyyy HH.mm.ss z"/>
+                </tstamp>
+
+                <echo file="${project.build.outputDirectory}/rhq-server-version.properties" append="false">Product-Name=${rhq.product.name}
+                  Product-Version=${project.version}
+                  Module-Name=${project.name}
+                  Module-Version=${project.version}
+                  Build-Number=${buildNumber}
+                  Build-Date=${build.time}
+                  Build-Jdk-Vendor=${java.vendor}
+                  Build-Jdk=${java.version}
+                  Build-OS-Name=${os.name}
+                  Build-OS-Version=${os.version}
 </echo>
-                     </target>
-                  </configuration>
-                  <goals>
-                     <goal>run</goal>
-                  </goals>
-               </execution>
+              </target>
+            </configuration>
+            <goals>
+              <goal>run</goal>
+            </goals>
+          </execution>
 
                <!--  in order to get JMS to work properly in embedded test container, extract jms-rs.rar classes -->
-               <execution>
-                  <id>Extract JMS classes from RAR needed for JMS tests</id>
-                  <phase>process-classes</phase>
-                  <configuration>
-                     <target>
-                        <unzip src="src/test/resources/jms-ra.rar" dest="target">
-                           <patternset>
-                              <include name="jms-ra.jar"/>
-                           </patternset>
-                        </unzip>
-                        <unzip src="target/jms-ra.jar" dest="target/test-classes">
-                           <patternset>
-                              <include name="org/**"/>
-                           </patternset>
-                        </unzip>
-                     </target>
-                  </configuration>
-                  <goals>
-                     <goal>run</goal>
-                  </goals>
-               </execution>
+          <execution>
+            <id>Extract JMS classes from RAR needed for JMS tests</id>
+            <phase>process-classes</phase>
+            <configuration>
+              <target>
+                <unzip src="src/test/resources/jms-ra.rar" dest="target">
+                  <patternset>
+                    <include name="jms-ra.jar"/>
+                  </patternset>
+                </unzip>
+                <unzip src="target/jms-ra.jar" dest="target/test-classes">
+                  <patternset>
+                    <include name="org/**"/>
+                  </patternset>
+                </unzip>
+              </target>
+            </configuration>
+            <goals>
+              <goal>run</goal>
+            </goals>
+          </execution>
 
-            </executions>
-         </plugin>
+        </executions>
+      </plugin>
 
-         <plugin>
-           <artifactId>maven-surefire-plugin</artifactId>
+      <plugin>
+        <artifactId>maven-surefire-plugin</artifactId>
             <!-- Everything but the web service tests, this is the standard test execution -->
-           <configuration>
-               <skipTests>true</skipTests>
-               <excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
-               <groups>${rhq.testng.includedGroups}</groups>
-               <properties>
-                  <property>
-                     <name>listener</name>
-                     <value>org.rhq.test.testng.StdoutReporter</value>
-                  </property>
-               </properties>
-               <systemPropertyVariables>
-                  <embeddedDeployment>true</embeddedDeployment>
-                  <deploymentDirectory>target/classes</deploymentDirectory>
-                  <hibernate.dialect>${rhq.test.ds.hibernate-dialect}</hibernate.dialect>
-                  <clean.db>${clean.db}</clean.db>
-                  <log4j.configDebug>false</log4j.configDebug>
-               </systemPropertyVariables>
-               <additionalClasspathElements>
+        <configuration>
+          <skipTests>true</skipTests>
+          <excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
+          <groups>${rhq.testng.includedGroups}</groups>
+          <properties>
+            <property>
+              <name>listener</name>
+              <value>org.rhq.test.testng.StdoutReporter</value>
+            </property>
+          </properties>
+          <systemPropertyVariables>
+            <embeddedDeployment>true</embeddedDeployment>
+            <deploymentDirectory>target/classes</deploymentDirectory>
+            <hibernate.dialect>${rhq.test.ds.hibernate-dialect}</hibernate.dialect>
+            <clean.db>${clean.db}</clean.db>
+            <log4j.configDebug>false</log4j.configDebug>
+          </systemPropertyVariables>
+          <additionalClasspathElements>
                   <!-- The below is required for tests to run against Oracle. -->
-                  <additionalClasspathElement>${settings.localRepository}/com/oracle/ojdbc6/${ojdbc6.version}/ojdbc6-${ojdbc6.version}.jar</additionalClasspathElement>
-               </additionalClasspathElements>
+            <additionalClasspathElement>${settings.localRepository}/com/oracle/ojdbc6/${ojdbc6.version}/ojdbc6-${ojdbc6.version}.jar</additionalClasspathElement>
+          </additionalClasspathElements>
+        </configuration>
+
+        <executions>
+
+          <execution>
+            <id>allExceptDbTests</id>
+            <goals>
+              <goal>test</goal>
+            </goals>
+            <configuration>
+              <skipTests>${skipTests}</skipTests>
+              <excludes>
+                <exclude>com/**/*.java</exclude>
+                <exclude>org/rhq/**/performance/**/*.java</exclude>
+                <exclude>org/rhq/enterprise/server/db/**</exclude>
+              </excludes>
             </configuration>
-
-            <executions>
-
-                <execution>
-                    <id>allExceptDbTests</id>
-                    <goals>
-                        <goal>test</goal>
-                    </goals>
-                    <configuration>
-                        <skipTests>${skipTests}</skipTests>
-                        <excludes>
-                            <exclude>com/**/*.java</exclude>
-                            <exclude>org/rhq/**/performance/**/*.java</exclude>
-                            <exclude>org/rhq/enterprise/server/db/**</exclude>
-                        </excludes>
-                    </configuration>
-                </execution>
-
-            </executions>
-         </plugin>
-
-         <plugin>
-            <groupId>org.antlr</groupId>
-            <artifactId>antlr3-maven-plugin</artifactId>
-            <version>3.2</version>
-            <executions>
-               <execution>
-                  <phase>generate-sources</phase>
-                  <goals>
-                     <goal>antlr</goal>
-                  </goals>
-                  <configuration>
-                     <conversionTimeout>30000</conversionTimeout>
-                     <debug>false</debug>
-                     <dfa>false</dfa>
-                     <nfa>false</nfa>
-                     <excludes>
-
-                     </excludes>
-                     <includes>
-
-                     </includes>
-                     <libDirectory>src/main/antlr3/imports</libDirectory>
-                     <messageFormat>antlr</messageFormat>
-                     <outputDirectory>target/generated-sources/antlr3</outputDirectory>
-                     <printGrammar>false</printGrammar>
-                     <profile>false</profile>
-                     <report>false</report>
-                     <sourceDirectory>src/main/antlr3</sourceDirectory>
-                     <trace>false</trace>
-                     <verbose>true</verbose>
-                  </configuration>
-               </execution>
-            </executions>
-         </plugin>
-
-         <plugin>
-            <groupId>org.codehaus.mojo</groupId>
-            <artifactId>build-helper-maven-plugin</artifactId>
-            <executions>
-                <execution>
-                    <id>add-filtered-sources</id>
-                    <phase>generate-sources</phase>
-                    <goals>
-                        <goal>add-source</goal>
-                    </goals>
-                    <configuration>
-                        <sources>
-                            <source>target/filtered-sources/java</source>
-                        </sources>
-                    </configuration>
-                </execution>
-                <execution>
-                    <id>add-antlr-sources</id>
-                    <phase>generate-sources</phase>
-                    <goals>
-                        <goal>add-source</goal>
-                    </goals>
-                    <configuration>
-                        <sources>
-                            <source>${basedir}/target/generated-sources/antlr3</source>
-                        </sources>
-                    </configuration>
-                </execution>
-            </executions>
-         </plugin>
+          </execution>
+
+        </executions>
+      </plugin>
+
+      <plugin>
+        <groupId>org.antlr</groupId>
+        <artifactId>antlr3-maven-plugin</artifactId>
+        <version>3.2</version>
+        <executions>
+          <execution>
+            <phase>generate-sources</phase>
+            <goals>
+              <goal>antlr</goal>
+            </goals>
+            <configuration>
+              <conversionTimeout>30000</conversionTimeout>
+              <debug>false</debug>
+              <dfa>false</dfa>
+              <nfa>false</nfa>
+              <excludes>
+
+              </excludes>
+              <includes>
+
+              </includes>
+              <libDirectory>src/main/antlr3/imports</libDirectory>
+              <messageFormat>antlr</messageFormat>
+              <outputDirectory>target/generated-sources/antlr3</outputDirectory>
+              <printGrammar>false</printGrammar>
+              <profile>false</profile>
+              <report>false</report>
+              <sourceDirectory>src/main/antlr3</sourceDirectory>
+              <trace>false</trace>
+              <verbose>true</verbose>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>build-helper-maven-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>add-filtered-sources</id>
+            <phase>generate-sources</phase>
+            <goals>
+              <goal>add-source</goal>
+            </goals>
+            <configuration>
+              <sources>
+                <source>target/filtered-sources/java</source>
+              </sources>
+            </configuration>
+          </execution>
+          <execution>
+            <id>add-antlr-sources</id>
+            <phase>generate-sources</phase>
+            <goals>
+              <goal>add-source</goal>
+            </goals>
+            <configuration>
+              <sources>
+                <source>${basedir}/target/generated-sources/antlr3</source>
+              </sources>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
 
         <!-- Document generation from the Annotations on the REST-API. -->
         <!-- TODO move to a better suited processing phase -->
-        <plugin>
-          <groupId>org.bsc.maven</groupId>
-          <artifactId>maven-processor-plugin</artifactId>
-          <version>2.0.6-redhat</version>
-          <configuration>
-            <processors>
-              <processor>org.rhq.helpers.rest_docs_generator.ClassLevelProcessor</processor>
-            </processors>
-            <compilerArguments>-AtargetDirectory=${project.build.directory}/docs/xml</compilerArguments>
+      <plugin>
+        <groupId>org.bsc.maven</groupId>
+        <artifactId>maven-processor-plugin</artifactId>
+        <version>2.0.6-redhat</version>
+        <configuration>
+          <processors>
+            <processor>org.rhq.helpers.rest_docs_generator.ClassLevelProcessor</processor>
+          </processors>
+          <compilerArguments>-AtargetDirectory=${project.build.directory}/docs/xml</compilerArguments>
             <!-- Comment the next line in to get more verbose output for debugging -->
             <!--<compilerArguments>-Averbose=true</compilerArguments>-->
-          </configuration>
-          <executions>
-            <execution>
-              <id>create-rest-api-reports</id>
-              <phase>process-classes</phase>
-              <goals>
+        </configuration>
+        <executions>
+          <execution>
+            <id>create-rest-api-reports</id>
+            <phase>process-classes</phase>
+            <goals>
                 <!-- We want to process the classes in src/ -->
-                <goal>process</goal>
-              </goals>
-            </execution>
-          </executions>
-        </plugin>
+              <goal>process</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
         <!-- Disable annotation processors during normal compilation -->
-        <plugin>
-          <groupId>org.apache.maven.plugins</groupId>
-          <artifactId>maven-compiler-plugin</artifactId>
-          <configuration>
-            <compilerArgument>-proc:none</compilerArgument>
-          </configuration>
-        </plugin>
-
-        <plugin>
-          <groupId>org.codehaus.mojo</groupId>
-          <artifactId>xml-maven-plugin</artifactId>
-          <executions>
-            <execution>
-              <phase>process-classes</phase>
-              <goals>
-                <goal>transform</goal>
-              </goals>
-            </execution>
-          </executions>
-          <configuration>
-            <transformationSets>
-              <transformationSet>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <configuration>
+          <compilerArgument>-proc:none</compilerArgument>
+        </configuration>
+      </plugin>
+
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>xml-maven-plugin</artifactId>
+        <executions>
+          <execution>
+            <phase>process-classes</phase>
+            <goals>
+              <goal>transform</goal>
+            </goals>
+          </execution>
+        </executions>
+        <configuration>
+          <transformationSets>
+            <transformationSet>
                 <!-- org.rhq.helpers.rest_docs_generator.test plugin wrote to target/docs/xml (see -AtargetDirectory above) -->
-                <dir>target/docs/xml</dir>
-                <includes><include>rest-api-out.xml</include></includes>
-                <stylesheet>src/main/xsl/apiout2html.xsl</stylesheet>
-                <parameters>
-                  <parameter>
-                    <name>basePath</name>
-                    <value>http://localhost:7080/rest/1</value>
-                  </parameter>
-                </parameters>
-                <outputDir>${project.build.directory}/docs/html</outputDir>
-                <fileMappers>
-                  <fileMapper implementation="org.codehaus.plexus.components.io.filemappers.FileExtensionMapper">
-                    <targetExtension>.html</targetExtension>
-                  </fileMapper>
-                </fileMappers>
-              </transformationSet>
-              <transformationSet>
+              <dir>target/docs/xml</dir>
+              <includes>
+                <include>rest-api-out.xml</include>
+              </includes>
+              <stylesheet>src/main/xsl/apiout2html.xsl</stylesheet>
+              <parameters>
+                <parameter>
+                  <name>basePath</name>
+                  <value>http://localhost:7080/rest/1</value>
+                </parameter>
+              </parameters>
+              <outputDir>${project.build.directory}/docs/html</outputDir>
+              <fileMappers>
+                <fileMapper implementation="org.codehaus.plexus.components.io.filemappers.FileExtensionMapper">
+                  <targetExtension>.html</targetExtension>
+                </fileMapper>
+              </fileMappers>
+            </transformationSet>
+            <transformationSet>
                 <!-- org.rhq.helpers.rest_docs_generator.test plugin wrote to target/docs/xml (see -AtargetDirectory above) -->
-                <dir>target/docs/xml</dir>
-                <includes><include>rest-api-out.xml</include></includes>
-                <stylesheet>src/main/xsl/apiout2docbook.xsl</stylesheet>
-                <parameters>
-                  <parameter>
-                    <name>basePath</name>
-                    <value>http://localhost:7080/rest/1</value>
-                  </parameter>
-                </parameters>
-                <outputDir>${project.build.directory}/docs/xml</outputDir>
-                <fileMappers>
-                  <fileMapper implementation="org.codehaus.plexus.components.io.filemappers.FileExtensionMapper">
-                    <targetExtension>.dbx.xml</targetExtension>
-                  </fileMapper>
-                </fileMappers>
-              </transformationSet>
-            </transformationSets>
-          </configuration>
-        </plugin>
-        <plugin>
-          <groupId>com.agilejava.docbkx</groupId>
-          <artifactId>docbkx-maven-plugin</artifactId>
-          <version>2.0.9</version>
-          <executions>
-              <execution>
-                <phase>process-classes</phase>
-                <goals>
-                  <goal>generate-pdf</goal>
-                  <goal>generate-html</goal>
-                </goals>
-              </execution>
-          </executions>
-          <configuration>
-            <sourceDirectory>target/docs/xml</sourceDirectory> <!-- from previous plugin, 2nd transformation set -->
-            <includes>rest-api-out.dbx.xml</includes>
-            <hyphenate>false</hyphenate>
-            <generateToc>true</generateToc>
-          </configuration>
-        </plugin>
-
-      </plugins>
-
-   </build>
+              <dir>target/docs/xml</dir>
+              <includes>
+                <include>rest-api-out.xml</include>
+              </includes>
+              <stylesheet>src/main/xsl/apiout2docbook.xsl</stylesheet>
+              <parameters>
+                <parameter>
+                  <name>basePath</name>
+                  <value>http://localhost:7080/rest/1</value>
+                </parameter>
+              </parameters>
+              <outputDir>${project.build.directory}/docs/xml</outputDir>
+              <fileMappers>
+                <fileMapper implementation="org.codehaus.plexus.components.io.filemappers.FileExtensionMapper">
+                  <targetExtension>.dbx.xml</targetExtension>
+                </fileMapper>
+              </fileMappers>
+            </transformationSet>
+          </transformationSets>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>com.agilejava.docbkx</groupId>
+        <artifactId>docbkx-maven-plugin</artifactId>
+        <version>2.0.9</version>
+        <executions>
+          <execution>
+            <phase>process-classes</phase>
+            <goals>
+              <goal>generate-pdf</goal>
+              <goal>generate-html</goal>
+            </goals>
+          </execution>
+        </executions>
+        <configuration>
+          <sourceDirectory>target/docs/xml</sourceDirectory> <!-- from previous plugin, 2nd transformation set -->
+          <includes>rest-api-out.dbx.xml</includes>
+          <hyphenate>false</hyphenate>
+          <generateToc>true</generateToc>
+        </configuration>
+      </plugin>
+
+    </plugins>
+
+  </build>
 
   <repositories>
     <repository>
       <!-- TODO change when the annotations are puplished. This is temporary for the swagger annotations for REST-docu -->
-       <id>sonatype-oss-snapshot</id>
-       <name>Sonatype OSS Snapshot repository</name>
-       <url>https://oss.sonatype.org/content/repositories/snapshots</url>
+      <id>sonatype-oss-snapshot</id>
+      <name>Sonatype OSS Snapshot repository</name>
+      <url>https://oss.sonatype.org/content/repositories/snapshots</url>
     </repository>
 
   </repositories>
 
-   <profiles>
+  <profiles>
 
-      <profile>
+    <profile>
          <!-- only if we are not running an individual set of tests via -Dtest do we do this -->
-         <id>no-individual-test</id>
-         <activation>
-            <property><name>!test</name></property>
-         </activation>
-         <build>
-            <plugins>
-               <plugin>
-                  <artifactId>maven-surefire-plugin</artifactId>
+      <id>no-individual-test</id>
+      <activation>
+        <property>
+          <name>!test</name>
+        </property>
+      </activation>
+      <build>
+        <plugins>
+          <plugin>
+            <artifactId>maven-surefire-plugin</artifactId>
                   <!-- Everything but the web service tests, this is the standard test execution -->
-                  <configuration>
-                     <skipTests>true</skipTests>
-                     <excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
-                     <groups>${rhq.testng.includedGroups}</groups>
-                     <properties>
-                        <property>
-                           <name>listener</name>
-                           <value>org.rhq.test.testng.StdoutReporter</value>
-                        </property>
-                     </properties>
-                     <systemPropertyVariables>
-                        <embeddedDeployment>true</embeddedDeployment>
-                        <deploymentDirectory>target/classes</deploymentDirectory>
-                        <hibernate.dialect>${rhq.test.ds.hibernate-dialect}</hibernate.dialect>
-                        <clean.db>${clean.db}</clean.db>
-                        <log4j.configDebug>false</log4j.configDebug>
-                     </systemPropertyVariables>
-                     <additionalClasspathElements>
+            <configuration>
+              <skipTests>true</skipTests>
+              <excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
+              <groups>${rhq.testng.includedGroups}</groups>
+              <properties>
+                <property>
+                  <name>listener</name>
+                  <value>org.rhq.test.testng.StdoutReporter</value>
+                </property>
+              </properties>
+              <systemPropertyVariables>
+                <embeddedDeployment>true</embeddedDeployment>
+                <deploymentDirectory>target/classes</deploymentDirectory>
+                <hibernate.dialect>${rhq.test.ds.hibernate-dialect}</hibernate.dialect>
+                <clean.db>${clean.db}</clean.db>
+                <log4j.configDebug>false</log4j.configDebug>
+              </systemPropertyVariables>
+              <additionalClasspathElements>
                      <!-- The below is required for tests to run against Oracle. -->
-                        <additionalClasspathElement>${settings.localRepository}/com/oracle/ojdbc6/${ojdbc6.version}/ojdbc6-${ojdbc6.version}.jar</additionalClasspathElement>
-                     </additionalClasspathElements>
-                  </configuration>
-                  <executions>
-                     <execution>
-                        <id>dbTestsOnly</id>
-                        <goals>
-                           <goal>test</goal>
-                        </goals>
-                        <configuration>
-                           <skipTests>${skipTests}</skipTests>
-                           <includes>
-                              <include>org/rhq/enterprise/server/db/**</include>
-                           </includes>
-                           <failIfNoTests>false</failIfNoTests>
-                        </configuration>
-                     </execution>
-                  </executions>
-               </plugin>
-            </plugins>
-         </build>
-      </profile>
-
-      <profile>
-         <id>dev</id>
-
-         <properties>
-            <rhq.rootDir>../../../..</rhq.rootDir>
-            <rhq.containerDir>${rhq.rootDir}/${rhq.defaultDevContainerPath}</rhq.containerDir>
-            <rhq.deploymentName>${project.build.finalName}-ejb3.jar</rhq.deploymentName>
-            <rhq.deploymentDir>${rhq.containerDir}/jbossas/server/default/deploy/${rhq.earName}/${rhq.deploymentName}</rhq.deploymentDir>
-         </properties>
-
-         <build>
-            <plugins>
-
-               <plugin>
-                  <artifactId>maven-antrun-plugin</artifactId>
-                  <executions>
-
-                     <execution>
-                        <id>deploy</id>
-                        <phase>compile</phase>
-                        <configuration>
-                           <target>
-                              <property name="deployment.dir" location="${rhq.deploymentDir}" />
-                              <echo>*** Copying updated files from target/classes to ${deployment.dir}...</echo>
-                              <copy todir="${deployment.dir}" verbose="${rhq.verbose}">
-                                 <fileset dir="target/classes" />
-                              </copy>
-                           </target>
-                        </configuration>
-                        <goals>
-                           <goal>run</goal>
-                        </goals>
-                     </execution>
+                <additionalClasspathElement>${settings.localRepository}/com/oracle/ojdbc6/${ojdbc6.version}/ojdbc6-${ojdbc6.version}.jar</additionalClasspathElement>
+              </additionalClasspathElements>
+            </configuration>
+            <executions>
+              <execution>
+                <id>dbTestsOnly</id>
+                <goals>
+                  <goal>test</goal>
+                </goals>
+                <configuration>
+                  <skipTests>${skipTests}</skipTests>
+                  <includes>
+                    <include>org/rhq/enterprise/server/db/**</include>
+                  </includes>
+                  <failIfNoTests>false</failIfNoTests>
+                </configuration>
+              </execution>
+            </executions>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+
+    <profile>
+      <id>dev</id>
+
+      <properties>
+        <rhq.rootDir>../../../..</rhq.rootDir>
+        <rhq.containerDir>${rhq.rootDir}/${rhq.defaultDevContainerPath}</rhq.containerDir>
+        <rhq.deploymentName>${project.build.finalName}-ejb3.jar</rhq.deploymentName>
+        <rhq.deploymentDir>${rhq.containerDir}/jbossas/server/default/deploy/${rhq.earName}/${rhq.deploymentName}</rhq.deploymentDir>
+      </properties>
+
+      <build>
+        <plugins>
+
+          <plugin>
+            <artifactId>maven-antrun-plugin</artifactId>
+            <executions>
+
+              <execution>
+                <id>deploy</id>
+                <phase>compile</phase>
+                <configuration>
+                  <target>
+                    <property name="deployment.dir" location="${rhq.deploymentDir}"/>
+                    <echo>*** Copying updated files from target/classes to ${deployment.dir}...</echo>
+                    <copy todir="${deployment.dir}" verbose="${rhq.verbose}">
+                      <fileset dir="target/classes"/>
+                    </copy>
+                  </target>
+                </configuration>
+                <goals>
+                  <goal>run</goal>
+                </goals>
+              </execution>
 
                      <!--
                         NOTE: The below execution is necessary to make sure the META-INF/MANIFEST.MF and
                         META-INF/maven/** files, which get created by the ejb plugin during the package phase, get
                         copied over to the deployment dir.
                      -->
-                     <execution>
-                        <id>deploy-jar-meta-inf</id>
-                        <phase>package</phase>
-                        <configuration>
-                           <target>
-                              <unjar src="${project.build.directory}/${project.build.finalName}.jar" dest="${rhq.deploymentDir}" overwrite="false">
-                                 <patternset>
-                                    <include name="META-INF/**" />
-                                 </patternset>
-                              </unjar>
-                           </target>
-                        </configuration>
-                        <goals>
-                           <goal>run</goal>
-                        </goals>
-                     </execution>
-
-                     <execution>
-                        <id>undeploy</id>
-                        <phase>clean</phase>
-                        <configuration>
-                           <target>
-                              <property name="deployment.dir" location="${rhq.deploymentDir}" />
-                              <echo>*** Deleting ${deployment.dir}${file.separator}...</echo>
-                              <delete dir="${deployment.dir}" />
-                           </target>
-                        </configuration>
-                        <goals>
-                           <goal>run</goal>
-                        </goals>
-                     </execution>
-
-                  </executions>
-               </plugin>
-
-            </plugins>
-         </build>
-      </profile>
+              <execution>
+                <id>deploy-jar-meta-inf</id>
+                <phase>package</phase>
+                <configuration>
+                  <target>
+                    <unjar src="${project.build.directory}/${project.build.finalName}.jar" dest="${rhq.deploymentDir}"
+                      overwrite="false">
+                      <patternset>
+                        <include name="META-INF/**"/>
+                      </patternset>
+                    </unjar>
+                  </target>
+                </configuration>
+                <goals>
+                  <goal>run</goal>
+                </goals>
+              </execution>
 
-      <!--  Add dependencies need for jdk5 builds. Remove when we stop supporting jdk5 -->
-      <profile>
-         <id>java-5-dependencies</id>
-         <activation>
-            <jdk>1.5</jdk>
-            <property>
-               <name>java5.home</name>
-            </property>
-         </activation>
+              <execution>
+                <id>undeploy</id>
+                <phase>clean</phase>
+                <configuration>
+                  <target>
+                    <property name="deployment.dir" location="${rhq.deploymentDir}"/>
+                    <echo>*** Deleting ${deployment.dir}${file.separator}...</echo>
+                    <delete dir="${deployment.dir}"/>
+                  </target>
+                </configuration>
+                <goals>
+                  <goal>run</goal>
+                </goals>
+              </execution>
 
-         <dependencies>
-            <dependency>
-               <groupId>jboss.jbossws</groupId>
-               <artifactId>jboss-jaxws</artifactId>
+            </executions>
+          </plugin>
+
+        </plugins>
+      </build>
+    </profile>
+
+      <!--  Add dependencies need for jdk5 builds. Remove when we stop supporting jdk5 -->
+    <profile>
+      <id>java-5-dependencies</id>
+      <activation>
+        <jdk>1.5</jdk>
+        <property>
+          <name>java5.home</name>
+        </property>
+      </activation>
+
+      <dependencies>
+        <dependency>
+          <groupId>jboss.jbossws</groupId>
+          <artifactId>jboss-jaxws</artifactId>
                <!-- NOTE: This version is old but is good enough to resolve the build dependency. -->
-               <version>3.0.1-native-2.0.4.GA</version>
-               <scope>provided</scope>
-            </dependency>
-         </dependencies>
-      </profile>
-
-      <profile>
-         <id>javadoc</id>
-         <activation>
-            <property>
-               <name>javadoc.outputDirectory</name>
-            </property>
-         </activation>
-
-         <build>
-            <plugins>
-               <plugin>
-                  <artifactId>maven-antrun-plugin</artifactId>
-                  <executions>
-
-                     <execution>
-                        <id>remote-api</id>
-                        <phase>compile</phase>
-                        <configuration>
-                           <target>
-                              <property name="javadoc.outputDirectory" value="${javadoc.outputDirectory}" />
-                              <property name="project.dir" value="./src/main/java/org/rhq/enterprise/server" />
-                              <property name="maven.compile.classpath" refid="maven.compile.classpath" />
-
-                              <mkdir dir="${javadoc.outputDirectory}/remote-api" />
-                              <javadoc destdir="${javadoc.outputDirectory}/remote-api" author="false" version="true" windowtitle="RHQ ${project.version} Remote API" noindex="false">
-                                 <classpath>
-                                    <pathelement path="${maven.compile.classpath}" />
-                                 </classpath>
-                                 <fileset dir="${project.dir}" defaultexcludes="yes">
-                                    <include name="**/*Remote.java" />
-                                 </fileset>
-                                 <link href="../domain/" />
-                                 <link href="http://download.oracle.com/javase/6/docs/api/" />
-                                 <bottom><![CDATA[Copyright &#169; 2005-2011 <a href="http://redhat.com/">Red Hat, Inc.</a>. All Rights Reserved.]]></bottom>
-                              </javadoc>
-                           </target>
-                        </configuration>
-                        <goals>
-                           <goal>run</goal>
-                        </goals>
-                     </execution>
-
-                  </executions>
-               </plugin>
-            </plugins>
-         </build>
-
-      </profile>
-
-      <profile>
-        <id>cobertura</id>
-        <build>
-         <plugins>
-           <plugin>
-              <artifactId>maven-antrun-plugin</artifactId>
-              <dependencies>
-               <dependency>
-                 <groupId>net.sourceforge.cobertura</groupId>
-                 <artifactId>cobertura</artifactId>
-                 <version>${cobertura.version}</version>
-               </dependency>
-             </dependencies>
-             <executions>
+          <version>3.0.1-native-2.0.4.GA</version>
+          <scope>provided</scope>
+        </dependency>
+      </dependencies>
+    </profile>
+
+    <profile>
+      <id>javadoc</id>
+      <activation>
+        <property>
+          <name>javadoc.outputDirectory</name>
+        </property>
+      </activation>
+
+      <build>
+        <plugins>
+          <plugin>
+            <artifactId>maven-antrun-plugin</artifactId>
+            <executions>
+
               <execution>
-               <id>cobertura-instrument</id>
-               <phase>process-test-classes</phase>
-                 <configuration>
-                   <target>
+                <id>remote-api</id>
+                <phase>compile</phase>
+                <configuration>
+                  <target>
+                    <property name="javadoc.outputDirectory" value="${javadoc.outputDirectory}"/>
+                    <property name="project.dir" value="./src/main/java/org/rhq/enterprise/server"/>
+                    <property name="maven.compile.classpath" refid="maven.compile.classpath"/>
+
+                    <mkdir dir="${javadoc.outputDirectory}/remote-api"/>
+                    <javadoc destdir="${javadoc.outputDirectory}/remote-api" author="false" version="true"
+                      windowtitle="RHQ ${project.version} Remote API" noindex="false">
+                      <classpath>
+                        <pathelement path="${maven.compile.classpath}"/>
+                      </classpath>
+                      <fileset dir="${project.dir}" defaultexcludes="yes">
+                        <include name="**/*Remote.java"/>
+                      </fileset>
+                      <link href="../domain/"/>
+                      <link href="http://download.oracle.com/javase/6/docs/api/"/>
+                      <bottom><![CDATA[Copyright &#169; 2005-2011 <a href="http://redhat.com/">Red Hat, Inc.</a>. All Rights Reserved.]]></bottom>
+                    </javadoc>
+                  </target>
+                </configuration>
+                <goals>
+                  <goal>run</goal>
+                </goals>
+              </execution>
+
+            </executions>
+          </plugin>
+        </plugins>
+      </build>
+
+    </profile>
+
+    <profile>
+      <id>cobertura</id>
+      <build>
+        <plugins>
+          <plugin>
+            <artifactId>maven-antrun-plugin</artifactId>
+            <dependencies>
+              <dependency>
+                <groupId>net.sourceforge.cobertura</groupId>
+                <artifactId>cobertura</artifactId>
+                <version>${cobertura.version}</version>
+              </dependency>
+            </dependencies>
+            <executions>
+              <execution>
+                <id>cobertura-instrument</id>
+                <phase>process-test-classes</phase>
+                <configuration>
+                  <target>
                    <!-- prepare directory structure for cobertura-->
-                   <mkdir dir="target/cobertura" />
-                   <mkdir dir="target/cobertura/backup" />
+                    <mkdir dir="target/cobertura"/>
+                    <mkdir dir="target/cobertura/backup"/>
                    <!-- backup all classes so that we can instrument the original classes-->
-                   <copy toDir="target/cobertura/backup" verbose="true" overwrite="true">
+                    <copy toDir="target/cobertura/backup" verbose="true" overwrite="true">
                       <fileset dir="target/classes">
-                         <include name="**/*.class" />
+                        <include name="**/*.class"/>
                       </fileset>
-                   </copy>
+                    </copy>
                    <!-- create a properties file and save there location of cobertura data file-->
-                   <touch file="target/classes/cobertura.properties" />
-                   <echo file="target/classes/cobertura.properties">net.sourceforge.cobertura.datafile=${project.build.directory}/cobertura/cobertura.ser</echo>
-                   <taskdef classpathref="maven.plugin.classpath" resource="tasks.properties" />
+                    <touch file="target/classes/cobertura.properties"/>
+                    <echo file="target/classes/cobertura.properties">net.sourceforge.cobertura.datafile=${project.build.directory}/cobertura/cobertura.ser</echo>
+                    <taskdef classpathref="maven.plugin.classpath" resource="tasks.properties"/>
                    <!-- instrument all classes in target/classes directory -->
-                   <cobertura-instrument datafile="${project.build.directory}/cobertura/cobertura.ser" todir="${project.build.directory}/classes">
-                     <fileset dir="${project.build.directory}/classes">
-                        <include name="**/*.class" />
-                        <exclude name="**/DynamicConfigurationPropertyLocal.class" />
-                        <exclude name="**/DynamicConfigurationPropertyBean.class" />
+                    <cobertura-instrument datafile="${project.build.directory}/cobertura/cobertura.ser"
+                      todir="${project.build.directory}/classes">
+                      <fileset dir="${project.build.directory}/classes">
+                        <include name="**/*.class"/>
+                        <exclude name="**/DynamicConfigurationPropertyLocal.class"/>
+                        <exclude name="**/DynamicConfigurationPropertyBean.class"/>
                       </fileset>
                     </cobertura-instrument>
-                   </target>
-                 </configuration>
-               <goals>
-                 <goal>run</goal>
-               </goals>
+                  </target>
+                </configuration>
+                <goals>
+                  <goal>run</goal>
+                </goals>
               </execution>
               <execution>
-               <id>cobertura-report</id>
-               <phase>prepare-package</phase>
-                 <configuration>
-                   <target>
-                     <taskdef classpathref="maven.plugin.classpath" resource="tasks.properties" />
+                <id>cobertura-report</id>
+                <phase>prepare-package</phase>
+                <configuration>
+                  <target>
+                    <taskdef classpathref="maven.plugin.classpath" resource="tasks.properties"/>
                      <!-- prepare directory structure for cobertura-->
-                     <mkdir dir="target/cobertura" />
-                     <mkdir dir="target/site/cobertura" />
+                    <mkdir dir="target/cobertura"/>
+                    <mkdir dir="target/site/cobertura"/>
                      <!-- restore classes from backup folder to classes folder -->
-                     <copy toDir="target/classes" verbose="true" overwrite="true">
+                    <copy toDir="target/classes" verbose="true" overwrite="true">
                       <fileset dir="target/cobertura/backup">
-                         <include name="**/*.class" />
+                        <include name="**/*.class"/>
                       </fileset>
-                     </copy>
+                    </copy>
                      <!-- delete backup folder-->
-                     <delete dir="target/cobertura/backup" />
+                    <delete dir="target/cobertura/backup"/>
                      <!-- create a code coverage report -->
-                     <cobertura-report format="html" datafile="${project.build.directory}/cobertura/cobertura.ser" destdir="${project.build.directory}/site/cobertura">
+                    <cobertura-report format="html" datafile="${project.build.directory}/cobertura/cobertura.ser"
+                      destdir="${project.build.directory}/site/cobertura">
                       <fileset dir="${basedir}/src/main/java">
-                         <include name="**/*.java" />
+                        <include name="**/*.java"/>
                       </fileset>
-                     </cobertura-report>
+                    </cobertura-report>
                      <!-- delete cobertura.properties file -->
-                     <delete file="target/classes/cobertura.properties" />
-                   </target>
-                 </configuration>
-               <goals>
-                 <goal>run</goal>
-               </goals>
-               </execution>
+                    <delete file="target/classes/cobertura.properties"/>
+                  </target>
+                </configuration>
+                <goals>
+                  <goal>run</goal>
+                </goals>
+              </execution>
             </executions>
-           </plugin>
-          </plugins>
-       </build>
-     </profile>
-   </profiles>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+  </profiles>
 
 </project>
diff --git a/modules/enterprise/server/xml-schemas/pom.xml b/modules/enterprise/server/xml-schemas/pom.xml
index 6923a7a..8e4bc21 100644
--- a/modules/enterprise/server/xml-schemas/pom.xml
+++ b/modules/enterprise/server/xml-schemas/pom.xml
@@ -1,82 +1,83 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 
-    <modelVersion>4.0.0</modelVersion>
-
-    <parent>
-        <groupId>org.rhq</groupId>
-        <artifactId>rhq-parent</artifactId>
-        <version>4.5.0-SNAPSHOT</version>
-        <relativePath>../../../../pom.xml</relativePath>
-    </parent>
+  <modelVersion>4.0.0</modelVersion>
 
+  <parent>
     <groupId>org.rhq</groupId>
-    <artifactId>rhq-enterprise-server-xml-schemas</artifactId>
-    <packaging>jar</packaging>
+    <artifactId>rhq-parent</artifactId>
+    <version>4.5.0-SNAPSHOT</version>
+    <relativePath>../../../../pom.xml</relativePath>
+  </parent>
+
+  <groupId>org.rhq</groupId>
+  <artifactId>rhq-enterprise-server-xml-schemas</artifactId>
+  <packaging>jar</packaging>
 
-    <name>RHQ Server XML Schemas</name>
-    <description>Server side XML schemas and JAXB APIs used mailing to support the RHQ Server plugin container</description>
+  <name>RHQ Server XML Schemas</name>
+  <description>Server side XML schemas and JAXB APIs used mailing to support the RHQ Server plugin container</description>
 
-    <dependencies>
-        <dependency>
-            <groupId>${rhq.groupId}</groupId>
-            <artifactId>rhq-core-domain</artifactId>
-            <version>${project.version}</version>
-            <scope>provided</scope> <!-- rhq.ear -->
-        </dependency>
+  <dependencies>
+    <dependency>
+      <groupId>${rhq.groupId}</groupId>
+      <artifactId>rhq-core-domain</artifactId>
+      <version>${project.version}</version>
+      <scope>provided</scope> <!-- rhq.ear -->
+    </dependency>
 
-        <dependency>
-            <groupId>${rhq.groupId}</groupId>
-            <artifactId>rhq-core-client-api</artifactId>
-            <version>${project.version}</version>
-        </dependency>
+    <dependency>
+      <groupId>${rhq.groupId}</groupId>
+      <artifactId>rhq-core-client-api</artifactId>
+      <version>${project.version}</version>
+    </dependency>
 
-        <dependency>
-            <groupId>javax.xml.bind</groupId>
-            <artifactId>jaxb-api</artifactId>
+    <dependency>
+      <groupId>javax.xml.bind</groupId>
+      <artifactId>jaxb-api</artifactId>
             <!-- NOTE: The version is defined in the root POM's dependencyManagement section. -->
-        </dependency>
+    </dependency>
 
-        <dependency>
-            <groupId>com.sun.xml.bind</groupId>
-            <artifactId>jaxb-impl</artifactId>
+    <dependency>
+      <groupId>com.sun.xml.bind</groupId>
+      <artifactId>jaxb-impl</artifactId>
             <!-- NOTE: The version is defined in the root POM's dependencyManagement section. -->
             <!--<scope>test</scope>  not sure about this -->
-        </dependency>
+    </dependency>
 
         <!--
             TODO: This is a fix for the Javac bug requiring annotations to be available when compiling dependent
             classes; it is fixed in JDK 6.
         -->
-        <dependency>
-            <groupId>jboss.jboss-embeddable-ejb3</groupId>
-            <artifactId>hibernate-all</artifactId>
-            <version>1.0.0.Alpha9</version>
-            <scope>provided</scope>
-        </dependency>
+    <dependency>
+      <groupId>jboss.jboss-embeddable-ejb3</groupId>
+      <artifactId>hibernate-all</artifactId>
+      <version>1.0.0.Alpha9</version>
+      <scope>provided</scope>
+    </dependency>
 
-    </dependencies>
+  </dependencies>
 
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>com.sun.tools.xjc.maven2</groupId>
-                <artifactId>maven-jaxb-plugin</artifactId>
-                <version>1.1</version>
-                <executions>
-                    <execution>
-                        <goals>
-                            <goal>generate</goal>
-                        </goals>
-                    </execution>
-                </executions>
-                <configuration>
-                    <generateDirectory>${basedir}/target/generated-sources/xjc</generateDirectory>
-                    <schemaDirectory>${basedir}/target/classes</schemaDirectory>
-                    <includeSchemas>
-                        <includeSchema>*.xsd</includeSchema>
-                    </includeSchemas>
-                </configuration>
-            </plugin>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>com.sun.tools.xjc.maven2</groupId>
+        <artifactId>maven-jaxb-plugin</artifactId>
+        <version>1.1</version>
+        <executions>
+          <execution>
+            <goals>
+              <goal>generate</goal>
+            </goals>
+          </execution>
+        </executions>
+        <configuration>
+          <generateDirectory>${basedir}/target/generated-sources/xjc</generateDirectory>
+          <schemaDirectory>${basedir}/target/classes</schemaDirectory>
+          <includeSchemas>
+            <includeSchema>*.xsd</includeSchema>
+          </includeSchemas>
+        </configuration>
+      </plugin>
 
             <!--
                 Because the JAXB generator needs all .xsd's available and in one place so they can reference each other
@@ -90,211 +91,213 @@
                 we still have a duplicate copy of the .xsd in our jar, but this is OK because it is a true duplicate
                 so it doesn't really matter that we have one copy here and one copy in client-api jar.
             -->
-            <plugin>
-                <artifactId>maven-antrun-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <id>Copy the schemas in one place, including rhq-configuration.xsd schema so we can reuse it</id>
-                        <phase>initialize</phase>
-                        <configuration>
-                            <target>
-                                <mkdir dir="${basedir}/target/classes" />
-                                <copy todir="${basedir}/target/classes">
-                                    <fileset dir="${basedir}/src/main/resources">
-                                        <include name="*.xsd" />
-                                    </fileset>
-                                    <fileset dir="${basedir}/../../../core/client-api/src/main/resources">
-                                        <include name="rhq-configuration.xsd" />
-                                    </fileset>
-                                </copy>
-                            </target>
-                        </configuration>
-                        <goals>
-                            <goal>run</goal>
-                        </goals>
-                    </execution>
-                    <execution>
-                        <id>purge duplicated JAXB-generated configuration schema classes</id>
-                        <phase>process-sources</phase>
-                        <configuration>
-                            <target>
-                                <delete dir="${basedir}/target/generated-sources/xjc/org/rhq/core" />
-                            </target>
-                        </configuration>
-                        <goals>
-                            <goal>run</goal>
-                        </goals>
-                    </execution>
-                </executions>
-            </plugin>
+      <plugin>
+        <artifactId>maven-antrun-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>Copy the schemas in one place, including rhq-configuration.xsd schema so we can reuse it</id>
+            <phase>initialize</phase>
+            <configuration>
+              <target>
+                <mkdir dir="${basedir}/target/classes"/>
+                <copy todir="${basedir}/target/classes">
+                  <fileset dir="${basedir}/src/main/resources">
+                    <include name="*.xsd"/>
+                  </fileset>
+                  <fileset dir="${basedir}/../../../core/client-api/src/main/resources">
+                    <include name="rhq-configuration.xsd"/>
+                  </fileset>
+                </copy>
+              </target>
+            </configuration>
+            <goals>
+              <goal>run</goal>
+            </goals>
+          </execution>
+          <execution>
+            <id>purge duplicated JAXB-generated configuration schema classes</id>
+            <phase>process-sources</phase>
+            <configuration>
+              <target>
+                <delete dir="${basedir}/target/generated-sources/xjc/org/rhq/core"/>
+              </target>
+            </configuration>
+            <goals>
+              <goal>run</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
 
-            <plugin>
-              <groupId>org.codehaus.mojo</groupId>
-              <artifactId>build-helper-maven-plugin</artifactId>
-              <executions>
-                <execution>
-                  <id>add-xjc-source</id>
-                  <phase>generate-sources</phase>
-                  <goals>
-                    <goal>add-source</goal>
-                  </goals>
-                  <configuration>
-                    <sources>
-                      <source>${basedir}/target/generated-sources/xjc</source>
-                    </sources>
-                  </configuration>
-                </execution>
-              </executions>
-            </plugin>
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>build-helper-maven-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>add-xjc-source</id>
+            <phase>generate-sources</phase>
+            <goals>
+              <goal>add-source</goal>
+            </goals>
+            <configuration>
+              <sources>
+                <source>${basedir}/target/generated-sources/xjc</source>
+              </sources>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
 
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-compiler-plugin</artifactId>
-                <configuration>
-                    <source>1.5</source>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <configuration>
+          <source>1.5</source>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
 
-    <profiles>
+  <profiles>
 
-        <profile>
-            <id>dev</id>
+    <profile>
+      <id>dev</id>
 
-            <properties>
-                <rhq.rootDir>../../../..</rhq.rootDir>
-                <rhq.containerDir>${rhq.rootDir}/${rhq.defaultDevContainerPath}</rhq.containerDir>
-                <rhq.deploymentDir>${rhq.containerDir}/jbossas/server/default/deploy/${rhq.earName}/lib</rhq.deploymentDir>
-            </properties>
+      <properties>
+        <rhq.rootDir>../../../..</rhq.rootDir>
+        <rhq.containerDir>${rhq.rootDir}/${rhq.defaultDevContainerPath}</rhq.containerDir>
+        <rhq.deploymentDir>${rhq.containerDir}/jbossas/server/default/deploy/${rhq.earName}/lib</rhq.deploymentDir>
+      </properties>
 
-            <build>
-                <plugins>
+      <build>
+        <plugins>
 
-                    <plugin>
-                        <artifactId>maven-antrun-plugin</artifactId>
-                        <executions>
+          <plugin>
+            <artifactId>maven-antrun-plugin</artifactId>
+            <executions>
 
-                            <execution>
-                                <id>deploy</id>
-                                <phase>compile</phase>
-                                <configuration>
-                                    <target>
-                                        <mkdir dir="${rhq.deploymentDir}" />
-                                        <property name="deployment.file" location="${rhq.deploymentDir}/${project.build.finalName}.jar" />
-                                        <echo>*** Updating ${deployment.file}...</echo>
-                                        <jar destfile="${deployment.file}" basedir="${project.build.outputDirectory}" />
-                                    </target>
-                                </configuration>
-                                <goals>
-                                    <goal>run</goal>
-                                </goals>
-                            </execution>
+              <execution>
+                <id>deploy</id>
+                <phase>compile</phase>
+                <configuration>
+                  <target>
+                    <mkdir dir="${rhq.deploymentDir}"/>
+                    <property name="deployment.file" location="${rhq.deploymentDir}/${project.build.finalName}.jar"/>
+                    <echo>*** Updating ${deployment.file}...</echo>
+                    <jar destfile="${deployment.file}" basedir="${project.build.outputDirectory}"/>
+                  </target>
+                </configuration>
+                <goals>
+                  <goal>run</goal>
+                </goals>
+              </execution>
 
-                            <execution>
-                                <id>undeploy</id>
-                                <phase>clean</phase>
-                                <configuration>
-                                    <target>
-                                        <property name="deployment.file" location="${rhq.deploymentDir}/${project.build.finalName}.jar" />
-                                        <echo>*** Deleting ${deployment.file}...</echo>
-                                        <delete file="${deployment.file}" />
-                                    </target>
-                                </configuration>
-                                <goals>
-                                    <goal>run</goal>
-                                </goals>
-                            </execution>
+              <execution>
+                <id>undeploy</id>
+                <phase>clean</phase>
+                <configuration>
+                  <target>
+                    <property name="deployment.file" location="${rhq.deploymentDir}/${project.build.finalName}.jar"/>
+                    <echo>*** Deleting ${deployment.file}...</echo>
+                    <delete file="${deployment.file}"/>
+                  </target>
+                </configuration>
+                <goals>
+                  <goal>run</goal>
+                </goals>
+              </execution>
 
-                        </executions>
-                    </plugin>
+            </executions>
+          </plugin>
 
-                </plugins>
-            </build>
-        </profile>
-       <profile>
+        </plugins>
+      </build>
+    </profile>
+    <profile>
       <id>cobertura</id>
       <activation>
         <activeByDefault>false</activeByDefault>
       </activation>
-        <build>
-         <plugins>
-           <plugin>
-             <artifactId>maven-antrun-plugin</artifactId>
-              <dependencies>
-               <dependency>
-                 <groupId>net.sourceforge.cobertura</groupId>
-                 <artifactId>cobertura</artifactId>
-                 <version>${cobertura.version}</version>
-               </dependency>
-             </dependencies>
-             <executions>
+      <build>
+        <plugins>
+          <plugin>
+            <artifactId>maven-antrun-plugin</artifactId>
+            <dependencies>
+              <dependency>
+                <groupId>net.sourceforge.cobertura</groupId>
+                <artifactId>cobertura</artifactId>
+                <version>${cobertura.version}</version>
+              </dependency>
+            </dependencies>
+            <executions>
               <execution>
-               <id>cobertura-instrument</id>
-               <phase>process-test-classes</phase>
-                 <configuration>
-                   <target>
+                <id>cobertura-instrument</id>
+                <phase>process-test-classes</phase>
+                <configuration>
+                  <target>
                    <!-- prepare directory structure for cobertura-->
-                   <mkdir dir="target/cobertura" />
-                   <mkdir dir="target/cobertura/backup" />
+                    <mkdir dir="target/cobertura"/>
+                    <mkdir dir="target/cobertura/backup"/>
                    <!-- backup all classes so that we can instrument the original classes-->
-                   <copy toDir="target/cobertura/backup" verbose="true" overwrite="true">
+                    <copy toDir="target/cobertura/backup" verbose="true" overwrite="true">
                       <fileset dir="target/classes">
-                         <include name="**/*.class" />
+                        <include name="**/*.class"/>
                       </fileset>
-                   </copy>
+                    </copy>
                    <!-- create a properties file and save there location of cobertura data file-->
-                   <touch file="target/classes/cobertura.properties" />
-                   <echo file="target/classes/cobertura.properties">net.sourceforge.cobertura.datafile=${project.build.directory}/cobertura/cobertura.ser</echo>
-                   <taskdef classpathref="maven.plugin.classpath" resource="tasks.properties" />
+                    <touch file="target/classes/cobertura.properties"/>
+                    <echo file="target/classes/cobertura.properties">net.sourceforge.cobertura.datafile=${project.build.directory}/cobertura/cobertura.ser</echo>
+                    <taskdef classpathref="maven.plugin.classpath" resource="tasks.properties"/>
                    <!-- instrument all classes in target/classes directory -->
-                   <cobertura-instrument datafile="${project.build.directory}/cobertura/cobertura.ser" todir="${project.build.directory}/classes">
-                     <fileset dir="${project.build.directory}/classes">
-                        <include name="**/*.class" />
+                    <cobertura-instrument datafile="${project.build.directory}/cobertura/cobertura.ser"
+                      todir="${project.build.directory}/classes">
+                      <fileset dir="${project.build.directory}/classes">
+                        <include name="**/*.class"/>
                       </fileset>
                     </cobertura-instrument>
-                   </target>
-                 </configuration>
-               <goals>
-                 <goal>run</goal>
-               </goals>
+                  </target>
+                </configuration>
+                <goals>
+                  <goal>run</goal>
+                </goals>
               </execution>
               <execution>
-               <id>cobertura-report</id>
-               <phase>prepare-package</phase>
-                 <configuration>
-                   <target>
-                     <taskdef classpathref="maven.plugin.classpath" resource="tasks.properties" />
+                <id>cobertura-report</id>
+                <phase>prepare-package</phase>
+                <configuration>
+                  <target>
+                    <taskdef classpathref="maven.plugin.classpath" resource="tasks.properties"/>
                      <!-- prepare directory structure for cobertura-->
-                     <mkdir dir="target/cobertura" />
-                     <mkdir dir="target/site/cobertura" />
+                    <mkdir dir="target/cobertura"/>
+                    <mkdir dir="target/site/cobertura"/>
                      <!-- restore classes from backup folder to classes folder -->
-                     <copy toDir="target/classes" verbose="true" overwrite="true">
+                    <copy toDir="target/classes" verbose="true" overwrite="true">
                       <fileset dir="target/cobertura/backup">
-                         <include name="**/*.class" />
+                        <include name="**/*.class"/>
                       </fileset>
-                     </copy>
+                    </copy>
                      <!-- delete backup folder-->
-                     <delete dir="target/cobertura/backup" />
+                    <delete dir="target/cobertura/backup"/>
                      <!-- create a code coverage report -->
-                     <cobertura-report format="html" datafile="${project.build.directory}/cobertura/cobertura.ser" destdir="${project.build.directory}/site/cobertura">
+                    <cobertura-report format="html" datafile="${project.build.directory}/cobertura/cobertura.ser"
+                      destdir="${project.build.directory}/site/cobertura">
                       <fileset dir="${basedir}/src/main/java">
-                         <include name="**/*.java" />
+                        <include name="**/*.java"/>
                       </fileset>
-                     </cobertura-report>
+                    </cobertura-report>
                      <!-- delete cobertura.properties file -->
-                     <delete file="target/classes/cobertura.properties" />
-                   </target>
-                 </configuration>
-               <goals>
-                 <goal>run</goal>
-               </goals>
-               </execution>
+                    <delete file="target/classes/cobertura.properties"/>
+                  </target>
+                </configuration>
+                <goals>
+                  <goal>run</goal>
+                </goals>
+              </execution>
             </executions>
-           </plugin>
-          </plugins>
-       </build>
-     </profile>
-    </profiles>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+  </profiles>
 
 </project>
diff --git a/modules/plugins/perftest/pom.xml b/modules/plugins/perftest/pom.xml
index e045081..9f93a29 100644
--- a/modules/plugins/perftest/pom.xml
+++ b/modules/plugins/perftest/pom.xml
@@ -1,291 +1,295 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 
-   <modelVersion>4.0.0</modelVersion>
+  <modelVersion>4.0.0</modelVersion>
 
-   <parent>
-      <groupId>org.rhq</groupId>
-      <artifactId>rhq-plugins-parent</artifactId>
-      <version>4.5.0-SNAPSHOT</version>
-   </parent>
+  <parent>
+    <groupId>org.rhq</groupId>
+    <artifactId>rhq-plugins-parent</artifactId>
+    <version>4.5.0-SNAPSHOT</version>
+  </parent>
 
-   <groupId>org.rhq</groupId>
-   <artifactId>rhq-perftest-plugin</artifactId>
-   <packaging>jar</packaging>
+  <groupId>org.rhq</groupId>
+  <artifactId>rhq-perftest-plugin</artifactId>
+  <packaging>jar</packaging>
 
-   <name>RHQ Performance Test Plugin</name>
-   <description>a plugin for performance testing</description>
+  <name>RHQ Performance Test Plugin</name>
+  <description>a plugin for performance testing</description>
 
-   <dependencies>
-      <dependency>
-         <groupId>javax.xml.bind</groupId>
-         <artifactId>jaxb-api</artifactId>
+  <dependencies>
+    <dependency>
+      <groupId>javax.xml.bind</groupId>
+      <artifactId>jaxb-api</artifactId>
          <!-- NOTE: The version is defined in the root POM's dependencyManagement section. -->
-      </dependency>
+    </dependency>
 
-      <dependency>
-         <groupId>com.sun.xml.bind</groupId>
-         <artifactId>jaxb-impl</artifactId>
+    <dependency>
+      <groupId>com.sun.xml.bind</groupId>
+      <artifactId>jaxb-impl</artifactId>
          <!-- NOTE: The version is defined in the root POM's dependencyManagement section. -->
-      </dependency>
-   </dependencies>
+    </dependency>
+  </dependencies>
 
-   <build>
-      <plugins>
-         <plugin>
-            <groupId>com.sun.tools.xjc.maven2</groupId>
-            <artifactId>maven-jaxb-plugin</artifactId>
-            <version>1.1</version>
-            <executions>
-               <execution>
-                  <goals>
-                     <goal>generate</goal>
-                  </goals>
-               </execution>
-            </executions>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>com.sun.tools.xjc.maven2</groupId>
+        <artifactId>maven-jaxb-plugin</artifactId>
+        <version>1.1</version>
+        <executions>
+          <execution>
+            <goals>
+              <goal>generate</goal>
+            </goals>
+          </execution>
+        </executions>
+        <configuration>
+          <generatePackage>org.rhq.plugins.perftest.scenario</generatePackage>
+          <generateDirectory>${basedir}/target/generated-sources/xjc</generateDirectory>
+        </configuration>
+      </plugin>
+
+      <plugin>
+        <artifactId>maven-dependency-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>copy-jaxb-deps</id>
+            <phase>process-resources</phase>
+            <goals>
+              <goal>copy</goal>
+            </goals>
             <configuration>
-               <generatePackage>org.rhq.plugins.perftest.scenario</generatePackage>
-               <generateDirectory>${basedir}/target/generated-sources/xjc</generateDirectory>
+              <artifactItems>
+                <artifactItem>
+                  <groupId>javax.xml.bind</groupId>
+                  <artifactId>jaxb-api</artifactId>
+                </artifactItem>
+                <artifactItem>
+                  <groupId>com.sun.xml.bind</groupId>
+                  <artifactId>jaxb-impl</artifactId>
+                </artifactItem>
+              </artifactItems>
+              <outputDirectory>${project.build.outputDirectory}/lib</outputDirectory>
             </configuration>
-         </plugin>
-
-         <plugin>
-            <artifactId>maven-dependency-plugin</artifactId>
-            <executions>
-               <execution>
-                  <id>copy-jaxb-deps</id>
-                  <phase>process-resources</phase>
-                  <goals>
-                     <goal>copy</goal>
-                  </goals>
-                  <configuration>
-                     <artifactItems>
-                        <artifactItem>
-                           <groupId>javax.xml.bind</groupId>
-                           <artifactId>jaxb-api</artifactId>
-                        </artifactItem>
-                        <artifactItem>
-                           <groupId>com.sun.xml.bind</groupId>
-                           <artifactId>jaxb-impl</artifactId>
-                        </artifactItem>
-                     </artifactItems>
-                     <outputDirectory>${project.build.outputDirectory}/lib</outputDirectory>
-                  </configuration>
-               </execution>
-            </executions>
-         </plugin>
+          </execution>
+        </executions>
+      </plugin>
 
-         <plugin>
-           <groupId>org.codehaus.mojo</groupId>
-           <artifactId>build-helper-maven-plugin</artifactId>
-           <executions>
-             <execution>
-               <id>add-xjc-source</id>
-               <phase>generate-sources</phase>
-               <goals>
-                 <goal>add-source</goal>
-               </goals>
-               <configuration>
-                 <sources>
-                   <source>${basedir}/target/generated-sources/xjc</source>
-                 </sources>
-               </configuration>
-             </execution>
-           </executions>
-         </plugin>
-
-         <plugin>
-            <artifactId>maven-surefire-plugin</artifactId>
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>build-helper-maven-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>add-xjc-source</id>
+            <phase>generate-sources</phase>
+            <goals>
+              <goal>add-source</goal>
+            </goals>
             <configuration>
-               <skip>true</skip>
+              <sources>
+                <source>${basedir}/target/generated-sources/xjc</source>
+              </sources>
             </configuration>
-            <executions>
-               <execution>
-                  <id>surefire-it</id>
-                  <phase>integration-test</phase>
-                  <goals>
-                     <goal>test</goal>
-                  </goals>
-                  <configuration>
-                     <skip>${maven.test.skip}</skip>
-                     <excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
-                     <useSystemClassLoader>false</useSystemClassLoader>
-                     <argLine>-Djava.library.path=${basedir}/target/itest/lib</argLine>
+          </execution>
+        </executions>
+      </plugin>
+
+      <plugin>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <configuration>
+          <skip>true</skip>
+        </configuration>
+        <executions>
+          <execution>
+            <id>surefire-it</id>
+            <phase>integration-test</phase>
+            <goals>
+              <goal>test</goal>
+            </goals>
+            <configuration>
+              <skip>${maven.test.skip}</skip>
+              <excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
+              <useSystemClassLoader>false</useSystemClassLoader>
+              <argLine>-Djava.library.path=${basedir}/target/itest/lib</argLine>
                      <!--
                      <argLine>-Djava.library.path=${basedir}/target/itest/lib -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>
                      -->
 
-                     <systemPropertyVariables>
-                        <project.artifactId>${project.artifactId}</project.artifactId>
-                        <project.version>${project.version}</project.version>
-                     </systemPropertyVariables>
-                  </configuration>
-               </execution>
-            </executions>
-         </plugin>
+              <systemPropertyVariables>
+                <project.artifactId>${project.artifactId}</project.artifactId>
+                <project.version>${project.version}</project.version>
+              </systemPropertyVariables>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
 
-      </plugins>
-   </build>
+    </plugins>
+  </build>
 
-   <profiles>
+  <profiles>
 
-      <profile>
-         <id>dev</id>
+    <profile>
+      <id>dev</id>
 
-         <properties>
-            <rhq.rootDir>../../..</rhq.rootDir>
-            <rhq.containerDir>${rhq.rootDir}/${rhq.defaultDevContainerPath}</rhq.containerDir>
-            <rhq.deploymentDir>${rhq.containerDir}/jbossas/server/default/deploy/${rhq.earName}/rhq-downloads/rhq-plugins</rhq.deploymentDir>
-         </properties>
+      <properties>
+        <rhq.rootDir>../../..</rhq.rootDir>
+        <rhq.containerDir>${rhq.rootDir}/${rhq.defaultDevContainerPath}</rhq.containerDir>
+        <rhq.deploymentDir>${rhq.containerDir}/jbossas/server/default/deploy/${rhq.earName}/rhq-downloads/rhq-plugins</rhq.deploymentDir>
+      </properties>
 
-         <build>
-            <plugins>
+      <build>
+        <plugins>
 
-               <plugin>
-                 <artifactId>maven-antrun-plugin</artifactId>
-                 <executions>
+          <plugin>
+            <artifactId>maven-antrun-plugin</artifactId>
+            <executions>
 
-                     <execution>
-                        <id>deploy</id>
-                        <phase>compile</phase>
-                        <configuration>
-                          <target>
-                            <mkdir dir="${rhq.deploymentDir}" />
-                            <property name="deployment.file" location="${rhq.deploymentDir}/${project.build.finalName}.jar" />
-                            <echo>*** Updating ${deployment.file}...</echo>
-                            <jar destfile="${deployment.file}" basedir="${project.build.outputDirectory}" update="true" />
-                          </target>
-                        </configuration>
-                        <goals>
-                          <goal>run</goal>
-                        </goals>
-                     </execution>
+              <execution>
+                <id>deploy</id>
+                <phase>compile</phase>
+                <configuration>
+                  <target>
+                    <mkdir dir="${rhq.deploymentDir}"/>
+                    <property name="deployment.file" location="${rhq.deploymentDir}/${project.build.finalName}.jar"/>
+                    <echo>*** Updating ${deployment.file}...</echo>
+                    <jar destfile="${deployment.file}" basedir="${project.build.outputDirectory}" update="true"/>
+                  </target>
+                </configuration>
+                <goals>
+                  <goal>run</goal>
+                </goals>
+              </execution>
 
-                     <execution>
-                        <id>deploy-jar-meta-inf</id>
-                        <phase>package</phase>
-                        <configuration>
-                          <target>
-                             <property name="deployment.file" location="${rhq.deploymentDir}/${project.build.finalName}.jar" />
-                             <echo>*** Updating META-INF dir in ${deployment.file}...</echo>
-                             <unjar src="${project.build.directory}/${project.build.finalName}.jar" dest="${project.build.outputDirectory}">
-                               <patternset><include name="META-INF/**" /></patternset>
-                             </unjar>
-                             <jar destfile="${deployment.file}" manifest="${project.build.outputDirectory}/META-INF/MANIFEST.MF" update="true">
-                             </jar>
-                          </target>
-                        </configuration>
-                        <goals>
-                          <goal>run</goal>
-                        </goals>
-                     </execution>
+              <execution>
+                <id>deploy-jar-meta-inf</id>
+                <phase>package</phase>
+                <configuration>
+                  <target>
+                    <property name="deployment.file" location="${rhq.deploymentDir}/${project.build.finalName}.jar"/>
+                    <echo>*** Updating META-INF dir in ${deployment.file}...</echo>
+                    <unjar src="${project.build.directory}/${project.build.finalName}.jar" dest="${project.build.outputDirectory}">
+                      <patternset>
+                        <include name="META-INF/**"/>
+                      </patternset>
+                    </unjar>
+                    <jar destfile="${deployment.file}" manifest="${project.build.outputDirectory}/META-INF/MANIFEST.MF"
+                      update="true">
+                    </jar>
+                  </target>
+                </configuration>
+                <goals>
+                  <goal>run</goal>
+                </goals>
+              </execution>
 
-                     <execution>
-                        <id>undeploy</id>
-                        <phase>clean</phase>
-                        <configuration>
-                          <target>
-                            <property name="deployment.file" location="${rhq.deploymentDir}/${project.build.finalName}.jar" />
-                            <echo>*** Deleting ${deployment.file}...</echo>
-                            <delete file="${deployment.file}" />
-                          </target>
-                        </configuration>
-                        <goals>
-                          <goal>run</goal>
-                        </goals>
-                     </execution>
+              <execution>
+                <id>undeploy</id>
+                <phase>clean</phase>
+                <configuration>
+                  <target>
+                    <property name="deployment.file" location="${rhq.deploymentDir}/${project.build.finalName}.jar"/>
+                    <echo>*** Deleting ${deployment.file}...</echo>
+                    <delete file="${deployment.file}"/>
+                  </target>
+                </configuration>
+                <goals>
+                  <goal>run</goal>
+                </goals>
+              </execution>
 
-                   </executions>
-               </plugin>
+            </executions>
+          </plugin>
 
-            </plugins>
-         </build>
-     </profile>
+        </plugins>
+      </build>
+    </profile>
 
-     <profile>
+    <profile>
       <id>cobertura-plugins</id>
       <activation>
         <activeByDefault>false</activeByDefault>
       </activation>
-        <build>
-         <plugins>
-           <plugin>
-             <artifactId>maven-antrun-plugin</artifactId>
-              <dependencies>
-               <dependency>
-                 <groupId>net.sourceforge.cobertura</groupId>
-                 <artifactId>cobertura</artifactId>
-                 <version>${cobertura.version}</version>
-               </dependency>
-             </dependencies>
-             <executions>
+      <build>
+        <plugins>
+          <plugin>
+            <artifactId>maven-antrun-plugin</artifactId>
+            <dependencies>
+              <dependency>
+                <groupId>net.sourceforge.cobertura</groupId>
+                <artifactId>cobertura</artifactId>
+                <version>${cobertura.version}</version>
+              </dependency>
+            </dependencies>
+            <executions>
               <execution>
-               <id>cobertura-instrument</id>
-               <phase>pre-integration-test</phase>
-                 <configuration>
-                   <target>
+                <id>cobertura-instrument</id>
+                <phase>pre-integration-test</phase>
+                <configuration>
+                  <target>
                    <!-- prepare directory structure for cobertura-->
-                   <mkdir dir="target/cobertura" />
-                   <mkdir dir="target/cobertura/backup" />
+                    <mkdir dir="target/cobertura"/>
+                    <mkdir dir="target/cobertura/backup"/>
                    <!-- backup all classes so that we can instrument the original classes-->
-                   <copy toDir="target/cobertura/backup" verbose="true" overwrite="true">
+                    <copy toDir="target/cobertura/backup" verbose="true" overwrite="true">
                       <fileset dir="target/classes">
-                         <include name="**/*.class" />
+                        <include name="**/*.class"/>
                       </fileset>
-                   </copy>
+                    </copy>
                    <!-- create a properties file and save there location of cobertura data file-->
-                   <touch file="target/classes/cobertura.properties" />
-                   <echo file="target/classes/cobertura.properties">net.sourceforge.cobertura.datafile=${project.build.directory}/cobertura/cobertura.ser</echo>
-                   <taskdef classpathref="maven.plugin.classpath" resource="tasks.properties" />
+                    <touch file="target/classes/cobertura.properties"/>
+                    <echo file="target/classes/cobertura.properties">net.sourceforge.cobertura.datafile=${project.build.directory}/cobertura/cobertura.ser</echo>
+                    <taskdef classpathref="maven.plugin.classpath" resource="tasks.properties"/>
                    <!-- instrument all classes in target/classes directory -->
-                   <cobertura-instrument datafile="${project.build.directory}/cobertura/cobertura.ser" todir="${project.build.directory}/classes">
-                     <fileset dir="${project.build.directory}/classes">
-                        <include name="**/*.class" />
+                    <cobertura-instrument datafile="${project.build.directory}/cobertura/cobertura.ser"
+                      todir="${project.build.directory}/classes">
+                      <fileset dir="${project.build.directory}/classes">
+                        <include name="**/*.class"/>
                       </fileset>
                     </cobertura-instrument>
-                   </target>
-                 </configuration>
-               <goals>
-                 <goal>run</goal>
-               </goals>
+                  </target>
+                </configuration>
+                <goals>
+                  <goal>run</goal>
+                </goals>
               </execution>
               <execution>
-               <id>cobertura-report</id>
-               <phase>post-integration-test</phase>
-                 <configuration>
-                   <target>
-                     <taskdef classpathref="maven.plugin.classpath" resource="tasks.properties" />
+                <id>cobertura-report</id>
+                <phase>post-integration-test</phase>
+                <configuration>
+                  <target>
+                    <taskdef classpathref="maven.plugin.classpath" resource="tasks.properties"/>
                      <!-- prepare directory structure for cobertura-->
-                     <mkdir dir="target/cobertura" />
-                     <mkdir dir="target/site/cobertura" />
+                    <mkdir dir="target/cobertura"/>
+                    <mkdir dir="target/site/cobertura"/>
                      <!-- restore classes from backup folder to classes folder -->
-                     <copy toDir="target/classes" verbose="true" overwrite="true">
+                    <copy toDir="target/classes" verbose="true" overwrite="true">
                       <fileset dir="target/cobertura/backup">
-                         <include name="**/*.class" />
+                        <include name="**/*.class"/>
                       </fileset>
-                     </copy>
+                    </copy>
                      <!-- delete backup folder-->
-                     <delete dir="target/cobertura/backup" />
+                    <delete dir="target/cobertura/backup"/>
                      <!-- create a code coverage report -->
-                     <cobertura-report format="html" datafile="${project.build.directory}/cobertura/cobertura.ser" destdir="${project.build.directory}/site/cobertura">
+                    <cobertura-report format="html" datafile="${project.build.directory}/cobertura/cobertura.ser"
+                      destdir="${project.build.directory}/site/cobertura">
                       <fileset dir="${basedir}/src/main/java">
-                         <include name="**/*.java" />
+                        <include name="**/*.java"/>
                       </fileset>
-                     </cobertura-report>
+                    </cobertura-report>
                      <!-- delete cobertura.properties file -->
-                     <delete file="target/classes/cobertura.properties" />
-                   </target>
-                 </configuration>
-               <goals>
-                 <goal>run</goal>
-               </goals>
-               </execution>
+                    <delete file="target/classes/cobertura.properties"/>
+                  </target>
+                </configuration>
+                <goals>
+                  <goal>run</goal>
+                </goals>
+              </execution>
             </executions>
-           </plugin>
-          </plugins>
-       </build>
-     </profile>
-   </profiles>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+  </profiles>
 
 </project>


commit 5a714f3df86fe659cf2bc5938accaa72482c362d
Author: Simeon Pinder <spinder at redhat.com>
Date:   Tue Jun 26 19:14:10 2012 -0400

     -Add a few more itests for SecurityDomain
       -exercises most of the Module Option Types
     -Remove Authentication (Classic) from ignore list
     -Add ability to override default discovery depth.

diff --git a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/AbstractJBossAS7PluginTest.java b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/AbstractJBossAS7PluginTest.java
index 04c40de..43e6e06 100644
--- a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/AbstractJBossAS7PluginTest.java
+++ b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/AbstractJBossAS7PluginTest.java
@@ -18,6 +18,8 @@
  */
 package org.rhq.modules.plugins.jbossas7.itest;
 
+import static org.testng.Assert.assertNotNull;
+
 import java.util.Set;
 
 import org.rhq.core.clientapi.agent.PluginContainerException;
@@ -35,8 +37,6 @@ import org.rhq.modules.plugins.jbossas7.itest.domain.DomainServerComponentTest;
 import org.rhq.modules.plugins.jbossas7.itest.standalone.StandaloneServerComponentTest;
 import org.rhq.test.arquillian.AfterDiscovery;
 
-import static org.testng.Assert.assertNotNull;
-
 /**
  * The base class for all as7 plugin integration tests.
  *
@@ -51,6 +51,16 @@ public abstract class AbstractJBossAS7PluginTest extends AbstractAgentPluginTest
 
     private static final int TYPE_HIERARCHY_DEPTH = 6;
 
+    private static int OVERRIDE_TYPE_HIERARCHY_DEPTH = -1;
+
+    public static int getMaxDiscoveryDepthOverride() {
+        return OVERRIDE_TYPE_HIERARCHY_DEPTH;
+    }
+
+    public static void setMaxDiscoveryDepthOverride(int overrideDepth) {
+        OVERRIDE_TYPE_HIERARCHY_DEPTH = overrideDepth;
+    }
+
     private static boolean createdManagementUsers;
 
     /**
@@ -115,6 +125,9 @@ public abstract class AbstractJBossAS7PluginTest extends AbstractAgentPluginTest
 
     @Override
     protected int getTypeHierarchyDepth() {
+        if (OVERRIDE_TYPE_HIERARCHY_DEPTH != -1) {
+            return OVERRIDE_TYPE_HIERARCHY_DEPTH;
+        }
         return TYPE_HIERARCHY_DEPTH;
     }
 
diff --git a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/ResourcesStandaloneServerTest.java b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/ResourcesStandaloneServerTest.java
index bd904b9..aad8739 100644
--- a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/ResourcesStandaloneServerTest.java
+++ b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/ResourcesStandaloneServerTest.java
@@ -84,7 +84,7 @@ public class ResourcesStandaloneServerTest extends AbstractJBossAS7PluginTest  {
         ignoredResources.add("Load Metric");
 
         //will revisit after BZ 826542 is resolved
-        ignoredResources.add("Authentication (Classic)");
+        //        ignoredResources.add("Authentication (Classic)");
 
         Resource platform = this.pluginContainer.getInventoryManager().getPlatform();
         Resource server = getResourceByTypeAndKey(platform, StandaloneServerComponentTest.RESOURCE_TYPE,
diff --git a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/SecurityModuleOptionsTest.java b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/SecurityModuleOptionsTest.java
index 7f9464a..e3f88af 100644
--- a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/SecurityModuleOptionsTest.java
+++ b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/SecurityModuleOptionsTest.java
@@ -21,9 +21,15 @@ package org.rhq.modules.plugins.jbossas7.itest.standalone;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertNotNull;
 
+import java.io.IOException;
+import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Set;
 
+import org.codehaus.jackson.JsonNode;
+import org.codehaus.jackson.JsonProcessingException;
+import org.codehaus.jackson.map.DeserializationConfig;
 import org.codehaus.jackson.map.ObjectMapper;
 import org.testng.annotations.Test;
 
@@ -32,17 +38,24 @@ import org.rhq.core.clientapi.agent.inventory.CreateResourceResponse;
 import org.rhq.core.clientapi.agent.inventory.DeleteResourceRequest;
 import org.rhq.core.clientapi.agent.inventory.DeleteResourceResponse;
 import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.Property;
 import org.rhq.core.domain.configuration.PropertySimple;
+import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
 import org.rhq.core.domain.resource.CreateResourceStatus;
 import org.rhq.core.domain.resource.DeleteResourceStatus;
 import org.rhq.core.domain.resource.InventoryStatus;
 import org.rhq.core.domain.resource.Resource;
 import org.rhq.core.domain.resource.ResourceCategory;
 import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.core.pc.configuration.ConfigurationManager;
 import org.rhq.core.pc.inventory.InventoryManager;
 import org.rhq.modules.plugins.jbossas7.ASConnection;
 import org.rhq.modules.plugins.jbossas7.ModuleOptionsComponent;
+import org.rhq.modules.plugins.jbossas7.ModuleOptionsComponent.Value;
 import org.rhq.modules.plugins.jbossas7.itest.AbstractJBossAS7PluginTest;
+import org.rhq.modules.plugins.jbossas7.json.Address;
+import org.rhq.modules.plugins.jbossas7.json.Operation;
+import org.rhq.modules.plugins.jbossas7.json.Result;
 import org.rhq.test.arquillian.RunDiscovery;
 
 /**
@@ -69,6 +82,7 @@ public class SecurityModuleOptionsTest extends AbstractJBossAS7PluginTest {
     private static String SECURITY_DOMAIN_RESOURCE_KEY = "security-domain";
     private static String AUTH_CLASSIC_RESOURCE_TYPE = "Authentication (Classic)";
     private static String AUTH_CLASSIC_RESOURCE_KEY = "authentication=classic";
+    private static String PROFILE = "profile=full-ha";
 
     protected static final String DC_HOST = System.getProperty("jboss.domain.bindAddress");
     protected static final int DC_HTTP_PORT = Integer.valueOf(System.getProperty("jboss.domain.httpManagementPort"));
@@ -83,6 +97,9 @@ public class SecurityModuleOptionsTest extends AbstractJBossAS7PluginTest {
     public static final ResourceType RESOURCE_TYPE = new ResourceType(SECURITY_RESOURCE_TYPE, PLUGIN_NAME,
         ResourceCategory.SERVICE, null);
     private static final String RESOURCE_KEY = SECURITY_RESOURCE_KEY;
+    private static Resource testSecurityDomain = null;
+    private String testSecurityDomainKey = null;
+    private ConfigurationManager testConfigurationManager = null;
 
     //Define some shared and reusable content
     static HashMap<String, String> jsonMap = new HashMap<String, String>();
@@ -100,19 +117,194 @@ public class SecurityModuleOptionsTest extends AbstractJBossAS7PluginTest {
                 "[{\"code\":\"Test\", \"type\":\"attribute\", \"module-options\":{\"mapping\":\"module\", \"mapping1\":\"module1\"}}]");
         jsonMap.put("provider-modules",
             "[{\"code\":\"Providers\", \"module-options\":{\"provider\":\"module\", \"provider1\":\"module1\"}}]");
+        jsonMap
+            .put("acl-modules",
+                "[{\"flag\":\"sufficient\", \"code\":\"ACL\", \"module-options\":{\"acl\":\"module\", \"acl1\":\"module1\"}}]");
+        jsonMap
+            .put("trust-modules",
+                "[{\"flag\":\"optional\", \"code\":\"TRUST\", \"module-options\":{\"trust\":\"module\", \"trust1\":\"module1\"}}]");
     }
 
-    @Test(priority = 10, groups = "discovery")
+    /** This method mass loads all the supported Module Option Types(Excluding authentication=jaspi, cannot co-exist with 
+     * authentication=classic) into a single SecurityDomain.  This is done as
+     * -i)creating all of the related hierarchy of types needed to exercise N Module Options Types and their associated 
+     *     Module Options instances would take too long to setup(N creates would signal N discovery runs before test could complete).
+     * -ii)setting the priority of this method lower than the discovery method means that we'll get all the same types in much 
+     *     less time.
+     *     
+     * @throws Exception
+     */
+    @Test(priority = 10)
+    public void testLoadStandardModuleOptionTypes() throws Exception {
+        mapper = new ObjectMapper();
+        mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+
+        //Adjust discovery depth to support deeper hierarchy depth of Module Option elements
+        setMaxDiscoveryDepthOverride(10);
+
+        //create new Security Domain
+        Address destination = new Address(PROFILE);
+        destination.addSegment(SECURITY_RESOURCE_KEY);
+        String securityDomainId = TEST_DOMAIN + "2";
+        destination.addSegment(SECURITY_DOMAIN_RESOURCE_KEY + "=" + securityDomainId);
+
+        ASConnection connection = getASConnection();
+        Result result = new Result();
+        //delete old one if present to setup clean slate
+        Operation op = new Operation("remove", destination);
+        result = connection.execute(op);
+
+        //build/rebuild hierarchy
+        op = new Operation("add", destination);
+        result = connection.execute(op);
+
+        //Ex. profile=standalone-ha,subsystem=security,security-domain
+        String addressPrefix = PROFILE + "," + SECURITY_RESOURCE_KEY + "," + SECURITY_DOMAIN_RESOURCE_KEY;
+
+        //loop over standard types and add base details for all of them to security domain
+        String address = "";
+        for (String attribute : jsonMap.keySet()) {
+            if (attribute.equals("policy-modules")) {
+                address = addressPrefix + "=" + securityDomainId + ",authorization=classic";
+            } else if (attribute.equals("acl-modules")) {
+                address = addressPrefix + "=" + securityDomainId + ",acl=classic";
+            } else if (attribute.equals("mapping-modules")) {
+                address = addressPrefix + "=" + securityDomainId + ",mapping=classic";
+            } else if (attribute.equals("trust-modules")) {
+                address = addressPrefix + "=" + securityDomainId + ",identity-trust=classic";
+            } else if (attribute.equals("provider-modules")) {
+                address = addressPrefix + "=" + securityDomainId + ",audit=classic";
+            } else if (attribute.equals("login-modules")) {
+                address = addressPrefix + "=" + securityDomainId + ",authentication=classic";
+            } else {
+                assert false : "An unknown attribute '" + attribute
+                    + "' was found. Is there a new type to be supported?";
+            }
+            //build the operation to add the component
+            ////Load json map into ModuleOptionType
+            List<Value> moduleTypeValue = new ArrayList<Value>();
+            try {
+                // loading jsonMap contents for Ex. 'login-module'
+                JsonNode node = mapper.readTree(jsonMap.get(attribute));
+                Object obj = mapper.treeToValue(node, Object.class);
+                result.setResult(obj);
+                result.setOutcome("success");
+            } catch (JsonProcessingException e) {
+                e.printStackTrace();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+
+            //populate the Value component complete with module Options.
+            moduleTypeValue = ModuleOptionsComponent.populateSecurityDomainModuleOptions(result,
+                ModuleOptionsComponent.loadModuleOptionType(attribute));
+            op = ModuleOptionsComponent.createAddModuleOptionTypeOperation(new Address(address), attribute,
+                moduleTypeValue);
+            //submit the command
+            result = connection.execute(op);
+        }
+    }
+
+    @Test(priority = 11, groups = "discovery")
     @RunDiscovery(discoverServices = true, discoverServers = true)
     public void initialDiscovery() throws Exception {
         Resource platform = this.pluginContainer.getInventoryManager().getPlatform();
         assertNotNull(platform);
         assertEquals(platform.getInventoryStatus(), InventoryStatus.COMMITTED);
 
-        Thread.sleep(20 * 1000L); // delay so that PC gets a chance to scan for resources
+        //Have thread sleep longer to discover deeper resource types. 
+        Thread.sleep(120 * 1000L); // delay so that PC gets a chance to scan for resources
     }
 
+    /** This test method exercises a number of things:
+     *  - that the security-domain children loaded have been created successfully
+     *  - that all of the supported Module Option Type children(excluding 'authentication=jaspi') have been 
+     *    discovered as AS7 types successfully.
+     *  - that the correct child attribute was specified for each type //Ex. acl=classic -> acl-modules
+     *  - 
+     * 
+     * @throws Exception
+     */
     @Test(priority = 12)
+    public void testDiscoveredSecurityNodes() throws Exception {
+        //lazy-load configurationManager
+        if (testConfigurationManager == null) {
+            testConfigurationManager = this.pluginContainer.getConfigurationManager();
+            testConfigurationManager = pluginContainer.getConfigurationManager();
+            testConfigurationManager.initialize();
+            Thread.sleep(20 * 1000L);
+        }
+        //iterate through list of nodes and make sure they've all been discovered
+        ////Ex. profile=full-ha,subsystem=security,security-domain=testDomain2,acl=classic
+        String attribute = null;
+        for (String jsonKey : jsonMap.keySet()) {
+            //Ex. policy-modules
+            attribute = jsonKey;
+            //spinder 6/26/12: Temporarily disable until figure out why NPE happens only for this type?
+            if (attribute.equals(ModuleOptionsComponent.ModuleOptionType.Authentication.getAttribute())) {
+                break;//
+            }
+            //Ex. name=acl-modules
+            //check the configuration for the Module Option Type Ex. 'Acl (Profile)' Resource. Should be able to verify components
+            Resource aclResource = getModuleOptionResourceResource(attribute);
+            //assert non-zero id returned
+            assert aclResource.getId() > 0 : "The resource was not properly initialized. Expected id >0 but got:"
+                + aclResource.getId();
+
+            //Now request the resource complete with resource config
+            Configuration loadedConfiguration = testConfigurationManager.loadResourceConfiguration(aclResource.getId());
+            String code = null;
+            String type = null;
+            String flag = null;
+            //populate the associated attributes if it's supported.
+            for (String key : loadedConfiguration.getAllProperties().keySet()) {
+                Property property = loadedConfiguration.getAllProperties().get(key);
+                if (key.equals("code")) {
+                    code = ((PropertySimple) property).getStringValue();
+                } else if (key.equals("flag")) {
+                    flag = ((PropertySimple) property).getStringValue();
+                } else {//Ex. type.
+                    type = ((PropertySimple) property).getStringValue();
+                }
+            }
+
+            //retrieve module options as well.
+            String jsonContent = jsonMap.get(attribute);
+            Result result = new Result();
+            try {
+                // loading jsonMap contents for Ex. 'login-module'
+                JsonNode node = mapper.readTree(jsonContent);
+                Object obj = mapper.treeToValue(node, Object.class);
+                result.setResult(obj);
+                result.setOutcome("success");
+            } catch (JsonProcessingException e) {
+                e.printStackTrace();
+                assert false;
+            } catch (IOException e) {
+                e.printStackTrace();
+                assert false;
+            }
+
+            //populate the Value component complete with module Options.
+            List<Value> moduleTypeValue = ModuleOptionsComponent.populateSecurityDomainModuleOptions(result,
+                ModuleOptionsComponent.loadModuleOptionType(attribute));
+            Value moduleOptionType = moduleTypeValue.get(0);
+            //Ex. retrieve the acl-modules component and assert values.
+            //always test 'code'
+            assert moduleOptionType.getCode().equals(code) : "Module Option 'code' value is not correct. Expected '"
+                + code + "' but was '" + moduleOptionType.getCode() + "'";
+            if (attribute.equals(ModuleOptionsComponent.ModuleOptionType.Mapping.getAttribute())) {
+                assert moduleOptionType.getType().equals(type) : "Mapping Module 'type' value is not correct. Expected '"
+                    + type + "' but was '" + moduleOptionType.getType() + "'";
+            } else if (!attribute.equals(ModuleOptionsComponent.ModuleOptionType.Audit.getAttribute())) {//Audit has no second parameter
+                assert moduleOptionType.getFlag().equals(flag) : "Provider Module 'flag' value is not correct. Expected '"
+                    + flag + "' but was '" + moduleOptionType.getFlag() + "'";
+            }
+        }
+        //TODO spinder 6-26-12: retrieve the Module Options and test them too.
+    }
+
+    @Test(priority = 13)
     public void testCreateSecurityDomain() throws Exception {
         //get the root security resource
         securityResource = getResource();
@@ -140,7 +332,7 @@ public class SecurityModuleOptionsTest extends AbstractJBossAS7PluginTest {
             + response.getErrorMessage();
     }
 
-    @Test(priority = 13)
+    @Test(priority = 14)
     public void testAuthenticationClassic() throws Exception {
         //get the root security resource
         securityResource = getResource();
@@ -179,7 +371,7 @@ public class SecurityModuleOptionsTest extends AbstractJBossAS7PluginTest {
             + response.getErrorMessage();
     }
 
-    @Test(priority = 14)
+    @Test(priority = 15)
     public void testDeleteSecurityDomain() throws Exception {
         //get the root security resource
         securityResource = getResource();
@@ -210,6 +402,15 @@ public class SecurityModuleOptionsTest extends AbstractJBossAS7PluginTest {
             + response.getErrorMessage();
     }
 
+    //    public static void main(String[] args) {
+    //        SecurityModuleOptionsTest setup = new SecurityModuleOptionsTest();
+    //        try {
+    //            setup.testLoadStandardModuleOptionTypes();
+    //        } catch (Exception e) {
+    //            e.printStackTrace();
+    //        }
+    //    }
+
     private Resource getResource() {
 
         InventoryManager im = pluginContainer.getInventoryManager();
@@ -220,6 +421,82 @@ public class SecurityModuleOptionsTest extends AbstractJBossAS7PluginTest {
         return bindings;
     }
 
+    /** Automates
+     * 
+     * @param optionAttributeType
+     * @return
+     */
+    private Resource getModuleOptionResourceResource(String optionAttributeType) {
+        Resource moduleOptionResource = null;
+        String securityDomainId = SECURITY_DOMAIN_RESOURCE_KEY + "=" + TEST_DOMAIN + "2";
+        if (testSecurityDomain == null) {
+            InventoryManager im = pluginContainer.getInventoryManager();
+            Resource platform = im.getPlatform();
+            //host controller
+            ResourceType hostControllerType = new ResourceType("JBossAS7 Host Controller", PLUGIN_NAME,
+                ResourceCategory.SERVER, null);
+            Resource hostController = getResourceByTypeAndKey(platform, hostControllerType,
+                "/tmp/jboss-as-6.0.0.GA/domain");
+            //profile=full-ha
+            ResourceType profileType = new ResourceType("Profile", PLUGIN_NAME, ResourceCategory.SERVICE, null);
+            String key = PROFILE;
+            Resource profile = getResourceByTypeAndKey(hostController, profileType, key);
+
+            //Security (Profile)
+            ResourceType securityType = new ResourceType("Security (Profile)", PLUGIN_NAME, ResourceCategory.SERVICE,
+                null);
+            key += "," + SECURITY_RESOURCE_KEY;
+            Resource security = getResourceByTypeAndKey(profile, securityType, key);
+
+            //Security Domain (Profile)
+            ResourceType domainType = new ResourceType("Security Domain (Profile)", PLUGIN_NAME,
+                ResourceCategory.SERVICE, null);
+            key += "," + securityDomainId;
+            testSecurityDomainKey = key;
+            testSecurityDomain = getResourceByTypeAndKey(security, domainType, key);
+        }
+
+        //acl=classic
+        String descriptorName = "";
+        String moduleAttribute = "";
+        //acl
+        if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.Acl.getAttribute())) {
+            descriptorName = "ACL (Profile)";
+            moduleAttribute = "acl=classic";
+        } else if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.Audit.getAttribute())) {
+            descriptorName = "Audit (Profile)";
+            moduleAttribute = "audit=classic";
+        } else if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.Authentication.getAttribute())) {
+            descriptorName = "Authentication (Classic - Profile)";
+            moduleAttribute = "authentication=classic";
+        } else if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.Authorization.getAttribute())) {
+            descriptorName = "Authorization (Profile)";
+            moduleAttribute = "authorization=classic";
+        } else if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.IdentityTrust.getAttribute())) {
+            descriptorName = "Identity Trust (Profile)";
+            moduleAttribute = "identity-trust=classic";
+        } else if (optionAttributeType.equals(ModuleOptionsComponent.ModuleOptionType.Mapping.getAttribute())) {
+            descriptorName = "Mapping (Profile)";
+            moduleAttribute = "mapping=classic";
+        }
+        //Build the right Module Option Type. Ex. ACL (Profile), etc.
+        ResourceType moduleOptionType = new ResourceType(descriptorName, PLUGIN_NAME, ResourceCategory.SERVICE, null);
+        ConfigurationDefinition cdef = new ConfigurationDefinition(descriptorName, null);
+        moduleOptionType.setResourceConfigurationDefinition(cdef);
+        //Ex. profile=full-ha,subsystem=security,security-domain=testDomain2,identity-trust=classic
+        String moduleOptionTypeKey = testSecurityDomainKey += "," + moduleAttribute;
+
+        if (!testSecurityDomainKey.endsWith(securityDomainId)) {
+            moduleOptionTypeKey = testSecurityDomainKey.substring(0, testSecurityDomainKey.indexOf(securityDomainId)
+                + securityDomainId.length())
+                + "," + moduleAttribute;
+        }
+
+        moduleOptionResource = getResourceByTypeAndKey(testSecurityDomain, moduleOptionType, moduleOptionTypeKey);
+
+        return moduleOptionResource;
+    }
+
     private Resource getResource(Resource parentResource, String pluginDescriptorTypeName, String resourceKey) {
         Resource resource = null;
         if (((parentResource != null) & (pluginDescriptorTypeName != null) & (resourceKey != null))


commit 8f00d2c8e2fde0d6a2d627a2780cbd4e75e200b5
Author: Jirka Kremser <jkremser at redhat.com>
Date:   Wed Jun 27 14:13:52 2012 +0200

    fix parametrization of class

diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractMeasurementDataTraitListDetailView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractMeasurementDataTraitListDetailView.java
index 60cb4d3..b40ca54 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractMeasurementDataTraitListDetailView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractMeasurementDataTraitListDetailView.java
@@ -38,7 +38,7 @@ import org.rhq.enterprise.gui.coregui.client.components.table.Table;
  *
  * @author Ian Springer
  */
-public abstract class AbstractMeasurementDataTraitListDetailView extends Table {
+public abstract class AbstractMeasurementDataTraitListDetailView extends Table<AbstractMeasurementDataTraitDataSource> {
     private static final String[] EXCLUDED_FIELD_NAMES = new String[] { MeasurementDataTraitCriteria.SORT_FIELD_DISPLAY_NAME };
 
     private static final SortSpecifier[] SORT_SPECIFIERS = new SortSpecifier[] {


commit 2d2ae3923fdaa1d94561f3995b4e59521e9267db
Author: Stefan Negrea <snegrea at redhat.com>
Date:   Tue Jun 26 23:03:56 2012 -0500

    [BZ 835710] Removed WebservicesComoponent class and moved the two resources using it to the generic BaseComponent.

diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/WebservicesComponent.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/WebservicesComponent.java
deleted file mode 100644
index 0dea886..0000000
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/WebservicesComponent.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package org.rhq.modules.plugins.jbossas7;
-
-import org.rhq.core.domain.configuration.Configuration;
-import org.rhq.core.pluginapi.configuration.ConfigurationFacet;
-import org.rhq.core.pluginapi.configuration.ConfigurationUpdateReport;
-import org.rhq.core.pluginapi.operation.OperationFacet;
-import org.rhq.core.pluginapi.operation.OperationResult;
-import org.rhq.modules.plugins.jbossas7.json.Operation;
-import org.rhq.modules.plugins.jbossas7.json.Result;
-
-/**
- * Support for Webservices subsystem.
- *  
- * @author Simeon Pinder
- */
-public class WebservicesComponent extends BaseComponent implements OperationFacet, ConfigurationFacet {
-
-    @Override
-    public Configuration loadResourceConfiguration() throws Exception {
-        Configuration config = super.loadResourceConfiguration();
-
-        return config;
-    }
-
-    @Override
-    public void updateResourceConfiguration(ConfigurationUpdateReport report) {
-
-        super.updateResourceConfiguration(report);
-    }
-
-    @Override
-    public OperationResult invokeOperation(String name, Configuration parameters) throws Exception {
-        Operation op = new Operation(name, getAddress());
-        OperationResult operationResult = new OperationResult();
-        Result result = null;
-
-        if ("list-proxies".equals(name)) {
-
-        } else {
-            /*
-             * This is a catch all for operations that are not explicitly treated above.
-             */
-            result = getASConnection().execute(op);
-            if (result.isSuccess()) {
-                operationResult.setSimpleResult("Success");
-            }
-        }
-
-        if (!result.isSuccess()) {
-            operationResult.setErrorMessage(result.getFailureDescription());
-        }
-
-        return operationResult;
-    }
-}
diff --git a/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml
index ecbaea2..e096c0e 100644
--- a/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml
@@ -1745,7 +1745,7 @@
 
     <service name="Webservices (Managed Server)"
              discovery="SubsystemDiscovery"
-             class="WebservicesComponent"
+             class="BaseComponent"
              singleton="true">
 
       <plugin-configuration>
@@ -3228,7 +3228,7 @@
       <plugin-configuration>
         <c:simple-property name="path" readOnly="true" default="login-modules" />
       </plugin-configuration>
-      
+
             &loginModuleResourceConfig;
 
       <service name="Module Options (Classic - Managed Server)" discovery="ModuleOptionsDiscoveryComponent"
@@ -6062,7 +6062,7 @@
       <plugin-configuration>
         <c:simple-property name="path" readOnly="true" default="login-modules" />
       </plugin-configuration>
-      
+
             &loginModuleResourceConfig;
 
       <service name="Module Options (Classic - Profile)" discovery="ModuleOptionsDiscoveryComponent" class="ModuleOptionsComponent"
@@ -8143,7 +8143,7 @@
 
   <service name="Webservices"
            discovery="SubsystemDiscovery"
-           class="WebservicesComponent"
+           class="BaseComponent"
            singleton="true">
 
     <runs-inside>
@@ -10631,7 +10631,7 @@
       <plugin-configuration>
         <c:simple-property name="path" readOnly="true" default="policy-modules" />
       </plugin-configuration>
-		     
+
                       &flagModuleResourceConfig;
 
       <service name="Module Options (Authorization)" discovery="ModuleOptionsDiscoveryComponent" class="ModuleOptionsComponent"


commit aa77d7ee32f40ee646fec469cac8211bada3abd1
Author: Ian Springer <ian.springer at redhat.com>
Date:   Tue Jun 26 16:35:36 2012 -0400

    [BZ 835687] upgrade Postgres driver from 9.1-901.jdbc4 to 9.1-902.jdbc4 (https://bugzilla.redhat.com/show_bug.cgi?id=835687)

diff --git a/pom.xml b/pom.xml
index 210b697..603b89d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -88,7 +88,7 @@
     <log4j.version>1.2.16</log4j.version>
     <ojdbc6.version>11.2.0.3.0</ojdbc6.version>
     <ems.version>1.3</ems.version>
-    <postgresql.version>9.1-901.jdbc4</postgresql.version>
+    <postgresql.version>9.1-902.jdbc4</postgresql.version>
     <h2.version>1.2.139</h2.version>
     <jtds.version>1.2.2</jtds.version>
     <richfaces.version>3.3.3.Final</richfaces.version>
@@ -179,7 +179,8 @@
     <!-- NOTE: The below line is a workaround for a Maven bug, where it does not expand settings.* properties
                used in the distributionManagement section of the POM. -->
     <localRepository>${user.home}/.m2/repository</localRepository>
-      <project.json.version>20080701</project.json.version>
+
+    <project.json.version>20080701</project.json.version>
   </properties>
 
 


commit 2dc5e65abef4476d0b2a6247d258488688232888
Author: Jirka Kremser <jkremser at redhat.com>
Date:   Tue Jun 26 18:02:25 2012 +0200

    [BZ 835574 - When setting up workspace, the dynamically generated classes are not added to classpath] Solved using the org.codehaus.mojo:build-helper-maven-plugin. It adds the generated sources. NOTE: the mvn "process-resources" should be checked in the IDE Maven settings

diff --git a/modules/core/client-api/pom.xml b/modules/core/client-api/pom.xml
index b5f049f..834ad85 100644
--- a/modules/core/client-api/pom.xml
+++ b/modules/core/client-api/pom.xml
@@ -120,6 +120,25 @@
                 </execution>
              </executions>
           </plugin>
+
+          <plugin>
+            <groupId>org.codehaus.mojo</groupId>
+            <artifactId>build-helper-maven-plugin</artifactId>
+            <executions>
+              <execution>
+                <id>add-xjc-source</id>
+                <phase>generate-sources</phase>
+                <goals>
+                  <goal>add-source</goal>
+                </goals>
+                <configuration>
+                  <sources>
+                    <source>${basedir}/target/generated-sources/xjc</source>
+                  </sources>
+                </configuration>
+              </execution>
+            </executions>
+          </plugin>
       </plugins>
    </build>
 
diff --git a/modules/enterprise/gui/coregui/pom.xml b/modules/enterprise/gui/coregui/pom.xml
index aac9b9c..29662c8 100644
--- a/modules/enterprise/gui/coregui/pom.xml
+++ b/modules/enterprise/gui/coregui/pom.xml
@@ -345,6 +345,25 @@
                 </configuration>
             </plugin>
 
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>build-helper-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>add-gwt-source</id>
+                        <phase>generate-sources</phase>
+                        <goals>
+                            <goal>add-source</goal>
+                        </goals>
+                        <configuration>
+                            <sources>
+                                <source>${basedir}/target/generated-sources/gwt</source>
+                            </sources>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+
             <!--
                <plugin>
                   <artifactId>maven-antrun-plugin</artifactId>
diff --git a/modules/enterprise/server/jar/pom.xml b/modules/enterprise/server/jar/pom.xml
index 2ad20a2..bf10fc1 100644
--- a/modules/enterprise/server/jar/pom.xml
+++ b/modules/enterprise/server/jar/pom.xml
@@ -775,6 +775,18 @@ Build-OS-Version=${os.version}
                         </sources>
                     </configuration>
                 </execution>
+                <execution>
+                    <id>add-antlr-sources</id>
+                    <phase>generate-sources</phase>
+                    <goals>
+                        <goal>add-source</goal>
+                    </goals>
+                    <configuration>
+                        <sources>
+                            <source>${basedir}/target/generated-sources/antlr3</source>
+                        </sources>
+                    </configuration>
+                </execution>
             </executions>
          </plugin>
 
diff --git a/modules/enterprise/server/xml-schemas/pom.xml b/modules/enterprise/server/xml-schemas/pom.xml
index d14f05d..6923a7a 100644
--- a/modules/enterprise/server/xml-schemas/pom.xml
+++ b/modules/enterprise/server/xml-schemas/pom.xml
@@ -129,6 +129,25 @@
             </plugin>
 
             <plugin>
+              <groupId>org.codehaus.mojo</groupId>
+              <artifactId>build-helper-maven-plugin</artifactId>
+              <executions>
+                <execution>
+                  <id>add-xjc-source</id>
+                  <phase>generate-sources</phase>
+                  <goals>
+                    <goal>add-source</goal>
+                  </goals>
+                  <configuration>
+                    <sources>
+                      <source>${basedir}/target/generated-sources/xjc</source>
+                    </sources>
+                  </configuration>
+                </execution>
+              </executions>
+            </plugin>
+
+            <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-compiler-plugin</artifactId>
                 <configuration>
diff --git a/modules/plugins/perftest/pom.xml b/modules/plugins/perftest/pom.xml
index 739505b..e045081 100644
--- a/modules/plugins/perftest/pom.xml
+++ b/modules/plugins/perftest/pom.xml
@@ -77,6 +77,25 @@
          </plugin>
 
          <plugin>
+           <groupId>org.codehaus.mojo</groupId>
+           <artifactId>build-helper-maven-plugin</artifactId>
+           <executions>
+             <execution>
+               <id>add-xjc-source</id>
+               <phase>generate-sources</phase>
+               <goals>
+                 <goal>add-source</goal>
+               </goals>
+               <configuration>
+                 <sources>
+                   <source>${basedir}/target/generated-sources/xjc</source>
+                 </sources>
+               </configuration>
+             </execution>
+           </executions>
+         </plugin>
+
+         <plugin>
             <artifactId>maven-surefire-plugin</artifactId>
             <configuration>
                <skip>true</skip>


commit 9ee338547c8d09cb716b6982c74a11d22af212ec
Author: Jay Shaughnessy <jshaughn at redhat.com>
Date:   Tue Jun 26 11:04:45 2012 -0400

    Provide more verbose Exception information in DEBUG mode.

diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java
index f7ae643..dce2e23 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java
@@ -380,8 +380,8 @@ public class ResourceManagerBean implements ResourceManagerLocal, ResourceManage
                 // The most likely reason for a failure, although unlikely in itself, is that newly discovered resources
                 // are currently being merged into the platform, and associated with the doomed agent.  In this case
                 // the user must wait until the merge is complete.  Make sure the caller knows about this possibility.
-                throw new IllegalStateException(
-                    "Failed to uninventory platform. This can happen if new resources were actively being imported. Please wait and try again shortly.");
+                String msg = "Failed to uninventory platform. This can happen if new resources were actively being imported. Please wait and try again shortly.";
+                throw new IllegalStateException(msg, (log.isDebugEnabled() ? e : null));
             }
 
             throw e;


commit 2af89d1a98d2a699590be823b3bb2d20d7ad2dea
Author: John Mazzitelli <mazz at redhat.com>
Date:   Mon Jun 25 15:39:44 2012 -0400

    [BZ] protect measurement facet from mucking with the plugin container's metric schedules. the bulk of this commit is adding a unit test to the arquillian test framework

diff --git a/modules/core/arquillian-integration/container/src/main/java/org/rhq/test/arquillian/FakeServerInventory.java b/modules/core/arquillian-integration/container/src/main/java/org/rhq/test/arquillian/FakeServerInventory.java
index 37e4ff2..b1ac175 100644
--- a/modules/core/arquillian-integration/container/src/main/java/org/rhq/test/arquillian/FakeServerInventory.java
+++ b/modules/core/arquillian-integration/container/src/main/java/org/rhq/test/arquillian/FakeServerInventory.java
@@ -32,6 +32,7 @@ import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -43,6 +44,12 @@ import org.rhq.core.clientapi.agent.upgrade.ResourceUpgradeResponse;
 import org.rhq.core.clientapi.server.discovery.InventoryReport;
 import org.rhq.core.domain.discovery.MergeResourceResponse;
 import org.rhq.core.domain.discovery.ResourceSyncInfo;
+import org.rhq.core.domain.measurement.DataType;
+import org.rhq.core.domain.measurement.DisplayType;
+import org.rhq.core.domain.measurement.MeasurementDefinition;
+import org.rhq.core.domain.measurement.MeasurementScheduleRequest;
+import org.rhq.core.domain.measurement.NumericType;
+import org.rhq.core.domain.measurement.ResourceMeasurementScheduleRequest;
 import org.rhq.core.domain.resource.InventoryStatus;
 import org.rhq.core.domain.resource.Resource;
 import org.rhq.core.domain.resource.ResourceError;
@@ -61,7 +68,6 @@ import org.rhq.core.domain.resource.ResourceType;
  * 
  * @author Lukas Krejci
  */
-// TODO (ips): Why don't we just make this implement DiscoveryServerService and use it as the actual server service?
 public class FakeServerInventory {
 
     private static final Log LOG = LogFactory.getLog(FakeServerInventory.class);
@@ -143,6 +149,7 @@ public class FakeServerInventory {
     private Resource platform;
     private Map<String, Resource> resourceStore = new HashMap<String, Resource>();
     private int counter;
+    private AtomicInteger metricScheduleCounter = new AtomicInteger(1); // used when creating measurement schedules
     private boolean failing;
     private boolean failUpgrade;
 
@@ -364,6 +371,73 @@ public class FakeServerInventory {
         };
     }
 
+    // this expects the mock invocation to have two parameters - Set<Integer> resourceIds, Boolean getChildSchedules
+    public synchronized Answer<Set<ResourceMeasurementScheduleRequest>> getLatestSchedulesForResourceIds() {
+        return new Answer<Set<ResourceMeasurementScheduleRequest>>() {
+            @Override
+            @SuppressWarnings("unchecked")
+            public Set<ResourceMeasurementScheduleRequest> answer(InvocationOnMock invocation) throws Throwable {
+                Object[] args = invocation.getArguments();
+                Set<Integer> resourceIds = (Set<Integer>) args[0];
+                Boolean getChildSchedules = (Boolean) args[1];
+
+                Set<Resource> resources = getResources(resourceIds, getChildSchedules);
+                Set<ResourceMeasurementScheduleRequest> allSchedules = new HashSet<ResourceMeasurementScheduleRequest>();
+                for (Resource resource : resources) {
+                    ResourceMeasurementScheduleRequest resourceSchedules = getDefaultMeasurementSchedules(resource);
+                    if (resourceSchedules != null) {
+                        allSchedules.add(resourceSchedules);
+                    }
+                }
+                return allSchedules;
+            }
+        };
+    }
+
+    // this expects the mock invocation to have one parameter - Set<Integer> resourceIds
+    public synchronized Answer<Set<ResourceMeasurementScheduleRequest>> postProcessNewlyCommittedResources() {
+        return new Answer<Set<ResourceMeasurementScheduleRequest>>() {
+            @Override
+            @SuppressWarnings("unchecked")
+            public Set<ResourceMeasurementScheduleRequest> answer(InvocationOnMock invocation) throws Throwable {
+                Object[] args = invocation.getArguments();
+                Set<Integer> resourceIds = (Set<Integer>) args[0];
+
+                Set<Resource> resources = getResources(resourceIds, false);
+                Set<ResourceMeasurementScheduleRequest> allSchedules = new HashSet<ResourceMeasurementScheduleRequest>();
+                for (Resource resource : resources) {
+                    ResourceMeasurementScheduleRequest resourceSchedules = getDefaultMeasurementSchedules(resource);
+                    if (resourceSchedules != null) {
+                        allSchedules.add(resourceSchedules);
+                    }
+                }
+                return allSchedules;
+            }
+        };
+    }
+
+    private ResourceMeasurementScheduleRequest getDefaultMeasurementSchedules(Resource resource) {
+        ResourceType rt = resource.getResourceType();
+        Set<MeasurementDefinition> metrics = rt.getMetricDefinitions();
+        if (metrics == null || metrics.isEmpty()) {
+            return null;
+        }
+
+        ResourceMeasurementScheduleRequest resourceSchedules = new ResourceMeasurementScheduleRequest(resource.getId());
+        for (MeasurementDefinition metric : metrics) {
+            int id = this.metricScheduleCounter.getAndIncrement();
+            String name = metric.getName();
+            long interval = metric.getDefaultInterval();
+            boolean enabled = metric.isDefaultOn() || metric.getDisplayType() == DisplayType.SUMMARY;
+            DataType dataType = metric.getDataType();
+            NumericType nDataType = metric.getNumericType();
+            MeasurementScheduleRequest schedule = new MeasurementScheduleRequest(id, name, interval, enabled, dataType,
+                nDataType);
+            resourceSchedules.addMeasurementScheduleRequest(schedule);
+        }
+        return resourceSchedules;
+    }
+
     public synchronized boolean isFailing() {
         return failing;
     }
diff --git a/modules/core/plugin-container-itest/src/test/java/org/rhq/core/pc/measurement/ReadOnlyScheduleSetTest.java b/modules/core/plugin-container-itest/src/test/java/org/rhq/core/pc/measurement/ReadOnlyScheduleSetTest.java
new file mode 100644
index 0000000..8435114
--- /dev/null
+++ b/modules/core/plugin-container-itest/src/test/java/org/rhq/core/pc/measurement/ReadOnlyScheduleSetTest.java
@@ -0,0 +1,105 @@
+package org.rhq.core.pc.measurement;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.when;
+
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.container.test.api.TargetsContainer;
+import org.jboss.arquillian.test.api.ArquillianResource;
+import org.jboss.arquillian.testng.Arquillian;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+
+import org.rhq.core.clientapi.server.discovery.InventoryReport;
+import org.rhq.core.domain.resource.InventoryStatus;
+import org.rhq.core.pc.PluginContainer;
+import org.rhq.core.pc.inventory.ResourceContainer;
+import org.rhq.plugins.test.measurement.BZ821058DiscoveryComponent;
+import org.rhq.plugins.test.measurement.BZ821058ResourceComponent;
+import org.rhq.test.arquillian.AfterDiscovery;
+import org.rhq.test.arquillian.BeforeDiscovery;
+import org.rhq.test.arquillian.FakeServerInventory;
+import org.rhq.test.arquillian.MockingServerServices;
+import org.rhq.test.arquillian.ResourceComponentInstances;
+import org.rhq.test.arquillian.ResourceContainers;
+import org.rhq.test.arquillian.RunDiscovery;
+import org.rhq.test.shrinkwrap.RhqAgentPluginArchive;
+
+/**
+ * Test for BZ 821058
+ */
+ at RunDiscovery
+public class ReadOnlyScheduleSetTest extends Arquillian {
+
+    @Deployment(name = "bz821058Plugin")
+    @TargetsContainer("connected-pc-with-metric-collection")
+    public static RhqAgentPluginArchive getTestPlugin() {
+        RhqAgentPluginArchive pluginJar = ShrinkWrap.create(RhqAgentPluginArchive.class, "bz821058-plugin-1.0.jar");
+        return pluginJar.setPluginDescriptor("bz821058-rhq-plugin.xml").addClasses(BZ821058DiscoveryComponent.class,
+            BZ821058ResourceComponent.class);
+    }
+
+    @ArquillianResource
+    private PluginContainer pluginContainer;
+
+    @ArquillianResource
+    public MockingServerServices serverServices;
+
+    private FakeServerInventory fakeServerInventory;
+    private FakeServerInventory.CompleteDiscoveryChecker discoveryCompleteChecker;
+
+    @ResourceContainers(plugin = "bz821058Plugin", resourceType = "BZ821058Server")
+    private Set<ResourceContainer> containers;
+
+    @ResourceComponentInstances(plugin = "bz821058Plugin", resourceType = "BZ821058Server")
+    private Set<BZ821058ResourceComponent> components;
+
+    @BeforeDiscovery(testMethods = "testBZ821058")
+    public void resetServerServices() throws Exception {
+        serverServices.resetMocks();
+        fakeServerInventory = new FakeServerInventory();
+        discoveryCompleteChecker = fakeServerInventory.createAsyncDiscoveryCompletionChecker(1);
+
+        // autoimport everything
+        when(serverServices.getDiscoveryServerService().mergeInventoryReport(any(InventoryReport.class))).then(
+            fakeServerInventory.mergeInventoryReport(InventoryStatus.COMMITTED));
+
+        // set up the metric schedules using the metric metadata to determine default intervals and enablement
+        when(serverServices.getDiscoveryServerService().postProcessNewlyCommittedResources(any(Set.class))).then(
+            fakeServerInventory.postProcessNewlyCommittedResources());
+    }
+
+    @AfterDiscovery
+    public void waitForAsyncDiscoveries() throws Exception {
+        if (discoveryCompleteChecker != null) {
+            discoveryCompleteChecker.waitForDiscoveryComplete(10000);
+        }
+    }
+
+    @Test(groups = "pc.itest.bz821058", priority = 20)
+    public void testBZ821058() throws Exception {
+        Assert.assertNotNull(pluginContainer);
+        Assert.assertTrue(pluginContainer.isStarted());
+
+        // make sure we have the resource container
+        Assert.assertEquals(containers.size(), 1, "missing container");
+
+        // make sure we have the resource component
+        Assert.assertEquals(components.size(), 1, "missing component");
+
+        assert containers.iterator().next().getResource().getInventoryStatus() == InventoryStatus.COMMITTED;
+
+        BZ821058ResourceComponent server = this.components.iterator().next();
+        // collection interval is set to 30s, and our container "connected-pc-with-metric-collection"
+        // is configured to start collecting metrics after an initial delay of 10s (see arquillian.xml).
+        // So let's give the test some time so the measurement facet can be called.
+        server.getValuesLatch.await(45, TimeUnit.SECONDS);
+
+        assert !server.errors.isEmpty() : "there should have been exceptions that occurred in the getValues method";
+    }
+}
diff --git a/modules/core/plugin-container-itest/src/test/java/org/rhq/plugins/test/measurement/BZ821058DiscoveryComponent.java b/modules/core/plugin-container-itest/src/test/java/org/rhq/plugins/test/measurement/BZ821058DiscoveryComponent.java
new file mode 100644
index 0000000..b9f49a4
--- /dev/null
+++ b/modules/core/plugin-container-itest/src/test/java/org/rhq/plugins/test/measurement/BZ821058DiscoveryComponent.java
@@ -0,0 +1,51 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 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.plugins.test.measurement;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.core.pluginapi.inventory.DiscoveredResourceDetails;
+import org.rhq.core.pluginapi.inventory.InvalidPluginConfigurationException;
+import org.rhq.core.pluginapi.inventory.ResourceComponent;
+import org.rhq.core.pluginapi.inventory.ResourceDiscoveryComponent;
+import org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext;
+
+public class BZ821058DiscoveryComponent implements ResourceDiscoveryComponent<ResourceComponent<?>> {
+
+    @Override
+    public Set<DiscoveredResourceDetails> discoverResources(ResourceDiscoveryContext<ResourceComponent<?>> context)
+        throws InvalidPluginConfigurationException, Exception {
+
+        HashSet<DiscoveredResourceDetails> details = new HashSet<DiscoveredResourceDetails>(1);
+        ResourceType rt = context.getResourceType();
+        String key = "bz821058";
+        String name = "bz821058";
+        String version = "1";
+        Configuration pc = context.getDefaultPluginConfiguration();
+        DiscoveredResourceDetails resource = new DiscoveredResourceDetails(rt, key, name, version, null, pc, null);
+        details.add(resource);
+
+        return details;
+    }
+
+}
diff --git a/modules/core/plugin-container-itest/src/test/java/org/rhq/plugins/test/measurement/BZ821058ResourceComponent.java b/modules/core/plugin-container-itest/src/test/java/org/rhq/plugins/test/measurement/BZ821058ResourceComponent.java
new file mode 100644
index 0000000..1ccadd6
--- /dev/null
+++ b/modules/core/plugin-container-itest/src/test/java/org/rhq/plugins/test/measurement/BZ821058ResourceComponent.java
@@ -0,0 +1,84 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 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.plugins.test.measurement;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.CountDownLatch;
+
+import org.rhq.core.domain.measurement.AvailabilityType;
+import org.rhq.core.domain.measurement.MeasurementDataNumeric;
+import org.rhq.core.domain.measurement.MeasurementReport;
+import org.rhq.core.domain.measurement.MeasurementScheduleRequest;
+import org.rhq.core.pluginapi.inventory.ResourceComponent;
+import org.rhq.core.pluginapi.inventory.ResourceContext;
+import org.rhq.core.pluginapi.measurement.MeasurementFacet;
+
+public class BZ821058ResourceComponent implements ResourceComponent<ResourceComponent<?>>, MeasurementFacet {
+
+    public List<Throwable> errors = Collections.synchronizedList(new ArrayList<Throwable>());
+    public CountDownLatch getValuesLatch = new CountDownLatch(1);
+
+    @Override
+    public AvailabilityType getAvailability() {
+        return AvailabilityType.UP;
+    }
+
+    @Override
+    public void start(ResourceContext<ResourceComponent<?>> context) throws Exception {
+    }
+
+    @Override
+    public void stop() {
+    }
+
+    /**
+     * To test BZ 821058, we just need to make sure we get exceptions if we try to
+     * manipulate the metrics set when this method is called by the PC.
+     */
+    @Override
+    public void getValues(MeasurementReport report, Set<MeasurementScheduleRequest> metrics) throws Exception {
+        try {
+            for (Iterator<MeasurementScheduleRequest> i = metrics.iterator(); i.hasNext();) {
+                MeasurementScheduleRequest metric = i.next();
+                report.addData(new MeasurementDataNumeric(metric, new Double(1.0)));
+                System.out.println("===============PRE REMOVE");
+                i.remove(); // this should not be allowed
+                System.out.println("===============POST REMOVE");
+            }
+        } catch (Throwable e) {
+            errors.add(e);
+        }
+
+        try {
+            System.out.println("===============PRE CLEAR");
+            metrics.clear(); // this should not be allowed
+            System.out.println("===============POST CLEAR");
+        } catch (Throwable e) {
+            errors.add(e);
+        }
+
+        getValuesLatch.countDown();
+        return;
+    }
+}
diff --git a/modules/core/plugin-container-itest/src/test/resources/arquillian.xml b/modules/core/plugin-container-itest/src/test/resources/arquillian.xml
index b8b9271..92968b2 100644
--- a/modules/core/plugin-container-itest/src/test/resources/arquillian.xml
+++ b/modules/core/plugin-container-itest/src/test/resources/arquillian.xml
@@ -4,6 +4,15 @@
   xsi:schemaLocation="http://jboss.org/schema/arquillian http://jboss.org/schema/arquillian/arquillian_1_0.xsd">
 
   <group qualifier="pcs">
+    <container qualifier="connected-pc-with-metric-collection">
+      <configuration>
+        <property name="serverServicesImplementationClassName">org.rhq.test.arquillian.MockingServerServices</property>
+        <property name="insideAgent">true</property>
+        <property name="startManagementBean">false</property>
+        <property name="measurementCollectionInitialDelay">10</property> <!-- start collecting metrics after 10s -->
+      </configuration>
+    </container>
+
     <container qualifier="connected-pc" default="true">
       <configuration>
         <property name="serverServicesImplementationClassName">org.rhq.test.arquillian.MockingServerServices</property>
diff --git a/modules/core/plugin-container-itest/src/test/resources/bz821058-rhq-plugin.xml b/modules/core/plugin-container-itest/src/test/resources/bz821058-rhq-plugin.xml
new file mode 100644
index 0000000..730a656
--- /dev/null
+++ b/modules/core/plugin-container-itest/src/test/resources/bz821058-rhq-plugin.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<plugin name="bz821058Plugin"
+        displayName="Plugin to test BZ 821058"
+        description="This will help test that measurement facet is given a read-only schedule set."
+        package="org.rhq.plugins.test.measurement"
+        version="1.0"
+        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xmlns="urn:xmlns:rhq-plugin"
+        xmlns:c="urn:xmlns:rhq-configuration">
+
+   <server name="BZ821058Server"
+           discovery="BZ821058DiscoveryComponent"
+           class="BZ821058ResourceComponent">
+
+      <metric property="metric1"
+              dataType="measurement"
+              defaultOn="true"
+              displayType="summary"
+              defaultInterval="30000" />
+
+      <metric property="metric2"
+              dataType="measurement"
+              defaultOn="true"
+              displayType="summary"
+              defaultInterval="30000" />
+   </server>
+</plugin>
+        
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/measurement/MeasurementCollectorRunner.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/measurement/MeasurementCollectorRunner.java
index 3714ad9..ac13b06 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/measurement/MeasurementCollectorRunner.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/measurement/MeasurementCollectorRunner.java
@@ -23,6 +23,7 @@
 package org.rhq.core.pc.measurement;
 
 import java.util.ArrayDeque;
+import java.util.Collections;
 import java.util.Date;
 import java.util.Set;
 import java.util.concurrent.Callable;
@@ -130,7 +131,7 @@ public class MeasurementCollectorRunner implements Callable<MeasurementReport>,
         Set<? extends MeasurementScheduleRequest> requests, Resource resource) {
         try {
             long start = System.currentTimeMillis();
-            measurementComponent.getValues(report, (Set<MeasurementScheduleRequest>) requests);
+            measurementComponent.getValues(report, Collections.unmodifiableSet(requests));
             long duration = (System.currentTimeMillis() - start);
             if (duration > 2000L) {
                 String message = "[PERF] Collection of measurements for [" + resource + "] (component=["
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/measurement/MeasurementManager.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/measurement/MeasurementManager.java
index 9ab82cb..dc7d0ca 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/measurement/MeasurementManager.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/measurement/MeasurementManager.java
@@ -469,7 +469,7 @@ public class MeasurementManager extends AgentService implements MeasurementAgent
         }
 
         try {
-            measurementFacet.getValues(report, requests);
+            measurementFacet.getValues(report, Collections.unmodifiableSet(requests));
         } catch (Throwable t) {
             LOG.error("Could not get measurement values", t);
             return Collections.emptySet();


commit 00ea14c228bd08d6572d0f17ef8040e447b9a0dd
Author: Jay Shaughnessy <jshaughn at redhat.com>
Date:   Mon Jun 25 12:47:42 2012 -0400

    [827647 Relative path for Drift Detections Definition Include/Excludes Path does not handle relative path alias or trailing file separator correctly]
    There were two ways to go here. One was to add special case handling for
    the various filter paths that equate to ".".  The other was to normalize
    in the Filter constructor.  Since I tried option 1 and missed a spot in my
    first try to fix it, I've now opted for option 2.  The downside is only that
    what the user types may get normalized to ".". But I added some more description
    text to state as much. Also, existing Filter paths using "/" or "./" will
    need to be updated to "." manually, but I doubt there are any out there
    currently since it wasn't working.

diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/drift/DriftConfigurationDefinition.java b/modules/core/domain/src/main/java/org/rhq/core/domain/drift/DriftConfigurationDefinition.java
index dee6e01..5eaaeab 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/drift/DriftConfigurationDefinition.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/drift/DriftConfigurationDefinition.java
@@ -519,7 +519,7 @@ public class DriftConfigurationDefinition implements Serializable {
 
     private static PropertyDefinitionSimple createIncludePath(boolean readOnly) {
         String name = PROP_PATH;
-        String description = "A file system directory path that is relative to (a sub-directory of) the base directory of the drift definition. The default is '.', the base directory itself.";
+        String description = "A file system directory path that is relative to (a sub-directory of) the base directory of the drift definition. The default is '.', the base directory itself.  Note that '/' and './' will be normalized to '.' for consistent handling.";
         boolean required = false;
         PropertySimpleType type = PropertySimpleType.STRING;
 
@@ -592,7 +592,7 @@ public class DriftConfigurationDefinition implements Serializable {
 
     private static PropertyDefinitionSimple createExcludePath(boolean readOnly) {
         String name = PROP_PATH;
-        String description = "A file system path that can be a directory or a file. The path is assumed to be relative to the base directory of the drift definition.";
+        String description = "A file system directory path that is relative to (a sub-directory of) the base directory of the drift definition. The default is '.', the base directory itself.  Note that '/' and './' will be normalized to '.' for consistent handling.";
         boolean required = true;
         PropertySimpleType type = PropertySimpleType.STRING;
 
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/drift/Filter.java b/modules/core/domain/src/main/java/org/rhq/core/domain/drift/Filter.java
index b57eb32..7e7bc43 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/drift/Filter.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/drift/Filter.java
@@ -41,7 +41,7 @@ public class Filter implements Serializable {
     }
 
     public void setPath(String path) {
-        if (path == null) {
+        if (path == null || "./".equals(path) || "/".equals(path)) {
             this.path = ".";
         } else {
             this.path = path;
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftDetector.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftDetector.java
index 92042e7..dbc7a1d 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftDetector.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftDetector.java
@@ -404,8 +404,7 @@ public class DriftDetector implements Runnable {
         }
     }
 
-    // package-private for test accessibility
-    static Set<File> getScanDirectories(final File basedir, List<Filter> includes) {
+    private static Set<File> getScanDirectories(final File basedir, List<Filter> includes) {
 
         Set<File> directories = new HashSet<File>();
 
@@ -414,8 +413,7 @@ public class DriftDetector implements Runnable {
         } else {
             for (Filter filter : includes) {
                 String path = filter.getPath();
-                // support various ways of expressing the base directory with relative paths  
-                if (".".equals(path) || "./".equals(path) || "/".equals(path)) {
+                if (".".equals(path)) {
                     directories.add(basedir);
                 } else {
                     directories.add(new File(basedir, path));
diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/FilterFileVisitorTest.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/FilterFileVisitorTest.java
index d6812ba..eb3678c 100644
--- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/FilterFileVisitorTest.java
+++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/FilterFileVisitorTest.java
@@ -31,10 +31,8 @@ import java.io.File;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Set;
 
 import org.apache.commons.io.FileUtils;
-import org.testng.Assert;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
@@ -85,12 +83,7 @@ public class FilterFileVisitorTest {
         List<Filter> includes = asList(new Filter(".", "foo*"), new Filter("./", "*.war"), new Filter("/", "goo*"));
         List<Filter> excludes = emptyList();
         TestVisitor visitor = new TestVisitor();
-
-        // This call normalizes the basedir.
-        Set<File> dirs = DriftDetector.getScanDirectories(basedir, includes);
-        Assert.assertEquals(dirs.size(), 1, "Should just be the basedir");
-        File normalizedBaseDir = dirs.iterator().next();
-        forEachFile(normalizedBaseDir, new FilterFileVisitor(normalizedBaseDir, includes, excludes, visitor));
+        forEachFile(basedir, new FilterFileVisitor(basedir, includes, excludes, visitor));
 
         assertCollectionEqualsNoOrder(asList(fooJar, gooJar, myapp), visitor.visitedFiles,
             "Filtering failed with multiple includes and no excludes");


commit 1c7723b1fab7b3e0c16d94804014f70f3976960d
Author: Jirka Kremser <jkremser at redhat.com>
Date:   Mon Jun 25 18:24:21 2012 +0200

    [BZ 675150 - GWT: Alert definition : Conditions : metrics not sorted] Added new a class for serted version of the SelectItem

diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/ServerPluginControlView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/ServerPluginControlView.java
index 597d158..df98a0a 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/ServerPluginControlView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/ServerPluginControlView.java
@@ -47,6 +47,7 @@ import org.rhq.enterprise.gui.coregui.client.CoreGUI;
 import org.rhq.enterprise.gui.coregui.client.ErrorMessageWindow;
 import org.rhq.enterprise.gui.coregui.client.ImageManager;
 import org.rhq.enterprise.gui.coregui.client.components.configuration.ConfigurationEditor;
+import org.rhq.enterprise.gui.coregui.client.components.form.SortedSelectItem;
 import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
 import org.rhq.enterprise.gui.coregui.client.gwt.PluginGWTServiceAsync;
 import org.rhq.enterprise.gui.coregui.client.util.message.Message;
@@ -100,7 +101,7 @@ public class ServerPluginControlView extends LocatableVStack {
         executeButton.setSrc(ImageManager.getOperationIcon());
         executeButton.setPrompt(MSG.common_button_execute());
 
-        final SelectItem controlNamesItem = new SelectItem("controlMenu", MSG.view_admin_plugins_serverControls_name());
+        final SelectItem controlNamesItem = new SortedSelectItem("controlMenu", MSG.view_admin_plugins_serverControls_name());
         LinkedHashMap<String, String> controlNames = new LinkedHashMap<String, String>();
         for (ServerPluginControlDefinition def : controlDefinitions) {
             controlNames.put(def.getName(), def.getDisplayName());
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/CliNotificationSenderForm.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/CliNotificationSenderForm.java
index 225c5c5..f63eb55 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/CliNotificationSenderForm.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/CliNotificationSenderForm.java
@@ -59,6 +59,7 @@ import org.rhq.enterprise.gui.coregui.client.CoreGUI;
 import org.rhq.enterprise.gui.coregui.client.ImageManager;
 import org.rhq.enterprise.gui.coregui.client.UserSessionManager;
 import org.rhq.enterprise.gui.coregui.client.components.form.RadioGroupWithComponentsItem;
+import org.rhq.enterprise.gui.coregui.client.components.form.SortedSelectItem;
 import org.rhq.enterprise.gui.coregui.client.components.upload.DynamicFormHandler;
 import org.rhq.enterprise.gui.coregui.client.components.upload.DynamicFormSubmitCompleteEvent;
 import org.rhq.enterprise.gui.coregui.client.components.upload.PackageVersionFileUploadForm;
@@ -226,7 +227,7 @@ public class CliNotificationSenderForm extends AbstractNotificationSenderForm {
                     SectionItem userSection = new SectionItem("userSection");
                     userSection.setDefaultValue(MSG.view_alert_definition_notification_cliScript_editor_whichUser());
 
-                    repoSelector = new SelectItem(extendLocatorId("repoSelector"), MSG
+                    repoSelector = new SortedSelectItem(extendLocatorId("repoSelector"), MSG
                         .view_alert_definition_notification_cliScript_editor_selectRepo());
                     repoSelector.setDefaultToFirstOption(true);
                     repoSelector.setWrapTitle(false);
@@ -557,7 +558,7 @@ public class CliNotificationSenderForm extends AbstractNotificationSenderForm {
     private DynamicForm createExistingPackageForm() {
         LocatableDynamicForm form = new LocatableDynamicForm(extendLocatorId("existingPackageForm"));
         form.setTitleOrientation(TitleOrientation.TOP);
-        existingPackageSelector = new SelectItem(extendLocatorId("existingPackageSelector"), "");
+        existingPackageSelector = new SortedSelectItem(extendLocatorId("existingPackageSelector"), "");
         existingPackageSelector.setDefaultToFirstOption(true);
         existingPackageSelector.setWrapTitle(false);
         existingPackageSelector.setRedrawOnChange(true);
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/NewConditionEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/NewConditionEditor.java
index c9785b8..2687a87 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/NewConditionEditor.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/NewConditionEditor.java
@@ -24,14 +24,12 @@
 package org.rhq.enterprise.gui.coregui.client.alert.definitions;
 
 import java.util.ArrayList;
-import java.util.Comparator;
 import java.util.EnumSet;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.Set;
-import java.util.SortedSet;
 import java.util.TreeSet;
 
 import com.smartgwt.client.types.Alignment;
@@ -62,6 +60,7 @@ import org.rhq.core.domain.resource.ResourceType;
 import org.rhq.enterprise.gui.coregui.client.CoreGUI;
 import org.rhq.enterprise.gui.coregui.client.components.form.DurationItem;
 import org.rhq.enterprise.gui.coregui.client.components.form.NumberWithUnitsValidator;
+import org.rhq.enterprise.gui.coregui.client.components.form.SortedSelectItem;
 import org.rhq.enterprise.gui.coregui.client.components.form.TimeUnit;
 import org.rhq.enterprise.gui.coregui.client.util.measurement.MeasurementParser;
 import org.rhq.enterprise.gui.coregui.client.util.message.Message;
@@ -176,7 +175,7 @@ public class NewConditionEditor extends LocatableDynamicForm {
 
         setMargin(20);
 
-        conditionTypeSelectItem = new SelectItem("conditionType",
+        conditionTypeSelectItem = new SortedSelectItem("conditionType",
             MSG.view_alert_definition_condition_editor_option_label());
         LinkedHashMap<String, String> condTypes = new LinkedHashMap<String, String>(7);
         condTypes.put(AlertConditionCategory.AVAILABILITY.name(),
@@ -761,7 +760,7 @@ public class NewConditionEditor extends LocatableDynamicForm {
             }
         }
 
-        SelectItem traitSelection = new SelectItem(TRAIT_METRIC_ITEMNAME,
+        SelectItem traitSelection = new SortedSelectItem(TRAIT_METRIC_ITEMNAME,
             MSG.view_alert_definition_condition_editor_metric_trait_change_value());
         traitSelection.setValueMap(traitsMap);
         traitSelection.setDefaultValue(traitsMap.keySet().iterator().next()); // just use the first one
@@ -782,7 +781,7 @@ public class NewConditionEditor extends LocatableDynamicForm {
         StaticTextItem helpItem = buildHelpTextItem("availabilityHelp", helpStr, ifFunc);
         formItems.add(helpItem);
 
-        SelectItem selection = new SelectItem(AVAILABILITY_ITEMNAME,
+        SelectItem selection = new SortedSelectItem(AVAILABILITY_ITEMNAME,
             MSG.view_alert_definition_condition_editor_availability_value());
         LinkedHashMap<String, String> avails = new LinkedHashMap<String, String>(2);
         avails.put(AlertConditionOperator.AVAIL_GOES_DOWN.name(),
@@ -815,7 +814,7 @@ public class NewConditionEditor extends LocatableDynamicForm {
         StaticTextItem helpItem = buildHelpTextItem("availabilityDurationHelp", helpStr, ifFunc);
         formItems.add(helpItem);
 
-        SelectItem selection = new SelectItem(AVAILABILITY_DURATION_ITEMNAME,
+        SelectItem selection = new SortedSelectItem(AVAILABILITY_DURATION_ITEMNAME,
             MSG.view_alert_definition_condition_editor_availabilityDuration());
         LinkedHashMap<String, String> avails = new LinkedHashMap<String, String>(2);
         avails.put(AlertConditionOperator.AVAIL_DURATION_DOWN.name(),
@@ -856,7 +855,7 @@ public class NewConditionEditor extends LocatableDynamicForm {
             ops.put(opDef.getName(), opDef.getDisplayName());
         }
 
-        SelectItem opSelection = new SelectItem(OPERATION_NAME_ITEMNAME, MSG.common_title_value());
+        SelectItem opSelection = new SortedSelectItem(OPERATION_NAME_ITEMNAME, MSG.common_title_value());
         opSelection.setValueMap(ops);
         opSelection.setDefaultValue(ops.keySet().iterator().next()); // just use the first one
         opSelection.setWidth("*");
@@ -864,7 +863,7 @@ public class NewConditionEditor extends LocatableDynamicForm {
         opSelection.setShowIfCondition(ifFunc);
         formItems.add(opSelection);
 
-        SelectItem opResultsSelection = new SelectItem(OPERATION_RESULTS_ITEMNAME, MSG.common_title_status());
+        SelectItem opResultsSelection = new SortedSelectItem(OPERATION_RESULTS_ITEMNAME, MSG.common_title_status());
         LinkedHashMap<String, String> operationStatuses = new LinkedHashMap<String, String>(4);
         operationStatuses.put(OperationRequestStatus.INPROGRESS.name(), MSG.common_status_inprogress());
         operationStatuses.put(OperationRequestStatus.SUCCESS.name(), MSG.common_status_success());
@@ -969,15 +968,7 @@ public class NewConditionEditor extends LocatableDynamicForm {
         }
 
         LinkedHashMap<String, String> metricsMap = new LinkedHashMap<String, String>();
-        SortedSet<MeasurementDefinition> sortedDefs = new TreeSet<MeasurementDefinition>(
-            new Comparator<MeasurementDefinition>() {
-
-                @Override
-                public int compare(MeasurementDefinition o1, MeasurementDefinition o2) {
-                    return o1.getDisplayName().compareTo(o2.getDisplayName());
-                }
-            });
-        sortedDefs.addAll(this.resourceType.getMetricDefinitions());
+        Set<MeasurementDefinition> sortedDefs = new HashSet<MeasurementDefinition>(this.resourceType.getMetricDefinitions());
 
         for (MeasurementDefinition def : sortedDefs) {
             if (def.getDataType() == DataType.MEASUREMENT) {
@@ -994,7 +985,7 @@ public class NewConditionEditor extends LocatableDynamicForm {
             return null; // all metrics should be hidden
         }
 
-        SelectItem metricSelection = new SelectItem(itemName,
+        SelectItem metricSelection = new SortedSelectItem(itemName,
             MSG.view_alert_definition_condition_editor_metric_threshold_name());
         metricSelection.setValueMap(metricsMap);
         metricSelection.setDefaultValue(metricsMap.keySet().iterator().next()); // just use the first one
@@ -1013,7 +1004,7 @@ public class NewConditionEditor extends LocatableDynamicForm {
             }
         }
 
-        SelectItem metricSelection = new SelectItem(itemName,
+        SelectItem metricSelection = new SortedSelectItem(itemName,
             MSG.view_alert_definition_condition_editor_metric_calltime_common_name());
         metricSelection.setValueMap(metricsMap);
         metricSelection.setDefaultValue(metricsMap.keySet().iterator().next()); // just use the first one
@@ -1033,7 +1024,7 @@ public class NewConditionEditor extends LocatableDynamicForm {
         comparators.put(">", "> (" + MSG.view_alert_definition_condition_editor_metric_threshold_comparator_greater()
             + ")");
 
-        SelectItem comparatorSelection = new SelectItem(itemName,
+        SelectItem comparatorSelection = new SortedSelectItem(itemName,
             MSG.view_alert_definition_condition_editor_metric_threshold_comparator());
         comparatorSelection.setValueMap(comparators);
         comparatorSelection.setDefaultValue("<");
@@ -1051,7 +1042,7 @@ public class NewConditionEditor extends LocatableDynamicForm {
         comparators.put("CH", MSG.view_alert_definition_condition_editor_metric_calltime_common_comparator_changes());
         comparators.put("HI", MSG.view_alert_definition_condition_editor_metric_calltime_common_comparator_grows());
 
-        SelectItem comparatorSelection = new SelectItem(itemName,
+        SelectItem comparatorSelection = new SortedSelectItem(itemName,
             MSG.view_alert_definition_condition_editor_metric_calltime_common_comparator());
         comparatorSelection.setValueMap(comparators);
         comparatorSelection.setDefaultValue("CH");
@@ -1070,7 +1061,7 @@ public class NewConditionEditor extends LocatableDynamicForm {
         comparators.put("<=", MSG.view_alert_definition_condition_editor_metric_range_comparator_inside_inclusive());
         comparators.put(">=", MSG.view_alert_definition_condition_editor_metric_range_comparator_outside_inclusive());
 
-        SelectItem comparatorSelection = new SelectItem(itemName,
+        SelectItem comparatorSelection = new SortedSelectItem(itemName,
             MSG.view_alert_definition_condition_editor_metric_range_comparator());
         comparatorSelection.setValueMap(comparators);
         comparatorSelection.setDefaultValue("<");
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/NewNotificationEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/NewNotificationEditor.java
index 666ecfa..9cf0850 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/NewNotificationEditor.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/NewNotificationEditor.java
@@ -45,6 +45,7 @@ import org.rhq.core.domain.alert.notification.AlertNotification;
 import org.rhq.core.domain.resource.Resource;
 import org.rhq.core.domain.resource.ResourceType;
 import org.rhq.enterprise.gui.coregui.client.CoreGUI;
+import org.rhq.enterprise.gui.coregui.client.components.form.SortedSelectItem;
 import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
 import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableDynamicForm;
 import org.rhq.enterprise.gui.coregui.client.util.selenium.SeleniumUtility;
@@ -84,7 +85,7 @@ public class NewNotificationEditor extends LocatableDynamicForm {
         senderCanvasItem.setShowTitle(false);
         senderCanvasItem.setColSpan(2);
 
-        notificationSenderSelectItem = new SelectItem("notificationSender", MSG
+        notificationSenderSelectItem = new SortedSelectItem("notificationSender", MSG
             .view_alert_definition_notification_editor_sender());
         notificationSenderSelectItem.setDefaultToFirstOption(true);
         notificationSenderSelectItem.setWrapTitle(false);
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/RecoveryAlertDefinitionForm.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/RecoveryAlertDefinitionForm.java
index 0e8f1b2..e34f2eb 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/RecoveryAlertDefinitionForm.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/RecoveryAlertDefinitionForm.java
@@ -37,6 +37,7 @@ import org.rhq.core.domain.alert.AlertDefinition;
 import org.rhq.core.domain.criteria.AlertDefinitionCriteria;
 import org.rhq.core.domain.util.PageList;
 import org.rhq.enterprise.gui.coregui.client.CoreGUI;
+import org.rhq.enterprise.gui.coregui.client.components.form.SortedSelectItem;
 import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
 import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableDynamicForm;
 
@@ -171,7 +172,7 @@ public class RecoveryAlertDefinitionForm extends LocatableDynamicForm implements
                 .view_alert_definition_recovery_editor_disable_when_fired());
             disableWhenFiredStatic.setWrapTitle(false);
 
-            recoverAlertSelection = new SelectItem("recoveryAlert", MSG
+            recoverAlertSelection = new SortedSelectItem("recoveryAlert", MSG
                 .view_alert_definition_recovery_editor_recovery_alert());
             recoverAlertSelection.setDefaultValue("0");
             recoverAlertSelection.setWrapTitle(false);
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ResourceOperationNotificationSenderForm.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ResourceOperationNotificationSenderForm.java
index 4a565a2..cc4e061 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ResourceOperationNotificationSenderForm.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ResourceOperationNotificationSenderForm.java
@@ -59,9 +59,10 @@ import org.rhq.core.domain.util.PageList;
 import org.rhq.enterprise.gui.coregui.client.CoreGUI;
 import org.rhq.enterprise.gui.coregui.client.alert.definitions.ResourceOperationNotificationInfo.ResourceSelectionMode;
 import org.rhq.enterprise.gui.coregui.client.components.configuration.ConfigurationEditor;
+import org.rhq.enterprise.gui.coregui.client.components.form.SortedSelectItem;
 import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
-import org.rhq.enterprise.gui.coregui.client.inventory.resource.selection.SingleResourcePicker;
 import org.rhq.enterprise.gui.coregui.client.inventory.resource.selection.ResourcePicker.OkHandler;
+import org.rhq.enterprise.gui.coregui.client.inventory.resource.selection.SingleResourcePicker;
 import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableDynamicForm;
 import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableHLayout;
 import org.rhq.enterprise.gui.coregui.client.util.selenium.SeleniumUtility;
@@ -109,7 +110,7 @@ public class ResourceOperationNotificationSenderForm extends AbstractNotificatio
         operationArgumentsCanvasItem.setHeight(400);
         operationArgumentsCanvasItem.setWidth(500);
 
-        operationSelectItem = new SelectItem("operationSelectItem", MSG
+        operationSelectItem = new SortedSelectItem("operationSelectItem", MSG
             .view_alert_definition_notification_operation_editor_common_operation());
         operationSelectItem.setStartRow(true);
         operationSelectItem.setEndRow(true);
@@ -160,7 +161,7 @@ public class ResourceOperationNotificationSenderForm extends AbstractNotificatio
 
         // for RELATIVE mode
 
-        ancestorTypeSelectItem = new SelectItem("ancestorTypeSelectItem", MSG
+        ancestorTypeSelectItem = new SortedSelectItem("ancestorTypeSelectItem", MSG
             .view_alert_definition_notification_operation_editor_relative_ancestor());
         ancestorTypeSelectItem.setStartRow(true);
         ancestorTypeSelectItem.setEndRow(true);
@@ -178,7 +179,7 @@ public class ResourceOperationNotificationSenderForm extends AbstractNotificatio
             }
         });
 
-        descendantTypeSelectItem = new SelectItem("descendantTypeSelectItem", MSG
+        descendantTypeSelectItem = new SortedSelectItem("descendantTypeSelectItem", MSG
             .view_alert_definition_notification_operation_editor_relative_descendant());
         descendantTypeSelectItem.setStartRow(true);
         descendantTypeSelectItem.setEndRow(false);
@@ -208,7 +209,7 @@ public class ResourceOperationNotificationSenderForm extends AbstractNotificatio
 
         // the mode selector menu
 
-        modeSelectItem = new SelectItem("modeSelectItem", MSG
+        modeSelectItem = new SortedSelectItem("modeSelectItem", MSG
             .view_alert_definition_notification_operation_editor_mode_title());
         modeSelectItem.setStartRow(true);
         modeSelectItem.setEndRow(true);
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/BundleSelector.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/BundleSelector.java
index fd1a659..037bc10 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/BundleSelector.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/BundleSelector.java
@@ -32,6 +32,7 @@ import org.rhq.core.domain.bundle.BundleType;
 import org.rhq.core.domain.criteria.BundleCriteria;
 import org.rhq.enterprise.gui.coregui.client.CoreGUI;
 import org.rhq.enterprise.gui.coregui.client.bundle.list.BundlesDataSource;
+import org.rhq.enterprise.gui.coregui.client.components.form.SortedSelectItem;
 import org.rhq.enterprise.gui.coregui.client.components.selector.AbstractSelector;
 import org.rhq.enterprise.gui.coregui.client.gwt.BundleGWTServiceAsync;
 import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
@@ -54,7 +55,7 @@ public class BundleSelector extends AbstractSelector<Bundle, BundleCriteria> {
         availableFilterForm.setNumCols(4);
         final TextItem search = new TextItem("search", MSG.common_title_search());
 
-        final SelectItem bundleTypeSelect = new SelectItem("bundleType", MSG.view_bundle_bundleType());
+        final SelectItem bundleTypeSelect = new SortedSelectItem("bundleType", MSG.view_bundle_bundleType());
         bundleService.getAllBundleTypes(new AsyncCallback<ArrayList<BundleType>>() {
             public void onFailure(Throwable caught) {
                 CoreGUI.getErrorHandler().handleError(MSG.dataSource_bundle_loadFailed(), caught);
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/create/BundleTypeDropDownSelectItem.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/create/BundleTypeDropDownSelectItem.java
index 959237b..572ad7e 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/create/BundleTypeDropDownSelectItem.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/create/BundleTypeDropDownSelectItem.java
@@ -23,12 +23,12 @@ import java.util.HashMap;
 
 import com.google.gwt.user.client.rpc.AsyncCallback;
 import com.smartgwt.client.types.Alignment;
-import com.smartgwt.client.widgets.form.fields.SelectItem;
 import com.smartgwt.client.widgets.form.fields.events.ChangedEvent;
 import com.smartgwt.client.widgets.form.fields.events.ChangedHandler;
 
 import org.rhq.core.domain.bundle.BundleType;
 import org.rhq.enterprise.gui.coregui.client.CoreGUI;
+import org.rhq.enterprise.gui.coregui.client.components.form.SortedSelectItem;
 import org.rhq.enterprise.gui.coregui.client.gwt.BundleGWTServiceAsync;
 import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
 import org.rhq.enterprise.gui.coregui.client.util.message.Message;
@@ -37,7 +37,7 @@ import org.rhq.enterprise.gui.coregui.client.util.message.Message.Severity;
 /**
  * Provides a drop down menu that allows one to select a bundle type.
  */
-public class BundleTypeDropDownSelectItem extends SelectItem {
+public class BundleTypeDropDownSelectItem extends SortedSelectItem {
 
     private final HashMap<String, BundleType> knownBundleTypes = new HashMap<String, BundleType>();
     private BundleType selected = null;
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/deploy/SelectBundleVersionStep.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/deploy/SelectBundleVersionStep.java
index e68d159..154217b 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/deploy/SelectBundleVersionStep.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/deploy/SelectBundleVersionStep.java
@@ -34,6 +34,7 @@ import org.rhq.core.domain.criteria.BundleDeploymentCriteria;
 import org.rhq.core.domain.criteria.BundleVersionCriteria;
 import org.rhq.core.domain.util.PageList;
 import org.rhq.enterprise.gui.coregui.client.CoreGUI;
+import org.rhq.enterprise.gui.coregui.client.components.form.SortedSelectItem;
 import org.rhq.enterprise.gui.coregui.client.components.wizard.AbstractWizardStep;
 import org.rhq.enterprise.gui.coregui.client.gwt.BundleGWTServiceAsync;
 import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
@@ -55,7 +56,7 @@ public class SelectBundleVersionStep extends AbstractWizardStep {
     private DynamicForm form;
 
     private RadioGroupItem radioGroupItem = new RadioGroupItem("options", "Deploy Options");
-    private SelectItem selectVersionItem = new SelectItem("selectVersion", "Deployment Version");
+    private SelectItem selectVersionItem = new SortedSelectItem("selectVersion", "Deployment Version");
     private LinkedHashMap<String, String> radioGroupValues = new LinkedHashMap<String, String>();
     private LinkedHashMap<String, String> selectVersionValues = new LinkedHashMap<String, String>();
     private PageList<BundleVersion> bundleVersions = null;
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/ConfigurationEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/ConfigurationEditor.java
index dc32e91..4e3e9df 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/ConfigurationEditor.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/ConfigurationEditor.java
@@ -117,6 +117,7 @@ import org.rhq.core.domain.resource.ResourceType;
 import org.rhq.enterprise.gui.coregui.client.CoreGUI;
 import org.rhq.enterprise.gui.coregui.client.ImageManager;
 import org.rhq.enterprise.gui.coregui.client.components.form.IsLongValidator;
+import org.rhq.enterprise.gui.coregui.client.components.form.SortedSelectItem;
 import org.rhq.enterprise.gui.coregui.client.gwt.ConfigurationGWTServiceAsync;
 import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
 import org.rhq.enterprise.gui.coregui.client.inventory.resource.type.ResourceTypeRepository;
@@ -830,7 +831,7 @@ public class ConfigurationEditor extends LocatableVLayout {
             LocatableDynamicForm deleteForm = new LocatableDynamicForm(deleteControlsLayout.extendLocatorId("Form"));
             deleteForm.setWidth100();
 
-            final SelectItem selectItem = new SelectItem();
+            final SelectItem selectItem = new SortedSelectItem();
             selectItem.setMultiple(true);
             selectItem.setMultipleAppearance(MultipleAppearance.GRID);
             selectItem.setTitle(MSG.common_button_delete());
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/GroupConfigurationEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/GroupConfigurationEditor.java
index 6b38965..b12382a 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/GroupConfigurationEditor.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/GroupConfigurationEditor.java
@@ -69,6 +69,7 @@ import org.rhq.core.domain.configuration.definition.PropertyDefinitionSimple;
 import org.rhq.enterprise.gui.coregui.client.CoreGUI;
 import org.rhq.enterprise.gui.coregui.client.ImageManager;
 import org.rhq.enterprise.gui.coregui.client.PopupWindow;
+import org.rhq.enterprise.gui.coregui.client.components.form.SortedSelectItem;
 import org.rhq.enterprise.gui.coregui.client.util.StringUtility;
 import org.rhq.enterprise.gui.coregui.client.util.message.Message;
 import org.rhq.enterprise.gui.coregui.client.util.message.Message.Severity;
@@ -755,12 +756,12 @@ public class GroupConfigurationEditor extends ConfigurationEditor {
                 ((ComboBoxItem) editorItem).setAddUnknownValues(true);
             } else {
                 if (valueOptions.size() > 5) {
-                    editorItem = new SelectItem();
+                    editorItem = new SortedSelectItem();
                 } else {
                     // TODO: we want RadioGroupItem, but smartgwt seems to have a bug and it won't render this when
                     //       our listgrid does not have the "unset" boolean field also present. If its just the value
                     //       field, the radio group editor won't show.
-                    editorItem = new SelectItem(); // new RadioGroupItem();
+                    editorItem = new SortedSelectItem(); // new RadioGroupItem();
                 }
             }
             editorItem.setValueMap(valueOptions);
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/form/SortedSelectItem.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/form/SortedSelectItem.java
new file mode 100644
index 0000000..4f483e9
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/form/SortedSelectItem.java
@@ -0,0 +1,96 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 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.gui.coregui.client.components.form;
+
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.LinkedHashMap;
+import java.util.Map.Entry;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import com.google.gwt.core.client.JavaScriptObject;
+import com.smartgwt.client.widgets.form.fields.SelectItem;
+
+/**
+ * A convenience class for a sorted variant of {@link SelectItem}.
+ *  
+ * @author Jirka Kremser
+ */
+public class SortedSelectItem extends SelectItem {
+    public SortedSelectItem() {
+        super();
+    }
+
+    public SortedSelectItem(JavaScriptObject jsObj) {
+        super(jsObj);
+    }
+
+    public SortedSelectItem(String name) {
+        super(name);
+    }
+
+    public SortedSelectItem(String name, String title) {
+        super(name, title);
+    }
+
+    @Override
+    public void setValueMap(@SuppressWarnings("rawtypes")
+    LinkedHashMap valueMap) {
+        if (valueMap == null) {
+            throw new IllegalArgumentException("valueMap cannot be null");
+        }
+        @SuppressWarnings("unchecked")
+        LinkedHashMap<String, String> safeValueMap = (LinkedHashMap<String, String>) valueMap;
+        LinkedHashMap<String, String> sortedValueMap = new LinkedHashMap<String, String>(valueMap.size());
+        SortedSet<Entry<String, String>> sortedEntries = new TreeSet<Entry<String, String>>(
+            new Comparator<Entry<String, String>>() {
+
+                @Override
+                public int compare(Entry<String, String> o1, Entry<String, String> o2) {
+                    return o1.getValue().compareTo(o2.getValue());
+                }
+            });
+        sortedEntries.addAll(safeValueMap.entrySet());
+        for (Entry<String, String> entry : sortedEntries) {
+            sortedValueMap.put(entry.getKey(), entry.getValue());
+        }
+
+        super.setValueMap(sortedValueMap);
+    }
+
+    @Override
+    public void setValueMap(String... valueMap) {
+        if (valueMap == null) {
+            throw new IllegalArgumentException("valueMap cannot be null");
+        }
+        String[] sortedValueArray = new String[valueMap.length];
+        System.arraycopy(valueMap, 0, sortedValueArray, 0, valueMap.length);
+        Arrays.sort(sortedValueArray);
+
+        super.setValueMap(sortedValueArray);
+    }
+
+    @Override
+    public void setValues(String... valueMap) {
+        setValueMap(valueMap);
+    }
+
+}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/inventory/groups/graph/ResourceGroupGraphPortlet.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/inventory/groups/graph/ResourceGroupGraphPortlet.java
index d91fc3b..7e75fae 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/inventory/groups/graph/ResourceGroupGraphPortlet.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/inventory/groups/graph/ResourceGroupGraphPortlet.java
@@ -35,6 +35,7 @@ import org.rhq.core.domain.common.EntityContext;
 import org.rhq.core.domain.configuration.PropertySimple;
 import org.rhq.core.domain.dashboard.DashboardPortlet;
 import org.rhq.core.domain.resource.group.GroupCategory;
+import org.rhq.enterprise.gui.coregui.client.components.form.SortedSelectItem;
 import org.rhq.enterprise.gui.coregui.client.components.selector.AssignedItemsChangedEvent;
 import org.rhq.enterprise.gui.coregui.client.components.selector.AssignedItemsChangedHandler;
 import org.rhq.enterprise.gui.coregui.client.dashboard.CustomSettingsPortlet;
@@ -125,7 +126,7 @@ public class ResourceGroupGraphPortlet extends ResourceGroupMetricGraphView impl
         //rec.setAttribute("name", "current");
         //resourceGroupSelector.setAssigned(new ListGridRecord[] { rec });
 
-        final SelectItem metric = new SelectItem(CFG_DEFINITION_ID, MSG.common_title_metric()) {
+        final SelectItem metric = new SortedSelectItem(CFG_DEFINITION_ID, MSG.common_title_metric()) {
             @Override
             protected Criteria getPickListFilterCriteria() {
                 Criteria criteria = new Criteria();
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/wizard/DriftAddDefinitionWizardInfoStep.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/wizard/DriftAddDefinitionWizardInfoStep.java
index c2139c1..63722cc 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/wizard/DriftAddDefinitionWizardInfoStep.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/wizard/DriftAddDefinitionWizardInfoStep.java
@@ -38,6 +38,7 @@ import org.rhq.core.domain.configuration.Configuration;
 import org.rhq.core.domain.configuration.definition.ConfigurationTemplate;
 import org.rhq.core.domain.drift.DriftConfigurationDefinition;
 import org.rhq.core.domain.drift.DriftDefinitionTemplate;
+import org.rhq.enterprise.gui.coregui.client.components.form.SortedSelectItem;
 import org.rhq.enterprise.gui.coregui.client.components.wizard.AbstractWizardStep;
 import org.rhq.enterprise.gui.coregui.client.util.FormUtility;
 import org.rhq.enterprise.gui.coregui.client.util.selenium.Locatable;
@@ -76,7 +77,7 @@ public class DriftAddDefinitionWizardInfoStep extends AbstractWizardStep {
             SpacerItem spacerItem = new SpacerItem("Spacer");
             formItems.add(spacerItem);
 
-            SelectItem templateSelectItem = new SelectItem("Template", MSG.view_drift_wizard_addDef_templatePrompt());
+            SelectItem templateSelectItem = new SortedSelectItem("Template", MSG.view_drift_wizard_addDef_templatePrompt());
             templateSelectItem.setTitleOrientation(TitleOrientation.TOP);
             templateSelectItem.setAlign(Alignment.LEFT);
             templateSelectItem.setWidth(300);
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/wizard/DriftPinTemplateWizardInfoStep.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/wizard/DriftPinTemplateWizardInfoStep.java
index 742b44d..ee7da2a 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/wizard/DriftPinTemplateWizardInfoStep.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/wizard/DriftPinTemplateWizardInfoStep.java
@@ -38,8 +38,9 @@ import com.smartgwt.client.widgets.form.fields.events.ChangedEvent;
 import com.smartgwt.client.widgets.form.fields.events.ChangedHandler;
 
 import org.rhq.core.domain.drift.DriftDefinitionComparator;
-import org.rhq.core.domain.drift.DriftDefinitionTemplate;
 import org.rhq.core.domain.drift.DriftDefinitionComparator.CompareMode;
+import org.rhq.core.domain.drift.DriftDefinitionTemplate;
+import org.rhq.enterprise.gui.coregui.client.components.form.SortedSelectItem;
 import org.rhq.enterprise.gui.coregui.client.components.wizard.AbstractWizardStep;
 import org.rhq.enterprise.gui.coregui.client.util.FormUtility;
 import org.rhq.enterprise.gui.coregui.client.util.selenium.Locatable;
@@ -59,7 +60,7 @@ public class DriftPinTemplateWizardInfoStep extends AbstractWizardStep {
     private AbstractDriftPinTemplateWizard wizard;
 
     private LocatableDynamicForm selectTemplateForm;
-    SelectItem selectTemplateItem = new SelectItem("Template", MSG.view_drift_wizard_addDef_templatePrompt());
+    SelectItem selectTemplateItem = new SortedSelectItem("Template", MSG.view_drift_wizard_addDef_templatePrompt());
 
     public DriftPinTemplateWizardInfoStep(AbstractDriftPinTemplateWizard wizard) {
         this.wizard = wizard;
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/operation/schedule/AbstractOperationScheduleDetailsView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/operation/schedule/AbstractOperationScheduleDetailsView.java
index 1ac329d..c52eb30 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/operation/schedule/AbstractOperationScheduleDetailsView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/operation/schedule/AbstractOperationScheduleDetailsView.java
@@ -60,6 +60,7 @@ import org.rhq.enterprise.gui.coregui.client.components.configuration.Configurat
 import org.rhq.enterprise.gui.coregui.client.components.form.AbstractRecordEditor;
 import org.rhq.enterprise.gui.coregui.client.components.form.DurationItem;
 import org.rhq.enterprise.gui.coregui.client.components.form.EnhancedDynamicForm;
+import org.rhq.enterprise.gui.coregui.client.components.form.SortedSelectItem;
 import org.rhq.enterprise.gui.coregui.client.components.form.TimeUnit;
 import org.rhq.enterprise.gui.coregui.client.components.form.UnitType;
 import org.rhq.enterprise.gui.coregui.client.components.trigger.JobTriggerEditor;
@@ -188,7 +189,7 @@ public abstract class AbstractOperationScheduleDetailsView extends
             items.add(idItem);
         }
 
-        SelectItem operationNameItem = new SelectItem(AbstractOperationScheduleDataSource.Field.OPERATION_NAME);
+        SelectItem operationNameItem = new SortedSelectItem(AbstractOperationScheduleDataSource.Field.OPERATION_NAME);
         operationNameItem.setShowTitle(true);
         items.add(operationNameItem);
         operationNameItem.addChangedHandler(new ChangedHandler() {
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/definitions/GroupDefinitionExpressionBuilder.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/definitions/GroupDefinitionExpressionBuilder.java
index d108dc4..2f99096 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/definitions/GroupDefinitionExpressionBuilder.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/definitions/GroupDefinitionExpressionBuilder.java
@@ -23,12 +23,26 @@
 
 package org.rhq.enterprise.gui.coregui.client.inventory.groups.definitions;
 
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+
 import com.google.gwt.user.client.rpc.AsyncCallback;
 import com.smartgwt.client.types.Alignment;
 import com.smartgwt.client.widgets.events.CloseClickEvent;
 import com.smartgwt.client.widgets.events.CloseClickHandler;
-import com.smartgwt.client.widgets.form.fields.*;
-import com.smartgwt.client.widgets.form.fields.events.*;
+import com.smartgwt.client.widgets.form.fields.ButtonItem;
+import com.smartgwt.client.widgets.form.fields.RadioGroupItem;
+import com.smartgwt.client.widgets.form.fields.SelectItem;
+import com.smartgwt.client.widgets.form.fields.TextAreaItem;
+import com.smartgwt.client.widgets.form.fields.TextItem;
+import com.smartgwt.client.widgets.form.fields.events.ChangeEvent;
+import com.smartgwt.client.widgets.form.fields.events.ChangeHandler;
+import com.smartgwt.client.widgets.form.fields.events.ChangedEvent;
+import com.smartgwt.client.widgets.form.fields.events.ChangedHandler;
+import com.smartgwt.client.widgets.form.fields.events.ClickEvent;
+import com.smartgwt.client.widgets.form.fields.events.ClickHandler;
+
 import org.rhq.core.domain.criteria.Criteria.Restriction;
 import org.rhq.core.domain.criteria.ResourceTypeCriteria;
 import org.rhq.core.domain.plugin.Plugin;
@@ -36,16 +50,13 @@ import org.rhq.core.domain.resource.ResourceType;
 import org.rhq.core.domain.util.PageControl;
 import org.rhq.core.domain.util.PageList;
 import org.rhq.enterprise.gui.coregui.client.CoreGUI;
+import org.rhq.enterprise.gui.coregui.client.components.form.SortedSelectItem;
 import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
 import org.rhq.enterprise.gui.coregui.client.gwt.GroupDefinitionExpressionBuilderGWTServiceAsync;
 import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableDynamicForm;
 import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableVLayout;
 import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableWindow;
 
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-
 /**
  * A dialog window that lets you build custom dynagroup expressions.
  * 
@@ -121,7 +132,7 @@ public class GroupDefinitionExpressionBuilder extends LocatableWindow {
             }
         });
 
-        this.compareTypeItem = new SelectItem("compareType", MSG.view_dynagroup_exprBuilder_comparisonType());
+        this.compareTypeItem = new SortedSelectItem("compareType", MSG.view_dynagroup_exprBuilder_comparisonType());
         this.compareTypeItem.setTooltip(MSG.view_dynagroup_exprBuilder_comparisonType_tooltip());
         this.compareTypeItem.setHoverWidth(250);
         this.compareTypeItem.setRedrawOnChange(true);
@@ -166,7 +177,7 @@ public class GroupDefinitionExpressionBuilder extends LocatableWindow {
             }
         });
 
-        this.resourceTypeItem = new SelectItem("resourceType", MSG.view_dynagroup_exprBuilder_resourceType());
+        this.resourceTypeItem = new SortedSelectItem("resourceType", MSG.view_dynagroup_exprBuilder_resourceType());
         this.resourceTypeItem.setTooltip(MSG.view_dynagroup_exprBuilder_resourceType_tooltip());
         this.resourceTypeItem.setHoverWidth(250);
         this.resourceTypeItem.setRedrawOnChange(true);
@@ -180,7 +191,7 @@ public class GroupDefinitionExpressionBuilder extends LocatableWindow {
             }
         });
 
-        this.pluginItem = new SelectItem("plugin", MSG.view_dynagroup_exprBuilder_definingPlugin());
+        this.pluginItem = new SortedSelectItem("plugin", MSG.view_dynagroup_exprBuilder_definingPlugin());
         this.pluginItem.setTooltip(MSG.view_dynagroup_exprBuilder_definingPlugin_tooltip());
         this.pluginItem.setHoverWidth(250);
         this.pluginItem.setRedrawOnChange(true);
@@ -223,7 +234,7 @@ public class GroupDefinitionExpressionBuilder extends LocatableWindow {
             }
         });
 
-        this.expressionTypeItem = new SelectItem("expressionType", MSG.view_dynagroup_exprBuilder_expressionType());
+        this.expressionTypeItem = new SortedSelectItem("expressionType", MSG.view_dynagroup_exprBuilder_expressionType());
         this.expressionTypeItem.setTooltip(MSG.view_dynagroup_exprBuilder_expressionType_tooltip());
         this.expressionTypeItem.setHoverWidth(250);
         this.expressionTypeItem.setRedrawOnChange(true);
@@ -243,7 +254,7 @@ public class GroupDefinitionExpressionBuilder extends LocatableWindow {
             }
         });
 
-        this.resourceItem = new SelectItem("resource", MSG.view_dynagroup_exprBuilder_resource());
+        this.resourceItem = new SortedSelectItem("resource", MSG.view_dynagroup_exprBuilder_resource());
         this.resourceItem.setTooltip(MSG.view_dynagroup_exprBuilder_resource_tooltip());
         this.resourceItem.setHoverWidth(250);
         this.resourceItem.setRedrawOnChange(true);
@@ -430,7 +441,6 @@ public class GroupDefinitionExpressionBuilder extends LocatableWindow {
                             typeNames.add(type.getName());
                             resourceTypeIds.put(type.getName(), Integer.valueOf(type.getId()));
                         }
-                        Collections.sort(typeNames);
                         resourceTypeItem.setValueMap(typeNames.toArray(new String[typeNames.size()]));
                     } else {
                         resourceTypeItem.setValueMap(new String[0]);
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/factory/ResourceFactoryInfoStep.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/factory/ResourceFactoryInfoStep.java
index 20ebf5f..329c7f9 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/factory/ResourceFactoryInfoStep.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/factory/ResourceFactoryInfoStep.java
@@ -37,6 +37,7 @@ import org.rhq.core.domain.configuration.Configuration;
 import org.rhq.core.domain.configuration.definition.ConfigurationTemplate;
 import org.rhq.core.domain.content.Architecture;
 import org.rhq.enterprise.gui.coregui.client.CoreGUI;
+import org.rhq.enterprise.gui.coregui.client.components.form.SortedSelectItem;
 import org.rhq.enterprise.gui.coregui.client.components.wizard.AbstractWizardStep;
 import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
 import org.rhq.enterprise.gui.coregui.client.util.selenium.Locatable;
@@ -147,7 +148,7 @@ public class ResourceFactoryInfoStep extends AbstractWizardStep {
             }
 
             if (null != templatePrompt) {
-                SelectItem templateSelect = new SelectItem("template", templatePrompt);
+                SelectItem templateSelect = new SortedSelectItem("template", templatePrompt);
                 templateSelect.setTitleOrientation(TitleOrientation.TOP);
                 templateSelect.setAlign(Alignment.LEFT);
                 templateSelect.setWidth(300);


commit 841e1f0adfabed848b9f841b1856e4abecf1620a
Author: Ian Springer <ian.springer at redhat.com>
Date:   Mon Jun 25 12:17:46 2012 -0400

    [BZ 835113] fix so EJB2 MDB Resources do not erroneously return an avail of DOWN (https://bugzilla.redhat.com/show_bug.cgi?id=835113)

diff --git a/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/Ejb2BeanComponent.java b/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/Ejb2BeanComponent.java
index ebbf9bb..c4ae68f 100644
--- a/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/Ejb2BeanComponent.java
+++ b/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/Ejb2BeanComponent.java
@@ -1,6 +1,6 @@
 /*
  * Jopr Management Platform
- * Copyright (C) 2005-2009 Red Hat, Inc.
+ * Copyright (C) 2005-2012 Red Hat, Inc.
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
@@ -27,7 +27,9 @@ import java.util.Set;
 import org.jboss.deployers.spi.management.ManagementView;
 import org.jboss.managed.api.ComponentType;
 import org.jboss.managed.api.ManagedComponent;
+import org.jboss.managed.api.RunState;
 
+import org.rhq.core.domain.measurement.AvailabilityType;
 import org.rhq.plugins.jbossas5.util.Ejb2BeanUtils;
 
 /**
@@ -39,6 +41,19 @@ public class Ejb2BeanComponent extends AbstractEjbBeanComponent {
     private static final ComponentType MDB_COMPONENT_TYPE = new ComponentType("EJB", "MDB");
 
     @Override
+    protected AvailabilityType getAvailabilityForRunState(RunState runState) {
+        AvailabilityType avail;
+        if (MDB_COMPONENT_TYPE.equals(getComponentType())) {
+            // This is a workaround for if BZ 835113.
+            avail = (runState == RunState.RUNNING || runState == RunState.UNKNOWN) ?
+                    AvailabilityType.UP : AvailabilityType.DOWN;
+        } else {
+            avail = super.getAvailabilityForRunState(runState);
+        }
+        return avail;
+    }
+
+    @Override
     protected ManagedComponent getManagedComponent() {
         if (MDB_COMPONENT_TYPE.equals(getComponentType())) {
             try {
diff --git a/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/ManagedComponentComponent.java b/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/ManagedComponentComponent.java
index 5d28473..a44cfc8 100644
--- a/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/ManagedComponentComponent.java
+++ b/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/ManagedComponentComponent.java
@@ -124,22 +124,32 @@ public class ManagedComponentComponent extends AbstractManagedComponent implemen
     // ResourceComponent Implementation  --------------------------------------------
 
     public AvailabilityType getAvailability() {
-        long timeSinceComponentRefresh = System.currentTimeMillis() - lastComponentRefresh;
-        if (timeSinceComponentRefresh > availRefreshInterval) {
-            if (log.isDebugEnabled()) {
-                log.debug("The availability refresh interval for [resourceKey: "
-                    + getResourceContext().getResourceKey() + ", type: " + componentType + ", name: " + componentName
-                    + "] has been exceeded by " + (timeSinceComponentRefresh - availRefreshInterval)
-                    + " ms. Reloading managed component.");
-            }
+        if (lastComponentRefresh == 0) {
+            // The managed component has not been refreshed at all yet.
             getManagedComponent();
+        } else {
+            long timeSinceComponentRefresh = System.currentTimeMillis() - lastComponentRefresh;
+            if (timeSinceComponentRefresh > availRefreshInterval) {
+                if (log.isDebugEnabled()) {
+                    log.debug("The availability refresh interval for [resourceKey: "
+                        + getResourceContext().getResourceKey() + ", type: " + componentType + ", name: " + componentName
+                        + "] has been exceeded by " + (timeSinceComponentRefresh - availRefreshInterval)
+                        + " ms. Reloading managed component...");
+                }
+                getManagedComponent();
+            }
         }
 
+        return getAvailabilityForRunState(runState);
+    }
+
+    protected AvailabilityType getAvailabilityForRunState(RunState runState) {
         if (runState == RunState.RUNNING) {
             return AvailabilityType.UP;
         } else {
             if (log.isDebugEnabled()) {
-                log.debug(componentType + " component '" + componentName + "' was not running, state was : " + runState);
+                log.debug(componentType + " component '" + componentName + "' was not running - state was [" + runState
+                        + "].");
             }
             return AvailabilityType.DOWN;
         }
diff --git a/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/serviceBinding/ManagerComponent.java b/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/serviceBinding/ManagerComponent.java
index ba2a4c9..eae8b13 100644
--- a/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/serviceBinding/ManagerComponent.java
+++ b/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/serviceBinding/ManagerComponent.java
@@ -71,13 +71,13 @@ public class ManagerComponent extends ManagedComponentComponent implements Creat
     private static final String RESOURCE_KEY_SEPARATOR = "!)@(#*";
 
     @Override
-    public AvailabilityType getAvailability() {
-        RunState runState = getManagedComponent().getRunState();
-        return (runState == RunState.RUNNING || runState == RunState.UNKNOWN) ? AvailabilityType.UP
-                    : AvailabilityType.DOWN;
+    protected AvailabilityType getAvailabilityForRunState(RunState runState) {
+        // This is a workaround for a bug where the binding manager MO will return a run state of UNKNOWN even when it's
+        // happily running.
+        return (runState == RunState.RUNNING || runState == RunState.UNKNOWN) ?
+               AvailabilityType.UP : AvailabilityType.DOWN;
     }
 
-
     // ConfigurationFacet -----------------------------
 
     @Override


commit b352ab20a4e0deb0d9eccf1d492de2917d2098c2
Author: Jirka Kremser <jkremser at redhat.com>
Date:   Mon Jun 25 15:16:12 2012 +0200

    [BZ 815321 - Platform alert conditions for availability (Goes Disabled and Goes Unknown ) should be removed] Options have been reomved when adding alert condition for resource of type platform

diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/NewConditionEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/NewConditionEditor.java
index 61e2f21..c9785b8 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/NewConditionEditor.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/NewConditionEditor.java
@@ -57,6 +57,7 @@ import org.rhq.core.domain.measurement.MeasurementUnits;
 import org.rhq.core.domain.measurement.NumericType;
 import org.rhq.core.domain.operation.OperationDefinition;
 import org.rhq.core.domain.operation.OperationRequestStatus;
+import org.rhq.core.domain.resource.ResourceCategory;
 import org.rhq.core.domain.resource.ResourceType;
 import org.rhq.enterprise.gui.coregui.client.CoreGUI;
 import org.rhq.enterprise.gui.coregui.client.components.form.DurationItem;
@@ -786,10 +787,13 @@ public class NewConditionEditor extends LocatableDynamicForm {
         LinkedHashMap<String, String> avails = new LinkedHashMap<String, String>(2);
         avails.put(AlertConditionOperator.AVAIL_GOES_DOWN.name(),
             MSG.view_alert_definition_condition_editor_operator_availability_goesDown());
-        avails.put(AlertConditionOperator.AVAIL_GOES_DISABLED.name(),
-            MSG.view_alert_definition_condition_editor_operator_availability_goesDisabled());
-        avails.put(AlertConditionOperator.AVAIL_GOES_UNKNOWN.name(),
-            MSG.view_alert_definition_condition_editor_operator_availability_goesUnknown());
+        // do not add 'Goes Disabled' and 'Goes Unknown' for platform
+        if (resourceType.getCategory() != ResourceCategory.PLATFORM) {
+            avails.put(AlertConditionOperator.AVAIL_GOES_DISABLED.name(),
+                MSG.view_alert_definition_condition_editor_operator_availability_goesDisabled());
+            avails.put(AlertConditionOperator.AVAIL_GOES_UNKNOWN.name(),
+                MSG.view_alert_definition_condition_editor_operator_availability_goesUnknown());
+        }
         avails.put(AlertConditionOperator.AVAIL_GOES_NOT_UP.name(),
             MSG.view_alert_definition_condition_editor_operator_availability_goesNotUp());
         avails.put(AlertConditionOperator.AVAIL_GOES_UP.name(),


commit 1fb0b4a36e7c66607dea51cc539511352702ed3f
Author: Ian Springer <ian.springer at redhat.com>
Date:   Fri Jun 22 17:21:57 2012 -0400

    delete the itest AS7 home dir before, as well as after, the itests run

diff --git a/modules/plugins/jboss-as-7/pom.xml b/modules/plugins/jboss-as-7/pom.xml
index 16eb982..a640c0541 100644
--- a/modules/plugins/jboss-as-7/pom.xml
+++ b/modules/plugins/jboss-as-7/pom.xml
@@ -305,9 +305,9 @@
                               location="${java.io.tmpdir}/jboss-${as7.product}-${as7.version}.zip"/>
                     <get src="${as7.url}" dest="${as7.zipfile}" usetimestamp="true" verbose="true"/>
                     <unzip src="${as7.zipfile}" dest="${java.io.tmpdir}"/>
+                    <delete dir="${jboss7.home}" verbose="true"/>
                     <move file="${java.io.tmpdir}/jboss-eap-6.0"
-                          tofile="${java.io.tmpdir}/jboss-as-${as7.version}" failonerror="false"
-                          overwrite="false"/>
+                          tofile="${jboss7.home}" failonerror="false"/>
 
                     <chmod perm="u+rx">
                       <fileset dir="${jboss7.home}/bin" includes="*.sh"/>
@@ -332,7 +332,7 @@
                 </goals>
                 <configuration>
                    <target>
-                      <delete dir="${jboss7.home}"/>
+                      <delete dir="${jboss7.home}" verbose="true"/>
                    </target>
                 </configuration>
               </execution>


commit d6eef33569e9285f488f047c30017c03215e85c6
Author: Jay Shaughnessy <jshaughn at redhat.com>
Date:   Fri Jun 22 17:19:59 2012 -0400

    Another attempt at fixing this test failure.  It's hard to fix linux failures on win :)

diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/FilterFileVisitorTest.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/FilterFileVisitorTest.java
index 8d31a82..d6812ba 100644
--- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/FilterFileVisitorTest.java
+++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/FilterFileVisitorTest.java
@@ -89,7 +89,8 @@ public class FilterFileVisitorTest {
         // This call normalizes the basedir.
         Set<File> dirs = DriftDetector.getScanDirectories(basedir, includes);
         Assert.assertEquals(dirs.size(), 1, "Should just be the basedir");
-        forEachFile(dirs.iterator().next(), new FilterFileVisitor(basedir, includes, excludes, visitor));
+        File normalizedBaseDir = dirs.iterator().next();
+        forEachFile(normalizedBaseDir, new FilterFileVisitor(normalizedBaseDir, includes, excludes, visitor));
 
         assertCollectionEqualsNoOrder(asList(fooJar, gooJar, myapp), visitor.visitedFiles,
             "Filtering failed with multiple includes and no excludes");


commit 2c5974fbda6a05ab0d7d233c190740d45df067d5
Author: Jay Shaughnessy <jshaughn at redhat.com>
Date:   Fri Jun 22 16:09:36 2012 -0400

    [830463 - Re-enabling (actually, updating) an alert definition clears condition logs for existing alerts]
    Some follow-on work. Add optimization such that if conditions are not being
    updated we don't detach the AlertCondition from the def, since they are
    unchanged.
    - Add related unit testing
    - re-enable the tests in AlertConditionTest, which pass but for some
      reason were not enabled.
    - Fix a few parameter names that I missed updating last time.

diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/alert/AlertDefinition.java b/modules/core/domain/src/main/java/org/rhq/core/domain/alert/AlertDefinition.java
index 397e254..71ca46c 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/alert/AlertDefinition.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/alert/AlertDefinition.java
@@ -62,7 +62,7 @@ import org.rhq.core.domain.resource.group.ResourceGroup;
  * @author Joseph Marques
  */
 @Entity
- at NamedQueries( { //
+ at NamedQueries({ //
     @NamedQuery(name = AlertDefinition.QUERY_FIND_ALL, query = "" //
         + "SELECT a " //
         + "  FROM AlertDefinition a " //
@@ -409,6 +409,16 @@ public class AlertDefinition implements Serializable {
     }
 
     public void update(AlertDefinition alertDef) {
+        update(alertDef, true);
+    }
+
+    /**
+     * @param alertDef
+     * @param updateConditions set to true if conditions are being updated.  This incurs overhead because the
+     * old AlertConditions get detached and replaced for no good reason, becoming a cleanup burden later on. Only
+     * set to false if you are sure the conditions are not being updated.  If false the conditions will not be updated.
+     */
+    public void update(AlertDefinition alertDef, boolean updateConditions) {
         /*
          * Don't copy the id, ctime, or mtime.
          */
@@ -440,15 +450,17 @@ public class AlertDefinition implements Serializable {
 
         this.recoveryId = alertDef.recoveryId;
 
-        // copy conditions
-        List<AlertCondition> copiedConditions = new ArrayList<AlertCondition>();
-        for (AlertCondition oldCondition : alertDef.getConditions()) {
-            AlertCondition newCondition = new AlertCondition(oldCondition);
-            newCondition.setAlertDefinition(this);
-            copiedConditions.add(newCondition);
+        // copy conditions if necessary
+        if (updateConditions) {
+            List<AlertCondition> copiedConditions = new ArrayList<AlertCondition>();
+            for (AlertCondition oldCondition : alertDef.getConditions()) {
+                AlertCondition newCondition = new AlertCondition(oldCondition);
+                newCondition.setAlertDefinition(this);
+                copiedConditions.add(newCondition);
+            }
+            this.removeAllConditions();
+            this.getConditions().addAll(copiedConditions);
         }
-        this.removeAllConditions();
-        this.getConditions().addAll(copiedConditions);
 
         // copy notifications
         List<AlertNotification> copiedNotifications = new ArrayList<AlertNotification>();
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/TemplateAlertDefinitionsView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/TemplateAlertDefinitionsView.java
index 987e62f..0c710b4 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/TemplateAlertDefinitionsView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/TemplateAlertDefinitionsView.java
@@ -206,7 +206,7 @@ public class TemplateAlertDefinitionsView extends AbstractAlertDefinitionsView {
     }
 
     @Override
-    protected void commitAlertDefinition(final AlertDefinition alertDefinition, boolean purgeInternals) {
+    protected void commitAlertDefinition(final AlertDefinition alertDefinition, boolean resetMatching) {
         if (alertDefinition.getId() == 0) {
             GWTServiceLookup.getAlertTemplateService().createAlertTemplate(alertDefinition,
                 Integer.valueOf(this.resourceType.getId()), new AsyncCallback<Integer>() {
@@ -224,7 +224,7 @@ public class TemplateAlertDefinitionsView extends AbstractAlertDefinitionsView {
                     }
                 });
         } else {
-            GWTServiceLookup.getAlertTemplateService().updateAlertTemplate(alertDefinition, purgeInternals,
+            GWTServiceLookup.getAlertTemplateService().updateAlertTemplate(alertDefinition, resetMatching,
                 new AsyncCallback<AlertDefinition>() {
                     @Override
                     public void onSuccess(AlertDefinition result) {
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/AlertTemplateGWTService.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/AlertTemplateGWTService.java
index e9af2cc..0a7f27b 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/AlertTemplateGWTService.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/AlertTemplateGWTService.java
@@ -30,11 +30,11 @@ public interface AlertTemplateGWTService extends RemoteService {
      * Updates a alert template definition.
      * 
      * @param alertDefinition
-     * @param purgeInternals must be true if you are updating conditions or dampening settings, can be false otherwise
+     * @param resetMatching must be true if you are updating conditions, condition expression, or dampening settings, can be false otherwise
      * @return the updated definition
      * @throws Exception
      */
-    AlertDefinition updateAlertTemplate(AlertDefinition alertDefinition, boolean purgeInternals)
+    AlertDefinition updateAlertTemplate(AlertDefinition alertDefinition, boolean resetMatching)
         throws RuntimeException;
 
     void enableAlertTemplates(Integer[] alertDefinitionIds) throws RuntimeException;
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/AlertTemplateGWTServiceImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/AlertTemplateGWTServiceImpl.java
index ceddfa7..7e1fd44 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/AlertTemplateGWTServiceImpl.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/AlertTemplateGWTServiceImpl.java
@@ -41,11 +41,11 @@ public class AlertTemplateGWTServiceImpl extends AbstractGWTServiceImpl implemen
     }
 
     @Override
-    public AlertDefinition updateAlertTemplate(AlertDefinition alertDefinition, boolean purgeInternals)
+    public AlertDefinition updateAlertTemplate(AlertDefinition alertDefinition, boolean resetMatching)
         throws RuntimeException {
         try {
             AlertDefinition results = alertTemplateManager.updateAlertTemplate(getSessionSubject(), alertDefinition,
-                purgeInternals);
+                resetMatching);
             return SerialUtility.prepare(results, "AlertTemplateService.updateAlertTemplate");
         } catch (Throwable t) {
             throw getExceptionToThrowToClient(t);
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerBean.java
index 5da131e..c4fdcda 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerBean.java
@@ -60,8 +60,8 @@ import org.rhq.enterprise.server.cloud.StatusManagerLocal;
 import org.rhq.enterprise.server.plugin.pc.alert.AlertSender;
 import org.rhq.enterprise.server.plugin.pc.alert.AlertSenderPluginManager;
 import org.rhq.enterprise.server.util.CriteriaQueryGenerator;
-import org.rhq.enterprise.server.util.CriteriaQueryRunner;
 import org.rhq.enterprise.server.util.CriteriaQueryGenerator.AuthorizationTokenType;
+import org.rhq.enterprise.server.util.CriteriaQueryRunner;
 
 /**
  * @author Joseph Marques
@@ -519,7 +519,7 @@ public class AlertDefinitionManagerBean implements AlertDefinitionManagerLocal,
             alertDefinition.setConditionExpression(BooleanExpression.ANY);
         }
 
-        oldAlertDefinition.update(alertDefinition);
+        oldAlertDefinition.update(alertDefinition, resetMatching);
         if (LOG.isDebugEnabled()) {
             LOG.debug("Updating: " + oldAlertDefinition);
             for (AlertCondition nextCondition : oldAlertDefinition.getConditions()) {
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertTemplateManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertTemplateManagerBean.java
index 94f1d35..5b4ad77 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertTemplateManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertTemplateManagerBean.java
@@ -231,7 +231,7 @@ public class AlertTemplateManagerBean implements AlertTemplateManagerLocal {
 
     @RequiredPermission(Permission.MANAGE_SETTINGS)
     @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
-    public AlertDefinition updateAlertTemplate(Subject user, AlertDefinition alertTemplate, boolean purgeInternals)
+    public AlertDefinition updateAlertTemplate(Subject user, AlertDefinition alertTemplate, boolean resetMatching)
         throws InvalidAlertDefinitionException, AlertDefinitionUpdateException, AlertNotificationValidationException {
         if (LOG.isDebugEnabled()) {
             LOG.debug("updateAlertTemplate: " + alertTemplate);
@@ -241,7 +241,7 @@ public class AlertTemplateManagerBean implements AlertTemplateManagerLocal {
         AlertDefinition updated = null;
         try {
             updated = alertDefinitionManager.updateAlertDefinition(user, alertTemplate.getId(), alertTemplate,
-                purgeInternals); // do not allow direct undeletes of an alert definition
+                resetMatching); // do not allow direct undeletes of an alert definition
         } catch (Throwable t) {
             throw new AlertDefinitionUpdateException("Failed to update an AlertTemplate "
                 + alertTemplate.toSimpleString(), t);
@@ -260,7 +260,7 @@ public class AlertTemplateManagerBean implements AlertTemplateManagerLocal {
         for (Integer alertDefinitionId : alertDefinitions) {
             try {
                 alertDefinitionManager
-                    .updateAlertDefinition(overlord, alertDefinitionId, alertTemplate, purgeInternals);
+                    .updateAlertDefinition(overlord, alertDefinitionId, alertTemplate, resetMatching);
             } catch (Throwable t) {
                 // continue on error, update as many as possible
                 if (firstThrowable == null) {
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/alert/test/AlertConditionTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/alert/test/AlertConditionTest.java
index 645d049..47ba274 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/alert/test/AlertConditionTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/alert/test/AlertConditionTest.java
@@ -20,12 +20,14 @@
 package org.rhq.enterprise.server.alert.test;
 
 import java.util.HashSet;
+import java.util.List;
 import java.util.Set;
 
 import javax.persistence.EntityManager;
 import javax.persistence.NoResultException;
 import javax.transaction.TransactionManager;
 
+import org.testng.Assert;
 import org.testng.annotations.AfterClass;
 import org.testng.annotations.AfterMethod;
 import org.testng.annotations.BeforeClass;
@@ -70,7 +72,7 @@ import org.rhq.test.TransactionCallbackWithContext;
 
 @Test
 public class AlertConditionTest extends UpdatePluginMetadataTestBase {
-    private static final boolean ENABLED = false;
+    private static final boolean ENABLED = true;
 
     // this must match the constant found in ServerManagerBean
     private static final String RHQ_SERVER_NAME_PROPERTY = "rhq.server.high-availability.name";
@@ -343,10 +345,84 @@ public class AlertConditionTest extends UpdatePluginMetadataTestBase {
         }
     }
 
+    @Test(enabled = ENABLED)
+    public void testBZ830463_updateDef() throws Exception {
+        // create our resource with alert definition
+        MeasurementDefinition metricDef = createResourceWithMetricSchedule();
+        AlertDefinition alertDef = createAlertDefinitionWithOneInsideRangeCondition(metricDef, resource.getId());
+
+        assert alertDef.getConditions().size() == 1 : "1 alertDef condition should exist";
+        AlertCondition condition = alertDef.getConditions().iterator().next();
+        int conditionId = condition.getId();
+
+        // re-load the resource so we get the measurement schedule
+        Resource resourceWithSchedules = loadResourceWithSchedules(resource.getId());
+        MeasurementSchedule schedule = resourceWithSchedules.getSchedules().iterator().next();
+
+        // simulate a measurement report coming from the agent - one values that fits in our range, so 1 alert is fired
+        MeasurementScheduleRequest request = new MeasurementScheduleRequest(schedule);
+        MeasurementReport report = new MeasurementReport();
+        report.addData(new MeasurementDataNumeric(getTimestamp(15), request, Double.valueOf(50.0))); // 50 < 60 AND 50 > 40
+        MeasurementDataManagerLocal dataManager = LookupUtil.getMeasurementDataManager();
+        dataManager.mergeMeasurementReport(report);
+
+        // wait for our JMS messages to process and see if we get any alerts
+        Thread.sleep(5000);
+
+        // make sure one alert was triggered
+        List<Alert> alerts = getAlerts(resourceWithSchedules.getId());
+        assert alerts.size() == 1 : "1 alert should have fired: " + alerts;
+        Alert alert = alerts.get(0);
+
+        assert alert.getConditionLogs().size() == 1 : "1 condition log should exist";
+        AlertConditionLog conditionLog = alert.getConditionLogs().iterator().next();
+        Assert.assertEquals(conditionLog.getCondition().getId(), conditionId,
+            "original condition should have been associated with the alert");
+
+        // update a non-condition aspect of the def and then update the def
+        String updatedDesc = "Updated Description";
+        alertDef.setDescription(updatedDesc);
+        AlertDefinition updatedAlertDef = LookupUtil.getAlertDefinitionManager().updateAlertDefinition(getOverlord(),
+            alertDef.getId(), alertDef, false); // note that resetMatching is false
+        assert updatedDesc.equals(updatedAlertDef.getDescription()) : "Description should be updated";
+        assert updatedAlertDef.getConditions().size() == 1 : "1 alertDef condition should exist after the update";
+        assert updatedAlertDef.getConditions().iterator().next().getId() == condition.getId() : "condition should not be updated";
+
+        // get the alert again, and make sure it still has a log with the same condition
+        alerts = getAlerts(resourceWithSchedules.getId());
+        assert alerts.size() == 1 : "1 alert should have fired: " + alerts;
+        alert = alerts.get(0);
+
+        assert alert.getConditionLogs().size() == 1 : "1 condition log should exist after the update";
+        conditionLog = alert.getConditionLogs().iterator().next();
+        Assert.assertEquals(conditionLog.getCondition().getId(), conditionId,
+            "original condition should still have been associated with the alert");
+
+        // update the condition on the def and then update the def
+        condition.setThreshold(Double.valueOf(41.0));
+        updatedAlertDef = LookupUtil.getAlertDefinitionManager().updateAlertDefinition(getOverlord(), alertDef.getId(),
+            alertDef, true); // note that resetMatching is true
+        assert updatedAlertDef.getConditions().size() == 1 : "1 alertDef condition should exist after the update";
+        assert updatedAlertDef.getConditions().iterator().next().getId() != condition.getId() : "condition should be updated";
+
+        // get the alert again, and make sure it still has a log with the same condition
+        alerts = getAlerts(resourceWithSchedules.getId());
+        assert alerts.size() == 1 : "1 alert should have fired: " + alerts;
+        alert = alerts.get(0);
+
+        assert alert.getConditionLogs().size() == 1 : "1 condition log should exist after the update";
+        conditionLog = alert.getConditionLogs().iterator().next();
+        Assert.assertEquals(conditionLog.getCondition().getId(), conditionId,
+            "original condition should still have been associated with the alert");
+
+        return;
+    }
+
     private PageList<Alert> getAlerts(int resourceId) {
         AlertManagerLocal alertManager = LookupUtil.getAlertManager();
         AlertCriteria alertCriteria = new AlertCriteria();
         alertCriteria.addFilterResourceIds(resourceId);
+        alertCriteria.fetchConditionLogs(true);
         PageList<Alert> alerts = alertManager.findAlertsByCriteria(getOverlord(), alertCriteria);
         return alerts;
     }


commit bcfdd405b76502e63573c0806e821ba900a205dc
Author: Mike Thompson <mithomps at redhat.com>
Date:   Fri Jun 22 11:31:55 2012 -0700

    [BZ 825230] Eliminate some of the space in the layout between the resource measurement sparkline graphs and the resource name link.

diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/resource/ResourceMetricsPortlet.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/resource/ResourceMetricsPortlet.java
index 8fb8f80..c27e626 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/resource/ResourceMetricsPortlet.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/resource/ResourceMetricsPortlet.java
@@ -240,16 +240,15 @@ public class ResourceMetricsPortlet extends GroupMetricsPortlet {
                                                         LocatableDynamicForm row = new LocatableDynamicForm(
                                                             recentMeasurementsContent.extendLocatorId(md.getName()));
                                                         row.setNumCols(3);
+                                                        row.setColWidths(65,"*","*");
                                                         row.setWidth100();
                                                         HTMLFlow graph = new HTMLFlow();
-                                                        //                        String contents = "<span id='sparkline_" + index + "' class='dynamicsparkline' width='0'>"
-                                                        //                            + commaDelimitedList + "</span>";
                                                         String contents = "<span id='sparkline_" + index
                                                             + "' class='dynamicsparkline' width='0' " + "values='"
                                                             + commaDelimitedList + "'>...</span>";
                                                         graph.setContents(contents);
                                                         graph.setContentsType(ContentsType.PAGE);
-                                                        //diable scrollbars on span
+                                                        //disable scrollbars on span
                                                         graph.setScrollbarSize(0);
 
                                                         CanvasItem graphContainer = new CanvasItem();


commit 93eafb3a0f72c469935a1d35da310826b9037eb5
Author: Simeon Pinder <spinder at redhat.com>
Date:   Fri Jun 22 14:08:09 2012 -0400

    Revert " Adding ability to disable deletion of as7 artifacts after an integration test run. Ex. -Ditest.deleteRoot=false" This is not consistently working.
    
    This reverts commit 37ba7b7ad179000571944b602a2cf6d0993632f2.

diff --git a/modules/plugins/jboss-as-7/pom.xml b/modules/plugins/jboss-as-7/pom.xml
index 7230b59..16eb982 100644
--- a/modules/plugins/jboss-as-7/pom.xml
+++ b/modules/plugins/jboss-as-7/pom.xml
@@ -331,22 +331,10 @@
                     <goal>run</goal>
                 </goals>
                 <configuration>
-              <tasks>
-                <taskdef resource="net/sf/antcontrib/antcontrib.properties"
-                  classpathref="maven.plugin.classpath" />
-                <if>
-                  <equals arg1="${itest.deleteRoot}" arg2="false" />
-                  <then>
-                    <echo message="*** By request not deleting the AS7 instances after 'integration-test' run." />
-                  </then>
-                  <else>
                    <target>
                       <delete dir="${jboss7.home}"/>
                    </target>
-                  </else>
-                </if>
-              </tasks>
-            </configuration>
+                </configuration>
               </execution>
             </executions>
           </plugin>


commit 5f8827fef9f40546edae97fc2747bd6f1cbf75df
Author: Mike Thompson <mithomps at redhat.com>
Date:   Fri Jun 22 09:51:49 2012 -0700

    [BZ 825230] Some measure names are not readable in JON EPP plugin. This is actually a global layout issue in the resource measurements portlet.

diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/resource/ResourceMetricsPortlet.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/resource/ResourceMetricsPortlet.java
index a625edf..8fb8f80 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/resource/ResourceMetricsPortlet.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/resource/ResourceMetricsPortlet.java
@@ -100,6 +100,7 @@ public class ResourceMetricsPortlet extends GroupMetricsPortlet {
         //display container
         final VLayout column = new VLayout();
         column.setHeight(10);//pack
+        column.setWidth100();
 
         //initialize to defaults
         end = System.currentTimeMillis();
@@ -267,6 +268,7 @@ public class ResourceMetricsPortlet extends GroupMetricsPortlet {
                                                             destination);
                                                         link.setTitleVAlign(VerticalAlignment.TOP);
                                                         link.setAlign(Alignment.LEFT);
+                                                        link.setClipValue(false);
                                                         link.addClickHandler(new ClickHandler() {
                                                             @Override
                                                             public void onClick(ClickEvent event) {
@@ -291,6 +293,7 @@ public class ResourceMetricsPortlet extends GroupMetricsPortlet {
                                                         value.setVAlign(VerticalAlignment.TOP);
 
                                                         row.setItems(graphContainer, link, value);
+                                                        row.setWidth100();
 
                                                         //if graph content returned
                                                         if ((md.getName().trim().indexOf("Trait.") == -1)


commit e27fe0d95627f061e9c9c9253d656f20662234cf
Author: Jay Shaughnessy <jshaughn at redhat.com>
Date:   Fri Jun 22 12:01:04 2012 -0400

    Fix test that was failingon Linux because it wasn't properly normalizing
    the include filter's basedir path.  This was a test-only problem and does
    not affect production code.

diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftDetector.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftDetector.java
index 1c9e50c..92042e7 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftDetector.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftDetector.java
@@ -404,7 +404,8 @@ public class DriftDetector implements Runnable {
         }
     }
 
-    private Set<File> getScanDirectories(final File basedir, List<Filter> includes) {
+    // package-private for test accessibility
+    static Set<File> getScanDirectories(final File basedir, List<Filter> includes) {
 
         Set<File> directories = new HashSet<File>();
 
diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/FilterFileVisitorTest.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/FilterFileVisitorTest.java
index a654607..8d31a82 100644
--- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/FilterFileVisitorTest.java
+++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/drift/FilterFileVisitorTest.java
@@ -31,8 +31,10 @@ import java.io.File;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Set;
 
 import org.apache.commons.io.FileUtils;
+import org.testng.Assert;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
@@ -71,6 +73,7 @@ public class FilterFileVisitorTest {
             visitor.visitedFiles, "Visitor should be called for every file when no filters specified");
     }
 
+    // This could be a DriftDetectorTest but fits well here. 
     @Test
     public void visitBaseDirFilesThatMatchFilters() throws Exception {
         File fooJar = touch(basedir, "foo.jar");
@@ -78,11 +81,15 @@ public class FilterFileVisitorTest {
         File myapp = touch(basedir, "myapp.war");
         touch(basedir, "bar.jar");
 
+        // These filter paths should all normalize to the same directory
         List<Filter> includes = asList(new Filter(".", "foo*"), new Filter("./", "*.war"), new Filter("/", "goo*"));
         List<Filter> excludes = emptyList();
         TestVisitor visitor = new TestVisitor();
 
-        forEachFile(basedir, new FilterFileVisitor(basedir, includes, excludes, visitor));
+        // This call normalizes the basedir.
+        Set<File> dirs = DriftDetector.getScanDirectories(basedir, includes);
+        Assert.assertEquals(dirs.size(), 1, "Should just be the basedir");
+        forEachFile(dirs.iterator().next(), new FilterFileVisitor(basedir, includes, excludes, visitor));
 
         assertCollectionEqualsNoOrder(asList(fooJar, gooJar, myapp), visitor.visitedFiles,
             "Filtering failed with multiple includes and no excludes");


commit b5ab75a28ec1a0bd62b914de1e52869f1bf6a9f1
Author: Ian Springer <ian.springer at redhat.com>
Date:   Fri Jun 22 11:41:22 2012 -0400

    get the as5 plugin descriptor generator compiling again

diff --git a/modules/jopr/tools/jbas5-plugin-descriptor-gen/pom.xml b/modules/jopr/tools/jbas5-plugin-descriptor-gen/pom.xml
index 965002a..dbeec8f 100644
--- a/modules/jopr/tools/jbas5-plugin-descriptor-gen/pom.xml
+++ b/modules/jopr/tools/jbas5-plugin-descriptor-gen/pom.xml
@@ -9,7 +9,7 @@
     <parent>
         <groupId>org.rhq</groupId>
         <artifactId>rhq-parent</artifactId>
-        <version>4.3.0-SNAPSHOT</version>
+        <version>4.5.0-SNAPSHOT</version>
         <relativePath>../../../../pom.xml</relativePath>
     </parent>
 
@@ -313,43 +313,33 @@ t section. -->
 
     <build>
         <plugins>
-            <plugin>
-                <artifactId>maven-compiler-plugin</artifactId>
-                <configuration>
-                    <source>1.5</source>
-                </configuration>
-            </plugin>
             
           <plugin>
-            <artifactId>maven-dependency-plugin</artifactId>
+            <artifactId>maven-assembly-plugin</artifactId>
+            <version>2.3</version>
+            <configuration>
+              <descriptorRefs>
+                <descriptorRef>jar-with-dependencies</descriptorRef>
+              </descriptorRefs>
+              <archive>
+                <manifest>
+                  <mainClass>org.jboss.jopr.tool.jbas5.PluginDescriptorGenerator</mainClass>
+                </manifest>
+              </archive>
+            </configuration>
             <executions>
               <execution>
-                <id>copy-dependencies</id>
+                <id>make-assembly</id>
+                <!-- this is used for inheritance merges -->
                 <phase>package</phase>
+                <!-- bind to the packaging phase -->
                 <goals>
-                  <goal>copy-dependencies</goal>
+                  <goal>single</goal>
                 </goals>
-                <configuration>              
-                  <includeScope>runtime</includeScope>
-                  <excludeTransitive>true</excludeTransitive>
-                  <outputDirectory>target/lib</outputDirectory>
-                </configuration>
               </execution>
             </executions>
           </plugin>
-      
-          <plugin>
-            <artifactId>maven-jar-plugin</artifactId>
-            <configuration>
-              <archive>
-                <manifest>
-                  <mainClass>org.jboss.jopr.tool.jbas5.PluginDescriptorGenerator</mainClass>
-                  <addClasspath>true</addClasspath>
-                  <classpathPrefix>lib</classpathPrefix>
-                </manifest>
-              </archive>
-            </configuration>
-          </plugin>                
+
         </plugins>
     </build>
 
diff --git a/modules/jopr/tools/jbas5-plugin-descriptor-gen/src/main/java/org/jboss/jopr/tool/jbas5/PluginDescriptorGenerator.java b/modules/jopr/tools/jbas5-plugin-descriptor-gen/src/main/java/org/jboss/jopr/tool/jbas5/PluginDescriptorGenerator.java
index 5019fea..31de2a8 100644
--- a/modules/jopr/tools/jbas5-plugin-descriptor-gen/src/main/java/org/jboss/jopr/tool/jbas5/PluginDescriptorGenerator.java
+++ b/modules/jopr/tools/jbas5-plugin-descriptor-gen/src/main/java/org/jboss/jopr/tool/jbas5/PluginDescriptorGenerator.java
@@ -26,6 +26,8 @@ import java.io.BufferedOutputStream;
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.OutputStream;
+import java.lang.String;
+import java.math.BigInteger;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -232,7 +234,7 @@ public class PluginDescriptorGenerator
             if (metricDef.getCategory() != null)
                 metricDescriptor.setCategory(metricDef.getCategory().name().toLowerCase());
             metricDescriptor.setDataType(metricDef.getDataType().name().toLowerCase());
-            metricDescriptor.setDefaultInterval((int)metricDef.getDefaultInterval());
+            metricDescriptor.setDefaultInterval(new BigInteger(String.valueOf(metricDef.getDefaultInterval())));
             metricDescriptor.setDefaultOn(metricDef.isDefaultOn());
             metricDescriptor.setDescription(metricDef.getDescription());
             metricDescriptor.setDestinationType(metricDef.getDestinationType());
@@ -312,7 +314,7 @@ public class PluginDescriptorGenerator
         {
             PropertyDefinitionMap propDefMap = (PropertyDefinitionMap)propDef;
             MapProperty mapProp = new MapProperty();
-            for (PropertyDefinition itemPropDef : propDefMap.getPropertyDefinitions().values())
+            for (PropertyDefinition itemPropDef : propDefMap.getPropertyDefinitions())
             {
                 ConfigurationProperty itemConfigProp = convertPropertyDefinitionToConfigurationProperty(itemPropDef);
                 JAXBElement propElement = getJAXBElement(itemConfigProp);


commit 6b1069c1b97337b69b3e9951e4b6df7a2c692646
Author: Jirka Kremser <jkremser at redhat.com>
Date:   Fri Jun 22 15:23:24 2012 +0200

    [BZ 815421 - Discovery Q: even with no entry, "select all" is active] If there are no enties, "select all" button is disabled

diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/discovery/ResourceAutodiscoveryView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/discovery/ResourceAutodiscoveryView.java
index 0e473a7..a7f20c0 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/discovery/ResourceAutodiscoveryView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/discovery/ResourceAutodiscoveryView.java
@@ -18,17 +18,18 @@
  */
 package org.rhq.enterprise.gui.coregui.client.inventory.resource.discovery;
 
+import java.util.ArrayList;
+import java.util.EnumSet;
+import java.util.List;
+
 import com.google.gwt.user.client.rpc.AsyncCallback;
 import com.smartgwt.client.data.Criteria;
 import com.smartgwt.client.data.DataSource;
 import com.smartgwt.client.types.Autofit;
 import com.smartgwt.client.types.SelectionAppearance;
-import com.smartgwt.client.types.VerticalAlignment;
 import com.smartgwt.client.util.BooleanCallback;
 import com.smartgwt.client.util.SC;
-import com.smartgwt.client.widgets.HTMLFlow;
 import com.smartgwt.client.widgets.IButton;
-import com.smartgwt.client.widgets.Img;
 import com.smartgwt.client.widgets.events.ClickEvent;
 import com.smartgwt.client.widgets.events.ClickHandler;
 import com.smartgwt.client.widgets.form.DynamicForm;
@@ -40,17 +41,16 @@ import com.smartgwt.client.widgets.grid.events.DataArrivedEvent;
 import com.smartgwt.client.widgets.grid.events.DataArrivedHandler;
 import com.smartgwt.client.widgets.grid.events.SelectionChangedHandler;
 import com.smartgwt.client.widgets.grid.events.SelectionEvent;
-import com.smartgwt.client.widgets.layout.HLayout;
 import com.smartgwt.client.widgets.layout.LayoutSpacer;
 import com.smartgwt.client.widgets.toolbar.ToolStrip;
 import com.smartgwt.client.widgets.tree.TreeGrid;
 import com.smartgwt.client.widgets.tree.TreeGridField;
 import com.smartgwt.client.widgets.tree.TreeNode;
+
 import org.rhq.core.domain.resource.InventoryStatus;
 import org.rhq.enterprise.gui.coregui.client.CoreGUI;
 import org.rhq.enterprise.gui.coregui.client.IconEnum;
 import org.rhq.enterprise.gui.coregui.client.RefreshableView;
-import org.rhq.enterprise.gui.coregui.client.components.TitleBar;
 import org.rhq.enterprise.gui.coregui.client.components.table.TimestampCellFormatter;
 import org.rhq.enterprise.gui.coregui.client.components.view.HasViewName;
 import org.rhq.enterprise.gui.coregui.client.components.view.ViewName;
@@ -63,10 +63,6 @@ import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableIButton;
 import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableTreeGrid;
 import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableVLayout;
 
-import java.util.ArrayList;
-import java.util.EnumSet;
-import java.util.List;
-
 /**
  * @author Greg Hinkle
  */
@@ -372,7 +368,7 @@ public class ResourceAutodiscoveryView extends LocatableVLayout implements Refre
     private void updateButtonEnablement(IButton selectAllButton, IButton deselectAllButton, IButton importButton,
         IButton ignoreButton, IButton unignoreButton) {
         if (treeGrid.getSelectedRecords().length == 0) {
-            selectAllButton.setDisabled(false);
+            selectAllButton.setDisabled(treeGrid.getRecords().length == 0);
             deselectAllButton.setDisabled(true);
             importButton.setDisabled(true);
             ignoreButton.setDisabled(true);


commit 7b77b38e5bdaa2b87f05be70bea8c1cdb08d14d8
Author: Simeon Pinder <spinder at redhat.com>
Date:   Fri Jun 22 08:46:14 2012 -0400

     [BZ 826542] add a few tests to exercise crud of Security Domain and some of Module Option framework.
      - only added one of this type as discovery needs to complete in between creates and slows down process significantly.
      - we need to come up with another way of prepopulating the other SecurityDomain types before full discovery.

diff --git a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/SecurityModuleOptionsTest.java b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/SecurityModuleOptionsTest.java
deleted file mode 100644
index e80ddec..0000000
--- a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/SecurityModuleOptionsTest.java
+++ /dev/null
@@ -1,319 +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 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.modules.plugins.jbossas7;
-//
-//import java.io.IOException;
-//import java.util.ArrayList;
-//import java.util.HashMap;
-//import java.util.LinkedHashMap;
-//import java.util.List;
-//
-//import org.codehaus.jackson.JsonGenerationException;
-//import org.codehaus.jackson.JsonNode;
-//import org.codehaus.jackson.JsonProcessingException;
-//import org.codehaus.jackson.map.JsonMappingException;
-//import org.codehaus.jackson.map.ObjectMapper;
-//import org.codehaus.jackson.map.SerializationConfig;
-//import org.testng.annotations.BeforeSuite;
-//import org.testng.annotations.Test;
-//
-//import org.rhq.modules.plugins.jbossas7.ModuleOptionsComponent.ModuleOptionType;
-//import org.rhq.modules.plugins.jbossas7.ModuleOptionsComponent.Value;
-//import org.rhq.modules.plugins.jbossas7.json.Address;
-//import org.rhq.modules.plugins.jbossas7.json.Operation;
-//import org.rhq.modules.plugins.jbossas7.json.ReadAttribute;
-//import org.rhq.modules.plugins.jbossas7.json.Remove;
-//import org.rhq.modules.plugins.jbossas7.json.Result;
-//import org.rhq.modules.plugins.jbossas7.json.WriteAttribute;
-//
-///**
-// * Test exercising the subsystem=security/SecurityDomain/[Authentication, Authorization, Mapping, Audit, Acl, 
-// *      Identity-Trust]
-// * @author Simeon Pinder
-// */
-//@Test(groups = "unit")
-//public class SecurityModuleOptionsTest extends AbstractConfigurationHandlingTest {
-//
-//    private static String user = "rhqadmin";
-//    private static String pass = "as7";
-//    private static String host = "localhost";
-//    private static ASConnection con = null;
-//    private static ObjectMapper mapper = null;
-//    private ModuleOptionsComponent moc = null;
-//
-//    //Define some shared and reusable content
-//    static HashMap<String, String> jsonMap = new HashMap<String, String>();
-//    static {
-//        jsonMap
-//            .put(
-//                "login-modules",
-//                "[{\"flag\":\"required\", \"code\":\"Ldap\", \"module-options\":{\"bindDn\":\"uid=ldapSecureUser,ou=People,dc=redat,dc=com\", \"bindPw\":\"test126\", \"allowEmptyPasswords\":\"true\"}}]");
-//        //              "[{\"flag\":\"required\", \"code\":\"Ldap\"}]");
-//        jsonMap
-//            .put(
-//                "policy-modules",
-//                "[{\"flag\":\"requisite\", \"code\":\"LdapExtended\", \"module-options\":{\"policy\":\"module\", \"policy1\":\"module1\"}}]");
-//        jsonMap
-//            .put("mapping-modules",
-//                "[{\"code\":\"Test\", \"type\":\"attribute\", \"module-options\":{\"mapping\":\"module\", \"mapping1\":\"module1\"}}]");
-//        jsonMap.put("provider-modules",
-//            "[{\"code\":\"Providers\", \"module-options\":{\"provider\":\"module\", \"provider1\":\"module1\"}}]");
-//    }
-//
-//    @BeforeSuite
-//    private void initializeConnectionDetails() {
-//        con = new ASConnection(host, 9990, user, pass);
-//        mapper = new ObjectMapper();
-//        mapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true);
-//
-//        moc = new ModuleOptionsComponent();
-//    }
-//
-//    public static void main(String[] args) {
-//        SecurityModuleOptionsTest test = new SecurityModuleOptionsTest();
-//        try {
-//            test.initializeConnectionDetails();
-//            test.testPopulateModuleOptionsAndTypes();
-//        } catch (Exception e) {
-//            // TODO Auto-generated catch block
-//            e.printStackTrace();
-//        }
-//
-//    }
-//
-//    /**The test reads the existing property values, deserializes them and writes the same 
-//     * contents back out to a running instance for all known ModuleOptionTypes.
-//     * 
-//     * @throws Exception
-//     */
-//    public void testPopulateModuleOptionsAndTypes() throws Exception {
-//
-//        //as7 node details.
-//        String securityDomainId = "testDomain";
-//        //TODO: spinder 6-6-12: this cannot run as a standalone itest until JIRA https://issues.jboss.org/browse/AS7-4951
-//        //      is addressed as there is no way to automate setup of the information being tested.
-//        String address = "subsystem=security,security-domain=" + securityDomainId + ",authentication=classic";
-//        boolean verboseOutput = true;
-//        boolean executeOperation = true;
-//        for (ModuleOptionType t : ModuleOptionType.values()) {
-//            String attribute = t.getAttribute();
-//            if (verboseOutput) {
-//                System.out.println("======= Running with ModuleOptionType:" + t + " attribute:" + attribute + ":");
-//            }
-//            if (attribute.equals("policy-modules")) {
-//                address = "subsystem=security,security-domain=" + securityDomainId + ",authorization=classic";
-//            } else if (attribute.equals("acl-modules")) {
-//                address = "subsystem=security,security-domain=" + securityDomainId + ",acl=classic";
-//            } else if (attribute.equals("mapping-modules")) {
-//                address = "subsystem=security,security-domain=" + securityDomainId + ",mapping=classic";
-//            } else if (attribute.equals("trust-modules")) {
-//                address = "subsystem=security,security-domain=" + securityDomainId + ",identity-trust=classic";
-//            } else if (attribute.equals("provider-modules")) {
-//                address = "subsystem=security,security-domain=" + securityDomainId + ",audit=classic";
-//            } else if (attribute.equals("login-modules")) {
-//                address = "subsystem=security,security-domain=" + securityDomainId + ",authentication=classic";
-//            } else {
-//                assert false : "An unknown attribute '" + attribute
-//                    + "' was found. Is there a new type to be supported?";
-//            }
-//
-//            //test operation- read property always available.
-//            Operation op = null;
-//
-//            //read the login-modules attribute
-//            op = new ReadAttribute(new Address(address), attribute);
-//            Result result = exerciseOperation(op, true, verboseOutput);
-//            assert result.isSuccess() == true : "The operation '" + op + "' failed to read the resource."
-//                + result.getFailureDescription();
-//            //extract current results
-//            Object rawResult = result.getResult();
-//            assert rawResult != null : "Read of attribute'" + attribute + "' from address '" + address
-//                + "' has returned no value. Are those values in the model?";
-//
-//            List<Value> list2 = new ArrayList<Value>();
-//            //populate the Value component complete with module Options.
-//            list2 = moc.populateSecurityDomainModuleOptions(result,
-//                ModuleOptionsComponent.loadModuleOptionType(attribute));
-//            if (verboseOutput) {
-//                if (rawResult != null) {
-//                    System.out.println("Raw Result is:" + rawResult + " and of type:" + rawResult.getClass());
-//                } else {
-//                    System.out.println("Read of attribute'" + attribute + "' from address '" + address
-//                        + "' has returned no value. Are those values in the model?");
-//                }
-//            }
-//            //write the login-modules attribute
-//            op = new WriteAttribute(new Address(address));
-//            op.addAdditionalProperty("name", attribute);//attribute to execute on
-//            op.addAdditionalProperty("value", list2);
-//
-//            //Now test the operation
-//            result = exerciseOperation(op, executeOperation, verboseOutput);
-//            assert ((result.isSuccess() == true) || (result.getOutcome() == null)) : "The operation '" + op
-//                + "' failed to write the resource.." + result.getFailureDescription();
-//
-//            //read the login-modules attribute
-//            op = new ReadAttribute(new Address(address), attribute);
-//            result = exerciseOperation(op, true, verboseOutput);
-//            assert (result.isSuccess() == true) : "The operation '" + op + "' failed to read the resource."
-//                + result.getFailureDescription();
-//        }
-//        if (verboseOutput) {
-//            System.out.println("Successfully detected,read and wrote out attribute values for:");
-//            for (ModuleOptionType type : ModuleOptionType.values()) {
-//                System.out.println("\n" + type.ordinal() + " " + type.name());
-//            }
-//        }
-//    }
-//
-//    /**Attempts to create a new Authentication node(authentication=classic) with a
-//     * 'login-modules' attribute complete with 'code':'Ldap' and 'flag':'required' 
-//     *  and some sample 'module-options' values.
-//     *  
-//     */
-//    @Test(enabled = true)
-//    public void testCreateSecurityDomainChildLoginModules() {
-//        boolean execute = true;
-//        boolean verboseOutput = false;
-//        String address = "subsystem=security,security-domain=testDomain3,authentication=classic";
-//        String attribute = ModuleOptionType.Authentication.getAttribute();
-//
-//        //test operation- read property always available.
-//        Operation op = null;
-//
-//        //read the login-modules attribute
-//        op = new ReadAttribute(new Address(address), attribute);
-//        Result result = exerciseOperation(op, execute, verboseOutput);
-//        assert result.isSuccess() == true : "The operation '" + op + "' failed to read the resource."
-//            + result.getFailureDescription();
-//
-//        //extract current results
-//        Object rawResult = result.getResult();
-//
-//        //#### Have to create new content for the new node.
-//        List<Value> moduleTypeValue = new ArrayList<Value>();
-//        try {
-//            // loading 'login-module'
-//            JsonNode node = mapper.readTree(jsonMap.get(attribute));
-//            result.setResult(mapper.treeToValue(node, Object.class));
-//        } catch (JsonProcessingException e) {
-//            e.printStackTrace();
-//        } catch (IOException e) {
-//            e.printStackTrace();
-//        }
-//
-//        //populate the Value component complete with module Options.
-//        moduleTypeValue = ModuleOptionsComponent.populateSecurityDomainModuleOptions(result,
-//            ModuleOptionsComponent.loadModuleOptionType(attribute));
-//
-//        //add the login-modules attribute
-//        op = ModuleOptionsComponent
-//            .createAddModuleOptionTypeOperation(new Address(address), attribute, moduleTypeValue);
-//
-//        result = exerciseOperation(op, execute, verboseOutput);
-//        assert ((result.isSuccess() == true) || (result.getOutcome() == null)) : "The operation '" + op
-//            + "' failed to write the resource.." + result.getFailureDescription();
-//
-//        //read the login-modules attribute
-//        op = new ReadAttribute(new Address(address), attribute);
-//        result = exerciseOperation(op, execute, verboseOutput);
-//        assert result.isSuccess() == true : "The operation '" + op + "' failed to read the resource."
-//            + result.getFailureDescription();
-//
-//        //exercise values retrieved from read
-//        List<Value> serverResponse = ModuleOptionsComponent.populateSecurityDomainModuleOptions(result,
-//            ModuleOptionsComponent.loadModuleOptionType(attribute));
-//        Value serverState = serverResponse.get(0);
-//        assert serverState.getFlag().equals("required") : "Incorrect state retrieved for 'flag'. Expected 'required'.";
-//        assert serverState.getCode().equals("Ldap") : "Incorrect state retrieved for 'code'. Expected 'Ldap'.";
-//        LinkedHashMap<String, Object> options = serverState.getOptions();
-//        assert options.size() == 3 : "Invalid number of module options returned. Expected 3.";
-//        int found = 0;
-//        for (String key : options.keySet()) {
-//            if (key.equals("bindPw")) {
-//                assert "test126".equals(options.get(key)) : "Module option value not correct for key '" + key + "'.";
-//                found++;
-//            } else if (key.equals("bindDn")) {
-//                assert "uid=ldapSecureUser,ou=People,dc=redat,dc=com".equals(options.get(key)) : "Module option value not correct for key '"
-//                    + key + "'.";
-//                found++;
-//            } else if (key.equals("allowEmptyPasswords")) {
-//                assert "true".equals(options.get(key)) : "Module option value not correct for key '" + key + "'.";
-//                found++;
-//            }
-//        }
-//        assert found == 3 : "All module options were not loaded.";
-//
-//        //remove the original node to reset for next run.
-//        op = new Remove(new Address(address));
-//        result = exerciseOperation(op, execute, verboseOutput);
-//        assert result.isSuccess() == true : "The operation '" + op + "' failed to remove the resource."
-//            + result.getFailureDescription();
-//    }
-//
-//    /** For each operation 
-//     *   - will write verbose json and operation details to system.out if verboseOutput = true;
-//     *   - will execute the operation against running server if execute = true.
-//     * 
-//     * @param op
-//     * @param execute
-//     * @param verboseOutput
-//     * @return
-//     */
-//    public static Result exerciseOperation(Operation op, boolean execute, boolean verboseOutput) {
-//        //display operation as AS7 plugin will build it
-//        if (verboseOutput) {
-//            System.out.println("\tOperation is:" + op);
-//        }
-//
-//        String jsonToSend = "";
-//        try {
-//            //            jsonToSend = mapper.writeValueAsString(op);
-//            jsonToSend = mapper.defaultPrettyPrintingWriter().writeValueAsString(op);
-//        } catch (JsonGenerationException e) {
-//            e.printStackTrace();
-//        } catch (JsonMappingException e) {
-//            e.printStackTrace();
-//        } catch (IOException e) {
-//            e.printStackTrace();
-//        }
-//        //As generated by jackson mapper
-//        if (verboseOutput) {
-//            System.out.println("@@@@ OUTBOUND JSON#\n" + jsonToSend + "#");
-//        }
-//
-//        //Execute the operation
-//        Result result = new Result();
-//        if (execute) {
-//            result = con.execute(op);
-//        } else {
-//            if (verboseOutput) {
-//                System.out.println("**** NOTE: Execution disabled . NOT exercising write-attribute operation. **** ");
-//            }
-//        }
-//        if (verboseOutput) {
-//            //result wrapper details 
-//            System.out.println("\tResult:" + result);
-//            //detailed results
-//            System.out.println("\tValue:" + result.getResult());
-//            System.out.println("-----------------------------------------------------\n");
-//        }
-//        return result;
-//    }
-//}
diff --git a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/SecurityModuleOptionsTest.java b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/SecurityModuleOptionsTest.java
new file mode 100644
index 0000000..7f9464a
--- /dev/null
+++ b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/SecurityModuleOptionsTest.java
@@ -0,0 +1,525 @@
+/*
+ * 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 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.modules.plugins.jbossas7.itest.standalone;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+
+import java.util.HashMap;
+import java.util.Set;
+
+import org.codehaus.jackson.map.ObjectMapper;
+import org.testng.annotations.Test;
+
+import org.rhq.core.clientapi.agent.inventory.CreateResourceRequest;
+import org.rhq.core.clientapi.agent.inventory.CreateResourceResponse;
+import org.rhq.core.clientapi.agent.inventory.DeleteResourceRequest;
+import org.rhq.core.clientapi.agent.inventory.DeleteResourceResponse;
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.PropertySimple;
+import org.rhq.core.domain.resource.CreateResourceStatus;
+import org.rhq.core.domain.resource.DeleteResourceStatus;
+import org.rhq.core.domain.resource.InventoryStatus;
+import org.rhq.core.domain.resource.Resource;
+import org.rhq.core.domain.resource.ResourceCategory;
+import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.core.pc.inventory.InventoryManager;
+import org.rhq.modules.plugins.jbossas7.ASConnection;
+import org.rhq.modules.plugins.jbossas7.ModuleOptionsComponent;
+import org.rhq.modules.plugins.jbossas7.itest.AbstractJBossAS7PluginTest;
+import org.rhq.test.arquillian.RunDiscovery;
+
+/**
+ * Test exercising the subsystem=security/SecurityDomain/[Authentication(Classic|Jaspi), 
+ * Authorization, Mapping, Audit, Acl, 
+ *      Identity-Trust]
+ * @author Simeon Pinder
+ */
+ at Test(groups = { "integration", "pc", "standalone" }, singleThreaded = true)
+public class SecurityModuleOptionsTest extends AbstractJBossAS7PluginTest {
+
+    private static String user = "rhqadmin";
+    private static String pass = "as7";
+    private static String host = "localhost";
+    private static ASConnection con = null;
+    private static ObjectMapper mapper = null;
+    private ModuleOptionsComponent moc = null;
+
+    private static String TEST_DOMAIN = "testDomain";
+    private static Resource securityResource = null;
+    private static String SECURITY_RESOURCE_TYPE = "Security";
+    private static String SECURITY_RESOURCE_KEY = "subsystem=security";
+    private static String SECURITY_DOMAIN_RESOURCE_TYPE = "Security Domain";
+    private static String SECURITY_DOMAIN_RESOURCE_KEY = "security-domain";
+    private static String AUTH_CLASSIC_RESOURCE_TYPE = "Authentication (Classic)";
+    private static String AUTH_CLASSIC_RESOURCE_KEY = "authentication=classic";
+
+    protected static final String DC_HOST = System.getProperty("jboss.domain.bindAddress");
+    protected static final int DC_HTTP_PORT = Integer.valueOf(System.getProperty("jboss.domain.httpManagementPort"));
+    protected static final String DC_USER = AbstractJBossAS7PluginTest.MANAGEMENT_USERNAME;
+    protected static final String DC_PASS = AbstractJBossAS7PluginTest.MANAGEMENT_PASSWORD;
+
+    ASConnection getASConnection() {
+        ASConnection connection = new ASConnection(DC_HOST, DC_HTTP_PORT, DC_USER, DC_PASS);
+        return connection;
+    }
+
+    public static final ResourceType RESOURCE_TYPE = new ResourceType(SECURITY_RESOURCE_TYPE, PLUGIN_NAME,
+        ResourceCategory.SERVICE, null);
+    private static final String RESOURCE_KEY = SECURITY_RESOURCE_KEY;
+
+    //Define some shared and reusable content
+    static HashMap<String, String> jsonMap = new HashMap<String, String>();
+    static {
+        jsonMap
+            .put(
+                "login-modules",
+                "[{\"flag\":\"required\", \"code\":\"Ldap\", \"module-options\":{\"bindDn\":\"uid=ldapSecureUser,ou=People,dc=redat,dc=com\", \"bindPw\":\"test126\", \"allowEmptyPasswords\":\"true\"}}]");
+        jsonMap
+            .put(
+                "policy-modules",
+                "[{\"flag\":\"requisite\", \"code\":\"LdapExtended\", \"module-options\":{\"policy\":\"module\", \"policy1\":\"module1\"}}]");
+        jsonMap
+            .put("mapping-modules",
+                "[{\"code\":\"Test\", \"type\":\"attribute\", \"module-options\":{\"mapping\":\"module\", \"mapping1\":\"module1\"}}]");
+        jsonMap.put("provider-modules",
+            "[{\"code\":\"Providers\", \"module-options\":{\"provider\":\"module\", \"provider1\":\"module1\"}}]");
+    }
+
+    @Test(priority = 10, groups = "discovery")
+    @RunDiscovery(discoverServices = true, discoverServers = true)
+    public void initialDiscovery() throws Exception {
+        Resource platform = this.pluginContainer.getInventoryManager().getPlatform();
+        assertNotNull(platform);
+        assertEquals(platform.getInventoryStatus(), InventoryStatus.COMMITTED);
+
+        Thread.sleep(20 * 1000L); // delay so that PC gets a chance to scan for resources
+    }
+
+    @Test(priority = 12)
+    public void testCreateSecurityDomain() throws Exception {
+        //get the root security resource
+        securityResource = getResource();
+
+        //plugin config
+        Configuration createPlugConfig = new Configuration();
+        createPlugConfig.put(new PropertySimple("path", SECURITY_DOMAIN_RESOURCE_KEY += "=" + TEST_DOMAIN));
+
+        //resource config
+        Configuration createResConfig = new Configuration();
+        createResConfig.put(new PropertySimple("name", TEST_DOMAIN));
+
+        CreateResourceRequest request = new CreateResourceRequest();
+        request.setParentResourceId(securityResource.getId());
+        request.setPluginConfiguration(createPlugConfig);
+        request.setPluginName(PLUGIN_NAME);
+        request.setResourceConfiguration(createResConfig);
+        request.setResourceName(TEST_DOMAIN);
+        request.setResourceTypeName(SECURITY_DOMAIN_RESOURCE_TYPE);
+
+        CreateResourceResponse response = pluginContainer.getResourceFactoryManager().executeCreateResourceImmediately(
+            request);
+
+        assert response.getStatus() == CreateResourceStatus.SUCCESS : "The Security Domain creation failed with an error mesasge: "
+            + response.getErrorMessage();
+    }
+
+    @Test(priority = 13)
+    public void testAuthenticationClassic() throws Exception {
+        //get the root security resource
+        securityResource = getResource();
+
+        //find TEST_DOMAIN 'security-domain'
+        Resource securityDomain = null;
+        Set<Resource> childResources = securityResource.getChildResources();
+        for (Resource r : childResources) {
+            if (r.getName().indexOf(TEST_DOMAIN) > -1) {
+                securityDomain = r;
+            }
+        }
+
+        //plugin config
+        Configuration createPlugConfig = new Configuration();
+        createPlugConfig.put(new PropertySimple("path", AUTH_CLASSIC_RESOURCE_KEY));
+
+        //resource config
+        Configuration createResConfig = new Configuration();
+        createResConfig.put(new PropertySimple("code", "Ldap"));
+        createResConfig.put(new PropertySimple("flag", "requisite"));
+
+        CreateResourceRequest request = new CreateResourceRequest();
+        request.setParentResourceId(securityDomain.getId());
+        request.setPluginConfiguration(createPlugConfig);
+        request.setPluginName(PLUGIN_NAME);
+        request.setResourceConfiguration(createResConfig);
+        request.setResourceName("Test - notUsed.");
+
+        request.setResourceTypeName(AUTH_CLASSIC_RESOURCE_TYPE);
+
+        CreateResourceResponse response = pluginContainer.getResourceFactoryManager().executeCreateResourceImmediately(
+            request);
+
+        assert response.getStatus() == CreateResourceStatus.SUCCESS : "The 'Authentication (Classic)' node creation failed with an error mesasge: "
+            + response.getErrorMessage();
+    }
+
+    @Test(priority = 14)
+    public void testDeleteSecurityDomain() throws Exception {
+        //get the root security resource
+        securityResource = getResource();
+        Resource found = null;
+        Set<Resource> childResources = securityResource.getChildResources();
+        for (Resource r : childResources) {
+            if (r.getName().indexOf(TEST_DOMAIN) > -1) {
+                found = r;
+            }
+        }
+
+        //plugin config
+        Configuration deletePlugConfig = new Configuration();
+        deletePlugConfig.put(new PropertySimple("path", SECURITY_DOMAIN_RESOURCE_KEY += "=" + TEST_DOMAIN));
+
+        //resource config
+        Configuration deleteResConfig = new Configuration();
+        deleteResConfig.put(new PropertySimple("name", TEST_DOMAIN));
+
+        DeleteResourceRequest request = new DeleteResourceRequest();
+        if (found != null) {
+            request.setResourceId(found.getId());
+        }
+        DeleteResourceResponse response = pluginContainer.getResourceFactoryManager().executeDeleteResourceImmediately(
+            request);
+
+        assert response.getStatus() == DeleteResourceStatus.SUCCESS : "The Security Domain deletion failed with an error mesasge: "
+            + response.getErrorMessage();
+    }
+
+    private Resource getResource() {
+
+        InventoryManager im = pluginContainer.getInventoryManager();
+        Resource platform = im.getPlatform();
+        Resource server = getResourceByTypeAndKey(platform, StandaloneServerComponentTest.RESOURCE_TYPE,
+            StandaloneServerComponentTest.RESOURCE_KEY);
+        Resource bindings = getResourceByTypeAndKey(server, RESOURCE_TYPE, RESOURCE_KEY);
+        return bindings;
+    }
+
+    private Resource getResource(Resource parentResource, String pluginDescriptorTypeName, String resourceKey) {
+        Resource resource = null;
+        if (((parentResource != null) & (pluginDescriptorTypeName != null) & (resourceKey != null))
+            & (((!pluginDescriptorTypeName.isEmpty()) & (!resourceKey.isEmpty())))) {
+            ResourceType resourceType = buildResourceType(pluginDescriptorTypeName);
+            resource = getResourceByTypeAndKey(parentResource, resourceType, resourceKey);
+        }
+        return resource;
+    }
+
+    private ResourceType buildResourceType(String pluginTypeName) {
+        ResourceType created = null;
+        if ((pluginTypeName != null) && (!pluginTypeName.isEmpty())) {
+            created = new ResourceType(pluginTypeName, PLUGIN_NAME, ResourceCategory.SERVICE, null);
+        }
+        return created;
+    }
+
+    //##################################################################
+    //    /**The test reads the existing property values, deserializes them and writes the same 
+    //     * contents back out to a running instance for all known ModuleOptionTypes.
+    //     * 
+    //     * @throws Exception
+    //     */
+    //    public void testPopulateModuleOptionsAndTypes() throws Exception {
+    //
+    //        //as7 node details.
+    //        String securityDomainId = "testDomain";
+    //        //TODO: spinder 6-6-12: this cannot run as a standalone itest until JIRA https://issues.jboss.org/browse/AS7-4951
+    //        //      is addressed as there is no way to automate setup of the information being tested.
+    //        String address = "subsystem=security,security-domain=" + securityDomainId + ",authentication=classic";
+    //        boolean verboseOutput = true;
+    //        boolean executeOperation = true;
+    //        for (ModuleOptionType t : ModuleOptionType.values()) {
+    //            String attribute = t.getAttribute();
+    //            if (verboseOutput) {
+    //                System.out.println("======= Running with ModuleOptionType:" + t + " attribute:" + attribute + ":");
+    //            }
+    //            if (attribute.equals("policy-modules")) {
+    //                address = "subsystem=security,security-domain=" + securityDomainId + ",authorization=classic";
+    //            } else if (attribute.equals("acl-modules")) {
+    //                address = "subsystem=security,security-domain=" + securityDomainId + ",acl=classic";
+    //            } else if (attribute.equals("mapping-modules")) {
+    //                address = "subsystem=security,security-domain=" + securityDomainId + ",mapping=classic";
+    //            } else if (attribute.equals("trust-modules")) {
+    //                address = "subsystem=security,security-domain=" + securityDomainId + ",identity-trust=classic";
+    //            } else if (attribute.equals("provider-modules")) {
+    //                address = "subsystem=security,security-domain=" + securityDomainId + ",audit=classic";
+    //            } else if (attribute.equals("login-modules")) {
+    //                address = "subsystem=security,security-domain=" + securityDomainId + ",authentication=classic";
+    //            } else {
+    //                assert false : "An unknown attribute '" + attribute
+    //                    + "' was found. Is there a new type to be supported?";
+    //            }
+    //
+    //            //test operation- read property always available.
+    //            Operation op = null;
+    //
+    //            //read the login-modules attribute
+    //            op = new ReadAttribute(new Address(address), attribute);
+    //            Result result = exerciseOperation(op, true, verboseOutput);
+    //            assert result.isSuccess() == true : "The operation '" + op + "' failed to read the resource."
+    //                + result.getFailureDescription();
+    //            //extract current results
+    //            Object rawResult = result.getResult();
+    //            assert rawResult != null : "Read of attribute'" + attribute + "' from address '" + address
+    //                + "' has returned no value. Are those values in the model?";
+    //
+    //            List<Value> list2 = new ArrayList<Value>();
+    //            //populate the Value component complete with module Options.
+    //            list2 = moc.populateSecurityDomainModuleOptions(result,
+    //                ModuleOptionsComponent.loadModuleOptionType(attribute));
+    //            if (verboseOutput) {
+    //                if (rawResult != null) {
+    //                    System.out.println("Raw Result is:" + rawResult + " and of type:" + rawResult.getClass());
+    //                } else {
+    //                    System.out.println("Read of attribute'" + attribute + "' from address '" + address
+    //                        + "' has returned no value. Are those values in the model?");
+    //                }
+    //            }
+    //            //write the login-modules attribute
+    //            op = new WriteAttribute(new Address(address));
+    //            op.addAdditionalProperty("name", attribute);//attribute to execute on
+    //            op.addAdditionalProperty("value", list2);
+    //
+    //            //Now test the operation
+    //            result = exerciseOperation(op, executeOperation, verboseOutput);
+    //            assert ((result.isSuccess() == true) || (result.getOutcome() == null)) : "The operation '" + op
+    //                + "' failed to write the resource.." + result.getFailureDescription();
+    //
+    //            //read the login-modules attribute
+    //            op = new ReadAttribute(new Address(address), attribute);
+    //            result = exerciseOperation(op, true, verboseOutput);
+    //            assert (result.isSuccess() == true) : "The operation '" + op + "' failed to read the resource."
+    //                + result.getFailureDescription();
+    //        }
+    //        if (verboseOutput) {
+    //            System.out.println("Successfully detected,read and wrote out attribute values for:");
+    //            for (ModuleOptionType type : ModuleOptionType.values()) {
+    //                System.out.println("\n" + type.ordinal() + " " + type.name());
+    //            }
+    //        }
+    //    }
+    //
+    //    /**Attempts to create a new Authentication node(authentication=classic) with a
+    //     * 'login-modules' attribute complete with 'code':'Ldap' and 'flag':'required' 
+    //     *  and some sample 'module-options' values.
+    //     *  
+    //     */
+    //    @Test(enabled = true)
+    //    public void testCreateSecurityDomainChildLoginModules() {
+    //        boolean execute = true;
+    //        boolean verboseOutput = false;
+    //        String address = "subsystem=security,security-domain=testDomain3,authentication=classic";
+    //        String attribute = ModuleOptionType.Authentication.getAttribute();
+    //
+    //        //test operation- read property always available.
+    //        Operation op = null;
+    //
+    //        //read the login-modules attribute
+    //        op = new ReadAttribute(new Address(address), attribute);
+    //        Result result = exerciseOperation(op, execute, verboseOutput);
+    //        assert result.isSuccess() == true : "The operation '" + op + "' failed to read the resource."
+    //            + result.getFailureDescription();
+    //
+    //        //extract current results
+    //        Object rawResult = result.getResult();
+    //
+    //        //#### Have to create new content for the new node.
+    //        List<Value> moduleTypeValue = new ArrayList<Value>();
+    //        try {
+    //            // loading 'login-module'
+    //            JsonNode node = mapper.readTree(jsonMap.get(attribute));
+    //            result.setResult(mapper.treeToValue(node, Object.class));
+    //        } catch (JsonProcessingException e) {
+    //            e.printStackTrace();
+    //        } catch (IOException e) {
+    //            e.printStackTrace();
+    //        }
+    //
+    //        //populate the Value component complete with module Options.
+    //        moduleTypeValue = ModuleOptionsComponent.populateSecurityDomainModuleOptions(result,
+    //            ModuleOptionsComponent.loadModuleOptionType(attribute));
+    //
+    //        //add the login-modules attribute
+    //        op = ModuleOptionsComponent
+    //            .createAddModuleOptionTypeOperation(new Address(address), attribute, moduleTypeValue);
+    //
+    //        result = exerciseOperation(op, execute, verboseOutput);
+    //        assert ((result.isSuccess() == true) || (result.getOutcome() == null)) : "The operation '" + op
+    //            + "' failed to write the resource.." + result.getFailureDescription();
+    //
+    //        //read the login-modules attribute
+    //        op = new ReadAttribute(new Address(address), attribute);
+    //        result = exerciseOperation(op, execute, verboseOutput);
+    //        assert result.isSuccess() == true : "The operation '" + op + "' failed to read the resource."
+    //            + result.getFailureDescription();
+    //
+    //        //exercise values retrieved from read
+    //        List<Value> serverResponse = ModuleOptionsComponent.populateSecurityDomainModuleOptions(result,
+    //            ModuleOptionsComponent.loadModuleOptionType(attribute));
+    //        Value serverState = serverResponse.get(0);
+    //        assert serverState.getFlag().equals("required") : "Incorrect state retrieved for 'flag'. Expected 'required'.";
+    //        assert serverState.getCode().equals("Ldap") : "Incorrect state retrieved for 'code'. Expected 'Ldap'.";
+    //        LinkedHashMap<String, Object> options = serverState.getOptions();
+    //        assert options.size() == 3 : "Invalid number of module options returned. Expected 3.";
+    //        int found = 0;
+    //        for (String key : options.keySet()) {
+    //            if (key.equals("bindPw")) {
+    //                assert "test126".equals(options.get(key)) : "Module option value not correct for key '" + key + "'.";
+    //                found++;
+    //            } else if (key.equals("bindDn")) {
+    //                assert "uid=ldapSecureUser,ou=People,dc=redat,dc=com".equals(options.get(key)) : "Module option value not correct for key '"
+    //                    + key + "'.";
+    //                found++;
+    //            } else if (key.equals("allowEmptyPasswords")) {
+    //                assert "true".equals(options.get(key)) : "Module option value not correct for key '" + key + "'.";
+    //                found++;
+    //            }
+    //        }
+    //        assert found == 3 : "All module options were not loaded.";
+    //
+    //        //remove the original node to reset for next run.
+    //        op = new Remove(new Address(address));
+    //        result = exerciseOperation(op, execute, verboseOutput);
+    //        assert result.isSuccess() == true : "The operation '" + op + "' failed to remove the resource."
+    //            + result.getFailureDescription();
+    //    }
+    //
+    //    /** For each operation 
+    //     *   - will write verbose json and operation details to system.out if verboseOutput = true;
+    //     *   - will execute the operation against running server if execute = true.
+    //     * 
+    //     * @param op
+    //     * @param execute
+    //     * @param verboseOutput
+    //     * @return
+    //     */
+    //    public static Result exerciseOperation(Operation op, boolean execute, boolean verboseOutput) {
+    //        //display operation as AS7 plugin will build it
+    //        if (verboseOutput) {
+    //            System.out.println("\tOperation is:" + op);
+    //        }
+    //
+    //        String jsonToSend = "";
+    //        try {
+    //            jsonToSend = mapper.defaultPrettyPrintingWriter().writeValueAsString(op);
+    //        } catch (JsonGenerationException e) {
+    //            e.printStackTrace();
+    //        } catch (JsonMappingException e) {
+    //            e.printStackTrace();
+    //        } catch (IOException e) {
+    //            e.printStackTrace();
+    //        }
+    //        //As generated by jackson mapper
+    //        if (verboseOutput) {
+    //            System.out.println("@@@@ OUTBOUND JSON#\n" + jsonToSend + "#");
+    //        }
+    //
+    //        //Execute the operation
+    //        Result result = new Result();
+    //        if (execute) {
+    //            result = con.execute(op);
+    //        } else {
+    //            if (verboseOutput) {
+    //                System.out.println("**** NOTE: Execution disabled . NOT exercising write-attribute operation. **** ");
+    //            }
+    //        }
+    //        if (verboseOutput) {
+    //            //result wrapper details 
+    //            System.out.println("\tResult:" + result);
+    //            //detailed results
+    //            System.out.println("\tValue:" + result.getResult());
+    //            System.out.println("-----------------------------------------------------\n");
+    //        }
+    //        return result;
+    //    }
+    //
+    //    @Test(priority = 10, groups = "discovery")
+    //    public void initialSetup() throws Exception {
+    //        String securityDomainId = TEST_DOMAIN + "1";
+    //        Result result = null;
+    //        Operation op = null;
+    //
+    //        //create the initial securityDomain
+    //        op = new Operation("add", new Address("subsystem=security,security-domain=" + securityDomainId));
+    //        ASConnection connection = getASConnection();
+    //        con = connection;
+    //        mapper = new ObjectMapper();
+    //        mapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true);
+    //
+    //        moc = new ModuleOptionsComponent();
+    //        result = connection.execute(op);
+    //        System.out.println("#### Op is:" + op);
+    //        System.out.println("#### Result is:" + result);
+    //
+    //        //iterate over jsonMap
+    //        for (String key : jsonMap.keySet()) {
+    //            String attribute = key;
+    //            String address = "";
+    //            if (attribute.equals("policy-modules")) {
+    //                address = "subsystem=security,security-domain=" + securityDomainId + ",authorization=classic";
+    //            } else if (attribute.equals("acl-modules")) {
+    //                address = "subsystem=security,security-domain=" + securityDomainId + ",acl=classic";
+    //            } else if (attribute.equals("mapping-modules")) {
+    //                address = "subsystem=security,security-domain=" + securityDomainId + ",mapping=classic";
+    //            } else if (attribute.equals("trust-modules")) {
+    //                address = "subsystem=security,security-domain=" + securityDomainId + ",identity-trust=classic";
+    //            } else if (attribute.equals("provider-modules")) {
+    //                address = "subsystem=security,security-domain=" + securityDomainId + ",audit=classic";
+    //            } else if (attribute.equals("login-modules")) {
+    //                address = "subsystem=security,security-domain=" + securityDomainId + ",authentication=classic";
+    //            } else {
+    //                assert false : "An unknown attribute '" + attribute
+    //                    + "' was found. Is there a new type to be supported?";
+    //            }
+    //            //#### Have to create new content for the new node.
+    //            List<Value> moduleTypeValue = new ArrayList<Value>();
+    //
+    //            try {
+    //                // loading 'login-module'
+    //                JsonNode node = mapper.readTree(jsonMap.get(attribute));
+    //                result.setResult(mapper.treeToValue(node, Object.class));
+    //            } catch (JsonProcessingException e) {
+    //                e.printStackTrace();
+    //            } catch (IOException e) {
+    //                e.printStackTrace();
+    //            }
+    //
+    //            //populate the Value component complete with module Options.
+    //            moduleTypeValue = ModuleOptionsComponent.populateSecurityDomainModuleOptions(result,
+    //                ModuleOptionsComponent.loadModuleOptionType(attribute));
+    //
+    //            //add the login-modules attribute
+    //            op = ModuleOptionsComponent.createAddModuleOptionTypeOperation(new Address(address), attribute,
+    //                moduleTypeValue);
+    //
+    //            result = exerciseOperation(op, true, true);
+    //            assert ((result.isSuccess() == true) || (result.getOutcome() == null)) : "The operation '" + op
+    //                + "' failed to write the resource.." + result.getFailureDescription();
+    //        }
+    //    }
+}


commit 37ba7b7ad179000571944b602a2cf6d0993632f2
Author: Simeon Pinder <spinder at redhat.com>
Date:   Fri Jun 22 02:51:27 2012 -0400

     Adding ability to disable deletion of as7 artifacts after an integration test run. Ex. -Ditest.deleteRoot=false

diff --git a/modules/plugins/jboss-as-7/pom.xml b/modules/plugins/jboss-as-7/pom.xml
index 16eb982..7230b59 100644
--- a/modules/plugins/jboss-as-7/pom.xml
+++ b/modules/plugins/jboss-as-7/pom.xml
@@ -331,10 +331,22 @@
                     <goal>run</goal>
                 </goals>
                 <configuration>
+              <tasks>
+                <taskdef resource="net/sf/antcontrib/antcontrib.properties"
+                  classpathref="maven.plugin.classpath" />
+                <if>
+                  <equals arg1="${itest.deleteRoot}" arg2="false" />
+                  <then>
+                    <echo message="*** By request not deleting the AS7 instances after 'integration-test' run." />
+                  </then>
+                  <else>
                    <target>
                       <delete dir="${jboss7.home}"/>
                    </target>
-                </configuration>
+                  </else>
+                </if>
+              </tasks>
+            </configuration>
               </execution>
             </executions>
           </plugin>


commit 251a17e5a6f972a57c53431b02b6f16867cf463c
Author: Ian Springer <ian.springer at redhat.com>
Date:   Thu Jun 21 17:46:45 2012 -0400

    [BZ 834434] add tooltips to STRING and LONG_STRING simple props that show full property values (https://bugzilla.redhat.com/show_bug.cgi?id=834434)

diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/ConfigurationEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/ConfigurationEditor.java
index 5748811..dc32e91 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/ConfigurationEditor.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/ConfigurationEditor.java
@@ -1401,6 +1401,8 @@ public class ConfigurationEditor extends LocatableVLayout {
         }
         valueItem.setValue(value);
 
+        setValueAsTooltipIfAppropriate(valueItem, value);
+
         valueItem.setRequired(propertyDefinitionSimple.isRequired());
         valueItem.setWidth(220);
 
@@ -1419,6 +1421,13 @@ public class ConfigurationEditor extends LocatableVLayout {
         return valueItem;
     }
 
+    private void setValueAsTooltipIfAppropriate(FormItem formItem, String value) {
+        if (((formItem instanceof TextItem) && !(formItem instanceof PasswordItem)) ||
+                (formItem instanceof TextAreaItem)) {
+            formItem.setTooltip(value);
+        }
+    }
+
     protected boolean shouldFireEventOnPropertyValueChange(FormItem formItem,
         PropertyDefinitionSimple propertyDefinitionSimple, PropertySimple propertySimple) {
         PropertyMap parentMap = propertySimple.getParentMap();
@@ -1429,6 +1438,9 @@ public class ConfigurationEditor extends LocatableVLayout {
         PropertyDefinitionSimple propertyDefinitionSimple) {
         propertySimple.setErrorMessage(null);
         propertySimple.setValue(value);
+
+        String stringValue = (value != null) ? value.toString() : null;
+        setValueAsTooltipIfAppropriate(formItem, stringValue);
     }
 
     protected static PropertyDefinition getTopLevelPropertyDefinition(PropertyDefinition propertyDefinition) {


commit 2652ac657bd0f7527d231bbfb7d464d1cd6ab3ce
Author: John Mazzitelli <mazz at redhat.com>
Date:   Thu Jun 21 14:13:40 2012 -0400

    add oracle and snmptrapd plugin test modules to eclipse classpath

diff --git a/.classpath b/.classpath
index 9362891..443abde 100644
--- a/.classpath
+++ b/.classpath
@@ -106,6 +106,7 @@
 	<classpathentry kind="src" path="modules/plugins/postgres/src/test/java"/>
 	<classpathentry kind="src" path="modules/plugins/mysql/src/main/java"/>
 	<classpathentry kind="src" path="modules/plugins/oracle/src/main/java"/>
+	<classpathentry kind="src" path="modules/plugins/oracle/src/test/java"/>
 	<classpathentry kind="src" path="modules/plugins/apache/src/main/java"/>
 	<classpathentry kind="src" path="modules/plugins/apache/src/test/java"/>
 	<classpathentry kind="src" path="modules/plugins/script/src/main/java"/>
@@ -115,6 +116,7 @@
 	<classpathentry kind="src" path="modules/plugins/filetemplate-bundle/src/main/java"/>
 	<classpathentry kind="src" path="modules/plugins/filetemplate-bundle/src/test/java"/>
 	<classpathentry kind="src" path="modules/plugins/snmptrapd/src/main/java"/>
+	<classpathentry kind="src" path="modules/plugins/snmptrapd/src/test/java"/>
 	<classpathentry kind="src" path="modules/plugins/byteman/src/main/java"/>
 	<classpathentry kind="src" path="modules/plugins/iis/src/main/java"/>
 	<classpathentry kind="src" path="modules/plugins/sshd/src/main/java"/>


commit cb316267fac790327fe62d1ac8c9ea9bccd3dbe7
Author: Ian Springer <ian.springer at redhat.com>
Date:   Thu Jun 21 11:55:32 2012 -0400

    [BZ 834353] update discovery to recognize BRMS as a separate product type (https://bugzilla.redhat.com/show_bug.cgi?id=834353)

diff --git a/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/ApplicationServerDiscoveryComponent.java b/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/ApplicationServerDiscoveryComponent.java
index 31c6ab3..01eb105 100644
--- a/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/ApplicationServerDiscoveryComponent.java
+++ b/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/ApplicationServerDiscoveryComponent.java
@@ -576,11 +576,16 @@ public class ApplicationServerDiscoveryComponent implements ResourceDiscoveryCom
         ComparableVersion version = new ComparableVersion(installInfo.getVersion());
         JBossProductType productType = installInfo.getProductType();
         ComparableVersion minimumVersion = MINIMUM_PRODUCT_VERSIONS.get(productType);
-        // The product is supported if the version is greater than or equal to the minimum version.
-        boolean supported = (version.compareTo(minimumVersion) >= 0);
-        if (!supported) {
-            log.debug(productType + " version " + version + " is not supported by this plugin (minimum " + productType
-                + " version is " + minimumVersion + ") - skipping...");
+        boolean supported;
+        if (minimumVersion != null) {
+            // The product is supported if the version is greater than or equal to the minimum version.
+            supported = (version.compareTo(minimumVersion) >= 0);
+            if (!supported) {
+                log.debug(productType + " version " + version + " is not supported by this plugin (minimum " + productType
+                    + " version is " + minimumVersion + ") - skipping...");
+            }
+        } else {
+            supported = true;
         }
         return supported;
     }
diff --git a/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/helper/JBossProductType.java b/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/helper/JBossProductType.java
index 818658b..de5d837 100644
--- a/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/helper/JBossProductType.java
+++ b/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/helper/JBossProductType.java
@@ -1,6 +1,6 @@
 /*
 * Jopr Management Platform
-* Copyright (C) 2005-2010 Red Hat, Inc.
+* Copyright (C) 2005-2012 Red Hat, Inc.
 * All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
@@ -31,10 +31,11 @@ import java.util.jar.Attributes;
  * @author Ian Springer
  */
 public enum JBossProductType {
-    AS("JBoss AS", "JBoss Application Server", "default"), // the public offering
-    EAP("JBoss EAP", "JBoss Enterprise Application Platform", "default"), // the customer offering
-    EWP("JBoss EWP", "JBoss Enterprise Web Platform", "default"), // the customer offering    
-    SOA("JBoss SOA-P", "JBoss Enterprise SOA Platform", "default"); // the customer SOA platform
+    AS("JBoss AS", "JBoss Application Server", "default"),
+    EAP("JBoss EAP", "JBoss Enterprise Application Platform", "default"),
+    EWP("JBoss EWP", "JBoss Enterprise Web Platform", "default"),
+    SOA("JBoss SOA-P", "JBoss Enterprise SOA Platform", "default"),
+    BRMS("JBoss BRMS", "JBoss Business Rules Management System", "default");
 
     public final String NAME;
     public final String DESCRIPTION;
@@ -43,6 +44,7 @@ public enum JBossProductType {
     private static final String EAP_IMPLEMENTATION_TITLE = "JBoss [EAP]";
     private static final String EWP_IMPLEMENTATION_TITLE = "JBoss [EWP]";
     private static final String SOA_IMPLEMENTATION_TITLE = "JBoss [SOA]";
+    private static final String BRMS_IMPLEMENTATION_TITLE = "JBoss [BRMS]";
 
     JBossProductType(String name, String description, String defaultConfigName) {
         this.NAME = name;
@@ -68,6 +70,8 @@ public enum JBossProductType {
                 result = JBossProductType.EWP;
             } else if (implementationTitle.equalsIgnoreCase(SOA_IMPLEMENTATION_TITLE)) {
                 result = JBossProductType.SOA;
+            } else if (implementationTitle.equalsIgnoreCase(BRMS_IMPLEMENTATION_TITLE)) {
+                result = JBossProductType.BRMS;
             }
         }
         return result;


commit a5ef337f5921c5cc52fd6a96c084925c46b8f4a1
Author: John Mazzitelli <mazz at redhat.com>
Date:   Wed Jun 20 17:26:41 2012 -0400

    [BZ 828843] fix bundle deploy wizard's configuration editor initialization so required properties that didn't exist in the live deployment config are set to their default values

diff --git a/modules/core/client-api/src/main/java/org/rhq/core/clientapi/agent/configuration/ConfigurationUtility.java b/modules/core/client-api/src/main/java/org/rhq/core/clientapi/agent/configuration/ConfigurationUtility.java
index 85ae0bb..6420978 100644
--- a/modules/core/client-api/src/main/java/org/rhq/core/clientapi/agent/configuration/ConfigurationUtility.java
+++ b/modules/core/client-api/src/main/java/org/rhq/core/clientapi/agent/configuration/ConfigurationUtility.java
@@ -22,31 +22,20 @@
  */
 package org.rhq.core.clientapi.agent.configuration;
 
-import java.util.ArrayList;
 import java.util.List;
-import java.util.Map;
 
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
-import org.rhq.core.domain.configuration.AbstractPropertyMap;
 import org.rhq.core.domain.configuration.Configuration;
-import org.rhq.core.domain.configuration.Property;
-import org.rhq.core.domain.configuration.PropertyDefinitionDynamic;
-import org.rhq.core.domain.configuration.PropertyList;
-import org.rhq.core.domain.configuration.PropertyMap;
-import org.rhq.core.domain.configuration.PropertySimple;
 import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
-import org.rhq.core.domain.configuration.definition.ConfigurationTemplate;
-import org.rhq.core.domain.configuration.definition.PropertyDefinition;
-import org.rhq.core.domain.configuration.definition.PropertyDefinitionList;
-import org.rhq.core.domain.configuration.definition.PropertyDefinitionMap;
-import org.rhq.core.domain.configuration.definition.PropertyDefinitionSimple;
 
 /**
  * Utility methods for working with {@link Configuration}s.
  *
  * @author Ian Springer
+ * 
+ * @deprecated use the utility found in the domain module -org.rhq.core.domain.configuration.ConfigurationUtility
  */
 public abstract class ConfigurationUtility {
 
@@ -60,21 +49,11 @@ public abstract class ConfigurationUtility {
      * for it, this method is a no-op and will return immediately.
      * 
      * @param configDef the configuration definition whose default template is to be created and set
+     *
+     * @deprecated use the utility found in the domain module -org.rhq.core.domain.configuration.ConfigurationUtility
      */
     public static void initializeDefaultTemplate(ConfigurationDefinition configDef) {
-        ConfigurationTemplate defaultTemplate = configDef.getDefaultTemplate();
-        if (defaultTemplate == null) {
-            Configuration defaultConfig = createDefaultConfiguration(configDef);
-            // not everything should have a default template - only stuff that has default values
-            if (!defaultConfig.getProperties().isEmpty()) {
-                defaultTemplate = new ConfigurationTemplate(ConfigurationTemplate.DEFAULT_TEMPLATE_NAME,
-                    ConfigurationTemplate.DEFAULT_TEMPLATE_NAME);
-                defaultTemplate.setDefault(true);
-                defaultTemplate.setConfiguration(defaultConfig);
-                configDef.putTemplate(defaultTemplate);
-            }
-        }
-        return;
+        org.rhq.core.domain.configuration.ConfigurationUtility.initializeDefaultTemplate(configDef);
     }
 
     /**
@@ -87,17 +66,12 @@ public abstract class ConfigurationUtility {
      * 
      * @param configurationDefinition the configuration definition whose default configuration is to be created
      * @return configuration the default configuration
+     *
+     * @deprecated use the utility found in the domain module -org.rhq.core.domain.configuration.ConfigurationUtility
      */
     public static Configuration createDefaultConfiguration(ConfigurationDefinition configurationDefinition) {
-        if (configurationDefinition == null) {
-            throw new IllegalArgumentException("configurationDefinition == null");
-        }
-        Configuration defaultConfig = new Configuration();
-        Map<String, PropertyDefinition> childPropertyDefinitions = configurationDefinition.getPropertyDefinitions();
-        for (PropertyDefinition childPropertyDefinition : childPropertyDefinitions.values()) {
-            createDefaultProperty(childPropertyDefinition, defaultConfig);
-        }
-        return defaultConfig;
+        return org.rhq.core.domain.configuration.ConfigurationUtility
+            .createDefaultConfiguration(configurationDefinition);
     }
 
     /**
@@ -107,19 +81,13 @@ public abstract class ConfigurationUtility {
      *
      * @param configuration           the configuration to be normalized
      * @param configurationDefinition the configuration definition to normalize the configuration against
+     *
+     * @deprecated use the utility found in the domain module -org.rhq.core.domain.configuration.ConfigurationUtility
      */
     public static void normalizeConfiguration(@NotNull Configuration configuration,
         @Nullable ConfigurationDefinition configurationDefinition) {
-        //noinspection ConstantConditions
-        if (configuration == null) {
-            throw new IllegalArgumentException("Configuration parameter is null.");
-        }
-        if (configurationDefinition != null) {
-            Map<String, PropertyDefinition> childPropertyDefinitions = configurationDefinition.getPropertyDefinitions();
-            for (PropertyDefinition childPropertyDefinition : childPropertyDefinitions.values()) {
-                normalizeProperty(childPropertyDefinition, configuration);
-            }
-        }
+        org.rhq.core.domain.configuration.ConfigurationUtility.normalizeConfiguration(configuration,
+            configurationDefinition, false, false);
     }
 
     /**
@@ -132,191 +100,13 @@ public abstract class ConfigurationUtility {
      * @param  configurationDefinition the configuration definition to validate the configuration against
      *
      * @return a list of messages describing any errors that were found
+     *
+     * @deprecated use the utility found in the domain module -org.rhq.core.domain.configuration.ConfigurationUtility
      */
     @NotNull
     public static List<String> validateConfiguration(@NotNull Configuration configuration,
         @Nullable ConfigurationDefinition configurationDefinition) {
-        List<String> errorMessages = new ArrayList<String>();
-        if (configurationDefinition != null) {
-            Map<String, PropertyDefinition> childPropertyDefinitions = configurationDefinition.getPropertyDefinitions();
-            for (PropertyDefinition childPropertyDefinition : childPropertyDefinitions.values()) {
-                validateProperty(childPropertyDefinition, configuration, errorMessages);
-            }
-        }
-        return errorMessages;
-    }
-
-    private static void createDefaultProperty(PropertyDefinition propertyDefinition,
-        AbstractPropertyMap parentPropertyMap) {
-
-        Property property = null;
-
-        if (propertyDefinition instanceof PropertyDefinitionSimple) {
-            String defaultValue = ((PropertyDefinitionSimple) propertyDefinition).getDefaultValue();
-            if (defaultValue != null || propertyDefinition.isRequired()) {
-                property = new PropertySimple(propertyDefinition.getName(), defaultValue);
-            }
-        } else if (propertyDefinition.isRequired()) {
-            if (propertyDefinition instanceof PropertyDefinitionMap) {
-                property = new PropertyMap(propertyDefinition.getName());
-                Map<String, PropertyDefinition> childPropertyDefinitions = ((PropertyDefinitionMap) propertyDefinition)
-                    .getMap();
-                for (PropertyDefinition childPropertyDefinition : childPropertyDefinitions.values()) {
-                    createDefaultProperty(childPropertyDefinition, (PropertyMap) property);
-                }
-            } else if (propertyDefinition instanceof PropertyDefinitionList) {
-                property = new PropertyList(propertyDefinition.getName());
-                PropertyDefinition listMemberPropertyDefinition = ((PropertyDefinitionList) propertyDefinition)
-                    .getMemberDefinition();
-                if (listMemberPropertyDefinition.isRequired()) {
-                    if (listMemberPropertyDefinition instanceof PropertyDefinitionMap) {
-                        // member property is a list-o-maps, create a default child map if appropriate
-                        PropertyDefinitionMap listMemberDefinitionMap = (PropertyDefinitionMap) listMemberPropertyDefinition;
-                        PropertyMap listMap = new PropertyMap(listMemberDefinitionMap.getName());
-                        createDefaultProperty(listMemberDefinitionMap, listMap);
-                        ((PropertyList) property).add(listMap);
-                    } else if (listMemberPropertyDefinition instanceof PropertyDefinitionSimple) {
-                        // member property is a simple, create a single list entry as its default if appropriate
-                        PropertyDefinitionSimple listMemberDefinitionSimple = (PropertyDefinitionSimple) listMemberPropertyDefinition;
-                        String defaultValue = listMemberDefinitionSimple.getDefaultValue();
-                        if (defaultValue != null || listMemberDefinitionSimple.isRequired()) {
-                            PropertySimple listSimple = new PropertySimple(listMemberDefinitionSimple.getName(),
-                                defaultValue);
-                            ((PropertyList) property).add(listSimple);
-                        }
-                    }
-                }
-            } else if (propertyDefinition instanceof PropertyDefinitionDynamic) {
-                // Dynamic property values should simply be stored as simple
-                property = new PropertySimple(propertyDefinition.getName(), null);
-            } else {
-                throw new IllegalStateException("Unsupported PropertyDefinition subclass: "
-                    + propertyDefinition.getClass().getName());
-            }
-        }
-
-        if (property != null) {
-            parentPropertyMap.put(property);
-        }
-    }
-
-    private static void normalizeProperty(PropertyDefinition propertyDefinition, AbstractPropertyMap parentPropertyMap) {
-        if (parentPropertyMap.getMap().keySet().contains(propertyDefinition.getName())) // property is already set
-        {
-            if (propertyDefinition instanceof PropertyDefinitionSimple) {
-                PropertySimple propertySimple = parentPropertyMap.getSimple(propertyDefinition.getName());
-                String value = propertySimple.getStringValue();
-                if (value != null) {
-                    if (value.equals("")) {
-                        // Normalize "" to null, since Oracle will do the same upon persistence.
-                        propertySimple.setStringValue(null);
-                    } else if (value.length() > PropertySimple.MAX_VALUE_LENGTH) {
-                        // Truncate the value to the max length allowed by the DB schema.
-                        propertySimple.setStringValue(value.substring(0, PropertySimple.MAX_VALUE_LENGTH));
-                    }
-                }
-            }
-
-            // If the property is a Map, recurse into it and normalize its child properties.
-            else if (propertyDefinition instanceof PropertyDefinitionMap) {
-                PropertyMap propertyMap = parentPropertyMap.getMap(propertyDefinition.getName());
-                PropertyDefinitionMap propertyDefinitionMap = (PropertyDefinitionMap) propertyDefinition;
-                normalizePropertyMap(propertyMap, propertyDefinitionMap);
-            } else if (propertyDefinition instanceof PropertyDefinitionList) {
-                PropertyDefinitionList propertyDefinitionList = (PropertyDefinitionList) propertyDefinition;
-                PropertyDefinition listMemberPropertyDefinition = propertyDefinitionList.getMemberDefinition();
-
-                // If the property is a List of Maps, iterate the list, and recurse into each Map and verify its child
-                // properties.
-                if (listMemberPropertyDefinition instanceof PropertyDefinitionMap) {
-                    PropertyDefinitionMap propertyDefinitionMap = (PropertyDefinitionMap) listMemberPropertyDefinition;
-                    PropertyList propertyList = parentPropertyMap.getList(propertyDefinition.getName());
-                    for (Property property : propertyList.getList()) {
-                        PropertyMap propertyMap = (PropertyMap) property;
-                        normalizePropertyMap(propertyMap, propertyDefinitionMap);
-                    }
-                }
-            }
-        } else // property is not set yet
-        {
-            Property property;
-            if (propertyDefinition instanceof PropertyDefinitionSimple) {
-                property = new PropertySimple(propertyDefinition.getName(), null);
-            } else if (propertyDefinition instanceof PropertyDefinitionMap) {
-                property = new PropertyMap(propertyDefinition.getName());
-            } else if (propertyDefinition instanceof PropertyDefinitionList) {
-                property = new PropertyList(propertyDefinition.getName());
-            } else if (propertyDefinition instanceof PropertyDefinitionDynamic) {
-                // Dynamic property values should simply be stored as simple
-                property = new PropertySimple(propertyDefinition.getName(), null);
-            } else {
-                throw new IllegalStateException("Unsupported PropertyDefinition subclass: "
-                    + propertyDefinition.getClass().getName());
-            }
-
-            parentPropertyMap.put(property);
-        }
-    }
-
-    private static void normalizePropertyMap(AbstractPropertyMap propertyMap,
-        PropertyDefinitionMap propertyDefinitionMap) {
-        Map<String, PropertyDefinition> childPropertyDefinitions = propertyDefinitionMap.getMap();
-        for (PropertyDefinition childPropertyDefinition : childPropertyDefinitions.values()) {
-            normalizeProperty(childPropertyDefinition, propertyMap);
-        }
-    }
-
-    private static void validateProperty(PropertyDefinition propertyDefinition, AbstractPropertyMap parentPropertyMap,
-        List<String> errorMessages) {
-        if (parentPropertyMap.getMap().keySet().contains(propertyDefinition.getName())) // property is already set
-        {
-            if (propertyDefinition instanceof PropertyDefinitionSimple) {
-                PropertySimple propertySimple = parentPropertyMap.getSimple(propertyDefinition.getName());
-                if (propertyDefinition.isRequired() && (propertySimple.getStringValue() == null)) {
-                    errorMessages.add("Required property '" + propertyDefinition.getName() + "' has a null value in "
-                        + parentPropertyMap + ".");
-                    propertySimple.setStringValue("");
-                }
-            }
-
-            // If the property is a Map, recurse into it and validate its child properties.
-            else if (propertyDefinition instanceof PropertyDefinitionMap) {
-                PropertyMap propertyMap = parentPropertyMap.getMap(propertyDefinition.getName());
-                PropertyDefinitionMap propertyDefinitionMap = (PropertyDefinitionMap) propertyDefinition;
-                validatePropertyMap(propertyMap, propertyDefinitionMap, errorMessages);
-            } else if (propertyDefinition instanceof PropertyDefinitionList) {
-                PropertyDefinitionList propertyDefinitionList = (PropertyDefinitionList) propertyDefinition;
-                PropertyDefinition listMemberPropertyDefinition = propertyDefinitionList.getMemberDefinition();
-
-                // If the property is a List of Maps, iterate the list, and recurse into each Map and validate its child
-                // properties.
-                if (listMemberPropertyDefinition instanceof PropertyDefinitionMap) {
-                    PropertyDefinitionMap propertyDefinitionMap = (PropertyDefinitionMap) listMemberPropertyDefinition;
-                    PropertyList propertyList = parentPropertyMap.getList(propertyDefinition.getName());
-                    for (Property property : propertyList.getList()) {
-                        PropertyMap propertyMap = (PropertyMap) property;
-                        validatePropertyMap(propertyMap, propertyDefinitionMap, errorMessages);
-                    }
-                }
-            }
-        } else // property is not set yet
-        {
-            if (propertyDefinition.isRequired()) {
-                errorMessages.add("Required property '" + propertyDefinition.getName() + "' was not set in "
-                    + parentPropertyMap + ".");
-                if (propertyDefinition instanceof PropertyDefinitionSimple) {
-                    PropertySimple propertySimple = new PropertySimple(propertyDefinition.getName(), "");
-                    parentPropertyMap.put(propertySimple);
-                }
-            }
-        }
-    }
-
-    private static void validatePropertyMap(AbstractPropertyMap propertyMap,
-        PropertyDefinitionMap propertyDefinitionMap, List<String> errorMessages) {
-        Map<String, PropertyDefinition> childPropertyDefinitions = propertyDefinitionMap.getMap();
-        for (PropertyDefinition childPropertyDefinition : childPropertyDefinitions.values()) {
-            validateProperty(childPropertyDefinition, propertyMap, errorMessages);
-        }
+        return org.rhq.core.domain.configuration.ConfigurationUtility.validateConfiguration(configuration,
+            configurationDefinition);
     }
 }
\ No newline at end of file
diff --git a/modules/core/client-api/src/test/java/org/rhq/core/clientapi/agent/configuration/ConfigurationUtilityTest.java b/modules/core/client-api/src/test/java/org/rhq/core/clientapi/agent/configuration/ConfigurationUtilityTest.java
deleted file mode 100644
index 3f3dccd..0000000
--- a/modules/core/client-api/src/test/java/org/rhq/core/clientapi/agent/configuration/ConfigurationUtilityTest.java
+++ /dev/null
@@ -1,322 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2010 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.core.clientapi.agent.configuration;
-
-import org.testng.annotations.Test;
-
-import org.rhq.core.domain.configuration.Configuration;
-import org.rhq.core.domain.configuration.PropertyList;
-import org.rhq.core.domain.configuration.PropertyMap;
-import org.rhq.core.domain.configuration.PropertySimple;
-import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
-import org.rhq.core.domain.configuration.definition.PropertyDefinitionList;
-import org.rhq.core.domain.configuration.definition.PropertyDefinitionMap;
-import org.rhq.core.domain.configuration.definition.PropertyDefinitionSimple;
-import org.rhq.core.domain.configuration.definition.PropertySimpleType;
-
- at Test
-public class ConfigurationUtilityTest {
-    public void testCreateDefaultNone() {
-        // no defaults, no required props - returned config should be empty
-        ConfigurationDefinition configDef = new ConfigurationDefinition("foo", null);
-
-        PropertyDefinitionSimple simple = new PropertyDefinitionSimple("simple", null, false, PropertySimpleType.STRING);
-        PropertyDefinitionMap map = new PropertyDefinitionMap("map", null, false, simple);
-        PropertyDefinitionList list = new PropertyDefinitionList("list", null, false, simple);
-
-        configDef.put(simple);
-        configDef.put(map);
-        configDef.put(list);
-
-        Configuration config = ConfigurationUtility.createDefaultConfiguration(configDef);
-        assert config != null;
-        assert config.getProperties().size() == 0;
-    }
-
-    public void testCreateDefaultSimple() {
-        ConfigurationDefinition configDef = new ConfigurationDefinition("foo", null);
-
-        PropertyDefinitionSimple simple = new PropertyDefinitionSimple("simple", null, false, PropertySimpleType.STRING);
-        PropertyDefinitionSimple simpleRequired = new PropertyDefinitionSimple("simpleRequired", null, true,
-            PropertySimpleType.STRING);
-        PropertyDefinitionSimple simpleDefault = new PropertyDefinitionSimple("simpleDefault", null, false,
-            PropertySimpleType.STRING);
-        PropertyDefinitionSimple simpleRequiredDefault = new PropertyDefinitionSimple("simpleRequiredDefault", null,
-            true, PropertySimpleType.STRING);
-
-        simpleDefault.setDefaultValue("!!simpleDefaultValue!!");
-        simpleRequiredDefault.setDefaultValue("!!simpleRequiredDefaultValue!!");
-
-        configDef.put(simple);
-        configDef.put(simpleRequired);
-        configDef.put(simpleDefault);
-        configDef.put(simpleRequiredDefault);
-
-        Configuration config = ConfigurationUtility.createDefaultConfiguration(configDef);
-        assert config != null;
-        assert config.getProperties().size() == 3; // simple is not required with no default - its not in the config
-        assert config.getSimple(simple.getName()) == null;
-        assert config.getSimpleValue(simpleRequired.getName(), null) == null;
-        assert config.getSimpleValue(simpleDefault.getName(), null).equals("!!simpleDefaultValue!!");
-        assert config.getSimpleValue(simpleRequiredDefault.getName(), null).equals("!!simpleRequiredDefaultValue!!");
-    }
-
-    public void testCreateDefaultMap() {
-        ConfigurationDefinition configDef = new ConfigurationDefinition("foo", null);
-
-        // a=not required, no default; c=not required, has default; d=required, has default
-        PropertyDefinitionSimple a = new PropertyDefinitionSimple("a", null, false, PropertySimpleType.STRING);
-        PropertyDefinitionSimple b = new PropertyDefinitionSimple("b", null, false, PropertySimpleType.STRING);
-        PropertyDefinitionSimple c = new PropertyDefinitionSimple("c", null, true, PropertySimpleType.STRING);
-        b.setDefaultValue("!!bDefaultValue!!");
-        c.setDefaultValue("!!cDefaultValue!!");
-
-        PropertyDefinitionMap map1 = new PropertyDefinitionMap("map1", null, false, a, b, c);
-        PropertyDefinitionMap mapRequired1 = new PropertyDefinitionMap("mapRequired1", null, true, a, b, c);
-        PropertyDefinitionMap mapRequiredDefault1 = new PropertyDefinitionMap("mapRequiredDefault1", null, true, a, b,
-            c);
-
-        configDef.put(map1);
-        configDef.put(mapRequired1);
-        configDef.put(mapRequiredDefault1);
-
-        Configuration config = ConfigurationUtility.createDefaultConfiguration(configDef);
-        assert config != null;
-        assert config.getProperties().size() == 2; // map is not required with no default - its not in the config
-        assert config.getMap(map1.getName()) == null;
-
-        // the two required maps have the same definitions - a,b,c as above. since a isn't required with no default, its not there
-        PropertyMap mapProp1 = config.getMap(mapRequired1.getName());
-        assert mapProp1 != null;
-        assert mapProp1.getSimple(a.getName()) == null;
-        assert mapProp1.getSimpleValue(b.getName(), null).equals("!!bDefaultValue!!");
-        assert mapProp1.getSimpleValue(c.getName(), null).equals("!!cDefaultValue!!");
-
-        mapProp1 = config.getMap(mapRequiredDefault1.getName());
-        assert mapProp1 != null;
-        assert mapProp1.getSimple(a.getName()) == null;
-        assert mapProp1.getSimpleValue(b.getName(), null).equals("!!bDefaultValue!!");
-        assert mapProp1.getSimpleValue(c.getName(), null).equals("!!cDefaultValue!!");
-    }
-
-    public void testCreateDefaultList() {
-        ConfigurationDefinition configDef = new ConfigurationDefinition("foo", null);
-
-        // a=not required, no default, b=required, has default
-        PropertyDefinitionSimple a = new PropertyDefinitionSimple("a", null, false, PropertySimpleType.STRING);
-        PropertyDefinitionSimple c = new PropertyDefinitionSimple("c", null, true, PropertySimpleType.STRING);
-        c.setDefaultValue("!!cDefaultValue!!");
-
-        PropertyDefinitionList list1 = new PropertyDefinitionList("list1", null, false, a);
-        PropertyDefinitionList listRequired1 = new PropertyDefinitionList("listRequired1", null, true, a);
-        PropertyDefinitionList listRequiredDefault1 = new PropertyDefinitionList("listRequiredDefault1", null, true, c);
-
-        configDef.put(list1);
-        configDef.put(listRequired1);
-        configDef.put(listRequiredDefault1);
-
-        Configuration config = ConfigurationUtility.createDefaultConfiguration(configDef);
-        assert config != null;
-        assert config.getProperties().size() == 2; // list is not required with no default - its not in the config
-        assert config.getList(list1.getName()) == null;
-
-        PropertyList listProp1 = config.getList(listRequired1.getName());
-        assert listProp1 != null;
-        assert listProp1.getList().isEmpty(); // has "a" definition, which is not required and has no default
-
-        listProp1 = config.getList(listRequiredDefault1.getName());
-        assert listProp1 != null;
-        assert listProp1.getList().get(0).getName().equals(c.getName());
-        assert ((PropertySimple) listProp1.getList().get(0)).getStringValue().equals("!!cDefaultValue!!");
-    }
-
-    public void testCreateDefaultListOMaps() {
-        ConfigurationDefinition configDef = new ConfigurationDefinition("foo", null);
-
-        // a=not required, no default; c=not required, has default; d=required, has default
-        PropertyDefinitionSimple a = new PropertyDefinitionSimple("a", null, false, PropertySimpleType.STRING);
-        PropertyDefinitionSimple b = new PropertyDefinitionSimple("b", null, false, PropertySimpleType.STRING);
-        PropertyDefinitionSimple c = new PropertyDefinitionSimple("c", null, true, PropertySimpleType.STRING);
-        b.setDefaultValue("!!bDefaultValue!!");
-        c.setDefaultValue("!!cDefaultValue!!");
-
-        PropertyDefinitionMap map2 = new PropertyDefinitionMap("map2", null, false, a, b, c);
-        PropertyDefinitionMap mapRequired2 = new PropertyDefinitionMap("mapRequired2", null, true, a, b, c);
-        PropertyDefinitionMap mapRequiredDefault2 = new PropertyDefinitionMap("mapRequiredDefault2", null, true, a, b,
-            c);
-
-        PropertyDefinitionList listX = new PropertyDefinitionList("listX", null, true, map2);
-        PropertyDefinitionList listY = new PropertyDefinitionList("listY", null, true, mapRequired2);
-        PropertyDefinitionList listZ = new PropertyDefinitionList("listZ", null, true, mapRequiredDefault2);
-
-        configDef.put(listX);
-        configDef.put(listY);
-        configDef.put(listZ);
-
-        Configuration config = ConfigurationUtility.createDefaultConfiguration(configDef);
-
-        assert config != null;
-        assert config.getProperties().size() == 3;
-
-        PropertyList listPropTest = config.getList(listX.getName());
-        assert listPropTest != null;
-        assert listPropTest.getList().isEmpty();
-
-        listPropTest = config.getList(listY.getName());
-        assert listPropTest != null;
-        PropertyMap childMap2 = (PropertyMap) listPropTest.getList().get(0);
-
-        listPropTest = config.getList(listZ.getName());
-        assert listPropTest != null;
-        PropertyMap childMap3 = (PropertyMap) listPropTest.getList().get(0);
-
-        assert childMap2.getName().equals(mapRequired2.getName());
-        assert childMap3.getName().equals(mapRequiredDefault2.getName());
-    }
-
-    public void testCreateDefaultAllSimpleMapList() {
-        // tests a big config def that has simples, lists, maps - combination of the other individual tests
-        ConfigurationDefinition configDef = new ConfigurationDefinition("foo", null);
-
-        // SETUP SIMPLE
-
-        PropertyDefinitionSimple simple = new PropertyDefinitionSimple("simple", null, false, PropertySimpleType.STRING);
-        PropertyDefinitionSimple simpleRequired = new PropertyDefinitionSimple("simpleRequired", null, true,
-            PropertySimpleType.STRING);
-        PropertyDefinitionSimple simpleDefault = new PropertyDefinitionSimple("simpleDefault", null, false,
-            PropertySimpleType.STRING);
-        PropertyDefinitionSimple simpleRequiredDefault = new PropertyDefinitionSimple("simpleRequiredDefault", null,
-            true, PropertySimpleType.STRING);
-
-        simpleDefault.setDefaultValue("!!simpleDefaultValue!!");
-        simpleRequiredDefault.setDefaultValue("!!simpleRequiredDefaultValue!!");
-
-        configDef.put(simple);
-        configDef.put(simpleRequired);
-        configDef.put(simpleDefault);
-        configDef.put(simpleRequiredDefault);
-
-        // SETUP MAP
-
-        // a=not required, no default; c=not required, has default; d=required, has default
-        PropertyDefinitionSimple a = new PropertyDefinitionSimple("a", null, false, PropertySimpleType.STRING);
-        PropertyDefinitionSimple b = new PropertyDefinitionSimple("b", null, false, PropertySimpleType.STRING);
-        PropertyDefinitionSimple c = new PropertyDefinitionSimple("c", null, true, PropertySimpleType.STRING);
-        b.setDefaultValue("!!bDefaultValue!!");
-        c.setDefaultValue("!!cDefaultValue!!");
-
-        PropertyDefinitionMap map1 = new PropertyDefinitionMap("map1", null, false, a, b, c);
-        PropertyDefinitionMap mapRequired1 = new PropertyDefinitionMap("mapRequired1", null, true, a, b, c);
-        PropertyDefinitionMap mapRequiredDefault1 = new PropertyDefinitionMap("mapRequiredDefault1", null, true, a, b,
-            c);
-
-        configDef.put(map1);
-        configDef.put(mapRequired1);
-        configDef.put(mapRequiredDefault1);
-
-        // SETUP LIST
-
-        PropertyDefinitionList list1 = new PropertyDefinitionList("list1", null, false, a);
-        PropertyDefinitionList listRequired1 = new PropertyDefinitionList("listRequired1", null, true, a);
-        PropertyDefinitionList listRequiredDefault1 = new PropertyDefinitionList("listRequiredDefault1", null, true, c);
-
-        configDef.put(list1);
-        configDef.put(listRequired1);
-        configDef.put(listRequiredDefault1);
-
-        // SETUP LIST-O-MAPS
-
-        PropertyDefinitionMap map2 = new PropertyDefinitionMap("map2", null, false, a, b, c);
-        PropertyDefinitionMap mapRequired2 = new PropertyDefinitionMap("mapRequired2", null, true, a, b, c);
-        PropertyDefinitionMap mapRequiredDefault2 = new PropertyDefinitionMap("mapRequiredDefault2", null, true, a, b,
-            c);
-
-        PropertyDefinitionList listX = new PropertyDefinitionList("listX", null, true, map2);
-        PropertyDefinitionList listY = new PropertyDefinitionList("listY", null, true, mapRequired2);
-        PropertyDefinitionList listZ = new PropertyDefinitionList("listZ", null, true, mapRequiredDefault2);
-
-        configDef.put(listX);
-        configDef.put(listY);
-        configDef.put(listZ);
-
-        // get the default config
-        Configuration config = ConfigurationUtility.createDefaultConfiguration(configDef);
-        assert config != null;
-        assert config.getProperties().size() == 10;
-
-        // ASSERT SIMPLE
-
-        assert config.getSimple(simple.getName()) == null;
-        assert config.getSimpleValue(simpleRequired.getName(), null) == null;
-        assert config.getSimpleValue(simpleDefault.getName(), null).equals("!!simpleDefaultValue!!");
-        assert config.getSimpleValue(simpleRequiredDefault.getName(), null).equals("!!simpleRequiredDefaultValue!!");
-
-        // ASSERT MAP
-
-        assert config.getMap(map1.getName()) == null;
-
-        // the two required maps have the same definitions - a,b,c as above. since a isn't required with no default, its not there
-        PropertyMap mapProp1 = config.getMap(mapRequired1.getName());
-        assert mapProp1 != null;
-        assert mapProp1.getSimple(a.getName()) == null;
-        assert mapProp1.getSimpleValue(b.getName(), null).equals("!!bDefaultValue!!");
-        assert mapProp1.getSimpleValue(c.getName(), null).equals("!!cDefaultValue!!");
-
-        mapProp1 = config.getMap(mapRequiredDefault1.getName());
-        assert mapProp1 != null;
-        assert mapProp1.getSimple(a.getName()) == null;
-        assert mapProp1.getSimpleValue(b.getName(), null).equals("!!bDefaultValue!!");
-        assert mapProp1.getSimpleValue(c.getName(), null).equals("!!cDefaultValue!!");
-
-        // ASSERT LIST
-
-        assert config.getList(list1.getName()) == null;
-
-        PropertyList listProp1 = config.getList(listRequired1.getName());
-        assert listProp1 != null;
-        assert listProp1.getList().isEmpty(); // has "a" definition, which is not required and has no default
-
-        listProp1 = config.getList(listRequiredDefault1.getName());
-        assert listProp1 != null;
-        assert listProp1.getList().get(0).getName().equals(c.getName());
-        assert ((PropertySimple) listProp1.getList().get(0)).getStringValue().equals("!!cDefaultValue!!");
-
-        // ASSERT LIST-O-MAPS
-
-        PropertyList listPropTest = config.getList(listX.getName());
-        assert listPropTest != null;
-        assert listPropTest.getList().isEmpty();
-
-        listPropTest = config.getList(listY.getName());
-        assert listPropTest != null;
-        PropertyMap childMap2 = (PropertyMap) listPropTest.getList().get(0);
-
-        listPropTest = config.getList(listZ.getName());
-        assert listPropTest != null;
-        PropertyMap childMap3 = (PropertyMap) listPropTest.getList().get(0);
-
-        assert childMap2.getName().equals(mapRequired2.getName());
-        assert childMap3.getName().equals(mapRequiredDefault2.getName());
-    }
-}
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/ConfigurationUtility.java b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/ConfigurationUtility.java
new file mode 100644
index 0000000..1c32526
--- /dev/null
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/ConfigurationUtility.java
@@ -0,0 +1,334 @@
+/*
+ * 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, 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.core.domain.configuration;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
+import org.rhq.core.domain.configuration.definition.ConfigurationTemplate;
+import org.rhq.core.domain.configuration.definition.PropertyDefinition;
+import org.rhq.core.domain.configuration.definition.PropertyDefinitionList;
+import org.rhq.core.domain.configuration.definition.PropertyDefinitionMap;
+import org.rhq.core.domain.configuration.definition.PropertyDefinitionSimple;
+
+/**
+ * Utility methods for working with {@link Configuration}s.
+ *
+ * @author Ian Springer
+ */
+public abstract class ConfigurationUtility {
+
+    /**
+     * This will populate the given configuration definition with a default template.
+     * A default template will only be created if one or more properties are required
+     * or have default values. If no property definition is required or has a default value,
+     * the default template will remain <code>null</code> in the given config definition.
+     * 
+     * Note that if the given configuration definition already has a default template defined
+     * for it, this method is a no-op and will return immediately.
+     * 
+     * @param configDef the configuration definition whose default template is to be created and set
+     */
+    public static void initializeDefaultTemplate(ConfigurationDefinition configDef) {
+        ConfigurationTemplate defaultTemplate = configDef.getDefaultTemplate();
+        if (defaultTemplate == null) {
+            Configuration defaultConfig = createDefaultConfiguration(configDef);
+            // not everything should have a default template - only stuff that has default values
+            if (!defaultConfig.getProperties().isEmpty()) {
+                defaultTemplate = new ConfigurationTemplate(ConfigurationTemplate.DEFAULT_TEMPLATE_NAME,
+                    ConfigurationTemplate.DEFAULT_TEMPLATE_NAME);
+                defaultTemplate.setDefault(true);
+                defaultTemplate.setConfiguration(defaultConfig);
+                configDef.putTemplate(defaultTemplate);
+            }
+        }
+        return;
+    }
+
+    /**
+     * Given a configuration definition, this will build and return a "default configuration" that
+     * can be validated with the definition. All required properties are set and all properties
+     * that define a default value are also set. If a required property does not have a default
+     * value defined in the definition, the property value will be set to <code>null</code>.
+     *
+     * Use this to help create the definition's default template.
+     * 
+     * @param configurationDefinition the configuration definition whose default configuration is to be created
+     * @return configuration the default configuration
+     */
+    public static Configuration createDefaultConfiguration(ConfigurationDefinition configurationDefinition) {
+        if (configurationDefinition == null) {
+            throw new IllegalArgumentException("configurationDefinition == null");
+        }
+        Configuration defaultConfig = new Configuration();
+        Map<String, PropertyDefinition> childPropertyDefinitions = configurationDefinition.getPropertyDefinitions();
+        for (PropertyDefinition childPropertyDefinition : childPropertyDefinitions.values()) {
+            createDefaultProperty(childPropertyDefinition, defaultConfig);
+        }
+        return defaultConfig;
+    }
+
+    /**
+     * "Normalize" the given configuration according to the given configuration definition. That is, for any optional
+     * properties that are not defined in the top-level configuration Map or any sub-Maps, set them.
+     * Map properties are set with an empty Map, and List properties with an empty List. By default, simple
+     * properties that are missing will be created and set with a null value. However, if normalizeRequiredDefaults is true,
+     * and a simple property is required with a default, this will set the required property to that default value.
+     * If normalizeOptionalDefaults is true, and a simple property is not required but has a default, this will set the
+     * optional property to that default. If a simple property does not have a default defined, no matter what those
+     * "normalize" booleans are, the simple property will still be set to null since this method won't know what value
+     * to set it to anyway.
+     *
+     * @param configuration             the configuration to be normalized (must not be null)
+     * @param configurationDefinition   the configuration definition to normalize the configuration against (may be null)
+     * @param normalizeRequiredDefaults if true, and a property is required, its default will be set as that property's value
+     * @param normalizeOptionalDefaults if true, and a property is optional, its default will be set as that property's value
+     */
+    public static void normalizeConfiguration(Configuration configuration,
+        ConfigurationDefinition configurationDefinition, boolean normalizeRequiredDefaults,
+        boolean normalizeOptionalDefaults) {
+        if (configuration == null) {
+            throw new IllegalArgumentException("Configuration parameter is null.");
+        }
+        if (configurationDefinition != null) {
+            Map<String, PropertyDefinition> childPropertyDefinitions = configurationDefinition.getPropertyDefinitions();
+            for (PropertyDefinition childPropertyDefinition : childPropertyDefinitions.values()) {
+                normalizeProperty(childPropertyDefinition, configuration, normalizeRequiredDefaults,
+                    normalizeOptionalDefaults);
+            }
+        }
+    }
+
+    /**
+     * Validate the given configuration according to the given configuration definition. That is, check that any
+     * required properties in the top-level configuration Map or any sub-Maps, are defined and, in the case of simple
+     * properties, check that they have a non-null value. A list of messages describing any errors that were found is
+     * returned. Additionally, any undefined or null simple properties will be assigned a value of "".
+     *
+     * @param  configuration           the configuration to be validated (must not be null)
+     * @param  configurationDefinition the configuration definition to validate the configuration against (may be null)
+     *
+     * @return a list of messages describing any errors that were found - will be empty if there are no messagse
+     */
+    public static List<String> validateConfiguration(Configuration configuration,
+        ConfigurationDefinition configurationDefinition) {
+        List<String> errorMessages = new ArrayList<String>();
+        if (configurationDefinition != null) {
+            Map<String, PropertyDefinition> childPropertyDefinitions = configurationDefinition.getPropertyDefinitions();
+            for (PropertyDefinition childPropertyDefinition : childPropertyDefinitions.values()) {
+                validateProperty(childPropertyDefinition, configuration, errorMessages);
+            }
+        }
+        return errorMessages;
+    }
+
+    private static void createDefaultProperty(PropertyDefinition propertyDefinition,
+        AbstractPropertyMap parentPropertyMap) {
+
+        Property property = null;
+
+        if (propertyDefinition instanceof PropertyDefinitionSimple) {
+            String defaultValue = ((PropertyDefinitionSimple) propertyDefinition).getDefaultValue();
+            if (defaultValue != null || propertyDefinition.isRequired()) {
+                property = new PropertySimple(propertyDefinition.getName(), defaultValue);
+            }
+        } else if (propertyDefinition.isRequired()) {
+            if (propertyDefinition instanceof PropertyDefinitionMap) {
+                property = new PropertyMap(propertyDefinition.getName());
+                Map<String, PropertyDefinition> childPropertyDefinitions = ((PropertyDefinitionMap) propertyDefinition)
+                    .getMap();
+                for (PropertyDefinition childPropertyDefinition : childPropertyDefinitions.values()) {
+                    createDefaultProperty(childPropertyDefinition, (PropertyMap) property);
+                }
+            } else if (propertyDefinition instanceof PropertyDefinitionList) {
+                property = new PropertyList(propertyDefinition.getName());
+                PropertyDefinition listMemberPropertyDefinition = ((PropertyDefinitionList) propertyDefinition)
+                    .getMemberDefinition();
+                if (listMemberPropertyDefinition.isRequired()) {
+                    if (listMemberPropertyDefinition instanceof PropertyDefinitionMap) {
+                        // member property is a list-o-maps, create a default child map if appropriate
+                        PropertyDefinitionMap listMemberDefinitionMap = (PropertyDefinitionMap) listMemberPropertyDefinition;
+                        PropertyMap listMap = new PropertyMap(listMemberDefinitionMap.getName());
+                        createDefaultProperty(listMemberDefinitionMap, listMap);
+                        ((PropertyList) property).add(listMap);
+                    } else if (listMemberPropertyDefinition instanceof PropertyDefinitionSimple) {
+                        // member property is a simple, create a single list entry as its default if appropriate
+                        PropertyDefinitionSimple listMemberDefinitionSimple = (PropertyDefinitionSimple) listMemberPropertyDefinition;
+                        String defaultValue = listMemberDefinitionSimple.getDefaultValue();
+                        if (defaultValue != null || listMemberDefinitionSimple.isRequired()) {
+                            PropertySimple listSimple = new PropertySimple(listMemberDefinitionSimple.getName(),
+                                defaultValue);
+                            ((PropertyList) property).add(listSimple);
+                        }
+                    }
+                }
+            } else if (propertyDefinition instanceof PropertyDefinitionDynamic) {
+                // Dynamic property values should simply be stored as simple
+                property = new PropertySimple(propertyDefinition.getName(), null);
+            } else {
+                throw new IllegalStateException("Unsupported PropertyDefinition subclass: "
+                    + propertyDefinition.getClass().getName());
+            }
+        }
+
+        if (property != null) {
+            parentPropertyMap.put(property);
+        }
+    }
+
+    private static void normalizeProperty(PropertyDefinition propertyDefinition, AbstractPropertyMap parentPropertyMap,
+        boolean normalizeRequiredDefaults, boolean normalizeOptionalDefaults) {
+        if (parentPropertyMap.getMap().keySet().contains(propertyDefinition.getName())) // property is already set
+        {
+            if (propertyDefinition instanceof PropertyDefinitionSimple) {
+                PropertySimple propertySimple = parentPropertyMap.getSimple(propertyDefinition.getName());
+                String value = propertySimple.getStringValue();
+                if (value != null) {
+                    if (value.equals("")) {
+                        // Normalize "" to null, since Oracle will do the same upon persistence.
+                        propertySimple.setStringValue(null);
+                    } else if (value.length() > PropertySimple.MAX_VALUE_LENGTH) {
+                        // Truncate the value to the max length allowed by the DB schema.
+                        propertySimple.setStringValue(value.substring(0, PropertySimple.MAX_VALUE_LENGTH));
+                    }
+                }
+            }
+
+            // If property is a Map, recurse into it and normalize its child properties.
+            else if (propertyDefinition instanceof PropertyDefinitionMap) {
+                PropertyMap propertyMap = parentPropertyMap.getMap(propertyDefinition.getName());
+                PropertyDefinitionMap propertyDefinitionMap = (PropertyDefinitionMap) propertyDefinition;
+                normalizePropertyMap(propertyMap, propertyDefinitionMap, false, false); // TODO do we want to pass normalizeRequired/OptionalDefaults?
+            } else if (propertyDefinition instanceof PropertyDefinitionList) {
+                PropertyDefinitionList propertyDefinitionList = (PropertyDefinitionList) propertyDefinition;
+                PropertyDefinition listMemberPropertyDefinition = propertyDefinitionList.getMemberDefinition();
+
+                // If property is a List of Maps, iterate the list and recurse into each Map and normalize its child properties.
+                if (listMemberPropertyDefinition instanceof PropertyDefinitionMap) {
+                    PropertyDefinitionMap propertyDefinitionMap = (PropertyDefinitionMap) listMemberPropertyDefinition;
+                    PropertyList propertyList = parentPropertyMap.getList(propertyDefinition.getName());
+                    for (Property property : propertyList.getList()) {
+                        PropertyMap propertyMap = (PropertyMap) property;
+                        normalizePropertyMap(propertyMap, propertyDefinitionMap, false, false); // TODO do we want to pass normalizeRequired/OptionalDefaults?
+                    }
+                }
+            }
+        } else // property is not set yet
+        {
+            Property property;
+            if (propertyDefinition instanceof PropertyDefinitionSimple) {
+                String value = null;
+                if (normalizeRequiredDefaults || normalizeOptionalDefaults) {
+                    if (propertyDefinition.isRequired()) {
+                        if (normalizeRequiredDefaults) {
+                            value = ((PropertyDefinitionSimple) propertyDefinition).getDefaultValue();
+                        }
+                    } else {
+                        if (normalizeOptionalDefaults) {
+                            value = ((PropertyDefinitionSimple) propertyDefinition).getDefaultValue();
+                        }
+                    }
+                }
+                property = new PropertySimple(propertyDefinition.getName(), value);
+            } else if (propertyDefinition instanceof PropertyDefinitionMap) {
+                property = new PropertyMap(propertyDefinition.getName());
+            } else if (propertyDefinition instanceof PropertyDefinitionList) {
+                property = new PropertyList(propertyDefinition.getName());
+            } else if (propertyDefinition instanceof PropertyDefinitionDynamic) {
+                // Dynamic property values should simply be stored as simple
+                property = new PropertySimple(propertyDefinition.getName(), null);
+            } else {
+                throw new IllegalStateException("Unsupported PropertyDefinition subclass: "
+                    + propertyDefinition.getClass().getName());
+            }
+
+            parentPropertyMap.put(property);
+        }
+    }
+
+    private static void normalizePropertyMap(AbstractPropertyMap propertyMap,
+        PropertyDefinitionMap propertyDefinitionMap, boolean normalizeRequiredDefaults,
+        boolean normalizeOptionalDefaults) {
+        Map<String, PropertyDefinition> childPropertyDefinitions = propertyDefinitionMap.getMap();
+        for (PropertyDefinition childPropertyDefinition : childPropertyDefinitions.values()) {
+            normalizeProperty(childPropertyDefinition, propertyMap, normalizeRequiredDefaults,
+                normalizeOptionalDefaults);
+        }
+    }
+
+    private static void validateProperty(PropertyDefinition propertyDefinition, AbstractPropertyMap parentPropertyMap,
+        List<String> errorMessages) {
+        if (parentPropertyMap.getMap().keySet().contains(propertyDefinition.getName())) // property is already set
+        {
+            if (propertyDefinition instanceof PropertyDefinitionSimple) {
+                PropertySimple propertySimple = parentPropertyMap.getSimple(propertyDefinition.getName());
+                if (propertyDefinition.isRequired() && (propertySimple.getStringValue() == null)) {
+                    errorMessages.add("Required property '" + propertyDefinition.getName() + "' has a null value in "
+                        + parentPropertyMap + ".");
+                    propertySimple.setStringValue("");
+                }
+            }
+
+            // If the property is a Map, recurse into it and validate its child properties.
+            else if (propertyDefinition instanceof PropertyDefinitionMap) {
+                PropertyMap propertyMap = parentPropertyMap.getMap(propertyDefinition.getName());
+                PropertyDefinitionMap propertyDefinitionMap = (PropertyDefinitionMap) propertyDefinition;
+                validatePropertyMap(propertyMap, propertyDefinitionMap, errorMessages);
+            } else if (propertyDefinition instanceof PropertyDefinitionList) {
+                PropertyDefinitionList propertyDefinitionList = (PropertyDefinitionList) propertyDefinition;
+                PropertyDefinition listMemberPropertyDefinition = propertyDefinitionList.getMemberDefinition();
+
+                // If the property is a List of Maps, iterate the list, and recurse into each Map and validate its child
+                // properties.
+                if (listMemberPropertyDefinition instanceof PropertyDefinitionMap) {
+                    PropertyDefinitionMap propertyDefinitionMap = (PropertyDefinitionMap) listMemberPropertyDefinition;
+                    PropertyList propertyList = parentPropertyMap.getList(propertyDefinition.getName());
+                    for (Property property : propertyList.getList()) {
+                        PropertyMap propertyMap = (PropertyMap) property;
+                        validatePropertyMap(propertyMap, propertyDefinitionMap, errorMessages);
+                    }
+                }
+            }
+        } else // property is not set yet
+        {
+            if (propertyDefinition.isRequired()) {
+                errorMessages.add("Required property '" + propertyDefinition.getName() + "' was not set in "
+                    + parentPropertyMap + ".");
+                if (propertyDefinition instanceof PropertyDefinitionSimple) {
+                    PropertySimple propertySimple = new PropertySimple(propertyDefinition.getName(), "");
+                    parentPropertyMap.put(propertySimple);
+                }
+            }
+        }
+    }
+
+    private static void validatePropertyMap(AbstractPropertyMap propertyMap,
+        PropertyDefinitionMap propertyDefinitionMap, List<String> errorMessages) {
+        Map<String, PropertyDefinition> childPropertyDefinitions = propertyDefinitionMap.getMap();
+        for (PropertyDefinition childPropertyDefinition : childPropertyDefinitions.values()) {
+            validateProperty(childPropertyDefinition, propertyMap, errorMessages);
+        }
+    }
+}
\ No newline at end of file
diff --git a/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/ConfigurationUtilityTest.java b/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/ConfigurationUtilityTest.java
new file mode 100644
index 0000000..7c49296
--- /dev/null
+++ b/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/ConfigurationUtilityTest.java
@@ -0,0 +1,363 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2010 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.core.domain.configuration;
+
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
+import org.rhq.core.domain.configuration.definition.PropertyDefinitionList;
+import org.rhq.core.domain.configuration.definition.PropertyDefinitionMap;
+import org.rhq.core.domain.configuration.definition.PropertyDefinitionSimple;
+import org.rhq.core.domain.configuration.definition.PropertySimpleType;
+
+ at Test
+public class ConfigurationUtilityTest {
+    public void testNormalizeDefaultSimple() {
+        ConfigurationDefinition configDef = new ConfigurationDefinition("foo", null);
+
+        PropertyDefinitionSimple simple = new PropertyDefinitionSimple("simple", null, false, PropertySimpleType.STRING);
+        PropertyDefinitionSimple simpleRequired = new PropertyDefinitionSimple("simpleRequired", null, true,
+            PropertySimpleType.STRING);
+        PropertyDefinitionSimple simpleDefault = new PropertyDefinitionSimple("simpleDefault", null, false,
+            PropertySimpleType.STRING);
+        PropertyDefinitionSimple simpleRequiredDefault = new PropertyDefinitionSimple("simpleRequiredDefault", null,
+            true, PropertySimpleType.STRING);
+
+        simpleDefault.setDefaultValue("!!simpleDefaultValue!!");
+        simpleRequiredDefault.setDefaultValue("!!simpleRequiredDefaultValue!!");
+
+        configDef.put(simple);
+        configDef.put(simpleRequired);
+        configDef.put(simpleDefault);
+        configDef.put(simpleRequiredDefault);
+
+        // test normalization
+        Configuration config = new Configuration();
+        ConfigurationUtility.normalizeConfiguration(config, configDef, false, false);
+        assert config.getProperties().size() == 4;
+        assert config.getSimpleValue(simple.getName(), null) == null;
+        assert config.getSimpleValue(simpleRequired.getName(), null) == null;
+        assert config.getSimpleValue(simpleDefault.getName(), null) == null;
+        assert config.getSimpleValue(simpleRequiredDefault.getName(), null) == null;
+
+        config = new Configuration();
+        ConfigurationUtility.normalizeConfiguration(config, configDef, true, false);
+        assert config.getProperties().size() == 4;
+        assert config.getSimpleValue(simple.getName(), null) == null;
+        assert config.getSimpleValue(simpleRequired.getName(), null) == null; // there is no default, so nothing to set
+        assert config.getSimpleValue(simpleDefault.getName(), null) == null;
+        assert config.getSimpleValue(simpleRequiredDefault.getName(), null).equals("!!simpleRequiredDefaultValue!!");
+
+        config = new Configuration();
+        ConfigurationUtility.normalizeConfiguration(config, configDef, false, true);
+        assert config.getProperties().size() == 4;
+        assert config.getSimpleValue(simple.getName(), null) == null; // there is no default, so nothing to set
+        assert config.getSimpleValue(simpleRequired.getName(), null) == null;
+        assert config.getSimpleValue(simpleDefault.getName(), null).equals("!!simpleDefaultValue!!");
+        assert config.getSimpleValue(simpleRequiredDefault.getName(), null) == null;
+    }
+
+    public void testCreateDefaultNone() {
+        // no defaults, no required props - returned config should be empty
+        ConfigurationDefinition configDef = new ConfigurationDefinition("foo", null);
+
+        PropertyDefinitionSimple simple = new PropertyDefinitionSimple("simple", null, false, PropertySimpleType.STRING);
+        PropertyDefinitionMap map = new PropertyDefinitionMap("map", null, false, simple);
+        PropertyDefinitionList list = new PropertyDefinitionList("list", null, false, simple);
+
+        configDef.put(simple);
+        configDef.put(map);
+        configDef.put(list);
+
+        Configuration config = ConfigurationUtility.createDefaultConfiguration(configDef);
+        assert config != null;
+        assert config.getProperties().size() == 0;
+    }
+
+    public void testCreateDefaultSimple() {
+        ConfigurationDefinition configDef = new ConfigurationDefinition("foo", null);
+
+        PropertyDefinitionSimple simple = new PropertyDefinitionSimple("simple", null, false, PropertySimpleType.STRING);
+        PropertyDefinitionSimple simpleRequired = new PropertyDefinitionSimple("simpleRequired", null, true,
+            PropertySimpleType.STRING);
+        PropertyDefinitionSimple simpleDefault = new PropertyDefinitionSimple("simpleDefault", null, false,
+            PropertySimpleType.STRING);
+        PropertyDefinitionSimple simpleRequiredDefault = new PropertyDefinitionSimple("simpleRequiredDefault", null,
+            true, PropertySimpleType.STRING);
+
+        simpleDefault.setDefaultValue("!!simpleDefaultValue!!");
+        simpleRequiredDefault.setDefaultValue("!!simpleRequiredDefaultValue!!");
+
+        configDef.put(simple);
+        configDef.put(simpleRequired);
+        configDef.put(simpleDefault);
+        configDef.put(simpleRequiredDefault);
+
+        Configuration config = ConfigurationUtility.createDefaultConfiguration(configDef);
+        assert config != null;
+        assert config.getProperties().size() == 3; // simple is not required with no default - its not in the config
+        assert config.getSimple(simple.getName()) == null;
+        assert config.getSimpleValue(simpleRequired.getName(), null) == null;
+        assert config.getSimpleValue(simpleDefault.getName(), null).equals("!!simpleDefaultValue!!");
+        assert config.getSimpleValue(simpleRequiredDefault.getName(), null).equals("!!simpleRequiredDefaultValue!!");
+    }
+
+    public void testCreateDefaultMap() {
+        ConfigurationDefinition configDef = new ConfigurationDefinition("foo", null);
+
+        // a=not required, no default; c=not required, has default; d=required, has default
+        PropertyDefinitionSimple a = new PropertyDefinitionSimple("a", null, false, PropertySimpleType.STRING);
+        PropertyDefinitionSimple b = new PropertyDefinitionSimple("b", null, false, PropertySimpleType.STRING);
+        PropertyDefinitionSimple c = new PropertyDefinitionSimple("c", null, true, PropertySimpleType.STRING);
+        b.setDefaultValue("!!bDefaultValue!!");
+        c.setDefaultValue("!!cDefaultValue!!");
+
+        PropertyDefinitionMap map1 = new PropertyDefinitionMap("map1", null, false, a, b, c);
+        PropertyDefinitionMap mapRequired1 = new PropertyDefinitionMap("mapRequired1", null, true, a, b, c);
+        PropertyDefinitionMap mapRequiredDefault1 = new PropertyDefinitionMap("mapRequiredDefault1", null, true, a, b,
+            c);
+
+        configDef.put(map1);
+        configDef.put(mapRequired1);
+        configDef.put(mapRequiredDefault1);
+
+        Configuration config = ConfigurationUtility.createDefaultConfiguration(configDef);
+        assert config != null;
+        assert config.getProperties().size() == 2; // map is not required with no default - its not in the config
+        assert config.getMap(map1.getName()) == null;
+
+        // the two required maps have the same definitions - a,b,c as above. since a isn't required with no default, its not there
+        PropertyMap mapProp1 = config.getMap(mapRequired1.getName());
+        assert mapProp1 != null;
+        assert mapProp1.getSimple(a.getName()) == null;
+        assert mapProp1.getSimpleValue(b.getName(), null).equals("!!bDefaultValue!!");
+        assert mapProp1.getSimpleValue(c.getName(), null).equals("!!cDefaultValue!!");
+
+        mapProp1 = config.getMap(mapRequiredDefault1.getName());
+        assert mapProp1 != null;
+        assert mapProp1.getSimple(a.getName()) == null;
+        assert mapProp1.getSimpleValue(b.getName(), null).equals("!!bDefaultValue!!");
+        assert mapProp1.getSimpleValue(c.getName(), null).equals("!!cDefaultValue!!");
+    }
+
+    public void testCreateDefaultList() {
+        ConfigurationDefinition configDef = new ConfigurationDefinition("foo", null);
+
+        // a=not required, no default, b=required, has default
+        PropertyDefinitionSimple a = new PropertyDefinitionSimple("a", null, false, PropertySimpleType.STRING);
+        PropertyDefinitionSimple c = new PropertyDefinitionSimple("c", null, true, PropertySimpleType.STRING);
+        c.setDefaultValue("!!cDefaultValue!!");
+
+        PropertyDefinitionList list1 = new PropertyDefinitionList("list1", null, false, a);
+        PropertyDefinitionList listRequired1 = new PropertyDefinitionList("listRequired1", null, true, a);
+        PropertyDefinitionList listRequiredDefault1 = new PropertyDefinitionList("listRequiredDefault1", null, true, c);
+
+        configDef.put(list1);
+        configDef.put(listRequired1);
+        configDef.put(listRequiredDefault1);
+
+        Configuration config = ConfigurationUtility.createDefaultConfiguration(configDef);
+        assert config != null;
+        assert config.getProperties().size() == 2; // list is not required with no default - its not in the config
+        assert config.getList(list1.getName()) == null;
+
+        PropertyList listProp1 = config.getList(listRequired1.getName());
+        assert listProp1 != null;
+        assert listProp1.getList().isEmpty(); // has "a" definition, which is not required and has no default
+
+        listProp1 = config.getList(listRequiredDefault1.getName());
+        assert listProp1 != null;
+        assert listProp1.getList().get(0).getName().equals(c.getName());
+        assert ((PropertySimple) listProp1.getList().get(0)).getStringValue().equals("!!cDefaultValue!!");
+    }
+
+    public void testCreateDefaultListOMaps() {
+        ConfigurationDefinition configDef = new ConfigurationDefinition("foo", null);
+
+        // a=not required, no default; c=not required, has default; d=required, has default
+        PropertyDefinitionSimple a = new PropertyDefinitionSimple("a", null, false, PropertySimpleType.STRING);
+        PropertyDefinitionSimple b = new PropertyDefinitionSimple("b", null, false, PropertySimpleType.STRING);
+        PropertyDefinitionSimple c = new PropertyDefinitionSimple("c", null, true, PropertySimpleType.STRING);
+        b.setDefaultValue("!!bDefaultValue!!");
+        c.setDefaultValue("!!cDefaultValue!!");
+
+        PropertyDefinitionMap map2 = new PropertyDefinitionMap("map2", null, false, a, b, c);
+        PropertyDefinitionMap mapRequired2 = new PropertyDefinitionMap("mapRequired2", null, true, a, b, c);
+        PropertyDefinitionMap mapRequiredDefault2 = new PropertyDefinitionMap("mapRequiredDefault2", null, true, a, b,
+            c);
+
+        PropertyDefinitionList listX = new PropertyDefinitionList("listX", null, true, map2);
+        PropertyDefinitionList listY = new PropertyDefinitionList("listY", null, true, mapRequired2);
+        PropertyDefinitionList listZ = new PropertyDefinitionList("listZ", null, true, mapRequiredDefault2);
+
+        configDef.put(listX);
+        configDef.put(listY);
+        configDef.put(listZ);
+
+        Configuration config = ConfigurationUtility.createDefaultConfiguration(configDef);
+
+        assert config != null;
+        assert config.getProperties().size() == 3;
+
+        PropertyList listPropTest = config.getList(listX.getName());
+        assert listPropTest != null;
+        assert listPropTest.getList().isEmpty();
+
+        listPropTest = config.getList(listY.getName());
+        assert listPropTest != null;
+        PropertyMap childMap2 = (PropertyMap) listPropTest.getList().get(0);
+
+        listPropTest = config.getList(listZ.getName());
+        assert listPropTest != null;
+        PropertyMap childMap3 = (PropertyMap) listPropTest.getList().get(0);
+
+        assert childMap2.getName().equals(mapRequired2.getName());
+        assert childMap3.getName().equals(mapRequiredDefault2.getName());
+    }
+
+    public void testCreateDefaultAllSimpleMapList() {
+        // tests a big config def that has simples, lists, maps - combination of the other individual tests
+        ConfigurationDefinition configDef = new ConfigurationDefinition("foo", null);
+
+        // SETUP SIMPLE
+
+        PropertyDefinitionSimple simple = new PropertyDefinitionSimple("simple", null, false, PropertySimpleType.STRING);
+        PropertyDefinitionSimple simpleRequired = new PropertyDefinitionSimple("simpleRequired", null, true,
+            PropertySimpleType.STRING);
+        PropertyDefinitionSimple simpleDefault = new PropertyDefinitionSimple("simpleDefault", null, false,
+            PropertySimpleType.STRING);
+        PropertyDefinitionSimple simpleRequiredDefault = new PropertyDefinitionSimple("simpleRequiredDefault", null,
+            true, PropertySimpleType.STRING);
+
+        simpleDefault.setDefaultValue("!!simpleDefaultValue!!");
+        simpleRequiredDefault.setDefaultValue("!!simpleRequiredDefaultValue!!");
+
+        configDef.put(simple);
+        configDef.put(simpleRequired);
+        configDef.put(simpleDefault);
+        configDef.put(simpleRequiredDefault);
+
+        // SETUP MAP
+
+        // a=not required, no default; c=not required, has default; d=required, has default
+        PropertyDefinitionSimple a = new PropertyDefinitionSimple("a", null, false, PropertySimpleType.STRING);
+        PropertyDefinitionSimple b = new PropertyDefinitionSimple("b", null, false, PropertySimpleType.STRING);
+        PropertyDefinitionSimple c = new PropertyDefinitionSimple("c", null, true, PropertySimpleType.STRING);
+        b.setDefaultValue("!!bDefaultValue!!");
+        c.setDefaultValue("!!cDefaultValue!!");
+
+        PropertyDefinitionMap map1 = new PropertyDefinitionMap("map1", null, false, a, b, c);
+        PropertyDefinitionMap mapRequired1 = new PropertyDefinitionMap("mapRequired1", null, true, a, b, c);
+        PropertyDefinitionMap mapRequiredDefault1 = new PropertyDefinitionMap("mapRequiredDefault1", null, true, a, b,
+            c);
+
+        configDef.put(map1);
+        configDef.put(mapRequired1);
+        configDef.put(mapRequiredDefault1);
+
+        // SETUP LIST
+
+        PropertyDefinitionList list1 = new PropertyDefinitionList("list1", null, false, a);
+        PropertyDefinitionList listRequired1 = new PropertyDefinitionList("listRequired1", null, true, a);
+        PropertyDefinitionList listRequiredDefault1 = new PropertyDefinitionList("listRequiredDefault1", null, true, c);
+
+        configDef.put(list1);
+        configDef.put(listRequired1);
+        configDef.put(listRequiredDefault1);
+
+        // SETUP LIST-O-MAPS
+
+        PropertyDefinitionMap map2 = new PropertyDefinitionMap("map2", null, false, a, b, c);
+        PropertyDefinitionMap mapRequired2 = new PropertyDefinitionMap("mapRequired2", null, true, a, b, c);
+        PropertyDefinitionMap mapRequiredDefault2 = new PropertyDefinitionMap("mapRequiredDefault2", null, true, a, b,
+            c);
+
+        PropertyDefinitionList listX = new PropertyDefinitionList("listX", null, true, map2);
+        PropertyDefinitionList listY = new PropertyDefinitionList("listY", null, true, mapRequired2);
+        PropertyDefinitionList listZ = new PropertyDefinitionList("listZ", null, true, mapRequiredDefault2);
+
+        configDef.put(listX);
+        configDef.put(listY);
+        configDef.put(listZ);
+
+        // get the default config
+        Configuration config = ConfigurationUtility.createDefaultConfiguration(configDef);
+        assert config != null;
+        assert config.getProperties().size() == 10;
+
+        // ASSERT SIMPLE
+
+        assert config.getSimple(simple.getName()) == null;
+        assert config.getSimpleValue(simpleRequired.getName(), null) == null;
+        assert config.getSimpleValue(simpleDefault.getName(), null).equals("!!simpleDefaultValue!!");
+        assert config.getSimpleValue(simpleRequiredDefault.getName(), null).equals("!!simpleRequiredDefaultValue!!");
+
+        // ASSERT MAP
+
+        assert config.getMap(map1.getName()) == null;
+
+        // the two required maps have the same definitions - a,b,c as above. since a isn't required with no default, its not there
+        PropertyMap mapProp1 = config.getMap(mapRequired1.getName());
+        assert mapProp1 != null;
+        assert mapProp1.getSimple(a.getName()) == null;
+        assert mapProp1.getSimpleValue(b.getName(), null).equals("!!bDefaultValue!!");
+        assert mapProp1.getSimpleValue(c.getName(), null).equals("!!cDefaultValue!!");
+
+        mapProp1 = config.getMap(mapRequiredDefault1.getName());
+        assert mapProp1 != null;
+        assert mapProp1.getSimple(a.getName()) == null;
+        assert mapProp1.getSimpleValue(b.getName(), null).equals("!!bDefaultValue!!");
+        assert mapProp1.getSimpleValue(c.getName(), null).equals("!!cDefaultValue!!");
+
+        // ASSERT LIST
+
+        assert config.getList(list1.getName()) == null;
+
+        PropertyList listProp1 = config.getList(listRequired1.getName());
+        assert listProp1 != null;
+        assert listProp1.getList().isEmpty(); // has "a" definition, which is not required and has no default
+
+        listProp1 = config.getList(listRequiredDefault1.getName());
+        assert listProp1 != null;
+        assert listProp1.getList().get(0).getName().equals(c.getName());
+        assert ((PropertySimple) listProp1.getList().get(0)).getStringValue().equals("!!cDefaultValue!!");
+
+        // ASSERT LIST-O-MAPS
+
+        PropertyList listPropTest = config.getList(listX.getName());
+        assert listPropTest != null;
+        assert listPropTest.getList().isEmpty();
+
+        listPropTest = config.getList(listY.getName());
+        assert listPropTest != null;
+        PropertyMap childMap2 = (PropertyMap) listPropTest.getList().get(0);
+
+        listPropTest = config.getList(listZ.getName());
+        assert listPropTest != null;
+        PropertyMap childMap3 = (PropertyMap) listPropTest.getList().get(0);
+
+        assert childMap2.getName().equals(mapRequired2.getName());
+        assert childMap3.getName().equals(mapRequiredDefault2.getName());
+    }
+}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/deploy/GetDeploymentConfigStep.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/deploy/GetDeploymentConfigStep.java
index 7fc0363..c295b74 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/deploy/GetDeploymentConfigStep.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/deploy/GetDeploymentConfigStep.java
@@ -19,13 +19,14 @@
 package org.rhq.enterprise.gui.coregui.client.bundle.deploy;
 
 import com.smartgwt.client.widgets.Canvas;
+import com.smartgwt.client.widgets.HTMLFlow;
 import com.smartgwt.client.widgets.layout.VLayout;
 
 import org.rhq.core.domain.bundle.BundleDeployment;
 import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.ConfigurationUtility;
 import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
 import org.rhq.core.domain.configuration.definition.ConfigurationTemplate;
-import org.rhq.enterprise.gui.coregui.client.components.HeaderLabel;
 import org.rhq.enterprise.gui.coregui.client.components.configuration.ConfigurationEditor;
 import org.rhq.enterprise.gui.coregui.client.components.wizard.AbstractWizardStep;
 import org.rhq.enterprise.gui.coregui.client.util.selenium.Locatable;
@@ -58,8 +59,11 @@ public class GetDeploymentConfigStep extends AbstractWizardStep {
                 // This has started behaving badly. Instead of moving ahead let's give them a message
                 // and a chance to go back to the previous screen. 
                 // this.wizard.getView().incrementStep();
-                HeaderLabel label = new HeaderLabel(MSG.view_bundle_deployWizard_getConfigSkip());
+                HTMLFlow label = new HTMLFlow(MSG.view_bundle_deployWizard_getConfigSkip());
                 label.setWidth100();
+                label.setHeight(50);
+                label.setStylePrimaryName("HeaderLabel");
+                label.setStyleName("HeaderLabel");
                 editor = new VLayout();
                 editor.addMember(label);
             } else {
@@ -100,9 +104,7 @@ public class GetDeploymentConfigStep extends AbstractWizardStep {
             config = new Configuration();
         } else {
             config = config.deepCopy(false);
-            //TODO: get access to this method, may need to add slsb call
-            //      also, may need to enhance this drop unnecessary config (maybe it can just stay around) 
-            //ConfigurationUtility.normalizeConfiguration(config, configDef);
+            ConfigurationUtility.normalizeConfiguration(config, configDef, true, false);
         }
 
         return config;


commit 8c13179ae885c491088980a88aee43d7b7bf77dd
Author: Mike Thompson <mithomps at redhat.com>
Date:   Wed Jun 20 12:53:30 2012 -0700

    [BZ 830323] Large artifacts get packaged in war file. Remove symbolMap data from GWT compiled war file.

diff --git a/modules/enterprise/gui/coregui/pom.xml b/modules/enterprise/gui/coregui/pom.xml
index 45308cc..aac9b9c 100644
--- a/modules/enterprise/gui/coregui/pom.xml
+++ b/modules/enterprise/gui/coregui/pom.xml
@@ -298,6 +298,8 @@
                     <compileSourcesArtifact>org.rhq:rhq-core-domain</compileSourcesArtifact>
                     <style>${gwt.style}</style>
                     <strict>true</strict>
+                    <!-- compiles gwt artifacts like symbolMap outside of war so it doesnt get packaged -->
+                    <deploy>${project.build.directory}/gwt-deploy</deploy>
                 </configuration>
 
                 <executions>


commit 3bbec0bbb45429d1f0769753466faa3e26e5623f
Author: Jay Shaughnessy <jshaughn at redhat.com>
Date:   Wed Jun 20 15:40:39 2012 -0400

    [830463 - Re-enabling (actually, updating) an alert definition clears condition logs for existing alerts]
    This is sort of complex. The underlying issue is that
    AlertDefinitionManagerBean.updateAlertDefinition(updatedDef) replaces
    existing AlertConditions with updatedDef.conditions.  The detached
    conditions were deleted (via Hibernate and DELETE_ORPHAN) regardless of the
    fact that they very possibly linked to AlertConditionLog records for existing
    Alerts.  These log records are what you need to display the actual condition
    evaluations that explain why the alert was fired.
    
    The fix was to allow the detached AlertCondition records to stay around and
    to deal with the fallout of doing that:
    - clean up orphaned AlertConditions (no def and no logs) in the data purge job
    - update queries backing AlertManager.deleteAlertsByContext()
    - update queries backing resource uninventory bulk delete
    
    Additionally, there was a lot of confusion around the 'purgeInternals' parameter
    for updateAlertDefinition().  It was initially thought that setting this true
    was responsible for the loss of AlertConditions backing the Alerts.  Actually,
    what this flag does, when set to true, is to erase any partial condition
    matching that has taken place.  It must be set true if conditions, dampening rules,
    or the condition expression (All vs Any matching) are being updated.  Otherwise
    it can be false.
    
    I renamed this flag to be 'resetMatching' to hopefully be more clear, and
    added some jdoc for the relevant methods.
    
    I had already refactored CoreGUI's editor to correctly set this flag before
    realizing it was not the root cause.  So that logic is in place and
    will optimize the update to some degree.
    
    I think the backend logic can be further optimized using this setting more
    intelligently.  I plan a subsequent check-in for that before setting to ON_QA.

diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/alert/AlertCondition.java b/modules/core/domain/src/main/java/org/rhq/core/domain/alert/AlertCondition.java
index 064400c..8a72244 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/alert/AlertCondition.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/alert/AlertCondition.java
@@ -290,7 +290,11 @@ import org.rhq.core.domain.operation.OperationRequestStatus;
         + "    FROM AlertCondition AS ac " //
         + "    JOIN ac.alertDefinition ad " //
         + "    JOIN ad.resource res " //
-        + "   WHERE ac.id = :alertConditionId ") })
+        + "   WHERE ac.id = :alertConditionId "),
+ @NamedQuery(name = AlertCondition.QUERY_DELETE_ORPHANED, query = "" //
+        + "  DELETE FROM AlertCondition ac " //
+        + "   WHERE ac.alertDefinition IS NULL " //
+        + "     AND NOT EXISTS ( SELECT acl FROM AlertConditionLog acl WHERE acl.condition.id = ac.id ) ") })
 @SequenceGenerator(name = "RHQ_ALERT_CONDITION_ID_SEQ", sequenceName = "RHQ_ALERT_CONDITION_ID_SEQ")
 @Table(name = "RHQ_ALERT_CONDITION")
 @XmlAccessorType(XmlAccessType.FIELD)
@@ -314,6 +318,8 @@ public class AlertCondition implements Serializable {
 
     public static final String QUERY_FIND_RESOURCE_STATUS_BY_CONDITION_ID = "AlertCondition.findResourceStatus";
 
+    public static final String QUERY_DELETE_ORPHANED = "AlertCondition.deleteOrphaned";
+
     public static final String RECOVERY_CONDITIONAL_EXPRESSION = "" //
         + " ( ad.recoveryId = 0 " //
         + " OR ( ad.recoveryId <> 0 " //
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/alert/AlertConditionLog.java b/modules/core/domain/src/main/java/org/rhq/core/domain/alert/AlertConditionLog.java
index d43bb7f..28355be 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/alert/AlertConditionLog.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/alert/AlertConditionLog.java
@@ -42,7 +42,7 @@ import javax.persistence.Table;
  * @author Joseph Marques
  */
 @Entity
- at NamedQueries( {
+ at NamedQueries({
     @NamedQuery(name = AlertConditionLog.QUERY_FIND_UNMATCHED_LOG_BY_ALERT_CONDITION_ID, //
     query = "SELECT acl " //
         + "    FROM AlertConditionLog AS acl " //
@@ -63,16 +63,27 @@ import javax.persistence.Table;
         + "                       FROM Alert a " //
         + "                       JOIN a.conditionLogs ac" // 
         + "                      WHERE a.id IN ( :alertIds ) )"),
-    // deletes condition logs via the alert def, not alerts, because not every condition log may not
-    // yet be associated with an alert. Also, avoids joining with the potentially large alert table
-    @NamedQuery(name = AlertConditionLog.QUERY_DELETE_BY_RESOURCES, //
+    // This query removes condition logs via the alert def, not alerts, because not every condition log may 
+    // yet be associated with an alert. This is required by Resource bulk delete to pick up the condition logs missed
+    // by QUERY_DELETE_BY_RESOURCES.  It will not get the logs for AlertConditions detached from the AlertDefinition.  
+    @NamedQuery(name = AlertConditionLog.QUERY_DELETE_BY_RESOURCES_BULK_DELETE, //
     query = "DELETE AlertConditionLog acl " //
         + "   WHERE acl.condition.id IN ( SELECT ac.id " //
         + "                             FROM AlertCondition ac " //
         + "                             JOIN ac.alertDefinition ad " //
         + "                            WHERE ad.resource.id IN ( :resourceIds ) ))"),
+    // This query will remove condition logs for conditions that are associated with alerts, regardless of whether
+    // the AlertCondition has been detached from the AlertDef. This is what you want if you are deleting alerts for
+    // a resource.  It does not fully satisfy Resource bulk delete. 
+    @NamedQuery(name = AlertConditionLog.QUERY_DELETE_BY_RESOURCES, //
+    query = "DELETE AlertConditionLog acl " //
+        + "   WHERE acl.alert.id IN ( SELECT alert.id " //
+        + "                             FROM AlertDefinition alertDef " //
+        + "                             JOIN alertDef.alerts alert " //
+        + "                            WHERE alertDef.resource.id IN ( :resourceIds ) ))"),
     @NamedQuery(name = AlertConditionLog.QUERY_DELETE_BY_RESOURCE_TEMPLATE, // 
-    query = "DELETE AlertConditionLog log " + "  WHERE  log.alert.id IN (SELECT alert.id "
+    query = "DELETE AlertConditionLog acl " //
+        + "   WHERE acl.alert.id IN (SELECT alert.id "
         + "                          FROM   AlertDefinition alertDef "
         + "                          JOIN   alertDef.alerts alert "
         + "                          WHERE  alertDef.resourceType.id = :resourceTypeId)"),
@@ -104,6 +115,7 @@ public class AlertConditionLog implements Serializable {
     public static final String QUERY_DELETE_ALL = "AlertConditionLog.deleteByAll";
     public static final String QUERY_DELETE_BY_ALERT_IDS = "AlertConditionLog.deleteByAlertIds";
     public static final String QUERY_DELETE_BY_RESOURCES = "AlertConditionLog.deleteByResources";
+    public static final String QUERY_DELETE_BY_RESOURCES_BULK_DELETE = "AlertConditionLog.deleteByResourcesBulkDelete";
     public static final String QUERY_DELETE_BY_RESOURCE_TEMPLATE = "AlertConditionLog.deleteByResourceType";
     public static final String QUERY_DELETE_BY_RESOURCE_GROUPS = "AlertConditionLog.deleteByResourceGroups";
     public static final String QUERY_DELETE_BY_ALERT_CTIME = "AlertConditionLog.deleteByAlertCTime";
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/alert/AlertDefinition.java b/modules/core/domain/src/main/java/org/rhq/core/domain/alert/AlertDefinition.java
index 7d5e3e8..397e254 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/alert/AlertDefinition.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/alert/AlertDefinition.java
@@ -354,11 +354,17 @@ public class AlertDefinition implements Serializable {
 
     @OneToMany(mappedBy = "alertDefinition", cascade = CascadeType.ALL)
     @OrderBy
-    @org.hibernate.annotations.Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
-    // primary key
+    // We used to use DELETE_ORPHAN here. But the problem is that the the AlertCondition record is needed by the
+    // associated AlertConditionLog for presentation purposes. So, keep the AlertCondition records even if they
+    // are detached from the AlertDefinition (e.g. when the def is updated, see update() below).  They will be
+    // cleaned up in the DataPurge job after all relevant alerts have been removed and there are no longer any
+    // referencing AlertConditionLog records.
     private Set<AlertCondition> conditions = new LinkedHashSet<AlertCondition>(1); // Most alerts will only have one condition.
 
     @OneToMany(mappedBy = "alertDefinition", cascade = CascadeType.ALL)
+    // Although similar to AlertCondition, we do use DELETE_ORPHAN here.  The reason is because AlertNotificationLog
+    // does not refer back to the AlertNotification record and therefore the notification logs are not affected
+    // by the loss of the AlertNotification that spawned the notification.
     @org.hibernate.annotations.Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
     private List<AlertNotification> alertNotifications = new ArrayList<AlertNotification>();
 
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/AbstractAlertDefinitionsView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/AbstractAlertDefinitionsView.java
index 7f2cce0..6a2fbf5 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/AbstractAlertDefinitionsView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/AbstractAlertDefinitionsView.java
@@ -199,5 +199,5 @@ public abstract class AbstractAlertDefinitionsView extends TableSection<Abstract
 
     protected abstract void disableButtonPressed(ListGridRecord[] selection);
 
-    protected abstract void commitAlertDefinition(AlertDefinition alertDefinition);
+    protected abstract void commitAlertDefinition(AlertDefinition alertDefinition, boolean isPurgeInternals);
 }
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ConditionsAlertDefinitionForm.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ConditionsAlertDefinitionForm.java
index d762b23..3b564d4 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ConditionsAlertDefinitionForm.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ConditionsAlertDefinitionForm.java
@@ -58,6 +58,7 @@ public class ConditionsAlertDefinitionForm extends LocatableVLayout implements E
     private StaticTextItem conditionExpressionStatic;
 
     private boolean formBuilt = false;
+    private boolean updated;
 
     public ConditionsAlertDefinitionForm(String locatorId, ResourceType resourceType) {
         this(locatorId, resourceType, null);
@@ -67,6 +68,7 @@ public class ConditionsAlertDefinitionForm extends LocatableVLayout implements E
         super(locatorId);
         this.resourceType = resourceType;
         this.alertDefinition = alertDefinition;
+        this.updated = false;
     }
 
     @Override
@@ -86,6 +88,11 @@ public class ConditionsAlertDefinitionForm extends LocatableVLayout implements E
     }
 
     @Override
+    public boolean isResetMatching() {
+        return updated || conditionsEditor.isUpdated();
+    }
+
+    @Override
     public void setAlertDefinition(AlertDefinition alertDef) {
         alertDefinition = alertDef;
 
@@ -113,8 +120,12 @@ public class ConditionsAlertDefinitionForm extends LocatableVLayout implements E
 
     @Override
     public void makeViewOnly() {
+        updated = false;
+
         conditionExpression.hide();
         conditionsEditor.setEditable(false);
+        conditionsEditor.setUpdated(false);
+
         conditionExpressionStatic.show();
 
         markForRedraw();
@@ -122,11 +133,15 @@ public class ConditionsAlertDefinitionForm extends LocatableVLayout implements E
 
     @Override
     public void saveAlertDefinition() {
+        updated = false;
+
         String condExpr = conditionExpression.getValue().toString();
         alertDefinition.setConditionExpression(BooleanExpression.valueOf(condExpr));
 
         HashSet<AlertCondition> conditions = conditionsEditor.getConditions();
         alertDefinition.setConditions(conditions);
+
+        conditionsEditor.setUpdated(false);
     }
 
     @Override
@@ -167,6 +182,8 @@ public class ConditionsAlertDefinitionForm extends LocatableVLayout implements E
             conditionExpression.addChangeHandler(new ChangeHandler() {
                 @Override
                 public void onChange(ChangeEvent event) {
+                    updated = true;
+
                     // Find out if this is using the ALL conjunction - if it is, we can't have more than one conditional use the same metric.
                     // If we do, immediately abort and warn the user. See BZ 737565
                     if ((BooleanExpression.ALL.name().equals(event.getValue().toString()))
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ConditionsEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ConditionsEditor.java
index 18b9beb..f3317ed 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ConditionsEditor.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ConditionsEditor.java
@@ -22,6 +22,11 @@
  */
 package org.rhq.enterprise.gui.coregui.client.alert.definitions;
 
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
 import com.smartgwt.client.data.DSRequest;
 import com.smartgwt.client.data.DSResponse;
 import com.smartgwt.client.data.DataSourceField;
@@ -33,6 +38,7 @@ import com.smartgwt.client.widgets.events.CloseClickEvent;
 import com.smartgwt.client.widgets.events.CloseClickHandler;
 import com.smartgwt.client.widgets.form.fields.SelectItem;
 import com.smartgwt.client.widgets.grid.ListGridRecord;
+
 import org.rhq.core.domain.alert.AlertCondition;
 import org.rhq.core.domain.criteria.Criteria;
 import org.rhq.core.domain.drift.DriftDefinitionTemplate;
@@ -48,11 +54,6 @@ import org.rhq.enterprise.gui.coregui.client.util.RPCDataSource;
 import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableVLayout;
 import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableWindow;
 
-import java.util.EnumSet;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
 /**
  * @author John Mazzitelli
  */
@@ -62,12 +63,14 @@ public class ConditionsEditor extends LocatableVLayout {
     private HashSet<AlertCondition> conditions;
     private Table<ConditionDataSource> table;
     private final SelectItem conditionExpression;
+    private boolean updated;
 
     public ConditionsEditor(String locatorId, SelectItem conditionExpression, ResourceType resourceType,
         HashSet<AlertCondition> conditions) {
         super(locatorId);
         this.conditionExpression = conditionExpression;
         this.resourceType = resourceType;
+        this.updated = false;
         setConditions(conditions);
     }
 
@@ -133,6 +136,14 @@ public class ConditionsEditor extends LocatableVLayout {
         table.setTableActionDisableOverride(!editable);
     }
 
+    public boolean isUpdated() {
+        return updated;
+    }
+
+    public void setUpdated(boolean updated) {
+        this.updated = updated;
+    }
+
     private class ConditionsTable extends Table<ConditionDataSource> {
         private ConditionsTable(String locatorId) {
             super(locatorId);
@@ -191,12 +202,14 @@ public class ConditionsEditor extends LocatableVLayout {
                                     }
                                 });
 
+                                final int numConditions = conditions.size();
                                 NewConditionEditor newConditionEditor = new NewConditionEditor(
                                     extendLocatorId("newConditionEditor"), conditions,
                                     ConditionsEditor.this.conditionExpression, ConditionsEditor.this.resourceType,
                                     new Runnable() {
                                         @Override
                                         public void run() {
+                                            updated = updated || numConditions != conditions.size();
                                             winModal.markForDestroy();
                                             refresh();
                                         }
@@ -215,6 +228,7 @@ public class ConditionsEditor extends LocatableVLayout {
                     for (ListGridRecord record : selection) {
                         AlertCondition cond = getDataSource().copyValues(record);
                         conditions.remove(cond);
+                        updated = true;
                     }
                     refresh();
                 }
@@ -237,8 +251,8 @@ public class ConditionsEditor extends LocatableVLayout {
         protected List<DataSourceField> addDataSourceFields() {
             List<DataSourceField> fields = super.addDataSourceFields();
 
-            DataSourceTextField conditionField = new DataSourceTextField(FIELD_CONDITION, MSG
-                .view_alert_common_tab_conditions_text());
+            DataSourceTextField conditionField = new DataSourceTextField(FIELD_CONDITION,
+                MSG.view_alert_common_tab_conditions_text());
             fields.add(conditionField);
 
             return fields;
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/DampeningAlertDefinitionForm.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/DampeningAlertDefinitionForm.java
index 3ba2182..c5ccfe3 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/DampeningAlertDefinitionForm.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/DampeningAlertDefinitionForm.java
@@ -34,9 +34,9 @@ import com.smartgwt.client.widgets.form.fields.events.ItemHoverEvent;
 import com.smartgwt.client.widgets.form.fields.events.ItemHoverHandler;
 
 import org.rhq.core.domain.alert.AlertDampening;
-import org.rhq.core.domain.alert.AlertDefinition;
 import org.rhq.core.domain.alert.AlertDampening.Category;
 import org.rhq.core.domain.alert.AlertDampening.TimeUnits;
+import org.rhq.core.domain.alert.AlertDefinition;
 import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableDynamicForm;
 
 /**
@@ -69,6 +69,8 @@ public class DampeningAlertDefinitionForm extends LocatableDynamicForm implement
     private SelectItem durationTimeUnitsSelection;
     private StaticTextItem durationTimeUnitsStatic;
 
+    private boolean updated;
+
     public DampeningAlertDefinitionForm(String locatorId) {
         this(locatorId, null);
     }
@@ -76,6 +78,7 @@ public class DampeningAlertDefinitionForm extends LocatableDynamicForm implement
     public DampeningAlertDefinitionForm(String locatorId, AlertDefinition alertDefinition) {
         super(locatorId);
         this.alertDefinition = alertDefinition;
+        this.updated = false;
     }
 
     @Override
@@ -237,6 +240,8 @@ public class DampeningAlertDefinitionForm extends LocatableDynamicForm implement
 
     @Override
     public void makeViewOnly() {
+        updated = false;
+
         dampeningRuleSelection.hide();
         dampeningRuleStatic.show();
 
@@ -318,6 +323,8 @@ public class DampeningAlertDefinitionForm extends LocatableDynamicForm implement
 
     @Override
     public void saveAlertDefinition() {
+        updated = false;
+
         AlertDampening.Category cat = AlertDampening.Category.valueOf(dampeningRuleSelection.getValue().toString());
         AlertDampening alertDampening = new AlertDampening(cat);
         switch (cat) {
@@ -381,6 +388,11 @@ public class DampeningAlertDefinitionForm extends LocatableDynamicForm implement
         markForRedraw();
     }
 
+    @Override
+    public boolean isResetMatching() {
+        return updated;
+    }
+
     private void buildForm() {
         if (!formBuilt) {
             dampeningRuleSelection = new SelectItem("dampeningRule", MSG.view_alert_common_tab_dampening());
@@ -413,8 +425,8 @@ public class DampeningAlertDefinitionForm extends LocatableDynamicForm implement
             // nothing to do - the none category has no ui components to render
 
             //  CONSECUTIVE_COUNT
-            consecutiveOccurrencesSpinner = new SpinnerItem("consecutiveOccurrencesSpinner", MSG
-                .view_alert_common_tab_dampening_consecutive_occurrences_label());
+            consecutiveOccurrencesSpinner = new SpinnerItem("consecutiveOccurrencesSpinner",
+                MSG.view_alert_common_tab_dampening_consecutive_occurrences_label());
             consecutiveOccurrencesSpinner.setWrapTitle(false);
             consecutiveOccurrencesSpinner.setMin(1);
             consecutiveOccurrencesSpinner.setMax(999999);
@@ -423,13 +435,19 @@ public class DampeningAlertDefinitionForm extends LocatableDynamicForm implement
             consecutiveOccurrencesSpinner.setHoverWidth(300);
             consecutiveOccurrencesSpinner.setTooltip(MSG
                 .view_alert_common_tab_dampening_consecutive_occurrences_label_tooltip());
-            consecutiveOccurrencesStatic = new StaticTextItem("consecutiveOccurrencesStatic", MSG
-                .view_alert_common_tab_dampening_consecutive_occurrences_label());
+            consecutiveOccurrencesStatic = new StaticTextItem("consecutiveOccurrencesStatic",
+                MSG.view_alert_common_tab_dampening_consecutive_occurrences_label());
             consecutiveOccurrencesStatic.setWrapTitle(false);
 
+            consecutiveOccurrencesSpinner.addChangedHandler(new ChangedHandler() {
+                public void onChanged(ChangedEvent event) {
+                    updated = true;
+                }
+            });
+
             //  PARTIAL_COUNT
-            partialOccurrencesSpinner = new SpinnerItem("partialOccurrencesSpinner", MSG
-                .view_alert_common_tab_dampening_partial_occurrences_label());
+            partialOccurrencesSpinner = new SpinnerItem("partialOccurrencesSpinner",
+                MSG.view_alert_common_tab_dampening_partial_occurrences_label());
             partialOccurrencesSpinner.setWrapTitle(false);
             partialOccurrencesSpinner.setMin(1);
             partialOccurrencesSpinner.setMax(999999);
@@ -438,12 +456,18 @@ public class DampeningAlertDefinitionForm extends LocatableDynamicForm implement
             partialOccurrencesSpinner.setHoverWidth(300);
             partialOccurrencesSpinner.setTooltip(MSG
                 .view_alert_common_tab_dampening_partial_occurrences_label_tooltip());
-            partialOccurrencesStatic = new StaticTextItem("partialOccurrencesStatic", MSG
-                .view_alert_common_tab_dampening_partial_occurrences_label());
+            partialOccurrencesStatic = new StaticTextItem("partialOccurrencesStatic",
+                MSG.view_alert_common_tab_dampening_partial_occurrences_label());
             partialOccurrencesStatic.setWrapTitle(false);
 
-            partialEvaluationsSpinner = new SpinnerItem("partialEvaluationsSpinner", MSG
-                .view_alert_common_tab_dampening_partial_evalatuions_label());
+            partialOccurrencesSpinner.addChangedHandler(new ChangedHandler() {
+                public void onChanged(ChangedEvent event) {
+                    updated = true;
+                }
+            });
+
+            partialEvaluationsSpinner = new SpinnerItem("partialEvaluationsSpinner",
+                MSG.view_alert_common_tab_dampening_partial_evalatuions_label());
             partialEvaluationsSpinner.setWrapTitle(false);
             partialEvaluationsSpinner.setMin(1);
             partialEvaluationsSpinner.setMax(999999);
@@ -452,13 +476,19 @@ public class DampeningAlertDefinitionForm extends LocatableDynamicForm implement
             partialEvaluationsSpinner.setHoverWidth(300);
             partialEvaluationsSpinner.setTooltip(MSG
                 .view_alert_common_tab_dampening_partial_evalatuions_label_tooltip());
-            partialEvaluationsStatic = new StaticTextItem("partialEvaluationStatic", MSG
-                .view_alert_common_tab_dampening_partial_evalatuions_label());
+            partialEvaluationsStatic = new StaticTextItem("partialEvaluationStatic",
+                MSG.view_alert_common_tab_dampening_partial_evalatuions_label());
             partialEvaluationsStatic.setWrapTitle(false);
 
+            partialEvaluationsSpinner.addChangedHandler(new ChangedHandler() {
+                public void onChanged(ChangedEvent event) {
+                    updated = true;
+                }
+            });
+
             //  DURATION_COUNT
-            durationOccurrencesSpinner = new SpinnerItem("durationOccurrencesSpinner", MSG
-                .view_alert_common_tab_dampening_duration_occurrences_label());
+            durationOccurrencesSpinner = new SpinnerItem("durationOccurrencesSpinner",
+                MSG.view_alert_common_tab_dampening_duration_occurrences_label());
             durationOccurrencesSpinner.setWrapTitle(false);
             durationOccurrencesSpinner.setMin(1);
             durationOccurrencesSpinner.setMax(999999);
@@ -467,12 +497,18 @@ public class DampeningAlertDefinitionForm extends LocatableDynamicForm implement
             durationOccurrencesSpinner.setHoverWidth(300);
             durationOccurrencesSpinner.setTooltip(MSG
                 .view_alert_common_tab_dampening_duration_occurrences_label_tooltip());
-            durationOccurrencesStatic = new StaticTextItem("durationOccurrencesStatic", MSG
-                .view_alert_common_tab_dampening_duration_occurrences_label());
+            durationOccurrencesStatic = new StaticTextItem("durationOccurrencesStatic",
+                MSG.view_alert_common_tab_dampening_duration_occurrences_label());
             durationOccurrencesStatic.setWrapTitle(false);
 
-            durationTimePeriodSpinner = new SpinnerItem("durationTimePeriodSpinner", MSG
-                .view_alert_common_tab_dampening_duration_period_label());
+            durationOccurrencesSpinner.addChangedHandler(new ChangedHandler() {
+                public void onChanged(ChangedEvent event) {
+                    updated = true;
+                }
+            });
+
+            durationTimePeriodSpinner = new SpinnerItem("durationTimePeriodSpinner",
+                MSG.view_alert_common_tab_dampening_duration_period_label());
             durationTimePeriodSpinner.setWrapTitle(false);
             durationTimePeriodSpinner.setMin(1);
             durationTimePeriodSpinner.setMax(999999);
@@ -480,10 +516,16 @@ public class DampeningAlertDefinitionForm extends LocatableDynamicForm implement
             durationTimePeriodSpinner.setDefaultValue(1);
             durationTimePeriodSpinner.setHoverWidth(300);
             durationTimePeriodSpinner.setTooltip(MSG.view_alert_common_tab_dampening_duration_period_label_tooltip());
-            durationTimePeriodStatic = new StaticTextItem("durationTimePeriodStatic", MSG
-                .view_alert_common_tab_dampening_duration_period_label());
+            durationTimePeriodStatic = new StaticTextItem("durationTimePeriodStatic",
+                MSG.view_alert_common_tab_dampening_duration_period_label());
             durationTimePeriodStatic.setWrapTitle(false);
 
+            durationTimePeriodSpinner.addChangedHandler(new ChangedHandler() {
+                public void onChanged(ChangedEvent event) {
+                    updated = true;
+                }
+            });
+
             durationTimeUnitsSelection = new SelectItem("durationTimeUnits", "");
             LinkedHashMap<String, String> units = new LinkedHashMap<String, String>(4);
             units.put(AlertDampening.TimeUnits.MINUTES.name(), getTimeUnitsTitle(AlertDampening.TimeUnits.MINUTES));
@@ -494,9 +536,17 @@ public class DampeningAlertDefinitionForm extends LocatableDynamicForm implement
             durationTimeUnitsSelection.setDefaultValue(AlertDampening.TimeUnits.MINUTES.name());
             durationTimeUnitsStatic = new StaticTextItem("durationTimeUnitsStatic", "");
 
+            durationTimeUnitsSelection.addChangedHandler(new ChangedHandler() {
+                public void onChanged(ChangedEvent event) {
+                    updated = true;
+                }
+            });
+
             dampeningRuleSelection.addChangedHandler(new ChangedHandler() {
                 @Override
                 public void onChanged(ChangedEvent event) {
+                    updated = true;
+
                     Category cat = AlertDampening.Category.valueOf(event.getValue().toString());
                     switch (cat) {
                     case NONE: {
@@ -536,8 +586,8 @@ public class DampeningAlertDefinitionForm extends LocatableDynamicForm implement
                         break;
                     }
                     default: {
-                        throw new IllegalStateException(MSG
-                            .view_alert_common_tab_invalid_dampening_category(cat.name())); // should never happen
+                        throw new IllegalStateException(
+                            MSG.view_alert_common_tab_invalid_dampening_category(cat.name())); // should never happen
                     }
                     }
                     markForRedraw();
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/EditAlertDefinitionForm.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/EditAlertDefinitionForm.java
index 439ed3e..da4dfd3 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/EditAlertDefinitionForm.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/EditAlertDefinitionForm.java
@@ -9,6 +9,8 @@ public interface EditAlertDefinitionForm {
 
     AlertDefinition getAlertDefinition();
 
+    boolean isResetMatching();
+
     void setAlertDefinition(AlertDefinition alertDef);
 
     void makeEditable();
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/GeneralPropertiesAlertDefinitionForm.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/GeneralPropertiesAlertDefinitionForm.java
index f154b26..fd07a64 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/GeneralPropertiesAlertDefinitionForm.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/GeneralPropertiesAlertDefinitionForm.java
@@ -32,8 +32,8 @@ import com.smartgwt.client.widgets.form.fields.StaticTextItem;
 import org.rhq.core.domain.alert.AlertDefinition;
 import org.rhq.core.domain.alert.AlertPriority;
 import org.rhq.enterprise.gui.coregui.client.ImageManager;
-import org.rhq.enterprise.gui.coregui.client.components.form.SimpleEditableTextAreaFormItem;
 import org.rhq.enterprise.gui.coregui.client.components.form.SimpleEditableFormItem;
+import org.rhq.enterprise.gui.coregui.client.components.form.SimpleEditableTextAreaFormItem;
 import org.rhq.enterprise.gui.coregui.client.components.form.StringLengthValidator;
 import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableDynamicForm;
 
@@ -197,6 +197,10 @@ public class GeneralPropertiesAlertDefinitionForm extends LocatableDynamicForm i
         markForRedraw();
     }
 
+    @Override
+    public boolean isResetMatching() {
+        return false;
+    }
     private void buildForm() {
         if (!formBuilt) {
             nameField = new SimpleEditableFormItem("name", MSG.common_title_name());
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/GroupAlertDefinitionsView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/GroupAlertDefinitionsView.java
index fc0dbb1..b277077 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/GroupAlertDefinitionsView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/GroupAlertDefinitionsView.java
@@ -198,7 +198,7 @@ public class GroupAlertDefinitionsView extends AbstractAlertDefinitionsView {
     }
 
     @Override
-    protected void commitAlertDefinition(final AlertDefinition alertDefinition) {
+    protected void commitAlertDefinition(final AlertDefinition alertDefinition, boolean purgeInternals) {
         if (alertDefinition.getId() == 0) {
             GWTServiceLookup.getGroupAlertDefinitionService().createGroupAlertDefinitions(alertDefinition,
                 Integer.valueOf(this.group.getId()), new AsyncCallback<Integer>() {
@@ -216,7 +216,8 @@ public class GroupAlertDefinitionsView extends AbstractAlertDefinitionsView {
                     }
                 });
         } else {
-            GWTServiceLookup.getGroupAlertDefinitionService().updateGroupAlertDefinitions(alertDefinition, true,
+            GWTServiceLookup.getGroupAlertDefinitionService().updateGroupAlertDefinitions(alertDefinition,
+                purgeInternals,
                 new AsyncCallback<AlertDefinition>() {
                     @Override
                     public void onSuccess(AlertDefinition result) {
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/NotificationsAlertDefinitionForm.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/NotificationsAlertDefinitionForm.java
index 26dbae8..8a428df 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/NotificationsAlertDefinitionForm.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/NotificationsAlertDefinitionForm.java
@@ -23,6 +23,9 @@
 
 package org.rhq.enterprise.gui.coregui.client.alert.definitions;
 
+import java.util.ArrayList;
+import java.util.List;
+
 import com.google.gwt.user.client.rpc.AsyncCallback;
 import com.smartgwt.client.data.DSRequest;
 import com.smartgwt.client.data.DSResponse;
@@ -38,6 +41,7 @@ import com.smartgwt.client.widgets.events.DoubleClickHandler;
 import com.smartgwt.client.widgets.grid.ListGrid;
 import com.smartgwt.client.widgets.grid.ListGridField;
 import com.smartgwt.client.widgets.grid.ListGridRecord;
+
 import org.rhq.core.domain.alert.AlertDefinition;
 import org.rhq.core.domain.alert.notification.AlertNotification;
 import org.rhq.core.domain.criteria.Criteria;
@@ -50,9 +54,6 @@ import org.rhq.enterprise.gui.coregui.client.util.RPCDataSource;
 import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableVLayout;
 import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableWindow;
 
-import java.util.ArrayList;
-import java.util.List;
-
 /**
  * @author John Mazzitelli
  */
@@ -142,6 +143,11 @@ public class NotificationsAlertDefinitionForm extends LocatableVLayout implement
         markForRedraw();
     }
 
+    @Override
+    public boolean isResetMatching() {
+        return false;
+    }
+
     private void buildForm() {
         if (!formBuilt) {
 
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/RecoveryAlertDefinitionForm.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/RecoveryAlertDefinitionForm.java
index a3cfea1..0e8f1b2 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/RecoveryAlertDefinitionForm.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/RecoveryAlertDefinitionForm.java
@@ -148,6 +148,11 @@ public class RecoveryAlertDefinitionForm extends LocatableDynamicForm implements
         markForRedraw();
     }
 
+    @Override
+    public boolean isResetMatching() {
+        return false;
+    }
+
     private void buildForm() {
         if (!formBuilt) {
             disableWhenFiredSelection = new RadioGroupItem("disableWhenFired", MSG
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ResourceAlertDefinitionsView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ResourceAlertDefinitionsView.java
index e31e554..00aa951 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ResourceAlertDefinitionsView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ResourceAlertDefinitionsView.java
@@ -194,7 +194,7 @@ public class ResourceAlertDefinitionsView extends AbstractAlertDefinitionsView {
     }
 
     @Override
-    protected void commitAlertDefinition(final AlertDefinition alertDefinition) {
+    protected void commitAlertDefinition(final AlertDefinition alertDefinition, boolean purgeInternals) {
         if (alertDefinition.getId() == 0) {
             GWTServiceLookup.getAlertDefinitionService().createAlertDefinition(alertDefinition,
                 Integer.valueOf(resource.getId()), new AsyncCallback<Integer>() {
@@ -213,7 +213,7 @@ public class ResourceAlertDefinitionsView extends AbstractAlertDefinitionsView {
                 });
         } else {
             GWTServiceLookup.getAlertDefinitionService().updateAlertDefinition(alertDefinition.getId(),
-                alertDefinition, true, new AsyncCallback<AlertDefinition>() {
+                alertDefinition, purgeInternals, new AsyncCallback<AlertDefinition>() {
                     @Override
                     public void onSuccess(AlertDefinition result) {
                         CoreGUI.getMessageCenter().notify(
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/SingleAlertDefinitionView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/SingleAlertDefinitionView.java
index f276937..f2007ce 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/SingleAlertDefinitionView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/SingleAlertDefinitionView.java
@@ -70,8 +70,8 @@ public class SingleAlertDefinitionView extends LocatableVLayout {
         final LocatableTabSet tabSet = new LocatableTabSet(this.getLocatorId());
         tabSet.setHeight100();
 
-        final Tab generalPropertiesTab = new LocatableTab(tabSet.extendLocatorId("General"), MSG
-            .view_alert_common_tab_general());
+        final Tab generalPropertiesTab = new LocatableTab(tabSet.extendLocatorId("General"),
+            MSG.view_alert_common_tab_general());
         generalProperties = new GeneralPropertiesAlertDefinitionForm(this.getLocatorId(), alertDefinition);
         generalPropertiesTab.setPane(generalProperties);
         generalPropertiesTab.addTabDeselectedHandler(new TabDeselectedHandler() {
@@ -84,14 +84,14 @@ public class SingleAlertDefinitionView extends LocatableVLayout {
             }
         });
 
-        Tab conditionsTab = new LocatableTab(tabSet.extendLocatorId("Conditions"), MSG
-            .view_alert_common_tab_conditions());
+        Tab conditionsTab = new LocatableTab(tabSet.extendLocatorId("Conditions"),
+            MSG.view_alert_common_tab_conditions());
         conditions = new ConditionsAlertDefinitionForm(this.getLocatorId(), alertDefView.getResourceType(),
             alertDefinition);
         conditionsTab.setPane(conditions);
 
-        Tab notificationsTab = new LocatableTab(tabSet.extendLocatorId("Notifications"), MSG
-            .view_alert_common_tab_notifications());
+        Tab notificationsTab = new LocatableTab(tabSet.extendLocatorId("Notifications"),
+            MSG.view_alert_common_tab_notifications());
         notifications = new NotificationsAlertDefinitionForm(this.getLocatorId(), alertDefinition);
         notificationsTab.setPane(notifications);
 
@@ -134,11 +134,12 @@ public class SingleAlertDefinitionView extends LocatableVLayout {
             @Override
             public void onClick(ClickEvent event) {
                 if (generalProperties.validate()) {
+                    boolean resetMatching = isResetMatching();
                     saveAlertDefinition();
                     setAlertDefinition(getAlertDefinition()); // loads data into static fields
                     makeViewOnly();
 
-                    alertDefView.commitAlertDefinition(getAlertDefinition());
+                    alertDefView.commitAlertDefinition(getAlertDefinition(), resetMatching);
                 } else {
                     tabSet.selectTab(generalPropertiesTab);
                 }
@@ -162,6 +163,10 @@ public class SingleAlertDefinitionView extends LocatableVLayout {
         return alertDefinition;
     }
 
+    public boolean isResetMatching() {
+        return conditions.isResetMatching() || dampening.isResetMatching();
+    }
+
     public void setAlertDefinition(AlertDefinition alertDef) {
         alertDefinition = alertDef;
 
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/TemplateAlertDefinitionsView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/TemplateAlertDefinitionsView.java
index 93b3a91..987e62f 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/TemplateAlertDefinitionsView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/TemplateAlertDefinitionsView.java
@@ -206,7 +206,7 @@ public class TemplateAlertDefinitionsView extends AbstractAlertDefinitionsView {
     }
 
     @Override
-    protected void commitAlertDefinition(final AlertDefinition alertDefinition) {
+    protected void commitAlertDefinition(final AlertDefinition alertDefinition, boolean purgeInternals) {
         if (alertDefinition.getId() == 0) {
             GWTServiceLookup.getAlertTemplateService().createAlertTemplate(alertDefinition,
                 Integer.valueOf(this.resourceType.getId()), new AsyncCallback<Integer>() {
@@ -224,7 +224,7 @@ public class TemplateAlertDefinitionsView extends AbstractAlertDefinitionsView {
                     }
                 });
         } else {
-            GWTServiceLookup.getAlertTemplateService().updateAlertTemplate(alertDefinition, true,
+            GWTServiceLookup.getAlertTemplateService().updateAlertTemplate(alertDefinition, purgeInternals,
                 new AsyncCallback<AlertDefinition>() {
                     @Override
                     public void onSuccess(AlertDefinition result) {
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/AlertDefinitionGWTService.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/AlertDefinitionGWTService.java
index ce73f0e..a356ff8 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/AlertDefinitionGWTService.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/AlertDefinitionGWTService.java
@@ -32,8 +32,8 @@ public interface AlertDefinitionGWTService extends RemoteService {
 
     int createAlertDefinition(AlertDefinition alertDefinition, Integer resourceId) throws RuntimeException;
 
-    AlertDefinition updateAlertDefinition(int alertDefinitionId, AlertDefinition alertDefinition,
-        boolean updateInternals) throws RuntimeException;
+    AlertDefinition updateAlertDefinition(int alertDefinitionId, AlertDefinition alertDefinition, boolean purgeInternals)
+        throws RuntimeException;
 
     int enableAlertDefinitions(int[] alertDefinitionIds) throws RuntimeException;
 
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/AlertDefinitionGWTServiceImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/AlertDefinitionGWTServiceImpl.java
index 88a134a..01ba237 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/AlertDefinitionGWTServiceImpl.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/AlertDefinitionGWTServiceImpl.java
@@ -74,10 +74,10 @@ public class AlertDefinitionGWTServiceImpl extends AbstractGWTServiceImpl implem
 
     @Override
     public AlertDefinition updateAlertDefinition(int alertDefinitionId, AlertDefinition alertDefinition,
-        boolean updateInternals) throws RuntimeException {
+        boolean resetMatching) throws RuntimeException {
         try {
             AlertDefinition results = alertDefManager.updateAlertDefinition(getSessionSubject(), alertDefinitionId,
-                alertDefinition, updateInternals);
+                alertDefinition, resetMatching);
             return SerialUtility.prepare(results, "updateAlertDefinition");
         } catch (Throwable t) {
             throw getExceptionToThrowToClient(t);
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertConditionLogManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertConditionLogManagerBean.java
index a26472e..bf87585 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertConditionLogManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertConditionLogManagerBean.java
@@ -102,9 +102,6 @@ public class AlertConditionLogManagerBean implements AlertConditionLogManagerLoc
             } catch (NoResultException nre) { // this is the expected case 90% of the time
                 // lookup the condition entity
                 AlertCondition condition = entityManager.find(AlertCondition.class, alertConditionId);
-                if (condition == null) {
-                    // the associated AlertDefinition must have been updated, which removes all previous AlertConditions
-                }
 
                 // persist the log entry
                 AlertConditionLog conditionLog = new AlertConditionLog(condition, ctime);
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertConditionManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertConditionManagerBean.java
index fa03aaf..6953bfc 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertConditionManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertConditionManagerBean.java
@@ -60,6 +60,7 @@ public class AlertConditionManagerBean implements AlertConditionManagerLocal {
     private AuthorizationManagerLocal authorizationManager;
 
     @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
+    @Override
     public Integer getAlertDefinitionByConditionIdInNewTransaction(int alertConditionId) {
         try {
             Query query = entityManager.createNamedQuery(AlertDefinition.QUERY_FIND_DEFINITION_ID_BY_CONDITION_ID);
@@ -77,6 +78,7 @@ public class AlertConditionManagerBean implements AlertConditionManagerLocal {
 
     @SuppressWarnings("unchecked")
     @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
+    @Override
     public PageList<? extends AbstractAlertConditionCategoryComposite> getAlertConditionComposites(Subject user,
         Integer agentId, AlertConditionCategory category, PageControl pageControl) {
         if (authorizationManager.isOverlord(user) == false) {
@@ -151,6 +153,7 @@ public class AlertConditionManagerBean implements AlertConditionManagerLocal {
     }
 
     @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
+    @Override
     public InventoryStatus getResourceStatusByConditionId(int alertConditionId) {
         try {
             Query query = entityManager.createNamedQuery(AlertCondition.QUERY_FIND_RESOURCE_STATUS_BY_CONDITION_ID);
@@ -165,4 +168,10 @@ public class AlertConditionManagerBean implements AlertConditionManagerLocal {
         }
     }
 
+    @Override
+    public int purgeOrphanedAlertConditions() {
+        Query purgeQuery = entityManager.createNamedQuery(AlertCondition.QUERY_DELETE_ORPHANED);
+        return purgeQuery.executeUpdate();
+    }
+
 }
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertConditionManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertConditionManagerLocal.java
index f659716..4c27c75 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertConditionManagerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertConditionManagerLocal.java
@@ -44,4 +44,6 @@ public interface AlertConditionManagerLocal {
 
     InventoryStatus getResourceStatusByConditionId(int alertConditionId);
 
+    int purgeOrphanedAlertConditions();
+
 }
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerBean.java
index c1c9d93..5da131e 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerBean.java
@@ -451,9 +451,9 @@ public class AlertDefinitionManagerBean implements AlertDefinitionManagerLocal,
 
     @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
     public AlertDefinition updateAlertDefinition(Subject subject, int alertDefinitionId,
-        AlertDefinition alertDefinition, boolean purgeInternals) throws InvalidAlertDefinitionException,
+        AlertDefinition alertDefinition, boolean resetMatching) throws InvalidAlertDefinitionException,
         AlertDefinitionUpdateException {
-        if (purgeInternals) {
+        if (resetMatching) {
             alertDefinitionManager.purgeInternals(alertDefinitionId);
         }
 
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerLocal.java
index 03c8945..d663198 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerLocal.java
@@ -60,8 +60,19 @@ public interface AlertDefinitionManagerLocal {
 
     void copyAlertDefinitions(Subject subject, Integer[] alertDefinitionIds);
 
+    /**
+     * @param subject
+     * @param alertDefinitionId
+     * @param alertDefinition
+     * @param resetMatching Incur the overhead of resetting any partial alert matching that has taken place. This *must*
+     * be set true if updating conditions, dampening rules or the conditionExpressin (ANY vs ALL).  If in doubt, set to true
+     * as the loss of partial matching is better than corrupted matching.
+     * @return
+     * @throws InvalidAlertDefinitionException
+     * @throws AlertDefinitionUpdateException
+     */
     AlertDefinition updateAlertDefinition(Subject subject, int alertDefinitionId, AlertDefinition alertDefinition,
-        boolean updateInternals) throws InvalidAlertDefinitionException, AlertDefinitionUpdateException;
+        boolean resetMatching) throws InvalidAlertDefinitionException, AlertDefinitionUpdateException;
 
     int purgeUnusedAlertDefinitions();
 
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/GroupAlertDefinitionManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/GroupAlertDefinitionManagerBean.java
index 8974c30..cde2f04 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/GroupAlertDefinitionManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/GroupAlertDefinitionManagerBean.java
@@ -216,7 +216,7 @@ public class GroupAlertDefinitionManagerBean implements GroupAlertDefinitionMana
 
     @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
     public AlertDefinition updateGroupAlertDefinitions(Subject subject, AlertDefinition groupAlertDefinition,
-        boolean purgeInternals) throws InvalidAlertDefinitionException, AlertDefinitionUpdateException {
+        boolean resetMatching) throws InvalidAlertDefinitionException, AlertDefinitionUpdateException {
         if (LOG.isDebugEnabled()) {
             LOG.debug("updateGroupAlertDefinition: " + groupAlertDefinition);
         }
@@ -225,7 +225,7 @@ public class GroupAlertDefinitionManagerBean implements GroupAlertDefinitionMana
         AlertDefinition updated = null;
         try {
             updated = alertDefinitionManager.updateAlertDefinition(subject, groupAlertDefinition.getId(),
-                groupAlertDefinition, purgeInternals); // do not allow direct undeletes of an alert definition
+                groupAlertDefinition, resetMatching); // do not allow direct undeletes of an alert definition
         } catch (Throwable t) {
             throw new AlertDefinitionUpdateException("Failed to update a GroupAlertDefinition: "
                 + groupAlertDefinition.toSimpleString(), t);
@@ -244,7 +244,7 @@ public class GroupAlertDefinitionManagerBean implements GroupAlertDefinitionMana
         for (Integer alertDefinitionId : alertDefinitions) {
             try {
                 alertDefinitionManager.updateAlertDefinition(overlord, alertDefinitionId, groupAlertDefinition,
-                    purgeInternals);
+                    resetMatching);
             } catch (Throwable t) {
                 // continue on error, update as many as possible
                 if (firstThrowable == null) {
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/GroupAlertDefinitionManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/GroupAlertDefinitionManagerLocal.java
index 3db4ea9..13faf1d 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/GroupAlertDefinitionManagerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/GroupAlertDefinitionManagerLocal.java
@@ -41,8 +41,18 @@ public interface GroupAlertDefinitionManagerLocal {
 
     int disableGroupAlertDefinitions(Subject subject, Integer[] groupAlertDefinitionIds);
 
+    /**
+     * @param subject
+     * @param groupAlertDefinition
+     * @param resetMatching Incur the overhead of resetting any partial alert matching that has taken place. This *must*
+     * be set true if updating conditions, dampening rules or the conditionExpressin (ANY vs ALL).  If in doubt, set to true
+     * as the loss of partial matching is better than corrupted matching.
+     * @return
+     * @throws InvalidAlertDefinitionException
+     * @throws AlertDefinitionUpdateException
+     */
     AlertDefinition updateGroupAlertDefinitions(Subject subject, AlertDefinition groupAlertDefinition,
-        boolean purgeInternals) throws InvalidAlertDefinitionException, AlertDefinitionUpdateException;
+        boolean resetMatching) throws InvalidAlertDefinitionException, AlertDefinitionUpdateException;
 
     // required to implement system side-effects as a result of modifying group membership or deleting groups
     void addGroupAlertDefinitions(Subject subject, int groupId, int[] resourcesIdsToAdd)
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java
index 79c7935..f7ae643 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java
@@ -511,13 +511,14 @@ public class ResourceManagerBean implements ResourceManagerLocal, ResourceManage
             PluginConfigurationUpdate.QUERY_DELETE_BY_RESOURCES_1, // first, delete the raw configs for the config
             PluginConfigurationUpdate.QUERY_DELETE_BY_RESOURCES_2, // then delete the config objects
             PluginConfigurationUpdate.QUERY_DELETE_BY_RESOURCES_3, // then the history objects wrapping those configs
-            AlertConditionLog.QUERY_DELETE_BY_RESOURCES, //    Don't
-            AlertNotificationLog.QUERY_DELETE_BY_RESOURCES, // alter
-            Alert.QUERY_DELETE_BY_RESOURCES, //                order
-            AlertCondition.QUERY_DELETE_BY_RESOURCES, //       of
-            AlertDampeningEvent.QUERY_DELETE_BY_RESOURCES, //  alert-
-            AlertNotification.QUERY_DELETE_BY_RESOURCES, //    related
-            AlertDefinition.QUERY_DELETE_BY_RESOURCES, //      deletes
+            AlertConditionLog.QUERY_DELETE_BY_RESOURCES, //             Don't
+            AlertConditionLog.QUERY_DELETE_BY_RESOURCES_BULK_DELETE, // alter               
+            AlertNotificationLog.QUERY_DELETE_BY_RESOURCES, //          the
+            Alert.QUERY_DELETE_BY_RESOURCES, //                         order
+            AlertCondition.QUERY_DELETE_BY_RESOURCES, //                of
+            AlertDampeningEvent.QUERY_DELETE_BY_RESOURCES, //           alert-
+            AlertNotification.QUERY_DELETE_BY_RESOURCES, //             related
+            AlertDefinition.QUERY_DELETE_BY_RESOURCES, //               deletes
             JPADrift.QUERY_DELETE_BY_RESOURCES, //       drift before changeset
             JPADriftChangeSet.QUERY_DELETE_BY_RESOURCES };
 
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/jobs/DataPurgeJob.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/jobs/DataPurgeJob.java
index 0cc04f4..dc8275c 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/jobs/DataPurgeJob.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/jobs/DataPurgeJob.java
@@ -32,6 +32,7 @@ import org.quartz.StatefulJob;
 
 import org.rhq.core.domain.auth.Subject;
 import org.rhq.enterprise.server.RHQConstants;
+import org.rhq.enterprise.server.alert.AlertConditionManagerLocal;
 import org.rhq.enterprise.server.alert.AlertDefinitionManagerLocal;
 import org.rhq.enterprise.server.alert.AlertManagerLocal;
 import org.rhq.enterprise.server.alert.AlertNotificationManagerLocal;
@@ -56,7 +57,6 @@ public class DataPurgeJob extends AbstractStatefulJob {
     private static final Log LOG = LogFactory.getLog(DataPurgeJob.class);
 
     private static long HOUR = 60 * 60 * 1000L;
-    private static long DAY = 24L * HOUR;
 
     /**
      * Schedules a purge job to trigger right now. This will not block - it schedules the job to trigger but immediately
@@ -118,6 +118,7 @@ public class DataPurgeJob extends AbstractStatefulJob {
         purgeEventData(LookupUtil.getEventManager(), systemConfig);
         purgeAlertData(LookupUtil.getAlertManager(), systemConfig);
         purgeUnusedAlertDefinitions(LookupUtil.getAlertDefinitionManager());
+        purgeOrphanedAlertConditions(LookupUtil.getAlertConditionManager());
         purgeOrphanedAlertNotifications(LookupUtil.getAlertNotificationManager());
         purgeMeasurementTraitData(LookupUtil.getMeasurementDataManager(), systemConfig);
         purgeAvailabilityData(LookupUtil.getAvailabilityManager(), systemConfig);
@@ -239,6 +240,21 @@ public class DataPurgeJob extends AbstractStatefulJob {
         }
     }
 
+    private void purgeOrphanedAlertConditions(AlertConditionManagerLocal alertConditionManager) {
+        long timeStart = System.currentTimeMillis();
+        LOG.info("Alert condition orphan purge starting at " + new Date(timeStart));
+        int orphansPurged = 0;
+
+        try {
+            orphansPurged = alertConditionManager.purgeOrphanedAlertConditions();
+        } catch (Exception e) {
+            LOG.error("Failed to purge alert condition data. Cause: " + e, e);
+        } finally {
+            long duration = System.currentTimeMillis() - timeStart;
+            LOG.info("Purged [" + orphansPurged + "] orphan alert conditions - completed in [" + duration + "]ms");
+        }
+    }
+
     private void purgeOrphanedAlertNotifications(AlertNotificationManagerLocal alertNotificationManager) {
         long timeStart = System.currentTimeMillis();
         LOG.info("Alert notification orphan purge starting at " + new Date(timeStart));


commit 18f46f5624b562364e6063451392905dc6e95725
Author: John Mazzitelli <mazz at redhat.com>
Date:   Wed Jun 20 14:04:02 2012 -0400

    fix eclipse classpath - location for swizzle is wrong

diff --git a/.classpath b/.classpath
index 76e080c..9362891 100644
--- a/.classpath
+++ b/.classpath
@@ -241,7 +241,7 @@
 	<classpathentry exported="true" kind="var" path="M2_REPO/org/jboss/jbossws/jbossws-native-core/3.1.1.GA/jbossws-native-core-3.1.1.GA.jar"/>
 	<classpathentry exported="true" kind="var" path="M2_REPO/org/apache/maven/maven-project/2.0.8/maven-project-2.0.8.jar"/>
 	<classpathentry exported="true" kind="var" path="M2_REPO/org/apache/maven/maven-plugin-api/2.0.8/maven-plugin-api-2.0.8.jar"/>
-	<classpathentry exported="true" kind="var" path="M2_REPO/org/codehaus/swizzle/1.6.1/swizzle-confluence-1.6.1.jar"/>
+	<classpathentry exported="true" kind="var" path="M2_REPO/org/codehaus/swizzle/swizzle-confluence/1.6.1/swizzle-confluence-1.6.1.jar"/>
 	<classpathentry exported="true" kind="var" path="M2_REPO/org/jvnet/inflector/0.7.0/inflector-0.7.0.jar"/>
 	<classpathentry exported="true" kind="var" path="M2_REPO/net/augeas/augeas/0.0.2/augeas-0.0.2.jar"/>
 	<classpathentry exported="true" kind="var" path="M2_REPO/org/json/json/20080701/json-20080701.jar"/>


commit 4482e902d123cc6881fe5b4308bbcf0ee9ff4846
Author: John Mazzitelli <mazz at redhat.com>
Date:   Wed Jun 20 12:31:33 2012 -0400

    add the ability to inspect the changed configuration in the test page that tests the config editor

diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/test/configuration/TestConfigurationView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/test/configuration/TestConfigurationView.java
index 3f3e154..31d17a3 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/test/configuration/TestConfigurationView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/test/configuration/TestConfigurationView.java
@@ -28,6 +28,10 @@ import com.smartgwt.client.widgets.events.ClickHandler;
 import com.smartgwt.client.widgets.layout.LayoutSpacer;
 
 import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.Property;
+import org.rhq.core.domain.configuration.PropertyList;
+import org.rhq.core.domain.configuration.PropertyMap;
+import org.rhq.core.domain.configuration.PropertySimple;
 import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
 import org.rhq.enterprise.gui.coregui.client.CoreGUI;
 import org.rhq.enterprise.gui.coregui.client.components.configuration.ConfigurationEditor;
@@ -133,9 +137,37 @@ public class TestConfigurationView
     }
 
     private void save() {
-        CoreGUI.getMessageCenter().notify(
-            new Message("Configuration updated.", "Test configuration updated."));
+        StringBuilder str = new StringBuilder("=~pre~=");
+        Configuration c = editor.getConfiguration();
+        Map<String, Property> allProps = c.getAllProperties();
+        for (Property prop : allProps.values()) {
+            getPropertyStrings(prop, str, "");
+        }
+        str.append("=~/pre~=");
+        CoreGUI.getMessageCenter().notify(new Message("Configuration updated.", str.toString()));
         reloadConfiguration();
     }
 
+    private void getPropertyStrings(Property prop, StringBuilder str, String indent) {
+        if (prop instanceof PropertySimple) {
+            String value = ((PropertySimple) prop).getStringValue();
+            str.append(indent + prop.getName() + "=" + ((value != null) ? value : "~~VALUE WAS NULL~~"));
+            str.append("\n");
+        } else if (prop instanceof PropertyMap) {
+            str.append(indent + prop.getName() + " MAP:\n");
+            PropertyMap propMap = (PropertyMap) prop;
+            Map<String, Property> map = propMap.getMap();
+            for (Property val : map.values()) {
+                getPropertyStrings(val, str, indent + "   ");
+            }
+        } else if (prop instanceof PropertyList) {
+            str.append(indent + prop.getName() + " LIST:\n");
+            PropertyList propList = (PropertyList) prop;
+            for (Property val : propList.getList()) {
+                getPropertyStrings(val, str, indent + "   ");
+            }
+        } else {
+            str.append("unknown prop type: " + prop);
+        }
+    }
 }


commit 953419eaa4392cb2826b76351e72ef30789d6b92
Author: John Mazzitelli <mazz at redhat.com>
Date:   Wed Jun 20 11:35:52 2012 -0400

    provide an eclipse external tool to allow eclipse developer to easily purge their RHQ dev-container server from extra plugins. this leaves intact a small subset of plugins. this allows for faster rhq server startup.

diff --git a/etc/eclipse-tools/maven/RHQ Delete Extra Plugins From Dev Container.launch b/etc/eclipse-tools/maven/RHQ Delete Extra Plugins From Dev Container.launch
new file mode 100644
index 0000000..1fa6810
--- /dev/null
+++ b/etc/eclipse-tools/maven/RHQ Delete Extra Plugins From Dev Container.launch	
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<launchConfiguration type="org.eclipse.ui.externaltools.ProgramLaunchConfigurationType">
+<stringAttribute key="bad_container_name" value="\rhq\etc\eclipse-tools\maven"/>
+<booleanAttribute key="org.eclipse.debug.core.appendEnvironmentVariables" value="true"/>
+<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
+<listEntry value="org.eclipse.ui.externaltools.launchGroup"/>
+</listAttribute>
+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${system_path:sh}"/>
+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="-c &quot;rm hadoop* jopr-jboss-as-5* jopr-jboss-cache* jopr-tomcat* modcluster* pattern* rhq-augeas* rhq-aliases* rhq-apache* rhq-byteman* rhq-cobbler* rhq-cron* rhq-database* rhq-grub* rhq-hosts* rhq-hudson* rhq-iis* rhq-irc* rhq-jboss-as-7* rhq-kickstart* rhq-mysql* rhq-netservices* rhq-oracle* rhq-postgres* rhq-postfix* rhq-samba* rhq-script2* rhq-snmp* rhq-sshd* rhq-sudoers* rhq-twitter* rhq-virt*&quot;"/>
+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/rhq/dev-container/jbossas/server/default/deploy/rhq.ear/rhq-downloads/rhq-plugins}"/>
+</launchConfiguration>


commit 76a9b14a24bf361f6916203c133500a77d98da73
Author: Lukas Krejci <lkrejci at redhat.com>
Date:   Wed Jun 20 15:29:43 2012 +0200

    Rename the method to be more descriptive.

diff --git a/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClient.java b/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClient.java
index e350302..384a6e0 100644
--- a/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClient.java
+++ b/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClient.java
@@ -81,7 +81,7 @@ public class LocalClient implements RhqFacade {
                         Object proxy = AccessController.doPrivileged(new PrivilegedAction<Object>() {
                             @Override
                             public Object run() {
-                                return getProxy(getLocalSLSB(manager), manager.remote());
+                                return getScriptingProxy(getLocalSLSB(manager), manager);
                             }
                         });
 
@@ -112,8 +112,8 @@ public class LocalClient implements RhqFacade {
         return remoteApiIface.cast(proxy);
     }
 
-    private <T> T getProxy(Object slsb, Class<T> iface) {
-        RhqManager manager = RhqManager.forInterface(iface);
+    private Object getScriptingProxy(Object slsb, RhqManager manager) {
+        Class<?> iface = manager.remote();
 
         Class<?> simplified = null;
 
@@ -128,7 +128,7 @@ public class LocalClient implements RhqFacade {
         Object proxy = Proxy.newProxyInstance(iface.getClassLoader(), new Class<?>[] { simplified },
             new LocalClientProxy(slsb, this, manager));
 
-        return iface.cast(proxy);
+        return proxy;
     }
 
     private Object getLocalSLSB(RhqManager manager) {


commit 56d3bb7e5f2b3ec81138841058edebe9a6bc1ac2
Author: Lukas Krejci <lkrejci at redhat.com>
Date:   Wed Jun 20 15:29:15 2012 +0200

    CLI code completion should now be language independent.

diff --git a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java
index 9811d2a..5d1af69 100644
--- a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java
+++ b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java
@@ -40,9 +40,6 @@ import java.util.Map;
 import javax.script.ScriptEngine;
 import javax.script.ScriptException;
 
-import gnu.getopt.Getopt;
-import gnu.getopt.LongOpt;
-
 import jline.ArgumentCompletor;
 import jline.Completor;
 import jline.ConsoleReader;
@@ -56,7 +53,11 @@ import org.rhq.core.domain.auth.Subject;
 import org.rhq.enterprise.client.commands.ClientCommand;
 import org.rhq.enterprise.client.commands.ScriptCommand;
 import org.rhq.enterprise.client.script.CommandLineParseException;
+import org.rhq.enterprise.client.utility.CLIMetadataProvider;
+import org.rhq.enterprise.client.utility.CodeCompletionCompletorWrapper;
+import org.rhq.enterprise.client.utility.DummyCodeCompletion;
 import org.rhq.enterprise.clientapi.RemoteClient;
+import org.rhq.scripting.CodeCompletion;
 
 /**
  * @author Greg Hinkle
@@ -100,7 +101,7 @@ public class ClientMain {
     // The subject that will be used to carry out all requested actions
     private Subject subject;
     
-    private InteractiveJavascriptCompletor serviceCompletor;
+    private CodeCompletion codeCompletion;
 
     private boolean interactiveMode = true;
 
@@ -199,12 +200,9 @@ public class ClientMain {
         sc.initClient(this);        
     }
     
-    private void initServiceCompletor() {
-        this.serviceCompletor.setContext(getScriptEngine().getContext());
-
-        if (remoteClient != null) {
-            this.serviceCompletor.setServices(remoteClient.getScriptingAPI());
-        }
+    private void initCodeCompletion() {
+        this.codeCompletion.setScriptContext(getScriptEngine().getContext());
+        this.codeCompletion.setMetadataProvider(new CLIMetadataProvider());
     }
 
     public ClientMain() {
@@ -233,12 +231,19 @@ public class ClientMain {
             Completor helpCompletor = new ArgumentCompletor(new Completor[] { new SimpleCompletor("help"),
                 new SimpleCompletor(commands.keySet().toArray(new String[commands.size()])) });
     
-            this.serviceCompletor = new InteractiveJavascriptCompletor(consoleReader);
-            consoleReader.addCompletor(new MultiCompletor(new Completor[] { serviceCompletor, helpCompletor,
+            this.codeCompletion = ScriptEngineFactory.getCodeCompletion(getLanguage());
+            if (codeCompletion == null) {
+                //the language module for this language doesn't support code completion
+                //let's provide a dummy one.
+                codeCompletion = new DummyCodeCompletion();
+            }
+
+            initCodeCompletion();
+
+            consoleReader.addCompletor(new MultiCompletor(new Completor[] {
+                new CodeCompletionCompletorWrapper(codeCompletion, outputWriter), helpCompletor,
                 commandCompletor }));
                 
-            initServiceCompletor();
-    
             // enable pagination
             consoleReader.setUsePagination(true);
         }
@@ -375,7 +380,7 @@ public class ClientMain {
         } else {
             boolean result = commands.get("exec").execute(this, args);
             if (loggedIn()) {
-                this.serviceCompletor.setContext(getScriptEngine().getContext());
+                this.codeCompletion.setScriptContext(getScriptEngine().getContext());
             }
 
             return result;
@@ -595,7 +600,7 @@ public class ClientMain {
 
         initScriptCommand();
         if (isInteractiveMode()) {
-            initServiceCompletor();
+            initCodeCompletion();
         }
     }
 
diff --git a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/InteractiveJavascriptCompletor.java b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/InteractiveJavascriptCompletor.java
deleted file mode 100644
index 0f1b232..0000000
--- a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/InteractiveJavascriptCompletor.java
+++ /dev/null
@@ -1,603 +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.client;
-
-import java.beans.BeanInfo;
-import java.beans.Introspector;
-import java.beans.MethodDescriptor;
-import java.beans.PropertyDescriptor;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
-import java.lang.reflect.Type;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import javax.jws.WebParam;
-import javax.script.Bindings;
-import javax.script.ScriptContext;
-
-import jline.Completor;
-import jline.ConsoleReader;
-
-import org.rhq.core.domain.auth.Subject;
-import org.rhq.enterprise.client.utility.ReflectionUtility;
-import org.rhq.enterprise.clientapi.RemoteClientProxy;
-
-/**
- * A Contextual JavaScript interactive completor. Not perfect, but
- * handles a fair number of cases.
- *
- * @author Greg Hinkle
- */
-public class InteractiveJavascriptCompletor implements Completor {
-
-    private Map<String, Object> services;
-
-    private ScriptContext context;
-
-    private String lastComplete;
-
-    // Consecutive times this exact complete has been requested
-    private int recomplete;
-    private ConsoleReader consoleReader;
-
-    private static final Set<String> IGNORED_METHODS;
-    static {
-        IGNORED_METHODS = new HashSet<String>();
-        IGNORED_METHODS.add("newProxyInstance");
-        IGNORED_METHODS.add("hashCode");
-        IGNORED_METHODS.add("equals");
-        IGNORED_METHODS.add("getInvocationHandler");
-        IGNORED_METHODS.add("setHandler");
-        IGNORED_METHODS.add("isProxyClass");
-        IGNORED_METHODS.add("newProxyInstance");
-        IGNORED_METHODS.add("getProxyClass");
-        IGNORED_METHODS.add("main");
-        IGNORED_METHODS.add("handler");
-        IGNORED_METHODS.add("init");
-        IGNORED_METHODS.add("initChildren");
-        IGNORED_METHODS.add("initMeasurements");
-        IGNORED_METHODS.add("initOperations");
-    }
-
-    public InteractiveJavascriptCompletor(ConsoleReader reader) {
-        this.consoleReader = reader;
-    }
-
-    public void setServices(Map<String, Object> services) {
-        this.services = services;
-    }
-
-    @Override
-    @SuppressWarnings("unchecked")
-    public int complete(String s, int i, @SuppressWarnings("rawtypes") List list) {
-        try {
-            if (lastComplete != null && lastComplete.equals(s)) {
-                recomplete++;
-            } else {
-                recomplete = 1;
-            }
-
-            lastComplete = s;
-
-            String base = s;
-
-            int rootLength = 0;
-
-            if (s.indexOf('=') > 0) {
-                base = s.substring(s.indexOf("=") + 1).trim();
-                rootLength = s.length() - base.length();
-            }
-
-            String[] call = base.split("\\.");
-            if (base.endsWith(".")) {
-                String[] argPadded = new String[call.length + 1];
-                System.arraycopy(call, 0, argPadded, 0, call.length);
-                argPadded[call.length] = "";
-                call = argPadded;
-            }
-
-            if (call.length == 1) {
-                Map<String, Object> matches = getContextMatches(call[0]);
-                if (matches.size() == 1 && matches.containsKey(call[0]) && !s.endsWith(".")) {
-                    list.add(".");
-                    return rootLength + call[0].length() + 1;
-
-                } else {
-                    list.addAll(matches.keySet());
-                }
-            } else {
-                Object rootObject = context.getAttribute(call[0]);
-                if (rootObject != null) {
-                    String theRest = base.substring(call[0].length() + 1, base.length());
-                    int matchIndex = contextComplete(rootObject, theRest, i, list);
-                    Collections.sort(list);
-                    return rootLength + call[0].length() + 1 + matchIndex;
-                }
-            }
-
-            Collections.sort(list);
-
-            return (list.size() == 0) ? (-1) : rootLength;
-        } catch (Exception e) {
-            e.printStackTrace();
-            return -1;
-        }
-    }
-
-    /**
-     * Base Object can be an object where we're looking for methods on it, or an
-     * interface. This recursively works off the completions left to right.
-     *
-     * Objects can be completed with fields or method calls.
-     * method parameters are completed with type matching
-     * method result chainings are completed based on declared return types
-     *
-     * e.g. have a Resource in context as myResource. Original string is
-     * "myResource.name". This method would be called with a baseObject ==
-     * to myResource and the string "name".
-     *
-     * Note: this method will not and should not execute methods, but will
-     * read field properties to continue chained completions.
-     *
-     * @param baseObject the context object or class to complete from
-     * @param s the relative command string to check
-     * @param i
-     * @param list
-     * @return location of relative completion
-     */
-    private int contextComplete(Object baseObject, String s, int i, List<String> list) {
-        String temp = s.split("\\(", 2)[0];
-        if (temp.contains(".")) {
-            String[] call = temp.split("\\.", 2);
-
-            String next = call[0];
-            if (next.contains("(")) {
-                next = next.substring(0, next.indexOf("("));
-            }
-
-            Map<String, List<Object>> matches = getContextMatches(baseObject, next);
-            if (!matches.isEmpty()) {
-                Object rootObject = matches.get(next).get(0);
-                if (rootObject instanceof PropertyDescriptor && !(baseObject instanceof Class)) {
-                    try {
-                        rootObject = invoke(baseObject, ((PropertyDescriptor) rootObject).getReadMethod());
-                    } catch (Exception e) {
-                        e.printStackTrace();
-                    }
-                } else if (rootObject instanceof Method) {
-                    rootObject = ((Method) rootObject).getReturnType();
-                }
-
-                return call[0].length() + 1 + contextComplete(rootObject, call[1], i, list);
-            } else {
-                return -1;
-            }
-        } else {
-            String[] call = s.split("\\(", 2);
-
-            Map<String, List<Object>> matches = getContextMatches(baseObject, call[0]);
-
-            if (call.length == 2 && matches.containsKey(call[0])) {
-
-                int x = 0;
-                for (String key : matches.keySet()) {
-
-                    List<Object> matchList = matches.get(key);
-
-                    if (recomplete == 2) {
-                        List<Method> methods = new ArrayList<Method>();
-                        for (Object match : matchList) {
-                            if (match instanceof Method) {
-                                methods.add((Method) match);
-                            }
-                        }
-                        displaySignatures(baseObject, methods.toArray(new Method[methods.size()]));
-                        return -1;
-                    }
-
-                    for (Object match : matchList) {
-
-                        if (key.equals(call[0]) && match instanceof Method) {
-
-                            int result = completeParameters(baseObject, call[1], i, list, (Method) match); // x should be the same for all calls
-                            if (result > 0) {
-                                x = result;
-                            }
-                        }
-                    }
-                }
-                return call[0].length() + 1 + x;
-            }
-
-            if (matches.size() == 1 && matches.containsKey(call[0])) {
-                if (matches.get(call[0]).get(0) instanceof Method) {
-                    list.add("(" + (((Method) matches.get(call[0]).get(0)).getParameterTypes().length == 0 ? ")" : ""));
-                }
-                return call[0].length() + 1;
-            }
-
-            if (recomplete == 2) {
-                List<Method> methods = new ArrayList<Method>();
-                for (List<Object> matchList : matches.values()) {
-                    for (Object val : matchList) {
-                        if (val instanceof Method) {
-                            methods.add((Method) val);
-                        }
-                    }
-                }
-                displaySignatures(baseObject, methods.toArray(new Method[methods.size()]));
-            } else {
-                if (matches.size() == 1 && matches.values().iterator().next().get(0) instanceof Method) {
-                    list.add(matches.keySet().iterator().next()
-                        + "("
-                        + ((((Method) matches.values().iterator().next().get(0)).getParameterTypes().length == 0 ? ")"
-                            : "")));
-                } else {
-                    list.addAll(matches.keySet());
-                }
-            }
-            return 0;
-
-        }
-    }
-
-    private void displaySignatures(Object object, Method... methods) {
-        try {
-            String start = this.consoleReader.getCursorBuffer().getBuffer().toString();
-            while ((this.consoleReader.getCursorBuffer().cursor > 0) && this.consoleReader.backspace()) {
-                ;
-            }
-            this.consoleReader.printNewline();
-            this.consoleReader.printNewline();
-            String[][] signatures = new String[methods.length][];
-            int i = 0;
-            for (Method m : methods) {
-                signatures[i++] = getSignature(object, m).split(" ", 2);
-            }
-
-            int maxReturnLength = 0;
-            for (String[] sig : signatures) {
-                if (sig[0].length() > maxReturnLength)
-                    maxReturnLength = sig[0].length();
-            }
-
-            for (String[] sig : signatures) {
-                for (i = 0; i < (maxReturnLength - sig[0].length()); i++) {
-                    this.consoleReader.printString(" ");
-                }
-
-                this.consoleReader.printString(sig[0]);
-                this.consoleReader.printString(" ");
-                this.consoleReader.printString(sig[1]);
-                this.consoleReader.printNewline();
-            }
-
-            this.consoleReader.drawLine();
-            this.consoleReader.putString(start);
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-    }
-
-    /**
-     * Split apart the parameters to a method call and complete the last parameter. If the last
-     * paramater has a valid value close that field with a "," for the next param or a ")" if is
-     * the last parameter. Does all machting according to the type of the parameters of the
-     * supplied method.
-     *
-     * @param baseObject
-     * @param params
-     * @param i
-     * @param list
-     * @param method
-     * @return
-     */
-    public int completeParameters(Object baseObject, String params, int i, List<String> list, Method method) {
-
-        String[] paramList = params.split(",");
-
-        Class<?>[] c = method.getParameterTypes();
-
-        String lastParam = paramList[paramList.length - 1];
-        int paramIndex = paramList.length - 1;
-        if (params.trim().endsWith(",")) {
-            lastParam = "";
-            paramIndex++;
-        }
-
-        int baseLength = 0;
-
-        for (int x = 0; x < paramIndex; x++) {
-            Object paramFound = context.getAttribute(paramList[x]);
-
-            if (paramFound != null && !c[x].isAssignableFrom(paramFound.getClass())) {
-                return -1;
-            }
-            baseLength += paramList[x].length() + 1;
-        }
-
-        if (paramIndex >= c.length) {
-            if (params.endsWith(")")) {
-                return -1;
-            } else {
-                list.add(params + ")");
-                return (params + ")").length();
-            }
-        } else {
-
-            if (baseObject instanceof Map && method.getName().equals("get") && method.getParameterTypes().length == 1) {
-                //unused Class<?> keyType = method.getParameterTypes()[0];
-                for (Object key : ((Map<?, ?>) baseObject).keySet()) {
-                    String lookupChoice = "\'" + String.valueOf(key) + "\'";
-                    if (lookupChoice.startsWith(lastParam)) {
-                        list.add(lookupChoice);
-                    }
-                }
-                if (list.size() == 1) {
-                    list.set(0, list.get(0) + ")");
-                }
-
-            } else {
-                Class<?> parameterType = c[paramIndex];
-
-                Map<String, Object> matches = getContextMatches(lastParam, parameterType);
-
-                if (matches.size() == 1 && matches.containsKey(lastParam)) {
-
-                    list.add(paramIndex == c.length - 1 ? ")" : ",");
-                    return baseLength + lastParam.length();
-                } else {
-                    list.addAll(matches.keySet());
-                }
-            }
-
-            return baseLength;
-        }
-    }
-
-    private Map<String, Object> getContextMatches(String start) {
-        Map<String, Object> found = new HashMap<String, Object>();
-        if (context != null) {
-            for (Integer scope : context.getScopes()) {
-                Bindings bindings = context.getBindings(scope);
-                for (String var : bindings.keySet()) {
-                    if (var.startsWith(start)) {
-                        found.put(var, bindings.get(var));
-                    }
-                }
-            }
-        }
-        if (services != null) {
-            for (String var : services.keySet()) {
-                if (var.startsWith(start)) {
-                    found.put(var, services.get(var));
-                }
-            }
-        }
-        return found;
-    }
-
-    /**
-     * Look through all available contexts to find bindings that both start with
-     * the supplied start and match the typeFilter.
-     * @param start
-     * @param typeFilter
-     * @return
-     */
-    private Map<String, Object> getContextMatches(String start, Class<?> typeFilter) {
-        Map<String, Object> found = new HashMap<String, Object>();
-        if (context != null) {
-            for (int scope : context.getScopes()) {
-                Bindings bindings = context.getBindings(scope);
-                for (String var : bindings.keySet()) {
-                    if (var.startsWith(start)) {
-
-                        if ((bindings.get(var) != null && typeFilter.isAssignableFrom(bindings.get(var).getClass()))
-                            || recomplete == 3) {
-                            found.put(var, bindings.get(var));
-                        }
-                    }
-                }
-            }
-
-            if (typeFilter.isEnum()) {
-                for (Object ec : typeFilter.getEnumConstants()) {
-                    Enum<?> e = (Enum<?>) ec;
-                    String code = typeFilter.getSimpleName() + "." + e.name();
-                    if (code.startsWith(start)) {
-                        found.put(typeFilter.getSimpleName() + "." + e.name(), e);
-                    }
-                }
-            }
-        }
-        return found;
-    }
-
-    private Map<String, List<Object>> getContextMatches(Object baseObject, String start) {
-        Map<String, List<Object>> found = new HashMap<String, List<Object>>();
-
-        Class<?> baseObjectClass = null;
-        if (baseObject instanceof Class) {
-            baseObjectClass = (Class<?>) baseObject;
-        } else {
-            baseObjectClass = baseObject.getClass();
-        }
-
-        try {
-            if (baseObjectClass.equals(Void.TYPE))
-                return found;
-
-            BeanInfo info = null;
-            if (baseObjectClass.isInterface() || baseObjectClass.equals(Object.class)) {
-                info = Introspector.getBeanInfo(baseObjectClass);
-            } else {
-                info = Introspector.getBeanInfo(baseObjectClass, Object.class);
-            }
-
-            Set<Method> methodsCovered = new HashSet<Method>();
-
-            PropertyDescriptor[] descriptors = info.getPropertyDescriptors();
-            for (PropertyDescriptor desc : descriptors) {
-                if (desc.getName().startsWith(start) && (!IGNORED_METHODS.contains(desc.getName()))) {
-
-                    List<Object> list = found.get(desc.getName());
-                    if (list == null) {
-                        list = new ArrayList<Object>();
-                        found.put(desc.getName(), list);
-                    }
-                    list.add(desc);
-
-                    methodsCovered.add(desc.getReadMethod());
-                    methodsCovered.add(desc.getWriteMethod());
-                }
-            }
-
-            MethodDescriptor[] methods = info.getMethodDescriptors();
-            for (MethodDescriptor desc : methods) {
-                if (desc.getName().startsWith(start) && !methodsCovered.contains(desc.getMethod())
-                    && !desc.getName().startsWith("_d") && !IGNORED_METHODS.contains(desc.getName())) {
-
-                    Method m = desc.getMethod();
-                    boolean isProxy = isProxyMethod(baseObject, m);
-                    Class<?>[] parameters = m.getParameterTypes();
-                    boolean startsWithSubject = ((parameters.length > 0) && parameters[0].equals(Subject.class));
-                    if ((isProxy && startsWithSubject) || !startsWithSubject) {
-
-                        List<Object> list = found.get(desc.getName());
-                        if (list == null) {
-                            list = new ArrayList<Object>();
-                            found.put(desc.getName(), list);
-                        }
-                        list.add(m);
-                    }
-                }
-            }
-
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-        return found;
-    }
-
-    private static String getSignature(Object object, Method m) {
-
-        // If its our service proxy lookup the original interface that has the annotations
-        if (isProxyMethod(object, m)) {
-            Class<?>[] params = m.getParameterTypes();
-            Class<?>[] newParams = new Class[params.length + 1];
-            System.arraycopy(params, 0, newParams, 1, params.length);
-            newParams[0] = Subject.class;
-
-            try {
-                m =
-                    ((RemoteClientProxy) Proxy.getInvocationHandler(object)).getRemoteInterface().getDeclaredMethod(
-                        m.getName(), newParams);
-            } catch (NoSuchMethodException nsme) {
-                //
-            }
-        }
-
-        StringBuilder buf = new StringBuilder();
-        Type[] params = m.getGenericParameterTypes();
-        Annotation[][] annotations = m.getParameterAnnotations();
-        int i = 0;
-
-        buf.append(ReflectionUtility.getSimpleTypeString(m.getGenericReturnType()));
-        buf.append(" ");
-
-        buf.append(m.getName());
-        buf.append("(");
-        boolean first = true;
-        for (Type type : params) {
-            if (i == 0 && type.equals(Subject.class)) {
-                i++;
-                continue;
-            }
-            if (!first) {
-                buf.append(", ");
-            } else {
-                first = false;
-            }
-
-            String name = null;
-
-            if (annotations != null && annotations.length >= i) {
-                Annotation[] as = annotations[i];
-                for (Annotation a : as) {
-                    if (a instanceof WebParam) {
-                        name = ReflectionUtility.getSimpleTypeString(type) + " " + ((WebParam) a).name();
-                    }
-                }
-            }
-
-            if (name == null) {
-                name = ReflectionUtility.getSimpleTypeString(type);
-            }
-
-            buf.append(name);
-
-            i++;
-        }
-        buf.append(")");
-        return buf.toString();
-    }
-
-    private static boolean isProxyMethod(Object object, Method m) {
-
-        boolean result = false;
-        if (object instanceof Proxy) {
-            if (Proxy.getInvocationHandler(object) instanceof RemoteClientProxy) {
-                try {
-                    m =
-                        ((RemoteClientProxy) Proxy.getInvocationHandler(object)).getRemoteInterface()
-                            .getDeclaredMethod(m.getName(), m.getParameterTypes());
-                } catch (NoSuchMethodException e) {
-                    result = true;
-                }
-            }
-        }
-        return result;
-    }
-
-    public ScriptContext getContext() {
-        return context;
-    }
-
-    public void setContext(ScriptContext context) {
-        this.context = context;
-    }
-
-    private static Object invoke(Object o, Method m) throws IllegalAccessException, InvocationTargetException {
-        boolean access = m.isAccessible();
-        m.setAccessible(true);
-        try {
-            return m.invoke(o);
-        } finally {
-            m.setAccessible(access);
-        }
-    }
-}
diff --git a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/utility/CLIMetadataProvider.java b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/utility/CLIMetadataProvider.java
new file mode 100644
index 0000000..ff98b5c
--- /dev/null
+++ b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/utility/CLIMetadataProvider.java
@@ -0,0 +1,72 @@
+/*
+ * RHQ Management Platform
+ * Copyright 2012, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.client.utility;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+
+import javax.jws.WebParam;
+
+import org.rhq.scripting.MetadataProvider;
+
+/**
+ * @author Lukas Krejci
+ */
+public class CLIMetadataProvider implements MetadataProvider {
+
+    @Override
+    public String getParameterName(Method method, int parameterIndex) {
+        String name = null;
+
+        Annotation[][] paramAnnotations = method.getParameterAnnotations();
+
+        if (paramAnnotations.length > parameterIndex) {
+            Annotation[] annotations = paramAnnotations[parameterIndex];
+            for (Annotation a : annotations) {
+                if (a instanceof WebParam) {
+                    name = ((WebParam) a).name();
+                    break;
+                }
+            }
+        }
+
+        return name;
+    }
+
+    @Override
+    public String getDocumentation(Class<?> clazz) {
+        // TODO it'd be fantastic if we could do this, wouldn't it? 
+        return null;
+    }
+
+    @Override
+    public String getDocumentation(Method method) {
+        // TODO it'd be fantastic if we could do this, wouldn't it? 
+        return null;
+    }
+
+    @Override
+    public String getTypeName(Type type, boolean fullNames) {
+        return ReflectionUtility.getTypeString(type, fullNames);
+    }
+
+}
diff --git a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/utility/CodeCompletionCompletorWrapper.java b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/utility/CodeCompletionCompletorWrapper.java
new file mode 100644
index 0000000..8f2570c
--- /dev/null
+++ b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/utility/CodeCompletionCompletorWrapper.java
@@ -0,0 +1,24 @@
+package org.rhq.enterprise.client.utility;
+
+import java.io.PrintWriter;
+import java.util.List;
+
+import jline.Completor;
+
+import org.rhq.scripting.CodeCompletion;
+
+public class CodeCompletionCompletorWrapper implements Completor {
+
+    private CodeCompletion completion;
+    private PrintWriter output;
+
+    public CodeCompletionCompletorWrapper(CodeCompletion completion, PrintWriter output) {
+        this.completion = completion;
+        this.output = output;
+    }
+
+    @Override
+    public int complete(String buffer, int cursor, List candidates) {
+        return completion.complete(output, buffer, cursor, candidates);
+    }
+}
diff --git a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/utility/DummyCodeCompletion.java b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/utility/DummyCodeCompletion.java
new file mode 100644
index 0000000..2c28a4f
--- /dev/null
+++ b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/utility/DummyCodeCompletion.java
@@ -0,0 +1,50 @@
+/*
+ * RHQ Management Platform
+ * Copyright 2012, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.client.utility;
+
+import java.io.PrintWriter;
+import java.util.List;
+
+import javax.script.ScriptContext;
+
+import org.rhq.scripting.CodeCompletion;
+import org.rhq.scripting.MetadataProvider;
+
+/**
+ * @author Lukas Krejci
+ *
+ */
+public class DummyCodeCompletion implements CodeCompletion {
+
+    @Override
+    public void setScriptContext(ScriptContext scriptContext) {
+    }
+
+    @Override
+    public void setMetadataProvider(MetadataProvider metadataProvider) {
+    }
+
+    @Override
+    public int complete(PrintWriter output, String context, int cursorPosition, List candidates) {
+        return cursorPosition;
+    }
+
+}
diff --git a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/utility/ReflectionUtility.java b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/utility/ReflectionUtility.java
index c5c2f08..3bcb1cc 100644
--- a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/utility/ReflectionUtility.java
+++ b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/utility/ReflectionUtility.java
@@ -18,10 +18,10 @@
  */
 package org.rhq.enterprise.client.utility;
 
-import java.lang.reflect.Type;
+import java.lang.reflect.GenericArrayType;
 import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
 import java.lang.reflect.TypeVariable;
-import java.lang.reflect.GenericArrayType;
 import java.lang.reflect.WildcardType;
 
 /**
@@ -32,6 +32,10 @@ public class ReflectionUtility {
 
 
     public static String getSimpleTypeString(Type type) {
+        return getTypeString(type, false);
+    }
+
+    public static String getTypeString(Type type, boolean fullNames) {
         if (type instanceof ParameterizedType) {
             ParameterizedType pType = (ParameterizedType) type;
             Type[] typeArguments = pType.getActualTypeArguments();
@@ -43,26 +47,29 @@ public class ReflectionUtility {
                     typeArgString += ",";
                 }
 
-                typeArgString += getSimpleTypeString(typeArgument);
+                typeArgString += getTypeString(typeArgument, fullNames);
             }
-            return getSimpleTypeString(pType.getRawType()) + "<" + typeArgString + ">";
-
+            return getTypeString(pType.getRawType(), fullNames) + "<" + typeArgString + ">";
 
         } else if (type instanceof TypeVariable) {
-            TypeVariable vType = (TypeVariable) type;
-            return vType.getClass().getSimpleName();
+            TypeVariable<?> vType = (TypeVariable<?>) type;
+            return getName(vType.getClass(), fullNames);
         } else if (type instanceof GenericArrayType) {
             GenericArrayType aType = (GenericArrayType) type;
-            return aType.getClass().getSimpleName() + "[" + getSimpleTypeString(aType.getGenericComponentType()) + "]";
+            return getName(aType.getClass(), fullNames) + "["
+                + getTypeString(aType.getGenericComponentType(), fullNames) + "]";
         } else if (type instanceof WildcardType) {
-            return ((WildcardType)type).toString();
+            return ((WildcardType) type).toString();
         } else {
             if (type == null) {
                 return "";
             } else {
-                return ((Class)type).getSimpleName();
+                return getName((Class<?>) type, fullNames);
             }
         }
     }
 
+    private static String getName(Class<?> cls, boolean fullName) {
+        return fullName ? cls.getName() : cls.getSimpleName();
+    }
 }
diff --git a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JavascriptCompletor.java b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JavascriptCompletor.java
index d1df7f5..36eb060 100644
--- a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JavascriptCompletor.java
+++ b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JavascriptCompletor.java
@@ -38,6 +38,9 @@ import java.util.Set;
 import javax.script.Bindings;
 import javax.script.ScriptContext;
 
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
 import org.rhq.scripting.CodeCompletion;
 import org.rhq.scripting.MetadataProvider;
 
@@ -50,7 +53,8 @@ import org.rhq.scripting.MetadataProvider;
  */
 public class JavascriptCompletor implements CodeCompletion {
 
-    private static final String SUBJECT_CLASS_NAME = "org.rhq.core.domain.auth.Subject";
+    private static final Log LOG = LogFactory.getLog(JavascriptCompletor.class);
+
     private ScriptContext context;
     private MetadataProvider metadataProvider;
 
@@ -473,26 +477,21 @@ public class JavascriptCompletor implements CodeCompletion {
                     && !desc.getName().startsWith("_d") && !IGNORED_METHODS.contains(desc.getName())) {
 
                     Method m = desc.getMethod();
-                    //TODO THIS IS SO WRONG - the methods are there but we just "forget" to
-                    //to mention them to the user.
-                    boolean isProxy = isProxyMethod(baseObject, m);
-                    Class<?>[] parameters = m.getParameterTypes();
-                    boolean startsWithSubject = ((parameters.length > 0) && isSubjectClass(parameters[0]));
-                    if ((isProxy && startsWithSubject) || !startsWithSubject) {
-
-                        List<Object> list = found.get(desc.getName());
-                        if (list == null) {
-                            list = new ArrayList<Object>();
-                            found.put(desc.getName(), list);
-                        }
-                        list.add(m);
+
+                    List<Object> list = found.get(desc.getName());
+                    if (list == null) {
+                        list = new ArrayList<Object>();
+                        found.put(desc.getName(), list);
                     }
+                    list.add(m);
                 }
             }
 
         } catch (Exception e) {
+            LOG.info("Failure during code completion", e);
             e.printStackTrace(output);
         }
+
         return found;
     }
 
@@ -529,26 +528,6 @@ public class JavascriptCompletor implements CodeCompletion {
         return buf.toString();
     }
 
-    private static boolean isProxyMethod(Object object, Method m) {
-        // TODO this has to be changed - we have the MetaDataProvider which should be able
-        // to provide enough info so that the completors don't have to go through these hoops.
-        return false;
-
-        //        boolean result = false;
-        //        if (object instanceof Proxy) {
-        //            if (Proxy.getInvocationHandler(object) instanceof RemoteClientProxy) {
-        //                try {
-        //                    m =
-        //                        ((RemoteClientProxy) Proxy.getInvocationHandler(object)).getRemoteInterface()
-        //                            .getDeclaredMethod(m.getName(), m.getParameterTypes());
-        //                } catch (NoSuchMethodException e) {
-        //                    result = true;
-        //                }
-        //            }
-        //        }
-        //        return result;
-    }
-
     @Override
     public void setScriptContext(ScriptContext context) {
         this.context = context;
@@ -563,16 +542,4 @@ public class JavascriptCompletor implements CodeCompletion {
             m.setAccessible(access);
         }
     }
-
-    private boolean isSubjectClass(Class<?> cls) {
-        while (cls != null) {
-            if (SUBJECT_CLASS_NAME.equals(cls.getName())) {
-                return true;
-            }
-
-            cls = cls.getSuperclass();
-        }
-        
-        return false;
-    }
 }


commit c7cd0fa0318df8039f0864dd2faf3b2d67d4aaef
Author: Lukas Krejci <lkrejci at redhat.com>
Date:   Wed Jun 20 15:23:53 2012 +0200

    The simplified interfaces no longer inherit from the remote interfaces.
    They just provide the same (or simplified) methods.

diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/InterfaceSimplifier.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/InterfaceSimplifier.java
index 8407206..d6835a0 100644
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/InterfaceSimplifier.java
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/InterfaceSimplifier.java
@@ -47,31 +47,29 @@ public class InterfaceSimplifier {
     
     public static Class<?> simplify(Class<?> intf) {
         try {
-            ClassPool cp = ClassPool.getDefault();
+            ClassPool classPool = ClassPool.getDefault();
 
             String simplifiedName = getSimplifiedName(intf);
             LOG.debug("Simplifying " + intf + " (simplified interface name: " + simplifiedName + ")...");
 
             try {
-                CtClass cached = cp.get(simplifiedName);
-                return Class.forName(simplifiedName, false, cp.getClassLoader());
+                @SuppressWarnings("unused")
+                CtClass cached = classPool.get(simplifiedName);
+                return Class.forName(simplifiedName, false, classPool.getClassLoader());
 
             } catch (NotFoundException e) {
                 // ok... load it
             } catch (ClassNotFoundException e) {
-                LOG.debug("Class [" + simplifiedName + "] not found - cause: " + e);
+                LOG.debug("Class [" + simplifiedName + "] not found - cause: " + e, e);
             }
 
-            CtClass cc = cp.get(intf.getName());
+            CtClass originalClass = classPool.get(intf.getName());
 
-            CtClass cz = cp.getAndRename(intf.getName(), simplifiedName);
-            //            CtClass cz = cp.makeInterface(simpleName, cc);
+            CtClass newClass = classPool.makeInterface(simplifiedName);
 
-            cz.defrost();
+            newClass.defrost();
 
-            cz.setSuperclass(cc);
-
-            CtMethod[] methods = cc.getMethods();
+            CtMethod[] methods = originalClass.getMethods();
 
             for (CtMethod originalMethod : methods) {
 
@@ -81,10 +79,10 @@ public class InterfaceSimplifier {
                     CtClass[] simpleParams = new CtClass[params.length - 1];
 
                     System.arraycopy(params, 1, simpleParams, 0, params.length - 1);
-                    cz.defrost();
+                    newClass.defrost();
 
                     CtMethod newMethod = CtNewMethod.abstractMethod(originalMethod.getReturnType(), originalMethod
-                        .getName(), simpleParams, null, cz);
+.getName(), simpleParams, null, newClass);
 
                     ParameterAnnotationsAttribute originalAnnotationsAttribute = (ParameterAnnotationsAttribute) originalMethod
                         .getMethodInfo().getAttribute(ParameterAnnotationsAttribute.visibleTag);
@@ -111,11 +109,11 @@ public class InterfaceSimplifier {
 
                     }
 
-                    cz.addMethod(newMethod);
+                    newClass.addMethod(newMethod);
                 }
             }
 
-            return cz.toClass();
+            return newClass.toClass();
 
         } catch (NotFoundException e) {
             LOG.debug("Failed to simplify " + intf + " - cause: " + e);
diff --git a/modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/test/LocalClientTest.java b/modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/test/LocalClientTest.java
index eac3705..2236923 100644
--- a/modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/test/LocalClientTest.java
+++ b/modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/test/LocalClientTest.java
@@ -33,14 +33,13 @@ import javax.naming.spi.InitialContextFactory;
 import org.jmock.Expectations;
 import org.jmock.api.Invocation;
 import org.jmock.lib.action.CustomAction;
+import org.testng.Assert;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 
 import org.rhq.bindings.client.RhqManager;
 import org.rhq.core.domain.auth.Subject;
 import org.rhq.enterprise.client.LocalClient;
-import org.rhq.enterprise.server.alert.AlertManagerLocal;
-import org.rhq.enterprise.server.alert.AlertManagerRemote;
 import org.rhq.test.JMockTest;
 
 /**
@@ -67,13 +66,6 @@ public class LocalClientTest extends JMockTest {
     @Test
     public void testResilienceAgainstContextClassloaders() throws Exception {
         CONTEXT_MOCK_FOR_TEST = context.mock(Context.class);
-        final AlertManagerRemote alertManagerMock = (AlertManagerRemote) Proxy.newProxyInstance(getClass().getClassLoader(), new Class<?>[] { AlertManagerRemote.class, AlertManagerLocal.class }, new InvocationHandler() {
-            @Override
-            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
-                return null;
-            }
-            
-        });
         
         context.checking(new Expectations() {{
             allowing(CONTEXT_MOCK_FOR_TEST).lookup(with(any(String.class)));
@@ -122,8 +114,14 @@ public class LocalClientTest extends JMockTest {
             //this call creates the proxy and is theoretically prone to the context classloader
             Object am = lc.getScriptingAPI().get("AlertManager");
 
-            //check that both the original and simplified methods exist on the returned object
-            am.getClass().getMethod("deleteAlerts", new Class<?>[] { Subject.class, int[].class });            
+            //check that only the simplified method exists on the returned object
+            try {
+                am.getClass().getMethod("deleteAlerts", new Class<?>[] { Subject.class, int[].class });
+                Assert.fail("The original remote interface method should not be available on the scripting API proxy.");
+            } catch (NoSuchMethodException e) {
+                //expected
+            }
+
             am.getClass().getMethod("deleteAlerts", new Class<?>[] { int[].class });
         } finally {
             Thread.currentThread().setContextClassLoader(origCl);


commit 32a6fdd2b88f8711c1d1c14763e8230a62a8eb91
Author: Lukas Krejci <lkrejci at redhat.com>
Date:   Wed Jun 20 15:21:44 2012 +0200

    Fixing the local client tests and some leftover compilation errors in
    the code after the RhqFacade refactoring.

diff --git a/modules/enterprise/gui/base-perspective-jar/src/main/java/org/rhq/enterprise/server/perspective/AbstractPerspectiveResourceUIBean.java b/modules/enterprise/gui/base-perspective-jar/src/main/java/org/rhq/enterprise/server/perspective/AbstractPerspectiveResourceUIBean.java
index 74f7ab8..f13e087 100644
--- a/modules/enterprise/gui/base-perspective-jar/src/main/java/org/rhq/enterprise/server/perspective/AbstractPerspectiveResourceUIBean.java
+++ b/modules/enterprise/gui/base-perspective-jar/src/main/java/org/rhq/enterprise/server/perspective/AbstractPerspectiveResourceUIBean.java
@@ -2,7 +2,9 @@ package org.rhq.enterprise.server.perspective;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+
 import org.jboss.seam.annotations.web.RequestParameter;
+
 import org.rhq.core.domain.auth.Subject;
 import org.rhq.core.domain.criteria.ResourceCriteria;
 import org.rhq.core.domain.resource.Resource;
@@ -37,7 +39,7 @@ public class AbstractPerspectiveResourceUIBean extends AbstractPerspectiveUIBean
         Subject subject = this.perspectiveClient.getSubject();
 
         // ***NOTE***: The javassist.NotFoundException stack traces that are logged by this call can be ignored.
-        ResourceManagerRemote resourceManager = remoteClient.getResourceManager();
+        ResourceManagerRemote resourceManager = remoteClient.getProxy(ResourceManagerRemote.class);
         ResourceCriteria resourceCriteria = new ResourceCriteria();
         resourceCriteria.addFilterId(this.rhqResourceId);
         PageList<Resource> resources = resourceManager.findResourcesByCriteria(subject, resourceCriteria);
diff --git a/modules/enterprise/gui/base-perspective-jar/src/main/java/org/rhq/enterprise/server/perspective/PerspectiveClientUIBean.java b/modules/enterprise/gui/base-perspective-jar/src/main/java/org/rhq/enterprise/server/perspective/PerspectiveClientUIBean.java
index 77d8f24..d73431a 100644
--- a/modules/enterprise/gui/base-perspective-jar/src/main/java/org/rhq/enterprise/server/perspective/PerspectiveClientUIBean.java
+++ b/modules/enterprise/gui/base-perspective-jar/src/main/java/org/rhq/enterprise/server/perspective/PerspectiveClientUIBean.java
@@ -87,7 +87,7 @@ public class PerspectiveClientUIBean {
         if (subject == null) {
             RemoteClient remoteClient = getRemoteClient();
             // ***NOTE***: The javassist.NotFoundException stack traces that are logged by this call can be ignored.
-            SubjectManagerRemote subjectManager = remoteClient.getSubjectManager();
+            SubjectManagerRemote subjectManager = remoteClient.getProxy(SubjectManagerRemote.class);
             if (this.rhqSessionId != null) {
                 log.info("Retrieving subject for user [" + getUsername() + "] and sessionId [" + this.rhqSessionId
                     + "]...");
diff --git a/modules/enterprise/server/client-api/pom.xml b/modules/enterprise/server/client-api/pom.xml
index 81b559c..91682fa 100644
--- a/modules/enterprise/server/client-api/pom.xml
+++ b/modules/enterprise/server/client-api/pom.xml
@@ -46,7 +46,15 @@
          <artifactId>test-utils</artifactId>
          <version>${project.version}</version>
          <scope>test</scope>
-      </dependency>            
+      </dependency>        
+
+      <!-- Needed for the successful creation of the fake SLSB impls in the LocalClient test. -->      
+      <dependency>
+         <groupId>org.opensymphony.quartz</groupId>
+         <artifactId>quartz</artifactId>
+         <!-- NOTE: The version is defined in the root POM's dependencyManagement section. -->
+         <scope>test</scope>
+      </dependency>          
   </dependencies>
 
     <profiles>
diff --git a/modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/test/LocalClientTest.java b/modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/test/LocalClientTest.java
index e9bd928..eac3705 100644
--- a/modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/test/LocalClientTest.java
+++ b/modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/test/LocalClientTest.java
@@ -31,9 +31,12 @@ import javax.naming.NamingException;
 import javax.naming.spi.InitialContextFactory;
 
 import org.jmock.Expectations;
+import org.jmock.api.Invocation;
+import org.jmock.lib.action.CustomAction;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 
+import org.rhq.bindings.client.RhqManager;
 import org.rhq.core.domain.auth.Subject;
 import org.rhq.enterprise.client.LocalClient;
 import org.rhq.enterprise.server.alert.AlertManagerLocal;
@@ -74,7 +77,36 @@ public class LocalClientTest extends JMockTest {
         
         context.checking(new Expectations() {{
             allowing(CONTEXT_MOCK_FOR_TEST).lookup(with(any(String.class)));
-            will(returnValue(alertManagerMock));
+                will(new CustomAction("Fake JNDI lookup") {
+
+                    @Override
+                    public Object invoke(Invocation invocation) throws Throwable {
+                        //the JNDI name is "rhq/<BEAN_NAME>/local"
+                        String jndiName = (String) invocation.getParameter(0);
+
+                        String beanName = jndiName.substring(jndiName.indexOf('/') + 1, jndiName.lastIndexOf('/'));
+
+                        String managerName = beanName.substring(0, beanName.length() - "Bean".length());
+
+                        //we basically need to define a mock implementation of both the local and remote
+                        //interface here - as if it were a proper SLSB.
+                        RhqManager manager = Enum.valueOf(RhqManager.class, managerName);
+                        Class<?> remoteIface = manager.remote();
+
+                        String localIfaceName = remoteIface.getName().substring(0,
+                            remoteIface.getName().length() - "Remote".length())
+                            + "Local";
+                        Class<?> localIface = Class.forName(localIfaceName);
+
+                        return Proxy.newProxyInstance(getClass().getClassLoader(), new Class<?>[] { localIface,
+                            remoteIface }, new InvocationHandler() {
+                            @Override
+                            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+                                return null;
+                            }
+                        });
+                    }
+                });
             
             allowing(CONTEXT_MOCK_FOR_TEST).close();
         }});


commit 51d5d2537e1dc159f7c1a71302be9f810ba63613
Author: Simeon Pinder <spinder at redhat.com>
Date:   Wed Jun 20 08:56:40 2012 -0400

     [BZ 826542] disable incorrect unit tests. More work necessary to get this to pass with Arquillian properly.

diff --git a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/SecurityModuleOptionsTest.java b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/SecurityModuleOptionsTest.java
index 49d8040..e80ddec 100644
--- a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/SecurityModuleOptionsTest.java
+++ b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/SecurityModuleOptionsTest.java
@@ -1,319 +1,319 @@
-/*
- * 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 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.modules.plugins.jbossas7;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.List;
-
-import org.codehaus.jackson.JsonGenerationException;
-import org.codehaus.jackson.JsonNode;
-import org.codehaus.jackson.JsonProcessingException;
-import org.codehaus.jackson.map.JsonMappingException;
-import org.codehaus.jackson.map.ObjectMapper;
-import org.codehaus.jackson.map.SerializationConfig;
-import org.testng.annotations.BeforeSuite;
-import org.testng.annotations.Test;
-
-import org.rhq.modules.plugins.jbossas7.ModuleOptionsComponent.ModuleOptionType;
-import org.rhq.modules.plugins.jbossas7.ModuleOptionsComponent.Value;
-import org.rhq.modules.plugins.jbossas7.json.Address;
-import org.rhq.modules.plugins.jbossas7.json.Operation;
-import org.rhq.modules.plugins.jbossas7.json.ReadAttribute;
-import org.rhq.modules.plugins.jbossas7.json.Remove;
-import org.rhq.modules.plugins.jbossas7.json.Result;
-import org.rhq.modules.plugins.jbossas7.json.WriteAttribute;
-
-/**
- * Test exercising the subsystem=security/SecurityDomain/[Authentication, Authorization, Mapping, Audit, Acl, 
- *      Identity-Trust]
- * @author Simeon Pinder
- */
- at Test(groups = "unit")
-public class SecurityModuleOptionsTest extends AbstractConfigurationHandlingTest {
-
-    private static String user = "rhqadmin";
-    private static String pass = "as7";
-    private static String host = "localhost";
-    private static ASConnection con = null;
-    private static ObjectMapper mapper = null;
-    private ModuleOptionsComponent moc = null;
-
-    //Define some shared and reusable content
-    static HashMap<String, String> jsonMap = new HashMap<String, String>();
-    static {
-        jsonMap
-            .put(
-                "login-modules",
-                "[{\"flag\":\"required\", \"code\":\"Ldap\", \"module-options\":{\"bindDn\":\"uid=ldapSecureUser,ou=People,dc=redat,dc=com\", \"bindPw\":\"test126\", \"allowEmptyPasswords\":\"true\"}}]");
-        //              "[{\"flag\":\"required\", \"code\":\"Ldap\"}]");
-        jsonMap
-            .put(
-                "policy-modules",
-                "[{\"flag\":\"requisite\", \"code\":\"LdapExtended\", \"module-options\":{\"policy\":\"module\", \"policy1\":\"module1\"}}]");
-        jsonMap
-            .put("mapping-modules",
-                "[{\"code\":\"Test\", \"type\":\"attribute\", \"module-options\":{\"mapping\":\"module\", \"mapping1\":\"module1\"}}]");
-        jsonMap.put("provider-modules",
-            "[{\"code\":\"Providers\", \"module-options\":{\"provider\":\"module\", \"provider1\":\"module1\"}}]");
-    }
-
-    @BeforeSuite
-    private void initializeConnectionDetails() {
-        con = new ASConnection(host, 9990, user, pass);
-        mapper = new ObjectMapper();
-        mapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true);
-
-        moc = new ModuleOptionsComponent();
-    }
-
-    public static void main(String[] args) {
-        SecurityModuleOptionsTest test = new SecurityModuleOptionsTest();
-        try {
-            test.initializeConnectionDetails();
-            test.testPopulateModuleOptionsAndTypes();
-        } catch (Exception e) {
-            // TODO Auto-generated catch block
-            e.printStackTrace();
-        }
-
-    }
-
-    /**The test reads the existing property values, deserializes them and writes the same 
-     * contents back out to a running instance for all known ModuleOptionTypes.
-     * 
-     * @throws Exception
-     */
-    public void testPopulateModuleOptionsAndTypes() throws Exception {
-
-        //as7 node details.
-        String securityDomainId = "testDomain";
-        //TODO: spinder 6-6-12: this cannot run as a standalone itest until JIRA https://issues.jboss.org/browse/AS7-4951
-        //      is addressed as there is no way to automate setup of the information being tested.
-        String address = "subsystem=security,security-domain=" + securityDomainId + ",authentication=classic";
-        boolean verboseOutput = true;
-        boolean executeOperation = true;
-        for (ModuleOptionType t : ModuleOptionType.values()) {
-            String attribute = t.getAttribute();
-            if (verboseOutput) {
-                System.out.println("======= Running with ModuleOptionType:" + t + " attribute:" + attribute + ":");
-            }
-            if (attribute.equals("policy-modules")) {
-                address = "subsystem=security,security-domain=" + securityDomainId + ",authorization=classic";
-            } else if (attribute.equals("acl-modules")) {
-                address = "subsystem=security,security-domain=" + securityDomainId + ",acl=classic";
-            } else if (attribute.equals("mapping-modules")) {
-                address = "subsystem=security,security-domain=" + securityDomainId + ",mapping=classic";
-            } else if (attribute.equals("trust-modules")) {
-                address = "subsystem=security,security-domain=" + securityDomainId + ",identity-trust=classic";
-            } else if (attribute.equals("provider-modules")) {
-                address = "subsystem=security,security-domain=" + securityDomainId + ",audit=classic";
-            } else if (attribute.equals("login-modules")) {
-                address = "subsystem=security,security-domain=" + securityDomainId + ",authentication=classic";
-            } else {
-                assert false : "An unknown attribute '" + attribute
-                    + "' was found. Is there a new type to be supported?";
-            }
-
-            //test operation- read property always available.
-            Operation op = null;
-
-            //read the login-modules attribute
-            op = new ReadAttribute(new Address(address), attribute);
-            Result result = exerciseOperation(op, true, verboseOutput);
-            assert result.isSuccess() == true : "The operation '" + op + "' failed to read the resource."
-                + result.getFailureDescription();
-            //extract current results
-            Object rawResult = result.getResult();
-            assert rawResult != null : "Read of attribute'" + attribute + "' from address '" + address
-                + "' has returned no value. Are those values in the model?";
-
-            List<Value> list2 = new ArrayList<Value>();
-            //populate the Value component complete with module Options.
-            list2 = moc.populateSecurityDomainModuleOptions(result,
-                ModuleOptionsComponent.loadModuleOptionType(attribute));
-            if (verboseOutput) {
-                if (rawResult != null) {
-                    System.out.println("Raw Result is:" + rawResult + " and of type:" + rawResult.getClass());
-                } else {
-                    System.out.println("Read of attribute'" + attribute + "' from address '" + address
-                        + "' has returned no value. Are those values in the model?");
-                }
-            }
-            //write the login-modules attribute
-            op = new WriteAttribute(new Address(address));
-            op.addAdditionalProperty("name", attribute);//attribute to execute on
-            op.addAdditionalProperty("value", list2);
-
-            //Now test the operation
-            result = exerciseOperation(op, executeOperation, verboseOutput);
-            assert ((result.isSuccess() == true) || (result.getOutcome() == null)) : "The operation '" + op
-                + "' failed to write the resource.." + result.getFailureDescription();
-
-            //read the login-modules attribute
-            op = new ReadAttribute(new Address(address), attribute);
-            result = exerciseOperation(op, true, verboseOutput);
-            assert (result.isSuccess() == true) : "The operation '" + op + "' failed to read the resource."
-                + result.getFailureDescription();
-        }
-        if (verboseOutput) {
-            System.out.println("Successfully detected,read and wrote out attribute values for:");
-            for (ModuleOptionType type : ModuleOptionType.values()) {
-                System.out.println("\n" + type.ordinal() + " " + type.name());
-            }
-        }
-    }
-
-    /**Attempts to create a new Authentication node(authentication=classic) with a
-     * 'login-modules' attribute complete with 'code':'Ldap' and 'flag':'required' 
-     *  and some sample 'module-options' values.
-     *  
-     */
-    @Test(enabled = true)
-    public void testCreateSecurityDomainChildLoginModules() {
-        boolean execute = true;
-        boolean verboseOutput = false;
-        String address = "subsystem=security,security-domain=testDomain3,authentication=classic";
-        String attribute = ModuleOptionType.Authentication.getAttribute();
-
-        //test operation- read property always available.
-        Operation op = null;
-
-        //read the login-modules attribute
-        op = new ReadAttribute(new Address(address), attribute);
-        Result result = exerciseOperation(op, execute, verboseOutput);
-        assert result.isSuccess() == true : "The operation '" + op + "' failed to read the resource."
-            + result.getFailureDescription();
-
-        //extract current results
-        Object rawResult = result.getResult();
-
-        //#### Have to create new content for the new node.
-        List<Value> moduleTypeValue = new ArrayList<Value>();
-        try {
-            // loading 'login-module'
-            JsonNode node = mapper.readTree(jsonMap.get(attribute));
-            result.setResult(mapper.treeToValue(node, Object.class));
-        } catch (JsonProcessingException e) {
-            e.printStackTrace();
-        } catch (IOException e) {
-            e.printStackTrace();
-        }
-
-        //populate the Value component complete with module Options.
-        moduleTypeValue = ModuleOptionsComponent.populateSecurityDomainModuleOptions(result,
-            ModuleOptionsComponent.loadModuleOptionType(attribute));
-
-        //add the login-modules attribute
-        op = ModuleOptionsComponent
-            .createAddModuleOptionTypeOperation(new Address(address), attribute, moduleTypeValue);
-
-        result = exerciseOperation(op, execute, verboseOutput);
-        assert ((result.isSuccess() == true) || (result.getOutcome() == null)) : "The operation '" + op
-            + "' failed to write the resource.." + result.getFailureDescription();
-
-        //read the login-modules attribute
-        op = new ReadAttribute(new Address(address), attribute);
-        result = exerciseOperation(op, execute, verboseOutput);
-        assert result.isSuccess() == true : "The operation '" + op + "' failed to read the resource."
-            + result.getFailureDescription();
-
-        //exercise values retrieved from read
-        List<Value> serverResponse = ModuleOptionsComponent.populateSecurityDomainModuleOptions(result,
-            ModuleOptionsComponent.loadModuleOptionType(attribute));
-        Value serverState = serverResponse.get(0);
-        assert serverState.getFlag().equals("required") : "Incorrect state retrieved for 'flag'. Expected 'required'.";
-        assert serverState.getCode().equals("Ldap") : "Incorrect state retrieved for 'code'. Expected 'Ldap'.";
-        LinkedHashMap<String, Object> options = serverState.getOptions();
-        assert options.size() == 3 : "Invalid number of module options returned. Expected 3.";
-        int found = 0;
-        for (String key : options.keySet()) {
-            if (key.equals("bindPw")) {
-                assert "test126".equals(options.get(key)) : "Module option value not correct for key '" + key + "'.";
-                found++;
-            } else if (key.equals("bindDn")) {
-                assert "uid=ldapSecureUser,ou=People,dc=redat,dc=com".equals(options.get(key)) : "Module option value not correct for key '"
-                    + key + "'.";
-                found++;
-            } else if (key.equals("allowEmptyPasswords")) {
-                assert "true".equals(options.get(key)) : "Module option value not correct for key '" + key + "'.";
-                found++;
-            }
-        }
-        assert found == 3 : "All module options were not loaded.";
-
-        //remove the original node to reset for next run.
-        op = new Remove(new Address(address));
-        result = exerciseOperation(op, execute, verboseOutput);
-        assert result.isSuccess() == true : "The operation '" + op + "' failed to remove the resource."
-            + result.getFailureDescription();
-    }
-
-    /** For each operation 
-     *   - will write verbose json and operation details to system.out if verboseOutput = true;
-     *   - will execute the operation against running server if execute = true.
-     * 
-     * @param op
-     * @param execute
-     * @param verboseOutput
-     * @return
-     */
-    public static Result exerciseOperation(Operation op, boolean execute, boolean verboseOutput) {
-        //display operation as AS7 plugin will build it
-        if (verboseOutput) {
-            System.out.println("\tOperation is:" + op);
-        }
-
-        String jsonToSend = "";
-        try {
-            //            jsonToSend = mapper.writeValueAsString(op);
-            jsonToSend = mapper.defaultPrettyPrintingWriter().writeValueAsString(op);
-        } catch (JsonGenerationException e) {
-            e.printStackTrace();
-        } catch (JsonMappingException e) {
-            e.printStackTrace();
-        } catch (IOException e) {
-            e.printStackTrace();
-        }
-        //As generated by jackson mapper
-        if (verboseOutput) {
-            System.out.println("@@@@ OUTBOUND JSON#\n" + jsonToSend + "#");
-        }
-
-        //Execute the operation
-        Result result = new Result();
-        if (execute) {
-            result = con.execute(op);
-        } else {
-            if (verboseOutput) {
-                System.out.println("**** NOTE: Execution disabled . NOT exercising write-attribute operation. **** ");
-            }
-        }
-        if (verboseOutput) {
-            //result wrapper details 
-            System.out.println("\tResult:" + result);
-            //detailed results
-            System.out.println("\tValue:" + result.getResult());
-            System.out.println("-----------------------------------------------------\n");
-        }
-        return result;
-    }
-}
+///*
+// * 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 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.modules.plugins.jbossas7;
+//
+//import java.io.IOException;
+//import java.util.ArrayList;
+//import java.util.HashMap;
+//import java.util.LinkedHashMap;
+//import java.util.List;
+//
+//import org.codehaus.jackson.JsonGenerationException;
+//import org.codehaus.jackson.JsonNode;
+//import org.codehaus.jackson.JsonProcessingException;
+//import org.codehaus.jackson.map.JsonMappingException;
+//import org.codehaus.jackson.map.ObjectMapper;
+//import org.codehaus.jackson.map.SerializationConfig;
+//import org.testng.annotations.BeforeSuite;
+//import org.testng.annotations.Test;
+//
+//import org.rhq.modules.plugins.jbossas7.ModuleOptionsComponent.ModuleOptionType;
+//import org.rhq.modules.plugins.jbossas7.ModuleOptionsComponent.Value;
+//import org.rhq.modules.plugins.jbossas7.json.Address;
+//import org.rhq.modules.plugins.jbossas7.json.Operation;
+//import org.rhq.modules.plugins.jbossas7.json.ReadAttribute;
+//import org.rhq.modules.plugins.jbossas7.json.Remove;
+//import org.rhq.modules.plugins.jbossas7.json.Result;
+//import org.rhq.modules.plugins.jbossas7.json.WriteAttribute;
+//
+///**
+// * Test exercising the subsystem=security/SecurityDomain/[Authentication, Authorization, Mapping, Audit, Acl, 
+// *      Identity-Trust]
+// * @author Simeon Pinder
+// */
+//@Test(groups = "unit")
+//public class SecurityModuleOptionsTest extends AbstractConfigurationHandlingTest {
+//
+//    private static String user = "rhqadmin";
+//    private static String pass = "as7";
+//    private static String host = "localhost";
+//    private static ASConnection con = null;
+//    private static ObjectMapper mapper = null;
+//    private ModuleOptionsComponent moc = null;
+//
+//    //Define some shared and reusable content
+//    static HashMap<String, String> jsonMap = new HashMap<String, String>();
+//    static {
+//        jsonMap
+//            .put(
+//                "login-modules",
+//                "[{\"flag\":\"required\", \"code\":\"Ldap\", \"module-options\":{\"bindDn\":\"uid=ldapSecureUser,ou=People,dc=redat,dc=com\", \"bindPw\":\"test126\", \"allowEmptyPasswords\":\"true\"}}]");
+//        //              "[{\"flag\":\"required\", \"code\":\"Ldap\"}]");
+//        jsonMap
+//            .put(
+//                "policy-modules",
+//                "[{\"flag\":\"requisite\", \"code\":\"LdapExtended\", \"module-options\":{\"policy\":\"module\", \"policy1\":\"module1\"}}]");
+//        jsonMap
+//            .put("mapping-modules",
+//                "[{\"code\":\"Test\", \"type\":\"attribute\", \"module-options\":{\"mapping\":\"module\", \"mapping1\":\"module1\"}}]");
+//        jsonMap.put("provider-modules",
+//            "[{\"code\":\"Providers\", \"module-options\":{\"provider\":\"module\", \"provider1\":\"module1\"}}]");
+//    }
+//
+//    @BeforeSuite
+//    private void initializeConnectionDetails() {
+//        con = new ASConnection(host, 9990, user, pass);
+//        mapper = new ObjectMapper();
+//        mapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true);
+//
+//        moc = new ModuleOptionsComponent();
+//    }
+//
+//    public static void main(String[] args) {
+//        SecurityModuleOptionsTest test = new SecurityModuleOptionsTest();
+//        try {
+//            test.initializeConnectionDetails();
+//            test.testPopulateModuleOptionsAndTypes();
+//        } catch (Exception e) {
+//            // TODO Auto-generated catch block
+//            e.printStackTrace();
+//        }
+//
+//    }
+//
+//    /**The test reads the existing property values, deserializes them and writes the same 
+//     * contents back out to a running instance for all known ModuleOptionTypes.
+//     * 
+//     * @throws Exception
+//     */
+//    public void testPopulateModuleOptionsAndTypes() throws Exception {
+//
+//        //as7 node details.
+//        String securityDomainId = "testDomain";
+//        //TODO: spinder 6-6-12: this cannot run as a standalone itest until JIRA https://issues.jboss.org/browse/AS7-4951
+//        //      is addressed as there is no way to automate setup of the information being tested.
+//        String address = "subsystem=security,security-domain=" + securityDomainId + ",authentication=classic";
+//        boolean verboseOutput = true;
+//        boolean executeOperation = true;
+//        for (ModuleOptionType t : ModuleOptionType.values()) {
+//            String attribute = t.getAttribute();
+//            if (verboseOutput) {
+//                System.out.println("======= Running with ModuleOptionType:" + t + " attribute:" + attribute + ":");
+//            }
+//            if (attribute.equals("policy-modules")) {
+//                address = "subsystem=security,security-domain=" + securityDomainId + ",authorization=classic";
+//            } else if (attribute.equals("acl-modules")) {
+//                address = "subsystem=security,security-domain=" + securityDomainId + ",acl=classic";
+//            } else if (attribute.equals("mapping-modules")) {
+//                address = "subsystem=security,security-domain=" + securityDomainId + ",mapping=classic";
+//            } else if (attribute.equals("trust-modules")) {
+//                address = "subsystem=security,security-domain=" + securityDomainId + ",identity-trust=classic";
+//            } else if (attribute.equals("provider-modules")) {
+//                address = "subsystem=security,security-domain=" + securityDomainId + ",audit=classic";
+//            } else if (attribute.equals("login-modules")) {
+//                address = "subsystem=security,security-domain=" + securityDomainId + ",authentication=classic";
+//            } else {
+//                assert false : "An unknown attribute '" + attribute
+//                    + "' was found. Is there a new type to be supported?";
+//            }
+//
+//            //test operation- read property always available.
+//            Operation op = null;
+//
+//            //read the login-modules attribute
+//            op = new ReadAttribute(new Address(address), attribute);
+//            Result result = exerciseOperation(op, true, verboseOutput);
+//            assert result.isSuccess() == true : "The operation '" + op + "' failed to read the resource."
+//                + result.getFailureDescription();
+//            //extract current results
+//            Object rawResult = result.getResult();
+//            assert rawResult != null : "Read of attribute'" + attribute + "' from address '" + address
+//                + "' has returned no value. Are those values in the model?";
+//
+//            List<Value> list2 = new ArrayList<Value>();
+//            //populate the Value component complete with module Options.
+//            list2 = moc.populateSecurityDomainModuleOptions(result,
+//                ModuleOptionsComponent.loadModuleOptionType(attribute));
+//            if (verboseOutput) {
+//                if (rawResult != null) {
+//                    System.out.println("Raw Result is:" + rawResult + " and of type:" + rawResult.getClass());
+//                } else {
+//                    System.out.println("Read of attribute'" + attribute + "' from address '" + address
+//                        + "' has returned no value. Are those values in the model?");
+//                }
+//            }
+//            //write the login-modules attribute
+//            op = new WriteAttribute(new Address(address));
+//            op.addAdditionalProperty("name", attribute);//attribute to execute on
+//            op.addAdditionalProperty("value", list2);
+//
+//            //Now test the operation
+//            result = exerciseOperation(op, executeOperation, verboseOutput);
+//            assert ((result.isSuccess() == true) || (result.getOutcome() == null)) : "The operation '" + op
+//                + "' failed to write the resource.." + result.getFailureDescription();
+//
+//            //read the login-modules attribute
+//            op = new ReadAttribute(new Address(address), attribute);
+//            result = exerciseOperation(op, true, verboseOutput);
+//            assert (result.isSuccess() == true) : "The operation '" + op + "' failed to read the resource."
+//                + result.getFailureDescription();
+//        }
+//        if (verboseOutput) {
+//            System.out.println("Successfully detected,read and wrote out attribute values for:");
+//            for (ModuleOptionType type : ModuleOptionType.values()) {
+//                System.out.println("\n" + type.ordinal() + " " + type.name());
+//            }
+//        }
+//    }
+//
+//    /**Attempts to create a new Authentication node(authentication=classic) with a
+//     * 'login-modules' attribute complete with 'code':'Ldap' and 'flag':'required' 
+//     *  and some sample 'module-options' values.
+//     *  
+//     */
+//    @Test(enabled = true)
+//    public void testCreateSecurityDomainChildLoginModules() {
+//        boolean execute = true;
+//        boolean verboseOutput = false;
+//        String address = "subsystem=security,security-domain=testDomain3,authentication=classic";
+//        String attribute = ModuleOptionType.Authentication.getAttribute();
+//
+//        //test operation- read property always available.
+//        Operation op = null;
+//
+//        //read the login-modules attribute
+//        op = new ReadAttribute(new Address(address), attribute);
+//        Result result = exerciseOperation(op, execute, verboseOutput);
+//        assert result.isSuccess() == true : "The operation '" + op + "' failed to read the resource."
+//            + result.getFailureDescription();
+//
+//        //extract current results
+//        Object rawResult = result.getResult();
+//
+//        //#### Have to create new content for the new node.
+//        List<Value> moduleTypeValue = new ArrayList<Value>();
+//        try {
+//            // loading 'login-module'
+//            JsonNode node = mapper.readTree(jsonMap.get(attribute));
+//            result.setResult(mapper.treeToValue(node, Object.class));
+//        } catch (JsonProcessingException e) {
+//            e.printStackTrace();
+//        } catch (IOException e) {
+//            e.printStackTrace();
+//        }
+//
+//        //populate the Value component complete with module Options.
+//        moduleTypeValue = ModuleOptionsComponent.populateSecurityDomainModuleOptions(result,
+//            ModuleOptionsComponent.loadModuleOptionType(attribute));
+//
+//        //add the login-modules attribute
+//        op = ModuleOptionsComponent
+//            .createAddModuleOptionTypeOperation(new Address(address), attribute, moduleTypeValue);
+//
+//        result = exerciseOperation(op, execute, verboseOutput);
+//        assert ((result.isSuccess() == true) || (result.getOutcome() == null)) : "The operation '" + op
+//            + "' failed to write the resource.." + result.getFailureDescription();
+//
+//        //read the login-modules attribute
+//        op = new ReadAttribute(new Address(address), attribute);
+//        result = exerciseOperation(op, execute, verboseOutput);
+//        assert result.isSuccess() == true : "The operation '" + op + "' failed to read the resource."
+//            + result.getFailureDescription();
+//
+//        //exercise values retrieved from read
+//        List<Value> serverResponse = ModuleOptionsComponent.populateSecurityDomainModuleOptions(result,
+//            ModuleOptionsComponent.loadModuleOptionType(attribute));
+//        Value serverState = serverResponse.get(0);
+//        assert serverState.getFlag().equals("required") : "Incorrect state retrieved for 'flag'. Expected 'required'.";
+//        assert serverState.getCode().equals("Ldap") : "Incorrect state retrieved for 'code'. Expected 'Ldap'.";
+//        LinkedHashMap<String, Object> options = serverState.getOptions();
+//        assert options.size() == 3 : "Invalid number of module options returned. Expected 3.";
+//        int found = 0;
+//        for (String key : options.keySet()) {
+//            if (key.equals("bindPw")) {
+//                assert "test126".equals(options.get(key)) : "Module option value not correct for key '" + key + "'.";
+//                found++;
+//            } else if (key.equals("bindDn")) {
+//                assert "uid=ldapSecureUser,ou=People,dc=redat,dc=com".equals(options.get(key)) : "Module option value not correct for key '"
+//                    + key + "'.";
+//                found++;
+//            } else if (key.equals("allowEmptyPasswords")) {
+//                assert "true".equals(options.get(key)) : "Module option value not correct for key '" + key + "'.";
+//                found++;
+//            }
+//        }
+//        assert found == 3 : "All module options were not loaded.";
+//
+//        //remove the original node to reset for next run.
+//        op = new Remove(new Address(address));
+//        result = exerciseOperation(op, execute, verboseOutput);
+//        assert result.isSuccess() == true : "The operation '" + op + "' failed to remove the resource."
+//            + result.getFailureDescription();
+//    }
+//
+//    /** For each operation 
+//     *   - will write verbose json and operation details to system.out if verboseOutput = true;
+//     *   - will execute the operation against running server if execute = true.
+//     * 
+//     * @param op
+//     * @param execute
+//     * @param verboseOutput
+//     * @return
+//     */
+//    public static Result exerciseOperation(Operation op, boolean execute, boolean verboseOutput) {
+//        //display operation as AS7 plugin will build it
+//        if (verboseOutput) {
+//            System.out.println("\tOperation is:" + op);
+//        }
+//
+//        String jsonToSend = "";
+//        try {
+//            //            jsonToSend = mapper.writeValueAsString(op);
+//            jsonToSend = mapper.defaultPrettyPrintingWriter().writeValueAsString(op);
+//        } catch (JsonGenerationException e) {
+//            e.printStackTrace();
+//        } catch (JsonMappingException e) {
+//            e.printStackTrace();
+//        } catch (IOException e) {
+//            e.printStackTrace();
+//        }
+//        //As generated by jackson mapper
+//        if (verboseOutput) {
+//            System.out.println("@@@@ OUTBOUND JSON#\n" + jsonToSend + "#");
+//        }
+//
+//        //Execute the operation
+//        Result result = new Result();
+//        if (execute) {
+//            result = con.execute(op);
+//        } else {
+//            if (verboseOutput) {
+//                System.out.println("**** NOTE: Execution disabled . NOT exercising write-attribute operation. **** ");
+//            }
+//        }
+//        if (verboseOutput) {
+//            //result wrapper details 
+//            System.out.println("\tResult:" + result);
+//            //detailed results
+//            System.out.println("\tValue:" + result.getResult());
+//            System.out.println("-----------------------------------------------------\n");
+//        }
+//        return result;
+//    }
+//}


commit 910d79257e03273a2f43465c41e9690373630ccd
Author: Lukas Krejci <lkrejci at redhat.com>
Date:   Wed Jun 20 12:25:57 2012 +0200

    Resolve the initializer using the ScriptEngine.NAME parameter rather than
    the language name - this is in line with how the different language support
    modules identify themselves.

diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/ScriptEngineFactory.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/ScriptEngineFactory.java
index df78b41..fbaf1a7 100644
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/ScriptEngineFactory.java
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/ScriptEngineFactory.java
@@ -216,7 +216,9 @@ public class ScriptEngineFactory {
             return;
         }
 
-        ScriptEngineInitializer initializer = getInitializer(scriptEngine.getFactory().getLanguageName());
+        ScriptEngineInitializer initializer = getInitializer((String) scriptEngine.getFactory().getParameter(
+            ScriptEngine.NAME));
+
         try {
             BeanInfo beanInfo = Introspector.getBeanInfo(object.getClass(), Object.class);
             MethodDescriptor[] methodDescriptors = beanInfo.getMethodDescriptors();
diff --git a/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptEngineProvider.java b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptEngineProvider.java
index db22068..2742970 100644
--- a/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptEngineProvider.java
+++ b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptEngineProvider.java
@@ -32,6 +32,8 @@ public interface ScriptEngineProvider {
 
     /**
      * @return the scripting language understood by this provider.
+     * This must return the same string as <code>ScriptEngine.getFactory().getParameter(ScriptEngine.NAME)</code>
+     * of the script engine that this provider provides (through the initializer).
      */
     @NotNull
     String getSupportedLanguage();


commit cdf864db43dc1c9908bdf157dd1eb283e05f5b14
Author: Lukas Krejci <lkrejci at redhat.com>
Date:   Wed Jun 20 12:22:41 2012 +0200

    Removing all the get*Manager() methods on the RhqFacade and replacing it
    with one generic getProxy(Class) method. This method returns a proxy of
    the original remote API interface (i.e. the interface is NOT simplified).
    
    The getManagers() method returns a map of manager proxies where
    the interfaces ARE simplified.
    
    This is in preparation for making the simplified interfaces NOT implement
    the original remote APIs so that we have greater freedom in what can be done
    with the API and also make code completion significantly more clean and
    simple.

diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/StandardBindings.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/StandardBindings.java
index 05e6a09..812b4ae 100644
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/StandardBindings.java
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/StandardBindings.java
@@ -120,7 +120,7 @@ public class StandardBindings extends HashMap<String, Object> {
         put(SCRIPT_UTIL, new ScriptUtil(rhqFacade));
 
         if (rhqFacade != null) {
-            managers = rhqFacade.getManagers();
+            managers = rhqFacade.getScriptingAPI();
 
             put(SUBJECT, rhqFacade.getSubject());
             put(PROXY_FACTORY, new ResourceClientFactory(rhqFacade, output));
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/AbstractRhqFacadeProxy.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/AbstractRhqFacadeProxy.java
index ef46bb2..bd37131 100644
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/AbstractRhqFacadeProxy.java
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/AbstractRhqFacadeProxy.java
@@ -50,23 +50,31 @@ public abstract class AbstractRhqFacadeProxy<T extends RhqFacade> implements Inv
     }
     
     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
-        Class<?>[] params = method.getParameterTypes();
-
+        Class<?>[] interfaces = method.getDeclaringClass().getInterfaces();
+        Class<?> originalClass;
+        if (interfaces != null && interfaces.length > 0) {
+            originalClass = interfaces[0];
+        } else {
+            originalClass = method.getDeclaringClass();
+        }
+        
         try {
-            Class<?>[] interfaces = method.getDeclaringClass().getInterfaces();
-
-            Class<?> originalClass;
-            if (interfaces != null && interfaces.length > 0) {
-                originalClass = interfaces[0];
-            } else {
-                originalClass = method.getDeclaringClass();
-            }
-
             // See if this method really exists or if its a simplified set of parameters
             originalClass.getMethod(method.getName(), method.getParameterTypes());
-
-        } catch (Exception e) {
+        } catch (NoSuchMethodException e) {
             // If this was not in the original interface it must've been added in the Simplifier... add back the subject argument
+            Class<?>[] origParams = method.getParameterTypes();
+            Class<?>[] params = new Class<?>[origParams.length + 1];
+            params[0] = Subject.class;
+            System.arraycopy(method.getParameterTypes(), 0, params, 1, origParams.length);
+            
+            try {
+                method = originalClass.getMethod(method.getName(), params);
+            } catch (NoSuchMethodException e2) {
+                throw new IllegalArgumentException("Method " + method + " doesn't seem to be present on the interface "
+                    + originalClass + " neither in its original or simplified form.");
+            }
+
             int numArgs = (null == args) ? 0 : args.length;
             Object[] newArgs = new Object[numArgs + 1];
             if (numArgs > 0) {
@@ -74,17 +82,9 @@ public abstract class AbstractRhqFacadeProxy<T extends RhqFacade> implements Inv
             }
             newArgs[0] = getRhqFacade().getSubject();
             args = newArgs;
-
-            int numParams = (null == params) ? 0 : params.length;
-            Class<?>[] newParams = new Class[numParams + 1];
-            if (numParams > 0) {
-                System.arraycopy(params, 0, newParams, 1, numParams);
-            }
-            newParams[0] = Subject.class;
-            params = newParams;
         }
         
-        return doInvoke(proxy, method, params, args);
+        return doInvoke(proxy, method, args);
     }
 
     /**
@@ -93,10 +93,9 @@ public abstract class AbstractRhqFacadeProxy<T extends RhqFacade> implements Inv
      * 
      * @param proxy the proxy the method is executing on
      * @param originalMethod the original method
-     * @param argTypes the de-simplified argument types
      * @param args the de-simplified argumens
      * @return the result of the invocation
      * @throws Throwable if invocation throws an error
      */
-    protected abstract Object doInvoke(Object proxy, Method originalMethod, Class<?>[] argTypes, Object[] args) throws Throwable;
+    protected abstract Object doInvoke(Object proxy, Method originalMethod, Object[] args) throws Throwable;
 }
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/ResourceClientProxy.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/ResourceClientProxy.java
index ff39171..10ee612 100644
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/ResourceClientProxy.java
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/ResourceClientProxy.java
@@ -67,7 +67,12 @@ import org.rhq.core.domain.util.PageOrdering;
 import org.rhq.core.domain.util.Summary;
 import org.rhq.core.server.MeasurementConverter;
 import org.rhq.core.util.MessageDigestGenerator;
+import org.rhq.enterprise.server.configuration.ConfigurationManagerRemote;
 import org.rhq.enterprise.server.content.ContentManagerRemote;
+import org.rhq.enterprise.server.measurement.MeasurementDataManagerRemote;
+import org.rhq.enterprise.server.measurement.MeasurementDefinitionManagerRemote;
+import org.rhq.enterprise.server.operation.OperationManagerRemote;
+import org.rhq.enterprise.server.resource.ResourceManagerRemote;
 import org.rhq.enterprise.server.resource.ResourceTypeNotFoundException;
 
 /**
@@ -199,7 +204,8 @@ public class ResourceClientProxy {
 
     public void init() {
 
-        this.resource = remoteClient.getResourceManager().getResource(remoteClient.getSubject(), resourceId);
+        this.resource = remoteClient.getProxy(ResourceManagerRemote.class).getResource(remoteClient.getSubject(),
+            resourceId);
 
         // Lazy init children, not here
         initMeasurements();
@@ -217,10 +223,11 @@ public class ResourceClientProxy {
     }
 
     private void initConfigDefs() {
-        this.resourceConfigurationDefinition = remoteClient.getConfigurationManager()
+        ConfigurationManagerRemote configurationManager = remoteClient.getProxy(ConfigurationManagerRemote.class);
+        this.resourceConfigurationDefinition = configurationManager
             .getResourceConfigurationDefinitionWithTemplatesForResourceType(remoteClient.getSubject(),
                 resource.getResourceType().getId());
-        this.pluginConfigurationDefinition = remoteClient.getConfigurationManager()
+        this.pluginConfigurationDefinition = configurationManager
             .getPluginConfigurationDefinitionForResourceType(remoteClient.getSubject(),
                 resource.getResourceType().getId());
     }
@@ -228,7 +235,7 @@ public class ResourceClientProxy {
     private void initChildren() {
         ResourceCriteria criteria = new ResourceCriteria();
         criteria.addFilterParentResourceId(resourceId);
-        PageList<Resource> childResources = remoteClient.getResourceManager().findResourcesByCriteria(
+        PageList<Resource> childResources = remoteClient.getProxy(ResourceManagerRemote.class).findResourcesByCriteria(
             remoteClient.getSubject(), criteria);
 
         for (Resource child : childResources) {
@@ -242,7 +249,7 @@ public class ResourceClientProxy {
 //        criteria.addFilterResourceTypeName(resource.getResourceType().getName());
 //        criteria.setStrict(true);
 
-        this.measurementDefinitions = remoteClient.getMeasurementDefinitionManager()
+        this.measurementDefinitions = remoteClient.getProxy(MeasurementDefinitionManagerRemote.class)
             .findMeasurementDefinitionsByCriteria(remoteClient.getSubject(), criteria);
 
         this.measurementMap = new HashMap<String, Measurement>();
@@ -263,7 +270,8 @@ public class ResourceClientProxy {
         criteria.fetchParametersConfigurationDefinition(true);
         criteria.fetchResultsConfigurationDefinition(true);
 
-        this.operationDefinitions = remoteClient.getOperationManager().findOperationDefinitionsByCriteria(
+        this.operationDefinitions = remoteClient.getProxy(OperationManagerRemote.class)
+            .findOperationDefinitionsByCriteria(
             remoteClient.getSubject(), criteria);
 
         for (OperationDefinition def : operationDefinitions) {
@@ -274,7 +282,7 @@ public class ResourceClientProxy {
     }
 
     private void initContent() {
-        ContentManagerRemote contentManager = remoteClient.getContentManager();
+        ContentManagerRemote contentManager = remoteClient.getProxy(ContentManagerRemote.class);
         List<PackageType> types = null;
         try {
             types = contentManager.findPackageTypes(remoteClient.getSubject(), resource.getResourceType().getName(),
@@ -302,7 +310,7 @@ public class ResourceClientProxy {
         }
 
         public List<PackageVersion> getInstalledPackages() {
-            ContentManagerRemote contentManager = remoteClient.getContentManager();
+            ContentManagerRemote contentManager = remoteClient.getProxy(ContentManagerRemote.class);
 
             PackageVersionCriteria criteria = new PackageVersionCriteria();
             criteria.addFilterResourceId(resourceId);
@@ -359,7 +367,7 @@ public class ResourceClientProxy {
 
         public Object getValue() {
             try {
-                Set<MeasurementData> d = remoteClient.getMeasurementDataManager().findLiveData(
+                Set<MeasurementData> d = remoteClient.getProxy(MeasurementDataManagerRemote.class).findLiveData(
                     remoteClient.getSubject(), resourceId, new int[] { definition.getId() });
                 MeasurementData data = d.iterator().next();
                 return data.getValue();
@@ -404,7 +412,9 @@ public class ResourceClientProxy {
             Configuration parameters = ConfigurationClassBuilder.translateParametersToConfig(definition
                 .getParametersConfigurationDefinition(), args);
 
-            ResourceOperationSchedule schedule = remoteClient.getOperationManager().scheduleResourceOperation(
+            OperationManagerRemote operationManager = remoteClient.getProxy(OperationManagerRemote.class);
+
+            ResourceOperationSchedule schedule = operationManager.scheduleResourceOperation(
                 remoteClient.getSubject(), resourceId, definition.getName(), 0, 0, 0, 30000, parameters,
                 "Executed from commandline");
 
@@ -421,7 +431,7 @@ public class ResourceClientProxy {
             ResourceOperationHistory history = null;
             while (history == null && retries-- > 0) {
                 Thread.sleep(1000);
-                PageList<ResourceOperationHistory> histories = remoteClient.getOperationManager()
+                PageList<ResourceOperationHistory> histories = operationManager
                     .findResourceOperationHistoriesByCriteria(remoteClient.getSubject(), criteria);
                 if (histories.size() > 0 && histories.get(0).getStatus() != OperationRequestStatus.INPROGRESS) {
                     history = histories.get(0);
@@ -459,7 +469,8 @@ public class ResourceClientProxy {
         public Configuration getPluginConfiguration() {
             if (!LazyLoadScenario.isShouldLoad())
                 return null;
-            return remoteClient.getConfigurationManager().getPluginConfiguration(remoteClient.getSubject(),
+            return remoteClient.getProxy(ConfigurationManagerRemote.class).getPluginConfiguration(
+                remoteClient.getSubject(),
                 resourceClientProxy.resourceId);
         }
 
@@ -468,8 +479,8 @@ public class ResourceClientProxy {
         }
 
         public PluginConfigurationUpdate updatePluginConfiguration(Configuration configuration) {
-            PluginConfigurationUpdate update =
-                remoteClient.getConfigurationManager().updatePluginConfiguration(
+            PluginConfigurationUpdate update = remoteClient.getProxy(ConfigurationManagerRemote.class)
+                .updatePluginConfiguration(
                     remoteClient.getSubject(),
                     resourceClientProxy.getId(),
                     configuration);
@@ -481,7 +492,8 @@ public class ResourceClientProxy {
             if (!LazyLoadScenario.isShouldLoad())
                 return null;
 
-            return remoteClient.getConfigurationManager().getResourceConfiguration(remoteClient.getSubject(),
+            return remoteClient.getProxy(ConfigurationManagerRemote.class).getResourceConfiguration(
+                remoteClient.getSubject(),
                 resourceClientProxy.resourceId);
         }
 
@@ -490,8 +502,8 @@ public class ResourceClientProxy {
         }
 
         public ResourceConfigurationUpdate updateResourceConfiguration(Configuration configuration) {
-            ResourceConfigurationUpdate update =
-                remoteClient.getConfigurationManager().updateResourceConfiguration(
+            ResourceConfigurationUpdate update = remoteClient.getProxy(ConfigurationManagerRemote.class)
+                .updateResourceConfiguration(
                     remoteClient.getSubject(),
                     resourceClientProxy.getId(),
                     configuration);
@@ -502,7 +514,8 @@ public class ResourceClientProxy {
 
         public InstalledPackage getBackingContent() {
 
-            return remoteClient.getContentManager().getBackingPackageForResource(remoteClient.getSubject(), resourceClientProxy.resourceId);
+            return remoteClient.getProxy(ContentManagerRemote.class).getBackingPackageForResource(
+                remoteClient.getSubject(), resourceClientProxy.resourceId);
         }
 
         /**
@@ -538,8 +551,9 @@ public class ResourceClientProxy {
 
             InstalledPackage oldPackage = getBackingContent();
 
-            PackageVersion pv =
-                    remoteClient.getContentManager().createPackageVersionWithDisplayVersion(
+            ContentManagerRemote contentManager = remoteClient.getProxy(ContentManagerRemote.class);
+
+            PackageVersion pv = contentManager.createPackageVersionWithDisplayVersion(
                         remoteClient.getSubject(),
                         oldPackage.getPackageVersion().getGeneralPackage().getName(),
                         oldPackage.getPackageVersion().getGeneralPackage().getPackageType().getId(),
@@ -548,7 +562,7 @@ public class ResourceClientProxy {
                         oldPackage.getPackageVersion().getArchitecture().getId(),
                         fileContents);
 
-            remoteClient.getContentManager().deployPackagesWithNote(
+            contentManager.deployPackagesWithNote(
                     remoteClient.getSubject(),
                     new int[] { resourceClientProxy.getId()},
                     new int[] {pv.getId()},
@@ -564,8 +578,7 @@ public class ResourceClientProxy {
             
             File file = new File(fileName);
 
-            byte[] data =
-                    remoteClient.getContentManager().getPackageBytes(
+            byte[] data = remoteClient.getProxy(ContentManagerRemote.class).getPackageBytes(
                             remoteClient.getSubject(), resourceClientProxy.resourceId, installedPackage.getId());
 
             FileOutputStream fos = new FileOutputStream(file);
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/RhqFacade.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/RhqFacade.java
index ca7fa83..b975436 100644
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/RhqFacade.java
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/RhqFacade.java
@@ -22,35 +22,6 @@ package org.rhq.bindings.client;
 import java.util.Map;
 
 import org.rhq.core.domain.auth.Subject;
-import org.rhq.enterprise.server.alert.AlertDefinitionManagerRemote;
-import org.rhq.enterprise.server.alert.AlertManagerRemote;
-import org.rhq.enterprise.server.auth.SubjectManagerRemote;
-import org.rhq.enterprise.server.authz.RoleManagerRemote;
-import org.rhq.enterprise.server.bundle.BundleManagerRemote;
-import org.rhq.enterprise.server.configuration.ConfigurationManagerRemote;
-import org.rhq.enterprise.server.content.ContentManagerRemote;
-import org.rhq.enterprise.server.content.RepoManagerRemote;
-import org.rhq.enterprise.server.discovery.DiscoveryBossRemote;
-import org.rhq.enterprise.server.drift.DriftManagerRemote;
-import org.rhq.enterprise.server.event.EventManagerRemote;
-import org.rhq.enterprise.server.install.remote.RemoteInstallManagerRemote;
-import org.rhq.enterprise.server.measurement.AvailabilityManagerRemote;
-import org.rhq.enterprise.server.measurement.CallTimeDataManagerRemote;
-import org.rhq.enterprise.server.measurement.MeasurementBaselineManagerRemote;
-import org.rhq.enterprise.server.measurement.MeasurementDataManagerRemote;
-import org.rhq.enterprise.server.measurement.MeasurementDefinitionManagerRemote;
-import org.rhq.enterprise.server.measurement.MeasurementScheduleManagerRemote;
-import org.rhq.enterprise.server.operation.OperationManagerRemote;
-import org.rhq.enterprise.server.report.DataAccessManagerRemote;
-import org.rhq.enterprise.server.resource.ResourceFactoryManagerRemote;
-import org.rhq.enterprise.server.resource.ResourceManagerRemote;
-import org.rhq.enterprise.server.resource.ResourceTypeManagerRemote;
-import org.rhq.enterprise.server.resource.group.ResourceGroupManagerRemote;
-import org.rhq.enterprise.server.search.SavedSearchManagerRemote;
-import org.rhq.enterprise.server.support.SupportManagerRemote;
-import org.rhq.enterprise.server.sync.SynchronizationManagerRemote;
-import org.rhq.enterprise.server.system.SystemManagerRemote;
-import org.rhq.enterprise.server.tagging.TagManagerRemote;
 
 /**
  * This is an interface through which the script can communicate with RHQ server.
@@ -70,69 +41,22 @@ public interface RhqFacade {
 
     boolean isLoggedIn();
 
-    AlertManagerRemote getAlertManager();
-
-    AlertDefinitionManagerRemote getAlertDefinitionManager();
-
-    AvailabilityManagerRemote getAvailabilityManager();
-
-    BundleManagerRemote getBundleManager();
-
-    CallTimeDataManagerRemote getCallTimeDataManager();
-
-    RepoManagerRemote getRepoManager();
-
-    ConfigurationManagerRemote getConfigurationManager();
-
-    ContentManagerRemote getContentManager();
-
-    DataAccessManagerRemote getDataAccessManager();
-
-    DiscoveryBossRemote getDiscoveryBoss();
-
-    DriftManagerRemote getDriftManager();
-
-    EventManagerRemote getEventManager();
-
-    MeasurementBaselineManagerRemote getMeasurementBaselineManager();
-
-    MeasurementDataManagerRemote getMeasurementDataManager();
-
-    MeasurementDefinitionManagerRemote getMeasurementDefinitionManager();
-
-    MeasurementScheduleManagerRemote getMeasurementScheduleManager();
-
-    OperationManagerRemote getOperationManager();
-
-    ResourceManagerRemote getResourceManager();
-
-    ResourceFactoryManagerRemote getResourceFactoryManager();
-
-    ResourceGroupManagerRemote getResourceGroupManager();
-
-    ResourceTypeManagerRemote getResourceTypeManager();
-
-    RoleManagerRemote getRoleManager();
-
-    SavedSearchManagerRemote getSavedSearchManager();
-
-    SubjectManagerRemote getSubjectManager();
-
-    SupportManagerRemote getSupportManager();
-
-    SystemManagerRemote getSystemManager();
-
-    RemoteInstallManagerRemote getRemoteInstallManager();
-
-    TagManagerRemote getTagManager();
-
-    SynchronizationManagerRemote getSynchronizationManager();
-    
     /**
      * This map is constructed using all the elements in the {@link RhqManager} enum which are then proxied
      * using this instance.
      * 
      * @return a map of all available proxied managers keyed by their names.
      */
-    Map<String, Object> getManagers();
+    Map<String, Object> getScriptingAPI();
+
+    /**
+     * Unlike the {@link #getScriptingAPI()} method that returns objects with modified signatures
+     * meant to be used by the scripting environment, this method provides the access to the "raw"
+     * remote API interface implementation backed by this RHQ facade implementation.
+     * 
+     * @param remoteApiIface one of the RHQ's remote API interfaces of which the proxied instance
+     * should be returned
+     * @return the proxy of the remote API interface backed by this facade
+     */
+    <T> T getProxy(Class<T> remoteApiIface);
 }
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/ScriptAssert.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/ScriptAssert.java
index 15ed37c..a268621 100644
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/ScriptAssert.java
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/ScriptAssert.java
@@ -245,20 +245,30 @@ public class ScriptAssert {
           }
     }
 
-    public void assertEquals(Object[] actual, Object[] expected, String msg) {
-        if (actual == expected) {
-            return;
-        }
+    /* These are no longer needed in Rhino 1.7R3, because native javascript arrays implement
+     * the collection interfaces.
+     */
+    /*    
+        public void assertEquals(Object[] actual, Object[] expected, String msg) {
+            if (actual == expected) {
+                return;
+            }
 
-        if ((actual == null && expected != null) || (actual != null && expected == null)) {
-            if (msg != null) {
-                fail(msg);
-            } else {
-                fail("Arrays not equal: " + Arrays.toString(expected) + " and " + Arrays.toString(actual));
+            if ((actual == null && expected != null) || (actual != null && expected == null)) {
+                if (msg != null) {
+                    fail(msg);
+                } else {
+                    fail("Arrays not equal: " + Arrays.toString(expected) + " and " + Arrays.toString(actual));
+                }
             }
+            assertEquals(Arrays.asList(actual), Arrays.asList(expected), msg);
+        }
+
+        public void assertEquals(Object[] actual, Object[] expected) {
+            assertEquals(actual, expected, null);
         }
-        assertEquals(Arrays.asList(actual), Arrays.asList(expected), msg);
-    }
+
+    */
 
     public void assertEqualsNoOrder(Object[] actual, Object[] expected, String msg) {
         if (actual == expected) {
@@ -288,10 +298,6 @@ public class ScriptAssert {
         }
     }
 
-    public void assertEquals(Object[] actual, Object[] expected) {
-        assertEquals(actual, expected, null);
-    }
-
     public void assertEqualsNoOrder(Object[] actual, Object[] expected) {
         assertEqualsNoOrder(actual, expected, null);
     }
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/ScriptUtil.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/ScriptUtil.java
index 6ed095e..bd121e7 100644
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/ScriptUtil.java
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/util/ScriptUtil.java
@@ -43,6 +43,7 @@ import org.rhq.core.domain.operation.bean.ResourceOperationSchedule;
 import org.rhq.core.domain.resource.Resource;
 import org.rhq.core.domain.util.PageList;
 import org.rhq.core.domain.util.PageOrdering;
+import org.rhq.enterprise.server.operation.OperationManagerRemote;
 import org.rhq.enterprise.server.resource.ResourceManagerRemote;
 
 /**
@@ -74,7 +75,7 @@ public class ScriptUtil {
             throw new IllegalStateException("The findResources() method requires a connection to the RHQ server.");
         }
         
-        ResourceManagerRemote resourceManager = remoteClient.getResourceManager();
+        ResourceManagerRemote resourceManager = remoteClient.getProxy(ResourceManagerRemote.class);
 
         ResourceCriteria criteria = new ResourceCriteria();
         criteria.addFilterName(string);
@@ -166,7 +167,7 @@ public class ScriptUtil {
 
         while(history == null && i < maxIntervals) {
             Thread.sleep(intervalDuration);
-            PageList<ResourceOperationHistory> histories = remoteClient.getOperationManager()
+            PageList<ResourceOperationHistory> histories = remoteClient.getProxy(OperationManagerRemote.class)
                     .findResourceOperationHistoriesByCriteria(remoteClient.getSubject(), criteria);
             if (histories.size() > 0 && histories.get(0).getStatus() != OperationRequestStatus.INPROGRESS) {
                 history = histories.get(0);
diff --git a/modules/enterprise/binding/src/test/java/org/rhq/bindings/FakeRhqFacade.java b/modules/enterprise/binding/src/test/java/org/rhq/bindings/FakeRhqFacade.java
index a3dcbdc..d42f3e1 100644
--- a/modules/enterprise/binding/src/test/java/org/rhq/bindings/FakeRhqFacade.java
+++ b/modules/enterprise/binding/src/test/java/org/rhq/bindings/FakeRhqFacade.java
@@ -24,35 +24,6 @@ import java.util.Map;
 
 import org.rhq.bindings.client.RhqFacade;
 import org.rhq.core.domain.auth.Subject;
-import org.rhq.enterprise.server.alert.AlertDefinitionManagerRemote;
-import org.rhq.enterprise.server.alert.AlertManagerRemote;
-import org.rhq.enterprise.server.auth.SubjectManagerRemote;
-import org.rhq.enterprise.server.authz.RoleManagerRemote;
-import org.rhq.enterprise.server.bundle.BundleManagerRemote;
-import org.rhq.enterprise.server.configuration.ConfigurationManagerRemote;
-import org.rhq.enterprise.server.content.ContentManagerRemote;
-import org.rhq.enterprise.server.content.RepoManagerRemote;
-import org.rhq.enterprise.server.discovery.DiscoveryBossRemote;
-import org.rhq.enterprise.server.drift.DriftManagerRemote;
-import org.rhq.enterprise.server.event.EventManagerRemote;
-import org.rhq.enterprise.server.install.remote.RemoteInstallManagerRemote;
-import org.rhq.enterprise.server.measurement.AvailabilityManagerRemote;
-import org.rhq.enterprise.server.measurement.CallTimeDataManagerRemote;
-import org.rhq.enterprise.server.measurement.MeasurementBaselineManagerRemote;
-import org.rhq.enterprise.server.measurement.MeasurementDataManagerRemote;
-import org.rhq.enterprise.server.measurement.MeasurementDefinitionManagerRemote;
-import org.rhq.enterprise.server.measurement.MeasurementScheduleManagerRemote;
-import org.rhq.enterprise.server.operation.OperationManagerRemote;
-import org.rhq.enterprise.server.report.DataAccessManagerRemote;
-import org.rhq.enterprise.server.resource.ResourceFactoryManagerRemote;
-import org.rhq.enterprise.server.resource.ResourceManagerRemote;
-import org.rhq.enterprise.server.resource.ResourceTypeManagerRemote;
-import org.rhq.enterprise.server.resource.group.ResourceGroupManagerRemote;
-import org.rhq.enterprise.server.search.SavedSearchManagerRemote;
-import org.rhq.enterprise.server.support.SupportManagerRemote;
-import org.rhq.enterprise.server.sync.SynchronizationManagerRemote;
-import org.rhq.enterprise.server.system.SystemManagerRemote;
-import org.rhq.enterprise.server.tagging.TagManagerRemote;
 
 public class FakeRhqFacade implements RhqFacade {
 
@@ -71,127 +42,13 @@ public class FakeRhqFacade implements RhqFacade {
     public boolean isLoggedIn() {
         return false;
     }
-
-    public AlertManagerRemote getAlertManager() {
-        return null;
-    }
-
-    public AlertDefinitionManagerRemote getAlertDefinitionManager() {
-        return null;
-    }
-
-    public AvailabilityManagerRemote getAvailabilityManager() {
-        return null;
-    }
-
-    public BundleManagerRemote getBundleManager() {
-        return null;
-    }
-
-    public CallTimeDataManagerRemote getCallTimeDataManager() {
-        return null;
-    }
-
-    public RepoManagerRemote getRepoManager() {
-        return null;
-    }
-
-    public ConfigurationManagerRemote getConfigurationManager() {
-        return null;
-    }
-
-    public ContentManagerRemote getContentManager() {
-        return null;
-    }
-
-    public DataAccessManagerRemote getDataAccessManager() {
-        return null;
-    }
-
-    public DiscoveryBossRemote getDiscoveryBoss() {
-        return null;
-    }
-
-    public EventManagerRemote getEventManager() {
-        return null;
-    }
-
-    public MeasurementBaselineManagerRemote getMeasurementBaselineManager() {
-        return null;
-    }
-
-    public MeasurementDataManagerRemote getMeasurementDataManager() {
-        return null;
-    }
-
-    public MeasurementDefinitionManagerRemote getMeasurementDefinitionManager() {
-        return null;
-    }
-
-    public MeasurementScheduleManagerRemote getMeasurementScheduleManager() {
-        return null;
-    }
-
-    public OperationManagerRemote getOperationManager() {
-        return null;
-    }
-
-    public ResourceManagerRemote getResourceManager() {
-        return null;
-    }
-
-    public ResourceFactoryManagerRemote getResourceFactoryManager() {
-        return null;
-    }
-
-    public ResourceGroupManagerRemote getResourceGroupManager() {
-        return null;
-    }
-
-    public ResourceTypeManagerRemote getResourceTypeManager() {
-        return null;
-    }
-
-    public RoleManagerRemote getRoleManager() {
-        return null;
-    }
-
-    public SavedSearchManagerRemote getSavedSearchManager() {
-        return null;
-    }
-
-    public SubjectManagerRemote getSubjectManager() {
-        return null;
-    }
-
-    public SupportManagerRemote getSupportManager() {
-        return null;
-    }
-
-    public SystemManagerRemote getSystemManager() {
-        return null;
-    }
-
-    public RemoteInstallManagerRemote getRemoteInstallManager() {
-        return null;
-    }
-
-    public TagManagerRemote getTagManager() {
-        return null;
-    }
-
-    @Override
-    public DriftManagerRemote getDriftManager() {
-        return null;
+    
+    public Map<String, Object> getScriptingAPI() {
+        return Collections.emptyMap();
     }
 
     @Override
-    public SynchronizationManagerRemote getSynchronizationManager() {
+    public <T> T getProxy(Class<T> remoteApiIface) {
         return null;
     }
-    
-    public Map<String, Object> getManagers() {
-        return Collections.emptyMap();
-    }
-
 }
diff --git a/modules/enterprise/binding/src/test/java/org/rhq/bindings/ScriptEngineTest.java b/modules/enterprise/binding/src/test/java/org/rhq/bindings/ScriptEngineTest.java
index 15184c1..c3d5450 100644
--- a/modules/enterprise/binding/src/test/java/org/rhq/bindings/ScriptEngineTest.java
+++ b/modules/enterprise/binding/src/test/java/org/rhq/bindings/ScriptEngineTest.java
@@ -86,11 +86,13 @@ public class ScriptEngineTest {
     }
     
     private ScriptEngine getScriptEngine() throws ScriptException, IOException {
-        return ScriptEngineFactory.getScriptEngine("JavaScript", new PackageFinder(Collections.<File>emptyList()), EMPTY_BINDINGS);
+        return ScriptEngineFactory.getScriptEngine("javascript", new PackageFinder(Collections.<File> emptyList()),
+            EMPTY_BINDINGS);
     }
     
     private ScriptEngine getSecuredScriptEngine() throws ScriptException, IOException {
-        return ScriptEngineFactory.getSecuredScriptEngine("JavaScript", new PackageFinder(Collections.<File>emptyList()), EMPTY_BINDINGS, new StandardScriptPermissions());
+        return ScriptEngineFactory.getSecuredScriptEngine("javascript",
+            new PackageFinder(Collections.<File> emptyList()), EMPTY_BINDINGS, new StandardScriptPermissions());
     }
     
     private void assertSecurityExceptionPresent(Throwable t) {
diff --git a/modules/enterprise/binding/src/test/java/org/rhq/bindings/util/ScriptAssertTest.java b/modules/enterprise/binding/src/test/java/org/rhq/bindings/util/ScriptAssertTest.java
index 8fed153..1d7f657 100644
--- a/modules/enterprise/binding/src/test/java/org/rhq/bindings/util/ScriptAssertTest.java
+++ b/modules/enterprise/binding/src/test/java/org/rhq/bindings/util/ScriptAssertTest.java
@@ -46,8 +46,7 @@ public class ScriptAssertTest {
     @BeforeTest
     public void verifyScriptEngineIsAvailable() throws Exception {
         StandardBindings bindings = new StandardBindings(new PrintWriter(System.out), new FakeRhqFacade());
-        engine =
-            ScriptEngineFactory.getScriptEngine("JavaScript", new PackageFinder(Collections.<File> emptyList()),
+        engine = ScriptEngineFactory.getScriptEngine("javascript", new PackageFinder(Collections.<File> emptyList()),
                 bindings);
     }
 
diff --git a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java
index 4a1ed62..9811d2a 100644
--- a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java
+++ b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java
@@ -203,7 +203,7 @@ public class ClientMain {
         this.serviceCompletor.setContext(getScriptEngine().getContext());
 
         if (remoteClient != null) {
-            this.serviceCompletor.setServices(remoteClient.getManagers());
+            this.serviceCompletor.setServices(remoteClient.getScriptingAPI());
         }
     }
 
diff --git a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/HelpCommand.java b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/HelpCommand.java
index 4676730..69b3c7a 100644
--- a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/HelpCommand.java
+++ b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/HelpCommand.java
@@ -61,7 +61,7 @@ public class HelpCommand implements ClientCommand {
             tw.setHideRowCount(true);
             tw.print(data);
         } else if ("api".equals(args[1])) {
-            Map<String, Object> services = client.getRemoteClient().getManagers();
+            Map<String, Object> services = client.getRemoteClient().getScriptingAPI();
             if (args.length == 2) {
                 TabularWriter tw = new TabularWriter(client.getPrintWriter(), "API", "Package");
                 tw.setWidth(client.getConsoleWidth());
diff --git a/modules/enterprise/remoting/cli/src/test/java/org/rhq/enterprise/client/commands/ScriptCommandTest.java b/modules/enterprise/remoting/cli/src/test/java/org/rhq/enterprise/client/commands/ScriptCommandTest.java
index fc59cf3..8cf3ceb 100644
--- a/modules/enterprise/remoting/cli/src/test/java/org/rhq/enterprise/client/commands/ScriptCommandTest.java
+++ b/modules/enterprise/remoting/cli/src/test/java/org/rhq/enterprise/client/commands/ScriptCommandTest.java
@@ -1,36 +1,23 @@
 package org.rhq.enterprise.client.commands;
 
-import static java.util.Collections.*;
 import static java.util.Arrays.asList;
-import static org.testng.Assert.*;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
 
-import java.util.Map;
-import java.util.Collections;
-import java.util.List;
 import java.util.ArrayList;
+import java.util.List;
+
+import javax.script.ScriptContext;
+import javax.script.ScriptEngine;
 
 import org.testng.annotations.Test;
-import org.rhq.enterprise.client.ClientMain;
-import org.rhq.enterprise.client.commands.ScriptCommand;
-import org.rhq.enterprise.clientapi.RemoteClient;
-import org.rhq.enterprise.server.alert.AlertManagerRemote;
-import org.rhq.enterprise.server.alert.AlertDefinitionManagerRemote;
-import org.rhq.enterprise.server.configuration.ConfigurationManagerRemote;
-import org.rhq.enterprise.server.content.RepoManagerRemote;
-import org.rhq.enterprise.server.content.ContentManagerRemote;
-import org.rhq.enterprise.server.operation.OperationManagerRemote;
-import org.rhq.enterprise.server.authz.RoleManagerRemote;
-import org.rhq.enterprise.server.resource.ResourceManagerRemote;
-import org.rhq.enterprise.server.resource.group.ResourceGroupManagerRemote;
-import org.rhq.enterprise.server.auth.SubjectManagerRemote;
+
 import org.rhq.bindings.client.RhqManager;
 import org.rhq.bindings.output.TabularWriter;
 import org.rhq.bindings.util.ScriptUtil;
 import org.rhq.core.domain.auth.Subject;
-
-import javax.script.ScriptEngine;
-import javax.script.ScriptContext;
-import javax.script.Bindings;
+import org.rhq.enterprise.client.ClientMain;
+import org.rhq.enterprise.clientapi.RemoteClient;
 
 public class ScriptCommandTest {
 
@@ -122,56 +109,6 @@ public class ScriptCommandTest {
         public RemoteClientStub(String host, int port) {
             super(host, port);
         }
-
-        @Override
-        public AlertManagerRemote getAlertManager() {
-            return null;
-        }
-
-        @Override
-        public AlertDefinitionManagerRemote getAlertDefinitionManager() {
-            return null;
-        }
-
-        @Override
-        public ConfigurationManagerRemote getConfigurationManager() {
-            return null;
-        }
-
-        @Override
-        public RepoManagerRemote getRepoManager() {
-            return null;
-        }
-
-        @Override
-        public ContentManagerRemote getContentManager() {
-            return null;
-        }
-
-        @Override
-        public OperationManagerRemote getOperationManager() {
-            return null;
-        }
-
-        @Override
-        public RoleManagerRemote getRoleManager() {
-            return null;
-        }
-
-        @Override
-        public ResourceManagerRemote getResourceManager() {
-            return null;
-        }
-
-        @Override
-        public ResourceGroupManagerRemote getResourceGroupManager() {
-            return null;
-        }
-
-        @Override
-        public SubjectManagerRemote getSubjectManager() {
-            return null;
-        }
     }
 
 }
diff --git a/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RemoteClient.java b/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RemoteClient.java
index 57829b9..4ea3267 100644
--- a/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RemoteClient.java
+++ b/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RemoteClient.java
@@ -19,6 +19,7 @@
 package org.rhq.enterprise.clientapi;
 
 import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -28,44 +29,18 @@ import org.apache.maven.artifact.versioning.ComparableVersion;
 
 import org.jboss.remoting.Client;
 import org.jboss.remoting.InvokerLocator;
+import org.jboss.remoting.invocation.NameBasedInvocation;
 import org.jboss.remoting.security.SSLSocketBuilder;
 import org.jboss.remoting.transport.http.ssl.HTTPSClientInvoker;
 
 import org.rhq.bindings.client.RhqFacade;
 import org.rhq.bindings.client.RhqManager;
+import org.rhq.bindings.util.InterfaceSimplifier;
 import org.rhq.core.domain.auth.Subject;
 import org.rhq.core.domain.common.ProductInfo;
 import org.rhq.enterprise.communications.util.SecurityUtil;
-import org.rhq.enterprise.server.alert.AlertDefinitionManagerRemote;
-import org.rhq.enterprise.server.alert.AlertManagerRemote;
 import org.rhq.enterprise.server.auth.SubjectManagerRemote;
-import org.rhq.enterprise.server.authz.RoleManagerRemote;
-import org.rhq.enterprise.server.bundle.BundleManagerRemote;
-import org.rhq.enterprise.server.configuration.ConfigurationManagerRemote;
-import org.rhq.enterprise.server.content.ContentManagerRemote;
-import org.rhq.enterprise.server.content.RepoManagerRemote;
-import org.rhq.enterprise.server.discovery.DiscoveryBossRemote;
-import org.rhq.enterprise.server.drift.DriftManagerRemote;
-import org.rhq.enterprise.server.drift.DriftTemplateManagerRemote;
-import org.rhq.enterprise.server.event.EventManagerRemote;
-import org.rhq.enterprise.server.install.remote.RemoteInstallManagerRemote;
-import org.rhq.enterprise.server.measurement.AvailabilityManagerRemote;
-import org.rhq.enterprise.server.measurement.CallTimeDataManagerRemote;
-import org.rhq.enterprise.server.measurement.MeasurementBaselineManagerRemote;
-import org.rhq.enterprise.server.measurement.MeasurementDataManagerRemote;
-import org.rhq.enterprise.server.measurement.MeasurementDefinitionManagerRemote;
-import org.rhq.enterprise.server.measurement.MeasurementScheduleManagerRemote;
-import org.rhq.enterprise.server.operation.OperationManagerRemote;
-import org.rhq.enterprise.server.report.DataAccessManagerRemote;
-import org.rhq.enterprise.server.resource.ResourceFactoryManagerRemote;
-import org.rhq.enterprise.server.resource.ResourceManagerRemote;
-import org.rhq.enterprise.server.resource.ResourceTypeManagerRemote;
-import org.rhq.enterprise.server.resource.group.ResourceGroupManagerRemote;
-import org.rhq.enterprise.server.search.SavedSearchManagerRemote;
-import org.rhq.enterprise.server.support.SupportManagerRemote;
-import org.rhq.enterprise.server.sync.SynchronizationManagerRemote;
 import org.rhq.enterprise.server.system.SystemManagerRemote;
-import org.rhq.enterprise.server.tagging.TagManagerRemote;
 
 /**
  * A remote access client that provides transparent servlet-based proxies to an RHQ Server.
@@ -127,6 +102,29 @@ public class RemoteClient implements RhqFacade {
         this.subsystem = subsystem;
     }
 
+    public <T> T remoteInvoke(RhqManager manager, Method method, Class<T> expectedReturnType, Object... parameters)
+        throws Throwable {
+
+        String methodSig = manager.beanName() + ":" + method.getName();
+
+        Class<?>[] paramTypes = method.getParameterTypes();
+        String[] paramSig = new String[paramTypes.length];
+        for (int x = 0; x < paramTypes.length; x++) {
+            paramSig[x] = paramTypes[x].getName();
+        }
+
+        NameBasedInvocation request = new NameBasedInvocation(methodSig, parameters, paramSig);
+
+        Object response = getRemotingClient().invoke(request);
+
+        if (response instanceof Throwable) {
+            throw (Throwable) response;
+        }
+
+        return response == null ? null : expectedReturnType.cast(response);
+
+    }
+
     /**
      * Connects to the remote server and logs in with the given credentials.
      * After successfully executing this, {@link #isLoggedIn()} will be <code>true</code>
@@ -144,7 +142,16 @@ public class RemoteClient implements RhqFacade {
         logout();
         doConnect();
 
-        this.subject = getSubjectManager().login(user, password);
+        Method loginMethod = SubjectManagerRemote.class.getDeclaredMethod("login", String.class, String.class);
+
+        try {
+            this.subject = remoteInvoke(RhqManager.SubjectManager, loginMethod, Subject.class, user, password);
+        } catch (Exception e) {
+            throw e;
+        } catch (Throwable e) {
+            throw new Exception("Failed to login due to a throwable of type " + e.getClass().getName(), e);
+        }
+
         this.loggedIn = true;
 
         return this.subject;
@@ -154,12 +161,16 @@ public class RemoteClient implements RhqFacade {
      * Logs out from the server and disconnects this client.
      */
     public void logout() {
-        try {
-            if (this.loggedIn && this.subject != null) {
-                getSubjectManager().logout(this.subject);
+        if (this.loggedIn && this.subject != null) {
+            try {
+                Method logoutMethod = SubjectManagerRemote.class.getDeclaredMethod("logout", Subject.class);
+                remoteInvoke(RhqManager.SubjectManager, logoutMethod, Void.class, this.subject);
+            } catch (NoSuchMethodException e) {
+                throw new IllegalStateException(
+                    "Couldn't find the logout method on the SubjectManagerRemote interface.", e);
+            } catch (Throwable e) {
+                // just keep going so we can disconnect this client
             }
-        } catch (Exception e) {
-            // just keep going so we can disconnect this client
         }
 
         doDisconnect();
@@ -260,145 +271,25 @@ public class RemoteClient implements RhqFacade {
         this.transport = transport;
     }
 
-    public AlertManagerRemote getAlertManager() {
-        return RemoteClientProxy.getProcessor(this, RhqManager.AlertManager);
-    }
-
-    public AlertDefinitionManagerRemote getAlertDefinitionManager() {
-        return RemoteClientProxy.getProcessor(this, RhqManager.AlertDefinitionManager);
-    }
-
-    public AvailabilityManagerRemote getAvailabilityManager() {
-        return RemoteClientProxy.getProcessor(this, RhqManager.AvailabilityManager);
-    }
-
-    public BundleManagerRemote getBundleManager() {
-        return RemoteClientProxy.getProcessor(this, RhqManager.BundleManager);
-    }
-
-    public CallTimeDataManagerRemote getCallTimeDataManager() {
-        return RemoteClientProxy.getProcessor(this, RhqManager.CallTimeDataManager);
-    }
-
-    public DriftManagerRemote getDriftManager() {
-        return RemoteClientProxy.getProcessor(this, RhqManager.DriftManager);
-    }
-
-    public DriftTemplateManagerRemote getDriftTemplateManager() {
-        return RemoteClientProxy.getProcessor(this, RhqManager.DriftTemplateManager);
-    }
-
-    public RepoManagerRemote getRepoManager() {
-        return RemoteClientProxy.getProcessor(this, RhqManager.RepoManager);
-    }
-
-    public ConfigurationManagerRemote getConfigurationManager() {
-        return RemoteClientProxy.getProcessor(this, RhqManager.ConfigurationManager);
-    }
-
-    public ContentManagerRemote getContentManager() {
-        return RemoteClientProxy.getProcessor(this, RhqManager.ContentManager);
-    }
-
-    public DataAccessManagerRemote getDataAccessManager() {
-        return RemoteClientProxy.getProcessor(this, RhqManager.DataAccessManager);
-    }
-
-    public DiscoveryBossRemote getDiscoveryBoss() {
-        return RemoteClientProxy.getProcessor(this, RhqManager.DiscoveryBoss);
-    }
-
-    public EventManagerRemote getEventManager() {
-        return RemoteClientProxy.getProcessor(this, RhqManager.EventManager);
-    }
-
-    public MeasurementBaselineManagerRemote getMeasurementBaselineManager() {
-        return RemoteClientProxy.getProcessor(this, RhqManager.MeasurementBaselineManager);
-    }
-
-    public MeasurementDataManagerRemote getMeasurementDataManager() {
-        return RemoteClientProxy.getProcessor(this, RhqManager.MeasurementDataManager);
-    }
-
-    public MeasurementDefinitionManagerRemote getMeasurementDefinitionManager() {
-        return RemoteClientProxy.getProcessor(this, RhqManager.MeasurementDefinitionManager);
-    }
-
-    public MeasurementScheduleManagerRemote getMeasurementScheduleManager() {
-        return RemoteClientProxy.getProcessor(this, RhqManager.MeasurementScheduleManager);
-    }
-
-    public OperationManagerRemote getOperationManager() {
-        return RemoteClientProxy.getProcessor(this, RhqManager.OperationManager);
-    }
-
-    public ResourceManagerRemote getResourceManager() {
-        return RemoteClientProxy.getProcessor(this, RhqManager.ResourceManager);
-    }
-
-    public ResourceFactoryManagerRemote getResourceFactoryManager() {
-        return RemoteClientProxy.getProcessor(this, RhqManager.ResourceFactoryManager);
-    }
-
-    public ResourceGroupManagerRemote getResourceGroupManager() {
-        return RemoteClientProxy.getProcessor(this, RhqManager.ResourceGroupManager);
-    }
-
-    public ResourceTypeManagerRemote getResourceTypeManager() {
-        return RemoteClientProxy.getProcessor(this, RhqManager.ResourceTypeManager);
-    }
-
-    public RoleManagerRemote getRoleManager() {
-        return RemoteClientProxy.getProcessor(this, RhqManager.RoleManager);
-    }
-
-    public SavedSearchManagerRemote getSavedSearchManager() {
-        return RemoteClientProxy.getProcessor(this, RhqManager.SavedSearchManager);
-    }
-
-    public SubjectManagerRemote getSubjectManager() {
-        return RemoteClientProxy.getProcessor(this, RhqManager.SubjectManager);
-    }
-
-    public SupportManagerRemote getSupportManager() {
-        return RemoteClientProxy.getProcessor(this, RhqManager.SupportManager);
-    }
-
-    public SystemManagerRemote getSystemManager() {
-        return RemoteClientProxy.getProcessor(this, RhqManager.SystemManager);
-    }
-
-    public RemoteInstallManagerRemote getRemoteInstallManager() {
-        return RemoteClientProxy.getProcessor(this, RhqManager.RemoteInstallManager);
-    }
-
-    public TagManagerRemote getTagManager() {
-        return RemoteClientProxy.getProcessor(this, RhqManager.TagManager);
-    }
-
-    public SynchronizationManagerRemote getSynchronizationManager() {
-        return RemoteClientProxy.getProcessor(this, RhqManager.SynchronizationManager);
-    }
-
     /**
      * Returns the map of all remote managers running in the server that this
      * client can talk to.
      *
      * @return Map K=manager name V=remote proxy
      */
-    public Map<String, Object> getManagers() {
+    public Map<String, Object> getScriptingAPI() {
         if (this.managers == null) {
 
             this.managers = new HashMap<String, Object>();
 
             for (RhqManager manager : RhqManager.values()) {
-                try {
-                    Method m = this.getClass().getMethod("get" + manager.name());
-                    if (manager.enabled()) {
-                        this.managers.put(manager.name(), m.invoke(this));
+                if (manager.enabled()) {
+                    try {
+                        Object proxy = getProcessor(this, manager, true);
+                        this.managers.put(manager.name(), proxy);
+                    } catch (Throwable e) {
+                        LOG.error("Failed to load manager " + manager + " due to missing class.", e);
                     }
-                } catch (Throwable e) {
-                    LOG.error("Failed to load manager " + manager + " due to missing class.", e);
                 }
             }
         }
@@ -407,6 +298,17 @@ public class RemoteClient implements RhqFacade {
     }
 
     @Override
+    public <T> T getProxy(Class<T> remoteApiIface) {
+        RhqManager manager = RhqManager.forInterface(remoteApiIface);
+
+        if (manager == null) {
+            throw new IllegalArgumentException("Unknown remote interface " + remoteApiIface);
+        }
+
+        return getProcessor(this, manager, false);
+    }
+
+    @Override
     public String toString() {
         return this.getClass().getSimpleName() + "[" + "transport=" + transport + ", host=" + host + ", port=" + port
             + ", subsystem=" + subsystem + ", connected=" + connected + ", loggedIn=" + loggedIn + ", subject="
@@ -443,6 +345,20 @@ public class RemoteClient implements RhqFacade {
         return (this.serverInfo != null) ? this.serverInfo.getBuildNumber() : null;
     }
 
+    @SuppressWarnings("unchecked")
+    private static <T> T getProcessor(RemoteClient remoteClient, RhqManager manager, boolean simplify) {
+        try {
+            RemoteClientProxy gpc = new RemoteClientProxy(remoteClient, manager);
+
+            Class<?> intf = simplify ? InterfaceSimplifier.simplify(manager.remote()) : manager.remote();
+
+            return (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class<?>[] { intf },
+                gpc);
+        } catch (Exception e) {
+            throw new RuntimeException("Failed to get remote connection proxy", e);
+        }
+    }
+
     private void doDisconnect() {
         try {
             if (this.remotingClient != null && this.remotingClient.isConnected()) {
@@ -470,13 +386,21 @@ public class RemoteClient implements RhqFacade {
         this.remotingClient.connect();
 
         // make sure the remote server can support this client
-        this.serverInfo = getSystemManager().getProductInfo(subject);
         try {
+            Method getProductInfoMethod = SystemManagerRemote.class.getDeclaredMethod("getProductInfo", Subject.class);
+
+            this.serverInfo = remoteInvoke(RhqManager.SystemManager, getProductInfoMethod, ProductInfo.class,
+                this.subject);
             checkServerSupported(this.serverInfo);
+        } catch (NoSuchMethodException e) {
+            throw new IllegalStateException("Could not find the getProductInfo(Subject) method on the SystemManager.",
+                e);
         } catch (Exception e) {
             // our client cannot be supported by the server - disconnect and rethrow the exception
             doDisconnect();
             throw e;
+        } catch (Throwable e) {
+            throw new IllegalStateException("Unknown error occured during connect.", e);
         }
     }
 
diff --git a/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RemoteClientProxy.java b/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RemoteClientProxy.java
index 23dea3c..a6b04f1 100644
--- a/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RemoteClientProxy.java
+++ b/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RemoteClientProxy.java
@@ -19,16 +19,12 @@
 package org.rhq.enterprise.clientapi;
 
 import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
-import org.jboss.remoting.invocation.NameBasedInvocation;
-
 import org.rhq.bindings.client.AbstractRhqFacadeProxy;
 import org.rhq.bindings.client.RhqManager;
-import org.rhq.bindings.util.InterfaceSimplifier;
 import org.rhq.core.domain.server.ExternalizableStrategy;
 
 /**
@@ -46,24 +42,11 @@ public class RemoteClientProxy extends AbstractRhqFacadeProxy<RemoteClient> {
         super(client, manager);
     }
 
+    @Deprecated
     public Class<?> getRemoteInterface() {
         return this.getManager().remote();
     }
 
-    @SuppressWarnings("unchecked")
-    public static <T> T getProcessor(RemoteClient remoteClient, RhqManager manager) {
-        try {
-            RemoteClientProxy gpc = new RemoteClientProxy(remoteClient, manager);
-
-            Class<?> intf = InterfaceSimplifier.simplify(manager.remote());
-
-            return (T) Proxy
-                .newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class<?>[] { intf }, gpc);
-        } catch (Exception e) {
-            throw new RuntimeException("Failed to get remote connection proxy", e);
-        }
-    }
-
     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
         try {
             return super.invoke(proxy, method, args);
@@ -73,29 +56,9 @@ public class RemoteClientProxy extends AbstractRhqFacadeProxy<RemoteClient> {
         }
     }
 
-    protected Object doInvoke(Object proxy, Method originalMethod, java.lang.Class<?>[] argTypes, Object[] args) throws Throwable  {
+    protected Object doInvoke(Object proxy, Method originalMethod, Object[] args) throws Throwable  {
         ExternalizableStrategy.setStrategy(ExternalizableStrategy.Subsystem.REFLECTIVE_SERIALIZATION);
 
-        String methodName = getManager().beanName() + ":" + originalMethod.getName();
-
-        String[] paramSig = createParamSignature(argTypes);
-
-        NameBasedInvocation request = new NameBasedInvocation(methodName, args, paramSig);
-
-        Object response = getRhqFacade().getRemotingClient().invoke(request);
-
-        if (response instanceof Throwable) {
-            throw (Throwable) response;
-        }
-
-        return response;
-    }
-
-    private String[] createParamSignature(Class<?>[] types) {
-        String[] paramSig = new String[types.length];
-        for (int x = 0; x < types.length; x++) {
-            paramSig[x] = types[x].getName();
-        }
-        return paramSig;
+        return getRhqFacade().remoteInvoke(getManager(), originalMethod, Object.class, args);
     }
 }
diff --git a/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClient.java b/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClient.java
index dbb4424..e350302 100644
--- a/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClient.java
+++ b/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClient.java
@@ -19,11 +19,9 @@
 
 package org.rhq.enterprise.client;
 
-import java.lang.reflect.Method;
 import java.lang.reflect.Proxy;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
-import java.security.PrivilegedActionException;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -34,36 +32,6 @@ import org.rhq.bindings.client.RhqFacade;
 import org.rhq.bindings.client.RhqManager;
 import org.rhq.bindings.util.InterfaceSimplifier;
 import org.rhq.core.domain.auth.Subject;
-import org.rhq.enterprise.server.alert.AlertDefinitionManagerRemote;
-import org.rhq.enterprise.server.alert.AlertManagerRemote;
-import org.rhq.enterprise.server.auth.SubjectManagerRemote;
-import org.rhq.enterprise.server.authz.RoleManagerRemote;
-import org.rhq.enterprise.server.bundle.BundleManagerRemote;
-import org.rhq.enterprise.server.configuration.ConfigurationManagerRemote;
-import org.rhq.enterprise.server.content.ContentManagerRemote;
-import org.rhq.enterprise.server.content.RepoManagerRemote;
-import org.rhq.enterprise.server.discovery.DiscoveryBossRemote;
-import org.rhq.enterprise.server.drift.DriftManagerRemote;
-import org.rhq.enterprise.server.drift.DriftTemplateManagerRemote;
-import org.rhq.enterprise.server.event.EventManagerRemote;
-import org.rhq.enterprise.server.install.remote.RemoteInstallManagerRemote;
-import org.rhq.enterprise.server.measurement.AvailabilityManagerRemote;
-import org.rhq.enterprise.server.measurement.CallTimeDataManagerRemote;
-import org.rhq.enterprise.server.measurement.MeasurementBaselineManagerRemote;
-import org.rhq.enterprise.server.measurement.MeasurementDataManagerRemote;
-import org.rhq.enterprise.server.measurement.MeasurementDefinitionManagerRemote;
-import org.rhq.enterprise.server.measurement.MeasurementScheduleManagerRemote;
-import org.rhq.enterprise.server.operation.OperationManagerRemote;
-import org.rhq.enterprise.server.report.DataAccessManagerRemote;
-import org.rhq.enterprise.server.resource.ResourceFactoryManagerRemote;
-import org.rhq.enterprise.server.resource.ResourceManagerRemote;
-import org.rhq.enterprise.server.resource.ResourceTypeManagerRemote;
-import org.rhq.enterprise.server.resource.group.ResourceGroupManagerRemote;
-import org.rhq.enterprise.server.search.SavedSearchManagerRemote;
-import org.rhq.enterprise.server.support.SupportManagerRemote;
-import org.rhq.enterprise.server.sync.SynchronizationManagerRemote;
-import org.rhq.enterprise.server.system.SystemManagerRemote;
-import org.rhq.enterprise.server.tagging.TagManagerRemote;
 import org.rhq.enterprise.server.util.LookupUtil;
 
 /**
@@ -102,331 +70,46 @@ public class LocalClient implements RhqFacade {
     }
 
     @Override
-    public AlertManagerRemote getAlertManager() {
-        return AccessController.doPrivileged(new PrivilegedAction<AlertManagerRemote>() {
-            @Override
-            public AlertManagerRemote run() {
-                return AccessController.doPrivileged(new PrivilegedAction<AlertManagerRemote>() {
-                    @Override
-                    public AlertManagerRemote run() {
-                        return getProxy(LookupUtil.getAlertManager(), AlertManagerRemote.class);
-                    }
-                });
-            }
-        });
-    }
-
-    @Override
-    public AlertDefinitionManagerRemote getAlertDefinitionManager() {
-        return AccessController.doPrivileged(new PrivilegedAction<AlertDefinitionManagerRemote>() {
-            @Override
-            public AlertDefinitionManagerRemote run() {
-                return getProxy(LookupUtil.getAlertDefinitionManager(), AlertDefinitionManagerRemote.class);
-            }
-        });
-    }
+    public Map<String, Object> getScriptingAPI() {
+        if (managers == null) {
 
-    @Override
-    public AvailabilityManagerRemote getAvailabilityManager() {
-        return AccessController.doPrivileged(new PrivilegedAction<AvailabilityManagerRemote>() {
-            @Override
-            public AvailabilityManagerRemote run() {
-                return getProxy(LookupUtil.getAvailabilityManager(), AvailabilityManagerRemote.class);
-            }
-        });
-    }
+            managers = new HashMap<String, Object>();
 
-    @Override
-    public BundleManagerRemote getBundleManager() {
-        return AccessController.doPrivileged(new PrivilegedAction<BundleManagerRemote>() {
-            @Override
-            public BundleManagerRemote run() {
-                return AccessController.doPrivileged(new PrivilegedAction<BundleManagerRemote>() {
-                    @Override
-                    public BundleManagerRemote run() {
-                        return getProxy(LookupUtil.getBundleManager(), BundleManagerRemote.class);
+            for (final RhqManager manager : RhqManager.values()) {
+                if (manager.enabled()) {
+                    try {
+                        Object proxy = AccessController.doPrivileged(new PrivilegedAction<Object>() {
+                            @Override
+                            public Object run() {
+                                return getProxy(getLocalSLSB(manager), manager.remote());
+                            }
+                        });
+
+                        managers.put(manager.name(), proxy);
+                    } catch (Throwable e) {
+                        LOG.error("Failed to load manager " + manager + " due to missing class.", e);
                     }
-                });
-            }
-        });
-    }
-
-    @Override
-    public CallTimeDataManagerRemote getCallTimeDataManager() {
-        return AccessController.doPrivileged(new PrivilegedAction<CallTimeDataManagerRemote>() {
-            @Override
-            public CallTimeDataManagerRemote run() {
-                return getProxy(LookupUtil.getCallTimeDataManager(), CallTimeDataManagerRemote.class);
-            }
-        });
-    }
-
-    @Override
-    public RepoManagerRemote getRepoManager() {
-        return AccessController.doPrivileged(new PrivilegedAction<RepoManagerRemote>() {
-            @Override
-            public RepoManagerRemote run() {
-                return getProxy(LookupUtil.getRepoManagerLocal(), RepoManagerRemote.class);
-            }
-        });
-    }
-
-    @Override
-    public ConfigurationManagerRemote getConfigurationManager() {
-        return AccessController.doPrivileged(new PrivilegedAction<ConfigurationManagerRemote>() {
-            @Override
-            public ConfigurationManagerRemote run() {
-                return getProxy(LookupUtil.getConfigurationManager(), ConfigurationManagerRemote.class);
-            }
-        });
-    }
-
-    @Override
-    public ContentManagerRemote getContentManager() {
-        return AccessController.doPrivileged(new PrivilegedAction<ContentManagerRemote>() {
-            @Override
-            public ContentManagerRemote run() {
-                return getProxy(LookupUtil.getContentManager(), ContentManagerRemote.class);
-            }
-        });
-    }
-
-    @Override
-    public DataAccessManagerRemote getDataAccessManager() {
-        return AccessController.doPrivileged(new PrivilegedAction<DataAccessManagerRemote>() {
-            @Override
-            public DataAccessManagerRemote run() {
-                return getProxy(LookupUtil.getDataAccessManager(), DataAccessManagerRemote.class);
-            }
-        });
-    }
-
-    @Override
-    public DiscoveryBossRemote getDiscoveryBoss() {
-        return AccessController.doPrivileged(new PrivilegedAction<DiscoveryBossRemote>() {
-            @Override
-            public DiscoveryBossRemote run() {
-                return getProxy(LookupUtil.getDiscoveryBoss(), DiscoveryBossRemote.class);
-            }
-        });
-    }
-
-    @Override
-    public DriftManagerRemote getDriftManager() {
-        return AccessController.doPrivileged(new PrivilegedAction<DriftManagerRemote>() {
-            @Override
-            public DriftManagerRemote run() {
-                return getProxy(LookupUtil.getDriftManager(), DriftManagerRemote.class);
-            }
-        });
-    }
-
-    public DriftTemplateManagerRemote getDriftTemplateManager() {
-        return AccessController.doPrivileged(new PrivilegedAction<DriftTemplateManagerRemote>() {
-            @Override
-            public DriftTemplateManagerRemote run() {
-                return getProxy(LookupUtil.getDriftTemplateManager(), DriftTemplateManagerRemote.class);
-            }
-        });
-    }
-
-    @Override
-    public EventManagerRemote getEventManager() {
-        return AccessController.doPrivileged(new PrivilegedAction<EventManagerRemote>() {
-            @Override
-            public EventManagerRemote run() {
-                return getProxy(LookupUtil.getEventManager(), EventManagerRemote.class);
-            }
-        });
-    }
-
-    @Override
-    public MeasurementBaselineManagerRemote getMeasurementBaselineManager() {
-        return AccessController.doPrivileged(new PrivilegedAction<MeasurementBaselineManagerRemote>() {
-            @Override
-            public MeasurementBaselineManagerRemote run() {
-                return getProxy(LookupUtil.getMeasurementBaselineManager(), MeasurementBaselineManagerRemote.class);
-            }
-        });
-    }
-
-    @Override
-    public MeasurementDataManagerRemote getMeasurementDataManager() {
-        return AccessController.doPrivileged(new PrivilegedAction<MeasurementDataManagerRemote>() {
-            @Override
-            public MeasurementDataManagerRemote run() {
-                return getProxy(LookupUtil.getMeasurementDataManager(), MeasurementDataManagerRemote.class);
-            }
-        });
-    }
-
-    @Override
-    public MeasurementDefinitionManagerRemote getMeasurementDefinitionManager() {
-        return AccessController.doPrivileged(new PrivilegedAction<MeasurementDefinitionManagerRemote>() {
-            @Override
-            public MeasurementDefinitionManagerRemote run() {
-                return getProxy(LookupUtil.getMeasurementDefinitionManager(), MeasurementDefinitionManagerRemote.class);
-            }
-        });
-    }
-
-    @Override
-    public MeasurementScheduleManagerRemote getMeasurementScheduleManager() {
-        return AccessController.doPrivileged(new PrivilegedAction<MeasurementScheduleManagerRemote>() {
-            @Override
-            public MeasurementScheduleManagerRemote run() {
-                return getProxy(LookupUtil.getMeasurementScheduleManager(), MeasurementScheduleManagerRemote.class);
-            }
-        });
-    }
-
-    @Override
-    public OperationManagerRemote getOperationManager() {
-        return AccessController.doPrivileged(new PrivilegedAction<OperationManagerRemote>() {
-            @Override
-            public OperationManagerRemote run() {
-                return getProxy(LookupUtil.getOperationManager(), OperationManagerRemote.class);
-            }
-        });
-    }
-
-    @Override
-    public ResourceManagerRemote getResourceManager() {
-        return AccessController.doPrivileged(new PrivilegedAction<ResourceManagerRemote>() {
-            @Override
-            public ResourceManagerRemote run() {
-                return getProxy(LookupUtil.getResourceManager(), ResourceManagerRemote.class);
-            }
-        });
-    }
-
-    @Override
-    public ResourceFactoryManagerRemote getResourceFactoryManager() {
-        return AccessController.doPrivileged(new PrivilegedAction<ResourceFactoryManagerRemote>() {
-            @Override
-            public ResourceFactoryManagerRemote run() {
-                return getProxy(LookupUtil.getResourceFactoryManager(), ResourceFactoryManagerRemote.class);
-            }
-        });
-    }
-
-    @Override
-    public ResourceGroupManagerRemote getResourceGroupManager() {
-        return AccessController.doPrivileged(new PrivilegedAction<ResourceGroupManagerRemote>() {
-            @Override
-            public ResourceGroupManagerRemote run() {
-                return getProxy(LookupUtil.getResourceGroupManager(), ResourceGroupManagerRemote.class);
-            }
-        });
-    }
-
-    @Override
-    public ResourceTypeManagerRemote getResourceTypeManager() {
-        return AccessController.doPrivileged(new PrivilegedAction<ResourceTypeManagerRemote>() {
-            @Override
-            public ResourceTypeManagerRemote run() {
-                return getProxy(LookupUtil.getResourceTypeManager(), ResourceTypeManagerRemote.class);
-            }
-        });
-    }
-
-    @Override
-    public RoleManagerRemote getRoleManager() {
-        return AccessController.doPrivileged(new PrivilegedAction<RoleManagerRemote>() {
-            @Override
-            public RoleManagerRemote run() {
-                return getProxy(LookupUtil.getRoleManager(), RoleManagerRemote.class);
-            }
-        });
-    }
-
-    @Override
-    public SavedSearchManagerRemote getSavedSearchManager() {
-        return AccessController.doPrivileged(new PrivilegedAction<SavedSearchManagerRemote>() {
-            @Override
-            public SavedSearchManagerRemote run() {
-                return getProxy(LookupUtil.getSavedSearchManager(), SavedSearchManagerRemote.class);
-            }
-        });
-    }
-
-    @Override
-    public SubjectManagerRemote getSubjectManager() {
-        return AccessController.doPrivileged(new PrivilegedAction<SubjectManagerRemote>() {
-            @Override
-            public SubjectManagerRemote run() {
-                return getProxy(LookupUtil.getSubjectManager(), SubjectManagerRemote.class);
-            }
-        });
-    }
-
-    @Override
-    public SupportManagerRemote getSupportManager() {
-        return AccessController.doPrivileged(new PrivilegedAction<SupportManagerRemote>() {
-            @Override
-            public SupportManagerRemote run() {
-                return getProxy(LookupUtil.getSupportManager(), SupportManagerRemote.class);
-            }
-        });
-    }
-
-    @Override
-    public SystemManagerRemote getSystemManager() {
-        return AccessController.doPrivileged(new PrivilegedAction<SystemManagerRemote>() {
-            @Override
-            public SystemManagerRemote run() {
-                return getProxy(LookupUtil.getSystemManager(), SystemManagerRemote.class);
-            }
-        });
-    }
-
-    @Override
-    public RemoteInstallManagerRemote getRemoteInstallManager() {
-        return AccessController.doPrivileged(new PrivilegedAction<RemoteInstallManagerRemote>() {
-            @Override
-            public RemoteInstallManagerRemote run() {
-                return getProxy(LookupUtil.getRemoteInstallManager(), RemoteInstallManagerRemote.class);
+                }
             }
-        });
-    }
+        }
 
-    @Override
-    public TagManagerRemote getTagManager() {
-        return AccessController.doPrivileged(new PrivilegedAction<TagManagerRemote>() {
-            @Override
-            public TagManagerRemote run() {
-                return getProxy(LookupUtil.getTagManager(), TagManagerRemote.class);
-            }
-        });
+        return managers;
     }
 
     @Override
-    public SynchronizationManagerRemote getSynchronizationManager() {
-        return AccessController.doPrivileged(new PrivilegedAction<SynchronizationManagerRemote>() {
-            @Override
-            public SynchronizationManagerRemote run() {
-                return getProxy(LookupUtil.getSynchronizationManager(), SynchronizationManagerRemote.class);
-            }
-        });
-    }
+    public <T> T getProxy(Class<T> remoteApiIface) {
+        RhqManager manager = RhqManager.forInterface(remoteApiIface);
 
-    @Override
-    public Map<String, Object> getManagers() {
-        if (managers == null) {
+        if (manager == null) {
+            throw new IllegalArgumentException("Unknown remote interface " + remoteApiIface);
+        }
 
-            managers = new HashMap<String, Object>();
+        Object localSLSB = getLocalSLSB(manager);
 
-            for (RhqManager manager : RhqManager.values()) {
-                try {
-                    Method m = getClass().getMethod("get" + manager.name());
-                    managers.put(manager.name(), m.invoke(this));
-                } catch (Throwable e) {
-                    LOG.error("Failed to load manager " + manager + " due to missing class.", e);
-                }
-            }
-        }
+        Object proxy = Proxy.newProxyInstance(remoteApiIface.getClassLoader(), new Class<?>[] { remoteApiIface },
+            new LocalClientProxy(localSLSB, this, manager));
 
-        return managers;
+        return remoteApiIface.cast(proxy);
     }
 
     private <T> T getProxy(Object slsb, Class<T> iface) {
@@ -442,10 +125,77 @@ public class LocalClient implements RhqFacade {
             Thread.currentThread().setContextClassLoader(cl);
         }
 
-        Object proxy =
-            Proxy.newProxyInstance(iface.getClassLoader(), new Class<?>[] { simplified }, new LocalClientProxy(slsb,
-                this, manager));
+        Object proxy = Proxy.newProxyInstance(iface.getClassLoader(), new Class<?>[] { simplified },
+            new LocalClientProxy(slsb, this, manager));
 
         return iface.cast(proxy);
     }
+
+    private Object getLocalSLSB(RhqManager manager) {
+        switch (manager) {
+        case AlertDefinitionManager:
+            return LookupUtil.getAlertDefinitionManager();
+        case AlertManager:
+            return LookupUtil.getAlertManager();
+        case AvailabilityManager:
+            return LookupUtil.getAvailabilityManager();
+        case BundleManager:
+            return LookupUtil.getBundleManager();
+        case CallTimeDataManager:
+            return LookupUtil.getCallTimeDataManager();
+        case ConfigurationManager:
+            return LookupUtil.getConfigurationManager();
+        case ContentManager:
+            return LookupUtil.getContentManager();
+        case DataAccessManager:
+            return LookupUtil.getDataAccessManager();
+        case DiscoveryBoss:
+            return LookupUtil.getDiscoveryBoss();
+        case DriftManager:
+            return LookupUtil.getDriftManager();
+        case DriftTemplateManager:
+            return LookupUtil.getDriftTemplateManager();
+        case EventManager:
+            return LookupUtil.getEventManager();
+        case MeasurementBaselineManager:
+            return LookupUtil.getMeasurementBaselineManager();
+        case MeasurementDataManager:
+            return LookupUtil.getMeasurementDataManager();
+        case MeasurementDefinitionManager:
+            return LookupUtil.getMeasurementDefinitionManager();
+        case MeasurementScheduleManager:
+            return LookupUtil.getMeasurementScheduleManager();
+        case OperationManager:
+            return LookupUtil.getOperationManager();
+        case RemoteInstallManager:
+            return LookupUtil.getRemoteInstallManager();
+        case RepoManager:
+            return LookupUtil.getRepoManagerLocal();
+        case ResourceFactoryManager:
+            return LookupUtil.getResourceFactoryManager();
+        case ResourceGroupManager:
+            return LookupUtil.getResourceGroupManager();
+        case ResourceManager:
+            return LookupUtil.getResourceManager();
+        case ResourceTypeManager:
+            return LookupUtil.getResourceTypeManager();
+        case RoleManager:
+            return LookupUtil.getRoleManager();
+        case SavedSearchManager:
+            return LookupUtil.getSavedSearchManager();
+        case SubjectManager:
+            return LookupUtil.getSubjectManager();
+        case SupportManager:
+            return LookupUtil.getSupportManager();
+        case SynchronizationManager:
+            return LookupUtil.getSynchronizationManager();
+        case SystemManager:
+            return LookupUtil.getSystemManager();
+        case TagManager:
+            return LookupUtil.getTagManager();
+        }
+
+        throw new IllegalStateException("LocalClient does not handle the manager: " + manager
+            + ". This is a bug, please report it.");
+    }
 }
diff --git a/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClientProxy.java b/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClientProxy.java
index 67bd5e7..54d20e0 100644
--- a/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClientProxy.java
+++ b/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClientProxy.java
@@ -56,9 +56,10 @@ public class LocalClientProxy extends AbstractRhqFacadeProxy<LocalClient> {
         }
     }
     
-    protected Object doInvoke(Object proxy, Method originalMethod, java.lang.Class<?>[] argTypes, final Object[] args) throws Throwable {
+    protected Object doInvoke(Object proxy, Method originalMethod, final Object[] args) throws Throwable {
         try {
-            final Method realMethod = localSLSB.getClass().getMethod(originalMethod.getName(), argTypes);
+            final Method realMethod = localSLSB.getClass().getMethod(originalMethod.getName(),
+                originalMethod.getParameterTypes());
 
             //run this through the privileged block to elevate the privs of the script
             //the scripts don't have the AllowEjbAccessPermission but this code has
@@ -72,7 +73,9 @@ public class LocalClientProxy extends AbstractRhqFacadeProxy<LocalClient> {
                 }
             });
         } catch (NoSuchMethodException e) {
-            throw new IllegalArgumentException("Method [" + originalMethod + "] does not have a desimplified counterpart with arguments " + Arrays.asList(argTypes) + ".", e);
+            throw new IllegalArgumentException("Method [" + originalMethod
+                + "] does not have a desimplified counterpart with arguments "
+                + Arrays.asList(originalMethod.getParameterTypes()) + ".", e);
         }
     };
     
diff --git a/modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/test/LocalClientTest.java b/modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/test/LocalClientTest.java
index 3b949e3..e9bd928 100644
--- a/modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/test/LocalClientTest.java
+++ b/modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/test/LocalClientTest.java
@@ -31,7 +31,6 @@ import javax.naming.NamingException;
 import javax.naming.spi.InitialContextFactory;
 
 import org.jmock.Expectations;
-import org.testng.Assert;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 
@@ -89,7 +88,7 @@ public class LocalClientTest extends JMockTest {
             LocalClient lc = new LocalClient(null);
             
             //this call creates the proxy and is theoretically prone to the context classloader
-            AlertManagerRemote am = lc.getAlertManager();
+            Object am = lc.getScriptingAPI().get("AlertManager");
 
             //check that both the original and simplified methods exist on the returned object
             am.getClass().getMethod("deleteAlerts", new Class<?>[] { Subject.class, int[].class });            


commit c9b69bbf92000a6cee0773eb51a34aaf41e57fff
Author: Heiko W. Rupp <hwr at redhat.com>
Date:   Wed Jun 20 11:28:09 2012 +0200

    Expose more group properties.

diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerBean.java
index 7f13618..5fa0089 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerBean.java
@@ -249,13 +249,9 @@ public class GroupHandlerBean extends AbstractRestBean implements GroupHandlerLo
      */
     private ResourceGroup fetchGroup(int groupId) {
         ResourceGroup resourceGroup;
-        resourceGroup = getFromCache(groupId,ResourceGroup.class);
-        if (resourceGroup==null) {
-            resourceGroup = resourceGroupManager.getResourceGroup(caller, groupId);
-            if (resourceGroup==null)
-                throw new StuffNotFoundException("Group with id " + groupId);
-            putToCache(groupId,ResourceGroup.class,resourceGroup);
-        }
+        resourceGroup = resourceGroupManager.getResourceGroup(caller, groupId);
+        if (resourceGroup==null)
+            throw new StuffNotFoundException("Group with id " + groupId);
         return resourceGroup;
     }
 
@@ -267,6 +263,10 @@ public class GroupHandlerBean extends AbstractRestBean implements GroupHandlerLo
         gr.setId(group.getId());
         gr.setCategory(group.getGroupCategory());
         gr.setRecursive(group.isRecursive());
+        if (group.getGroupDefinition()!=null)
+            gr.setDynaGroupDefinitionId(group.getGroupDefinition().getId());
+        gr.setExplicitCount(group.getExplicitResources().size());
+        gr.setImplicitCount(group.getImplicitResources().size());
         UriBuilder uriBuilder = uriInfo.getBaseUriBuilder();
         uriBuilder.path("/group/{id}");
         URI uri = uriBuilder.build(group.getId());
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/GroupRest.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/GroupRest.java
index 4c9079b..c43f911 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/GroupRest.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/GroupRest.java
@@ -21,6 +21,9 @@ public class GroupRest {
     private Integer resourceTypeId;
     private boolean recursive;
     private GroupCategory category;
+    private int dynaGroupDefinitionId;
+    private int explicitCount;
+    private int implicitCount;
 
     List<Link> links = new ArrayList<Link>();
 
@@ -79,4 +82,28 @@ public class GroupRest {
     public void setLinks(List<Link> links) {
         this.links = links;
     }
+
+    public int getDynaGroupDefinitionId() {
+        return dynaGroupDefinitionId;
+    }
+
+    public void setDynaGroupDefinitionId(int dynaGroupDefinitionId) {
+        this.dynaGroupDefinitionId = dynaGroupDefinitionId;
+    }
+
+    public int getExplicitCount() {
+        return explicitCount;
+    }
+
+    public void setExplicitCount(int explicitCount) {
+        this.explicitCount = explicitCount;
+    }
+
+    public int getImplicitCount() {
+        return implicitCount;
+    }
+
+    public void setImplicitCount(int implicitCount) {
+        this.implicitCount = implicitCount;
+    }
 }
diff --git a/modules/enterprise/server/jar/src/main/resources/rest_templates/group.ftl b/modules/enterprise/server/jar/src/main/resources/rest_templates/group.ftl
index 6edaf99..03a69bb 100644
--- a/modules/enterprise/server/jar/src/main/resources/rest_templates/group.ftl
+++ b/modules/enterprise/server/jar/src/main/resources/rest_templates/group.ftl
@@ -44,6 +44,17 @@
         <tr>
             <td>Recursive</td><td>${var.recursive?string("Yes","No")}</td>
         </tr>
+        <tr>
+            <td>DynaGroup</td><td>${(var.dynaGroupDefinitionId > 0)?string("Yes","No")}</td>
+        </tr>
+        <tr>
+            <td>Resource Count</td>
+            <td>${var.explicitCount}
+                <#if var.recursive>
+            ( Implicit: ${var.implicitCount} )
+                </#if>
+            </td>
+        </tr>
     </table>
     <a href="/rest/1/group/${var.id?c}/resources.html">Resources</a><br/>
 </html>


commit 76dee23a84b0a14362f8ed22be6f5e8b6e4ba707
Author: Heiko W. Rupp <hwr at redhat.com>
Date:   Tue Jun 19 21:10:16 2012 +0200

    Use the same job id over the place to prevent IndexOutOfBoundExceptions later.

diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java
index cb233f8..d8b9851 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java
@@ -296,13 +296,14 @@ public class OperationsHandlerBean extends AbstractRestBean implements Operation
         MediaType mediaType = httpHeaders.getAcceptableMediaTypes().get(0);
 
         ResourceOperationHistoryCriteria criteria = new ResourceOperationHistoryCriteria();
-        criteria.addFilterJobId(new JobId(jobName));
+        JobId jobId = new JobId(jobName);
+        criteria.addFilterJobId(jobId);
 
         ResourceOperationHistory history ;//= opsManager.getOperationHistoryByJobId(caller,jobName);
         List<ResourceOperationHistory> list = opsManager.findResourceOperationHistoriesByCriteria(caller,criteria);
         if (list==null || list.isEmpty()) {
-            log.info("No history with id " + new HistoryJobId(jobName) + " found");
-            throw new StuffNotFoundException("OperationHistory with id " + new HistoryJobId(jobName));
+            log.info("No history with id " + jobId + " found");
+            throw new StuffNotFoundException("OperationHistory with id " + jobId);
         }
 
         history = list.get(0);


commit 6528df9ea4eb462faed0504089faa21b55671a79
Author: Heiko W. Rupp <hwr at redhat.com>
Date:   Tue Jun 19 18:07:05 2012 +0200

    Prevent a possible "No session exception"

diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java
index a4bc84e..79012a1 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java
@@ -327,13 +327,13 @@ public class AbstractRestBean {
         return true;
     }
 
-    public ResourceWithType fillRWT(org.rhq.core.domain.resource.Resource res, UriInfo uriInfo) {
+    public ResourceWithType fillRWT(Resource res, UriInfo uriInfo) {
         ResourceType resourceType = res.getResourceType();
         ResourceWithType rwt = new ResourceWithType(res.getName(),res.getId());
         rwt.setTypeName(resourceType.getName());
         rwt.setTypeId(resourceType.getId());
         rwt.setPluginName(resourceType.getPlugin());
-        org.rhq.core.domain.resource.Resource parent = res.getParentResource();
+        Resource parent = res.getParentResource();
         if (parent!=null) {
             rwt.setParentId(parent.getId());
         }
@@ -382,6 +382,10 @@ public class AbstractRestBean {
 
     protected Resource fetchResource(int resourceId) {
         Resource res;
+        res = resMgr.getResource(caller, resourceId);
+        if (res==null)
+            throw new StuffNotFoundException("Resource with id " + resourceId);
+/*
         res = getFromCache(resourceId, Resource.class);
         if (res == null) {
             res = resMgr.getResource(caller, resourceId);
@@ -390,6 +394,7 @@ public class AbstractRestBean {
             else
                 throw new StuffNotFoundException("Resource with id " + resourceId);
         }
+*/
         return res;
     }
 }


commit 09e7b73cf38378ccc825b8c9041ddc8b6a6b5429
Author: Lukas Krejci <lkrejci at redhat.com>
Date:   Wed Jun 20 09:37:39 2012 +0200

    Renaming "RhqManagers" to "RhqManager".

diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/AbstractRhqFacadeProxy.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/AbstractRhqFacadeProxy.java
index 7f3a56f..ef46bb2 100644
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/AbstractRhqFacadeProxy.java
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/AbstractRhqFacadeProxy.java
@@ -34,9 +34,9 @@ import org.rhq.core.domain.auth.Subject;
 public abstract class AbstractRhqFacadeProxy<T extends RhqFacade> implements InvocationHandler {
 
     private T facade;
-    private RhqManagers manager;
+    private RhqManager manager;
     
-    protected AbstractRhqFacadeProxy(T facade, RhqManagers manager) {
+    protected AbstractRhqFacadeProxy(T facade, RhqManager manager) {
         this.facade = facade;
         this.manager = manager;
     }
@@ -45,7 +45,7 @@ public abstract class AbstractRhqFacadeProxy<T extends RhqFacade> implements Inv
         return facade;
     }
     
-    protected RhqManagers getManager() {
+    protected RhqManager getManager() {
         return manager;
     }
     
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/RhqFacade.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/RhqFacade.java
index f2bde27..ca7fa83 100644
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/RhqFacade.java
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/RhqFacade.java
@@ -129,7 +129,7 @@ public interface RhqFacade {
     SynchronizationManagerRemote getSynchronizationManager();
     
     /**
-     * This map is constructed using all the elements in the {@link RhqManagers} enum which are then proxied
+     * This map is constructed using all the elements in the {@link RhqManager} enum which are then proxied
      * using this instance.
      * 
      * @return a map of all available proxied managers keyed by their names.
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/RhqManager.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/RhqManager.java
new file mode 100644
index 0000000..cfa52e2
--- /dev/null
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/RhqManager.java
@@ -0,0 +1,133 @@
+/*
+ * 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 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.bindings.client;
+
+import org.rhq.enterprise.server.alert.AlertDefinitionManagerRemote;
+import org.rhq.enterprise.server.alert.AlertManagerRemote;
+import org.rhq.enterprise.server.auth.SubjectManagerRemote;
+import org.rhq.enterprise.server.authz.RoleManagerRemote;
+import org.rhq.enterprise.server.bundle.BundleManagerRemote;
+import org.rhq.enterprise.server.configuration.ConfigurationManagerRemote;
+import org.rhq.enterprise.server.content.ContentManagerRemote;
+import org.rhq.enterprise.server.content.RepoManagerRemote;
+import org.rhq.enterprise.server.discovery.DiscoveryBossRemote;
+import org.rhq.enterprise.server.drift.DriftManagerRemote;
+import org.rhq.enterprise.server.drift.DriftTemplateManagerRemote;
+import org.rhq.enterprise.server.event.EventManagerRemote;
+import org.rhq.enterprise.server.install.remote.RemoteInstallManagerRemote;
+import org.rhq.enterprise.server.measurement.AvailabilityManagerRemote;
+import org.rhq.enterprise.server.measurement.CallTimeDataManagerRemote;
+import org.rhq.enterprise.server.measurement.MeasurementBaselineManagerRemote;
+import org.rhq.enterprise.server.measurement.MeasurementDataManagerRemote;
+import org.rhq.enterprise.server.measurement.MeasurementDefinitionManagerRemote;
+import org.rhq.enterprise.server.measurement.MeasurementScheduleManagerRemote;
+import org.rhq.enterprise.server.operation.OperationManagerRemote;
+import org.rhq.enterprise.server.report.DataAccessManagerRemote;
+import org.rhq.enterprise.server.resource.ResourceFactoryManagerRemote;
+import org.rhq.enterprise.server.resource.ResourceManagerRemote;
+import org.rhq.enterprise.server.resource.ResourceTypeManagerRemote;
+import org.rhq.enterprise.server.resource.group.ResourceGroupManagerRemote;
+import org.rhq.enterprise.server.search.SavedSearchManagerRemote;
+import org.rhq.enterprise.server.support.SupportManagerRemote;
+import org.rhq.enterprise.server.sync.SynchronizationManagerRemote;
+import org.rhq.enterprise.server.system.SystemManagerRemote;
+import org.rhq.enterprise.server.tagging.TagManagerRemote;
+
+/**
+ * An enumeration of all remote SLSBs of the RHQ server.
+ *
+ * @author Lukas Krejci
+ * @author Greg Hinkle
+ */
+public enum RhqManager {
+    AlertManager(AlertManagerRemote.class, "${AlertManager}"), //
+    AlertDefinitionManager(AlertDefinitionManagerRemote.class, "${AlertDefinitionManager}"), //
+    AvailabilityManager(AvailabilityManagerRemote.class, "${AvailabilityManager}"), //
+    BundleManager(BundleManagerRemote.class, "${BundleManager}"), //
+    CallTimeDataManager(CallTimeDataManagerRemote.class, "${CallTimeDataManager}"), //
+    RepoManager(RepoManagerRemote.class, "${RepoManager}"), //
+    ConfigurationManager(ConfigurationManagerRemote.class, "${ConfigurationManager}"), //
+    ContentManager(ContentManagerRemote.class, "${ContentManager}"), //
+    DataAccessManager(DataAccessManagerRemote.class, "${DataAccessManager}"), //
+    DriftManager(DriftManagerRemote.class, "${DriftManager}"), //
+    DriftTemplateManager(DriftTemplateManagerRemote.class, "${DriftTemplateManager}"), //
+    DiscoveryBoss(DiscoveryBossRemote.class, "${DiscoveryBoss}"), //
+    EventManager(EventManagerRemote.class, "${EventManager}"), //
+    MeasurementBaselineManager(MeasurementBaselineManagerRemote.class, "${MeasurementBaselineManager}"), //
+    MeasurementDataManager(MeasurementDataManagerRemote.class, "${MeasurementDataManager}"), //
+    MeasurementDefinitionManager(MeasurementDefinitionManagerRemote.class, "${MeasurementDefinitionManager}"), //
+    MeasurementScheduleManager(MeasurementScheduleManagerRemote.class, "${MeasurementScheduleManager}"), //
+    OperationManager(OperationManagerRemote.class, "${OperationManager}"), //
+    ResourceManager(ResourceManagerRemote.class, "${ResourceManager}"), //
+    ResourceFactoryManager(ResourceFactoryManagerRemote.class, "${ResourceFactoryManager}"), //
+    ResourceGroupManager(ResourceGroupManagerRemote.class, "${ResourceGroupManager}"), //
+    ResourceTypeManager(ResourceTypeManagerRemote.class, "${ResourceTypeManager}"), //
+    RoleManager(RoleManagerRemote.class, "${RoleManager}"), //
+    SavedSearchManager(SavedSearchManagerRemote.class, "${SavedSearchManager}"), //
+    SubjectManager(SubjectManagerRemote.class, "${SubjectManager}"), //
+    SupportManager(SupportManagerRemote.class, "${SupportManager}"), //
+    SystemManager(SystemManagerRemote.class, "${SystemManager}"), //
+    RemoteInstallManager(RemoteInstallManagerRemote.class, "${RemoteInstallManager}"), //
+    TagManager(TagManagerRemote.class, "${TagManager}"), //
+    SynchronizationManager(SynchronizationManagerRemote.class, "${SynchronizationManager}");
+
+    private Class<?> remote;
+    private String remoteName;
+    private String beanName;
+    private boolean enabled;
+
+    private RhqManager(Class<?> remote, String enable) {
+        this.remote = remote;
+        this.beanName = this.name() + "Bean";
+        this.remoteName = this.name() + "Remote";
+        //defaults and evaluates to TRUE unless the string contains "false". Done to defend against 
+        //possible errors in string replacement during rhq build.
+        this.enabled = true;
+        if ((enable != null) && (enable.trim().length() > 0)) {
+            this.enabled = (enable.trim().equalsIgnoreCase("false")) ? Boolean.FALSE : Boolean.TRUE;
+        }
+    }
+
+    public static RhqManager forInterface(Class<?> iface) {
+        for (RhqManager m : values()) {
+            if (m.remote().equals(iface)) {
+                return m;
+            }
+        }
+
+        return null;
+    }
+
+    public Class<?> remote() {
+        return this.remote;
+    }
+
+    public String beanName() {
+        return this.beanName;
+    }
+
+    public String remoteName() {
+        return this.remoteName;
+    }
+
+    public boolean enabled() {
+        return this.enabled;
+    }
+}
\ No newline at end of file
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/RhqManagers.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/RhqManagers.java
deleted file mode 100644
index dfe600c..0000000
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/client/RhqManagers.java
+++ /dev/null
@@ -1,133 +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 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.bindings.client;
-
-import org.rhq.enterprise.server.alert.AlertDefinitionManagerRemote;
-import org.rhq.enterprise.server.alert.AlertManagerRemote;
-import org.rhq.enterprise.server.auth.SubjectManagerRemote;
-import org.rhq.enterprise.server.authz.RoleManagerRemote;
-import org.rhq.enterprise.server.bundle.BundleManagerRemote;
-import org.rhq.enterprise.server.configuration.ConfigurationManagerRemote;
-import org.rhq.enterprise.server.content.ContentManagerRemote;
-import org.rhq.enterprise.server.content.RepoManagerRemote;
-import org.rhq.enterprise.server.discovery.DiscoveryBossRemote;
-import org.rhq.enterprise.server.drift.DriftManagerRemote;
-import org.rhq.enterprise.server.drift.DriftTemplateManagerRemote;
-import org.rhq.enterprise.server.event.EventManagerRemote;
-import org.rhq.enterprise.server.install.remote.RemoteInstallManagerRemote;
-import org.rhq.enterprise.server.measurement.AvailabilityManagerRemote;
-import org.rhq.enterprise.server.measurement.CallTimeDataManagerRemote;
-import org.rhq.enterprise.server.measurement.MeasurementBaselineManagerRemote;
-import org.rhq.enterprise.server.measurement.MeasurementDataManagerRemote;
-import org.rhq.enterprise.server.measurement.MeasurementDefinitionManagerRemote;
-import org.rhq.enterprise.server.measurement.MeasurementScheduleManagerRemote;
-import org.rhq.enterprise.server.operation.OperationManagerRemote;
-import org.rhq.enterprise.server.report.DataAccessManagerRemote;
-import org.rhq.enterprise.server.resource.ResourceFactoryManagerRemote;
-import org.rhq.enterprise.server.resource.ResourceManagerRemote;
-import org.rhq.enterprise.server.resource.ResourceTypeManagerRemote;
-import org.rhq.enterprise.server.resource.group.ResourceGroupManagerRemote;
-import org.rhq.enterprise.server.search.SavedSearchManagerRemote;
-import org.rhq.enterprise.server.support.SupportManagerRemote;
-import org.rhq.enterprise.server.sync.SynchronizationManagerRemote;
-import org.rhq.enterprise.server.system.SystemManagerRemote;
-import org.rhq.enterprise.server.tagging.TagManagerRemote;
-
-/**
- * An enumeration of all remote SLSBs of the RHQ server.
- *
- * @author Lukas Krejci
- * @author Greg Hinkle
- */
-public enum RhqManagers {
-    AlertManager(AlertManagerRemote.class, "${AlertManager}"), //
-    AlertDefinitionManager(AlertDefinitionManagerRemote.class, "${AlertDefinitionManager}"), //
-    AvailabilityManager(AvailabilityManagerRemote.class, "${AvailabilityManager}"), //
-    BundleManager(BundleManagerRemote.class, "${BundleManager}"), //
-    CallTimeDataManager(CallTimeDataManagerRemote.class, "${CallTimeDataManager}"), //
-    RepoManager(RepoManagerRemote.class, "${RepoManager}"), //
-    ConfigurationManager(ConfigurationManagerRemote.class, "${ConfigurationManager}"), //
-    ContentManager(ContentManagerRemote.class, "${ContentManager}"), //
-    DataAccessManager(DataAccessManagerRemote.class, "${DataAccessManager}"), //
-    DriftManager(DriftManagerRemote.class, "${DriftManager}"), //
-    DriftTemplateManager(DriftTemplateManagerRemote.class, "${DriftTemplateManager}"), //
-    DiscoveryBoss(DiscoveryBossRemote.class, "${DiscoveryBoss}"), //
-    EventManager(EventManagerRemote.class, "${EventManager}"), //
-    MeasurementBaselineManager(MeasurementBaselineManagerRemote.class, "${MeasurementBaselineManager}"), //
-    MeasurementDataManager(MeasurementDataManagerRemote.class, "${MeasurementDataManager}"), //
-    MeasurementDefinitionManager(MeasurementDefinitionManagerRemote.class, "${MeasurementDefinitionManager}"), //
-    MeasurementScheduleManager(MeasurementScheduleManagerRemote.class, "${MeasurementScheduleManager}"), //
-    OperationManager(OperationManagerRemote.class, "${OperationManager}"), //
-    ResourceManager(ResourceManagerRemote.class, "${ResourceManager}"), //
-    ResourceFactoryManager(ResourceFactoryManagerRemote.class, "${ResourceFactoryManager}"), //
-    ResourceGroupManager(ResourceGroupManagerRemote.class, "${ResourceGroupManager}"), //
-    ResourceTypeManager(ResourceTypeManagerRemote.class, "${ResourceTypeManager}"), //
-    RoleManager(RoleManagerRemote.class, "${RoleManager}"), //
-    SavedSearchManager(SavedSearchManagerRemote.class, "${SavedSearchManager}"), //
-    SubjectManager(SubjectManagerRemote.class, "${SubjectManager}"), //
-    SupportManager(SupportManagerRemote.class, "${SupportManager}"), //
-    SystemManager(SystemManagerRemote.class, "${SystemManager}"), //
-    RemoteInstallManager(RemoteInstallManagerRemote.class, "${RemoteInstallManager}"), //
-    TagManager(TagManagerRemote.class, "${TagManager}"), //
-    SynchronizationManager(SynchronizationManagerRemote.class, "${SynchronizationManager}");
-
-    private Class<?> remote;
-    private String remoteName;
-    private String beanName;
-    private boolean enabled;
-
-    private RhqManagers(Class<?> remote, String enable) {
-        this.remote = remote;
-        this.beanName = this.name() + "Bean";
-        this.remoteName = this.name() + "Remote";
-        //defaults and evaluates to TRUE unless the string contains "false". Done to defend against 
-        //possible errors in string replacement during rhq build.
-        this.enabled = true;
-        if ((enable != null) && (enable.trim().length() > 0)) {
-            this.enabled = (enable.trim().equalsIgnoreCase("false")) ? Boolean.FALSE : Boolean.TRUE;
-        }
-    }
-
-    public static RhqManagers forInterface(Class<?> iface) {
-        for (RhqManagers m : values()) {
-            if (m.remote().equals(iface)) {
-                return m;
-            }
-        }
-
-        return null;
-    }
-
-    public Class<?> remote() {
-        return this.remote;
-    }
-
-    public String beanName() {
-        return this.beanName;
-    }
-
-    public String remoteName() {
-        return this.remoteName;
-    }
-
-    public boolean enabled() {
-        return this.enabled;
-    }
-}
\ No newline at end of file
diff --git a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/ScriptCommand.java b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/ScriptCommand.java
index f3084d1..e80c346 100644
--- a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/ScriptCommand.java
+++ b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/ScriptCommand.java
@@ -36,7 +36,7 @@ import org.apache.commons.logging.LogFactory;
 
 import org.rhq.bindings.ScriptEngineFactory;
 import org.rhq.bindings.StandardBindings;
-import org.rhq.bindings.client.RhqManagers;
+import org.rhq.bindings.client.RhqManager;
 import org.rhq.bindings.output.TabularWriter;
 import org.rhq.bindings.util.PackageFinder;
 import org.rhq.enterprise.client.ClientMain;
@@ -295,6 +295,6 @@ public class ScriptCommand implements ClientCommand {
 
     public String getDetailedHelp() {
         return "Execute a statement or a script. The following service managers are available: "
-            + Arrays.toString(RhqManagers.values());
+            + Arrays.toString(RhqManager.values());
     }
 }
diff --git a/modules/enterprise/remoting/cli/src/test/java/org/rhq/enterprise/client/commands/ScriptCommandTest.java b/modules/enterprise/remoting/cli/src/test/java/org/rhq/enterprise/client/commands/ScriptCommandTest.java
index fe109a8..fc59cf3 100644
--- a/modules/enterprise/remoting/cli/src/test/java/org/rhq/enterprise/client/commands/ScriptCommandTest.java
+++ b/modules/enterprise/remoting/cli/src/test/java/org/rhq/enterprise/client/commands/ScriptCommandTest.java
@@ -23,7 +23,7 @@ import org.rhq.enterprise.server.authz.RoleManagerRemote;
 import org.rhq.enterprise.server.resource.ResourceManagerRemote;
 import org.rhq.enterprise.server.resource.group.ResourceGroupManagerRemote;
 import org.rhq.enterprise.server.auth.SubjectManagerRemote;
-import org.rhq.bindings.client.RhqManagers;
+import org.rhq.bindings.client.RhqManager;
 import org.rhq.bindings.output.TabularWriter;
 import org.rhq.bindings.util.ScriptUtil;
 import org.rhq.core.domain.auth.Subject;
@@ -76,7 +76,7 @@ public class ScriptCommandTest {
         ScriptEngine scriptEngine = client.getScriptEngine();
         List<String> mgrsNotBound = new ArrayList<String>();
 
-        for (RhqManagers mgr : RhqManagers.values()) {
+        for (RhqManager mgr : RhqManager.values()) {
             if (!scriptEngine.getBindings(ScriptContext.ENGINE_SCOPE).containsKey(mgr.name())) {
                 mgrsNotBound.add(mgr.remoteName());
             }
diff --git a/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RemoteClient.java b/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RemoteClient.java
index d0fb529..57829b9 100644
--- a/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RemoteClient.java
+++ b/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RemoteClient.java
@@ -32,7 +32,7 @@ import org.jboss.remoting.security.SSLSocketBuilder;
 import org.jboss.remoting.transport.http.ssl.HTTPSClientInvoker;
 
 import org.rhq.bindings.client.RhqFacade;
-import org.rhq.bindings.client.RhqManagers;
+import org.rhq.bindings.client.RhqManager;
 import org.rhq.core.domain.auth.Subject;
 import org.rhq.core.domain.common.ProductInfo;
 import org.rhq.enterprise.communications.util.SecurityUtil;
@@ -261,123 +261,123 @@ public class RemoteClient implements RhqFacade {
     }
 
     public AlertManagerRemote getAlertManager() {
-        return RemoteClientProxy.getProcessor(this, RhqManagers.AlertManager);
+        return RemoteClientProxy.getProcessor(this, RhqManager.AlertManager);
     }
 
     public AlertDefinitionManagerRemote getAlertDefinitionManager() {
-        return RemoteClientProxy.getProcessor(this, RhqManagers.AlertDefinitionManager);
+        return RemoteClientProxy.getProcessor(this, RhqManager.AlertDefinitionManager);
     }
 
     public AvailabilityManagerRemote getAvailabilityManager() {
-        return RemoteClientProxy.getProcessor(this, RhqManagers.AvailabilityManager);
+        return RemoteClientProxy.getProcessor(this, RhqManager.AvailabilityManager);
     }
 
     public BundleManagerRemote getBundleManager() {
-        return RemoteClientProxy.getProcessor(this, RhqManagers.BundleManager);
+        return RemoteClientProxy.getProcessor(this, RhqManager.BundleManager);
     }
 
     public CallTimeDataManagerRemote getCallTimeDataManager() {
-        return RemoteClientProxy.getProcessor(this, RhqManagers.CallTimeDataManager);
+        return RemoteClientProxy.getProcessor(this, RhqManager.CallTimeDataManager);
     }
 
     public DriftManagerRemote getDriftManager() {
-        return RemoteClientProxy.getProcessor(this, RhqManagers.DriftManager);
+        return RemoteClientProxy.getProcessor(this, RhqManager.DriftManager);
     }
 
     public DriftTemplateManagerRemote getDriftTemplateManager() {
-        return RemoteClientProxy.getProcessor(this, RhqManagers.DriftTemplateManager);
+        return RemoteClientProxy.getProcessor(this, RhqManager.DriftTemplateManager);
     }
 
     public RepoManagerRemote getRepoManager() {
-        return RemoteClientProxy.getProcessor(this, RhqManagers.RepoManager);
+        return RemoteClientProxy.getProcessor(this, RhqManager.RepoManager);
     }
 
     public ConfigurationManagerRemote getConfigurationManager() {
-        return RemoteClientProxy.getProcessor(this, RhqManagers.ConfigurationManager);
+        return RemoteClientProxy.getProcessor(this, RhqManager.ConfigurationManager);
     }
 
     public ContentManagerRemote getContentManager() {
-        return RemoteClientProxy.getProcessor(this, RhqManagers.ContentManager);
+        return RemoteClientProxy.getProcessor(this, RhqManager.ContentManager);
     }
 
     public DataAccessManagerRemote getDataAccessManager() {
-        return RemoteClientProxy.getProcessor(this, RhqManagers.DataAccessManager);
+        return RemoteClientProxy.getProcessor(this, RhqManager.DataAccessManager);
     }
 
     public DiscoveryBossRemote getDiscoveryBoss() {
-        return RemoteClientProxy.getProcessor(this, RhqManagers.DiscoveryBoss);
+        return RemoteClientProxy.getProcessor(this, RhqManager.DiscoveryBoss);
     }
 
     public EventManagerRemote getEventManager() {
-        return RemoteClientProxy.getProcessor(this, RhqManagers.EventManager);
+        return RemoteClientProxy.getProcessor(this, RhqManager.EventManager);
     }
 
     public MeasurementBaselineManagerRemote getMeasurementBaselineManager() {
-        return RemoteClientProxy.getProcessor(this, RhqManagers.MeasurementBaselineManager);
+        return RemoteClientProxy.getProcessor(this, RhqManager.MeasurementBaselineManager);
     }
 
     public MeasurementDataManagerRemote getMeasurementDataManager() {
-        return RemoteClientProxy.getProcessor(this, RhqManagers.MeasurementDataManager);
+        return RemoteClientProxy.getProcessor(this, RhqManager.MeasurementDataManager);
     }
 
     public MeasurementDefinitionManagerRemote getMeasurementDefinitionManager() {
-        return RemoteClientProxy.getProcessor(this, RhqManagers.MeasurementDefinitionManager);
+        return RemoteClientProxy.getProcessor(this, RhqManager.MeasurementDefinitionManager);
     }
 
     public MeasurementScheduleManagerRemote getMeasurementScheduleManager() {
-        return RemoteClientProxy.getProcessor(this, RhqManagers.MeasurementScheduleManager);
+        return RemoteClientProxy.getProcessor(this, RhqManager.MeasurementScheduleManager);
     }
 
     public OperationManagerRemote getOperationManager() {
-        return RemoteClientProxy.getProcessor(this, RhqManagers.OperationManager);
+        return RemoteClientProxy.getProcessor(this, RhqManager.OperationManager);
     }
 
     public ResourceManagerRemote getResourceManager() {
-        return RemoteClientProxy.getProcessor(this, RhqManagers.ResourceManager);
+        return RemoteClientProxy.getProcessor(this, RhqManager.ResourceManager);
     }
 
     public ResourceFactoryManagerRemote getResourceFactoryManager() {
-        return RemoteClientProxy.getProcessor(this, RhqManagers.ResourceFactoryManager);
+        return RemoteClientProxy.getProcessor(this, RhqManager.ResourceFactoryManager);
     }
 
     public ResourceGroupManagerRemote getResourceGroupManager() {
-        return RemoteClientProxy.getProcessor(this, RhqManagers.ResourceGroupManager);
+        return RemoteClientProxy.getProcessor(this, RhqManager.ResourceGroupManager);
     }
 
     public ResourceTypeManagerRemote getResourceTypeManager() {
-        return RemoteClientProxy.getProcessor(this, RhqManagers.ResourceTypeManager);
+        return RemoteClientProxy.getProcessor(this, RhqManager.ResourceTypeManager);
     }
 
     public RoleManagerRemote getRoleManager() {
-        return RemoteClientProxy.getProcessor(this, RhqManagers.RoleManager);
+        return RemoteClientProxy.getProcessor(this, RhqManager.RoleManager);
     }
 
     public SavedSearchManagerRemote getSavedSearchManager() {
-        return RemoteClientProxy.getProcessor(this, RhqManagers.SavedSearchManager);
+        return RemoteClientProxy.getProcessor(this, RhqManager.SavedSearchManager);
     }
 
     public SubjectManagerRemote getSubjectManager() {
-        return RemoteClientProxy.getProcessor(this, RhqManagers.SubjectManager);
+        return RemoteClientProxy.getProcessor(this, RhqManager.SubjectManager);
     }
 
     public SupportManagerRemote getSupportManager() {
-        return RemoteClientProxy.getProcessor(this, RhqManagers.SupportManager);
+        return RemoteClientProxy.getProcessor(this, RhqManager.SupportManager);
     }
 
     public SystemManagerRemote getSystemManager() {
-        return RemoteClientProxy.getProcessor(this, RhqManagers.SystemManager);
+        return RemoteClientProxy.getProcessor(this, RhqManager.SystemManager);
     }
 
     public RemoteInstallManagerRemote getRemoteInstallManager() {
-        return RemoteClientProxy.getProcessor(this, RhqManagers.RemoteInstallManager);
+        return RemoteClientProxy.getProcessor(this, RhqManager.RemoteInstallManager);
     }
 
     public TagManagerRemote getTagManager() {
-        return RemoteClientProxy.getProcessor(this, RhqManagers.TagManager);
+        return RemoteClientProxy.getProcessor(this, RhqManager.TagManager);
     }
 
     public SynchronizationManagerRemote getSynchronizationManager() {
-        return RemoteClientProxy.getProcessor(this, RhqManagers.SynchronizationManager);
+        return RemoteClientProxy.getProcessor(this, RhqManager.SynchronizationManager);
     }
 
     /**
@@ -391,7 +391,7 @@ public class RemoteClient implements RhqFacade {
 
             this.managers = new HashMap<String, Object>();
 
-            for (RhqManagers manager : RhqManagers.values()) {
+            for (RhqManager manager : RhqManager.values()) {
                 try {
                     Method m = this.getClass().getMethod("get" + manager.name());
                     if (manager.enabled()) {
diff --git a/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RemoteClientProxy.java b/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RemoteClientProxy.java
index e9751c2..23dea3c 100644
--- a/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RemoteClientProxy.java
+++ b/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RemoteClientProxy.java
@@ -27,7 +27,7 @@ import org.apache.commons.logging.LogFactory;
 import org.jboss.remoting.invocation.NameBasedInvocation;
 
 import org.rhq.bindings.client.AbstractRhqFacadeProxy;
-import org.rhq.bindings.client.RhqManagers;
+import org.rhq.bindings.client.RhqManager;
 import org.rhq.bindings.util.InterfaceSimplifier;
 import org.rhq.core.domain.server.ExternalizableStrategy;
 
@@ -42,7 +42,7 @@ public class RemoteClientProxy extends AbstractRhqFacadeProxy<RemoteClient> {
 
     private static final Log LOG = LogFactory.getLog(RemoteClientProxy.class);
 
-    public RemoteClientProxy(RemoteClient client, RhqManagers manager) {
+    public RemoteClientProxy(RemoteClient client, RhqManager manager) {
         super(client, manager);
     }
 
@@ -51,7 +51,7 @@ public class RemoteClientProxy extends AbstractRhqFacadeProxy<RemoteClient> {
     }
 
     @SuppressWarnings("unchecked")
-    public static <T> T getProcessor(RemoteClient remoteClient, RhqManagers manager) {
+    public static <T> T getProcessor(RemoteClient remoteClient, RhqManager manager) {
         try {
             RemoteClientProxy gpc = new RemoteClientProxy(remoteClient, manager);
 
diff --git a/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClient.java b/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClient.java
index 2e48048..dbb4424 100644
--- a/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClient.java
+++ b/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClient.java
@@ -31,7 +31,7 @@ import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
 import org.rhq.bindings.client.RhqFacade;
-import org.rhq.bindings.client.RhqManagers;
+import org.rhq.bindings.client.RhqManager;
 import org.rhq.bindings.util.InterfaceSimplifier;
 import org.rhq.core.domain.auth.Subject;
 import org.rhq.enterprise.server.alert.AlertDefinitionManagerRemote;
@@ -416,7 +416,7 @@ public class LocalClient implements RhqFacade {
 
             managers = new HashMap<String, Object>();
 
-            for (RhqManagers manager : RhqManagers.values()) {
+            for (RhqManager manager : RhqManager.values()) {
                 try {
                     Method m = getClass().getMethod("get" + manager.name());
                     managers.put(manager.name(), m.invoke(this));
@@ -430,7 +430,7 @@ public class LocalClient implements RhqFacade {
     }
 
     private <T> T getProxy(Object slsb, Class<T> iface) {
-        RhqManagers manager = RhqManagers.forInterface(iface);
+        RhqManager manager = RhqManager.forInterface(iface);
 
         Class<?> simplified = null;
 
diff --git a/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClientProxy.java b/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClientProxy.java
index e9f1e4d..67bd5e7 100644
--- a/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClientProxy.java
+++ b/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/LocalClientProxy.java
@@ -28,7 +28,7 @@ import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
 import org.rhq.bindings.client.AbstractRhqFacadeProxy;
-import org.rhq.bindings.client.RhqManagers;
+import org.rhq.bindings.client.RhqManager;
 
 /**
  * This is a proxy interface that simply calls given (de-simplified) method on a provided object.
@@ -42,7 +42,7 @@ public class LocalClientProxy extends AbstractRhqFacadeProxy<LocalClient> {
     
     private Object localSLSB;
     
-    public LocalClientProxy(Object localSLSB, LocalClient client, RhqManagers manager) {
+    public LocalClientProxy(Object localSLSB, LocalClient client, RhqManager manager) {
         super(client, manager);
         this.localSLSB = localSLSB;
     }


commit 573dd3715035d095bd65f823dc9539e72a27fbe9
Author: Lukas Krejci <lkrejci at redhat.com>
Date:   Wed Jun 20 09:22:03 2012 +0200

    Making it all compile again and provide basic abstractions to cut the code completion out of the CLI.

diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/StandardBindings.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/StandardBindings.java
index da544c4..05e6a09 100644
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/StandardBindings.java
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/StandardBindings.java
@@ -133,13 +133,11 @@ public class StandardBindings extends HashMap<String, Object> {
         putAll(managers);
     }
 
-    @Override
     public void preInject(ScriptEngine scriptEngine) {
         ((ScriptUtil) get(SCRIPT_UTIL)).init(scriptEngine);
         ((ScriptAssert) get(ASSERT)).init(scriptEngine);
     }
 
-    @Override
     public void postInject(ScriptEngine scriptEngine) {
         ScriptEngineFactory.bindIndirectionMethods(scriptEngine, SCRIPT_UTIL);
         ScriptEngineFactory.bindIndirectionMethods(scriptEngine, ASSERT);
diff --git a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java
index 7ebe141..4a1ed62 100644
--- a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java
+++ b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java
@@ -22,6 +22,9 @@
  */
 package org.rhq.enterprise.client;
 
+import gnu.getopt.Getopt;
+import gnu.getopt.LongOpt;
+
 import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.IOException;
@@ -34,6 +37,9 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import javax.script.ScriptEngine;
+import javax.script.ScriptException;
+
 import gnu.getopt.Getopt;
 import gnu.getopt.LongOpt;
 
@@ -44,6 +50,8 @@ import jline.MultiCompletor;
 import jline.SimpleCompletor;
 import mazz.i18n.Msg;
 
+import org.rhq.bindings.ScriptEngineFactory;
+import org.rhq.bindings.util.PackageFinder;
 import org.rhq.core.domain.auth.Subject;
 import org.rhq.enterprise.client.commands.ClientCommand;
 import org.rhq.enterprise.client.commands.ScriptCommand;
diff --git a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/InteractiveJavascriptCompletor.java b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/InteractiveJavascriptCompletor.java
index f51e148..0f1b232 100644
--- a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/InteractiveJavascriptCompletor.java
+++ b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/InteractiveJavascriptCompletor.java
@@ -91,6 +91,7 @@ public class InteractiveJavascriptCompletor implements Completor {
         this.services = services;
     }
 
+    @Override
     @SuppressWarnings("unchecked")
     public int complete(String s, int i, @SuppressWarnings("rawtypes") List list) {
         try {
@@ -168,7 +169,7 @@ public class InteractiveJavascriptCompletor implements Completor {
      * @param list
      * @return location of relative completion
      */
-    public int contextComplete(Object baseObject, String s, int i, List<String> list) {
+    private int contextComplete(Object baseObject, String s, int i, List<String> list) {
         String temp = s.split("\\(", 2)[0];
         if (temp.contains(".")) {
             String[] call = temp.split("\\.", 2);
diff --git a/modules/enterprise/remoting/cli/src/main/scripts/rhq-client.build.xml b/modules/enterprise/remoting/cli/src/main/scripts/rhq-client.build.xml
index ecf304e..202bef7 100644
--- a/modules/enterprise/remoting/cli/src/main/scripts/rhq-client.build.xml
+++ b/modules/enterprise/remoting/cli/src/main/scripts/rhq-client.build.xml
@@ -67,6 +67,10 @@
       <copy file="${settings.localRepository}/net/sf/opencsv/opencsv/${opencsv.version}/opencsv-${opencsv.version}.jar" tofile="${lib.home}/opencsv-${opencsv.version}.jar" verbose="true" />
    	  <copy file="${settings.localRepository}/org/rhq/rhq-script-bindings/${project.version}/rhq-script-bindings-${project.version}.jar" tofile="${lib.home}/rhq-script-bindings-${project.version}.jar" verbose="true" />
    	  <copy file="${settings.localRepository}/hibernate-annotations/hibernate-annotations/${hibernate-annotations.version}/hibernate-annotations-${hibernate-annotations.version}.jar" todir="${lib.home}" verbose="true" />
+
+      <copy file="${settings.localRepository}/org/rhq/rhq-scripting-api/${project.version}/rhq-scripting-api-${project.version}.jar" tofile="${lib.home}/rhq-scripting-api-${project.version}.jar" verbose="true" />
+      <copy file="${settings.localRepository}/org/rhq/rhq-scripting-javascript/${project.version}/rhq-scripting-javascript-${project.version}.jar" tofile="${lib.home}/rhq-scripting-javascript-${project.version}.jar" verbose="true" />
+   	  <copy file="${settings.localRepository}/org/mozilla/rhino/${rhino.version}/rhino-${rhino.version}.jar" tofile="${lib.home}/rhino-${rhino.version}.jar" verbose="true" />
    </target>
 
    <target name="prepare-samples-dir">
diff --git a/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/CodeCompletion.java b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/CodeCompletion.java
index f8beb28..2c89718 100644
--- a/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/CodeCompletion.java
+++ b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/CodeCompletion.java
@@ -19,8 +19,11 @@
 
 package org.rhq.scripting;
 
+import java.io.PrintWriter;
 import java.util.List;
 
+import javax.script.ScriptContext;
+
 /**
  * An interface for performing code completion in a given language.
  * This inspired by the jline's <code>Completor</code> interface but
@@ -32,8 +35,29 @@ import java.util.List;
 public interface CodeCompletion {
 
     /**
+     * The code completor can use the provided script context to find out about possible
+     * completions.
+     * <p>
+     * This method is called once before the first {@link #complete(PrintWriter, String, int, List)} method
+     * is called.
+     * 
+     * @param scriptContext
+     */
+    void setScriptContext(ScriptContext scriptContext);
+    
+    /**
+     * Provides the code completion implementation with the metadata provider it can use to
+     * format more meaningful completion hints.
+     * 
+     * @param metadataProvider
+     */
+    void setMetadataProvider(MetadataProvider metadataProvider);
+
+    /**
      * Generates the completion candidates and fills the supplied list with them.
      * 
+     * @param output the output the completor can use to write some additional information to convey some
+     * additional info to the user
      * @param context the context of the code completion, usually that is the current
      * statement being edited by the user
      * @param cursorPosition the position of the cursor inside the context
@@ -42,5 +66,5 @@ public interface CodeCompletion {
      * @return the character index in the context for which the completion candidates were
      * actually generated (might be different from the cursorPosition).
      */
-    int complete(String context, int cursorPosition, @SuppressWarnings("rawtypes") List candidates);
+    int complete(PrintWriter output, String context, int cursorPosition, @SuppressWarnings("rawtypes") List candidates);
 }
diff --git a/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/MetadataProvider.java b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/MetadataProvider.java
new file mode 100644
index 0000000..598d952
--- /dev/null
+++ b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/MetadataProvider.java
@@ -0,0 +1,69 @@
+/*
+ * RHQ Management Platform
+ * Copyright 2012, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.scripting;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+
+/**
+ * The scripting implementations don't have to supply an implementation of this interface but
+ * rather one is provided to the {@link CodeCompletion}.
+ * <p>
+ * The code completion can ask this implementation for various metadata on methods or classes.
+ * <p>
+ * The {@link CodeCompletion} implementations can use this information to format more meaningful
+ * completion hints.
+ * 
+ * @author Lukas Krejci
+ */
+public interface MetadataProvider {
+
+    /**
+     * Tries to determine the name of a parameter on a method.
+     * 
+     * @param method the method
+     * @param parameterIndex the index of the method parameter
+     * @return The name of the parameter or null if it could not be determined
+     */
+    String getParameterName(Method method, int parameterIndex);
+
+    /**
+     * @param clazz
+     * @return the (java)doc on a class or null if none could be determined 
+     */
+    String getDocumentation(Class<?> clazz);
+
+    /**
+     * @param method
+     * @return the (java)doc on a method or null if none could be determined
+     */
+    String getDocumentation(Method method);
+
+    /**
+     * This is a utility method for determining the type name including the type parameters.
+     * 
+     * @param type the type to determine the name for
+     * @param fullNames if true, all the types and type parameters will be the full class names, otherwise
+     *                  only the simple name of the class / type parameter will be used.
+     * @return the name of the type including type parameters
+     */
+    String getTypeName(Type type, boolean fullNames);
+}
diff --git a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JavascriptCompletor.java b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JavascriptCompletor.java
new file mode 100644
index 0000000..d1df7f5
--- /dev/null
+++ b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JavascriptCompletor.java
@@ -0,0 +1,578 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 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.scripting.javascript;
+
+import java.beans.BeanInfo;
+import java.beans.Introspector;
+import java.beans.MethodDescriptor;
+import java.beans.PropertyDescriptor;
+import java.io.PrintWriter;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.script.Bindings;
+import javax.script.ScriptContext;
+
+import org.rhq.scripting.CodeCompletion;
+import org.rhq.scripting.MetadataProvider;
+
+/**
+ * A Contextual JavaScript interactive completor. Not perfect, but
+ * handles a fair number of cases.
+ *
+ * @author Greg Hinkle
+ * @author Lukas Krejci
+ */
+public class JavascriptCompletor implements CodeCompletion {
+
+    private static final String SUBJECT_CLASS_NAME = "org.rhq.core.domain.auth.Subject";
+    private ScriptContext context;
+    private MetadataProvider metadataProvider;
+
+    private String lastComplete;
+
+    // Consecutive times this exact complete has been requested
+    private int recomplete;
+
+    private static final Set<String> IGNORED_METHODS;
+    static {
+        IGNORED_METHODS = new HashSet<String>();
+        IGNORED_METHODS.add("newProxyInstance");
+        IGNORED_METHODS.add("hashCode");
+        IGNORED_METHODS.add("equals");
+        IGNORED_METHODS.add("getInvocationHandler");
+        IGNORED_METHODS.add("setHandler");
+        IGNORED_METHODS.add("isProxyClass");
+        IGNORED_METHODS.add("newProxyInstance");
+        IGNORED_METHODS.add("getProxyClass");
+        IGNORED_METHODS.add("main");
+        IGNORED_METHODS.add("handler");
+        IGNORED_METHODS.add("init");
+        IGNORED_METHODS.add("initChildren");
+        IGNORED_METHODS.add("initMeasurements");
+        IGNORED_METHODS.add("initOperations");
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public int complete(PrintWriter output, String s, int i, @SuppressWarnings("rawtypes") List list) {
+        try {
+            if (lastComplete != null && lastComplete.equals(s)) {
+                recomplete++;
+            } else {
+                recomplete = 1;
+            }
+
+            lastComplete = s;
+
+            String base = s;
+
+            int rootLength = 0;
+
+            if (s.indexOf('=') > 0) {
+                base = s.substring(s.indexOf("=") + 1).trim();
+                rootLength = s.length() - base.length();
+            }
+
+            String[] call = base.split("\\.");
+            if (base.endsWith(".")) {
+                String[] argPadded = new String[call.length + 1];
+                System.arraycopy(call, 0, argPadded, 0, call.length);
+                argPadded[call.length] = "";
+                call = argPadded;
+            }
+
+            if (call.length == 1) {
+                Map<String, Object> matches = getContextMatches(call[0]);
+                if (matches.size() == 1 && matches.containsKey(call[0]) && !s.endsWith(".")) {
+                    list.add(".");
+                    return rootLength + call[0].length() + 1;
+
+                } else {
+                    list.addAll(matches.keySet());
+                }
+            } else {
+                Object rootObject = context.getAttribute(call[0]);
+                if (rootObject != null) {
+                    String theRest = base.substring(call[0].length() + 1, base.length());
+                    int matchIndex = contextComplete(output, rootObject, theRest, i, list);
+                    Collections.sort(list);
+                    return rootLength + call[0].length() + 1 + matchIndex;
+                }
+            }
+
+            Collections.sort(list);
+
+            return (list.size() == 0) ? (-1) : rootLength;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return -1;
+        }
+    }
+
+    @Override
+    public void setMetadataProvider(MetadataProvider metadataProvider) {
+        this.metadataProvider = metadataProvider;
+    }
+
+    /**
+     * Base Object can be an object where we're looking for methods on it, or an
+     * interface. This recursively works off the completions left to right.
+     *
+     * Objects can be completed with fields or method calls.
+     * method parameters are completed with type matching
+     * method result chainings are completed based on declared return types
+     *
+     * e.g. have a Resource in context as myResource. Original string is
+     * "myResource.name". This method would be called with a baseObject ==
+     * to myResource and the string "name".
+     *
+     * Note: this method will not and should not execute methods, but will
+     * read field properties to continue chained completions.
+     *
+     * @param output the output that can the completor use to convey info to the user
+     * @param baseObject the context object or class to complete from
+     * @param s the relative command string to check
+     * @param i
+     * @param list
+     * @return location of relative completion
+     */
+    private int contextComplete(PrintWriter output, Object baseObject, String s, int i, List<String> list) {
+        String temp = s.split("\\(", 2)[0];
+        if (temp.contains(".")) {
+            String[] call = temp.split("\\.", 2);
+
+            String next = call[0];
+            if (next.contains("(")) {
+                next = next.substring(0, next.indexOf("("));
+            }
+
+            Map<String, List<Object>> matches = getContextMatches(output, baseObject, next);
+            if (!matches.isEmpty()) {
+                Object rootObject = matches.get(next).get(0);
+                if (rootObject instanceof PropertyDescriptor && !(baseObject instanceof Class)) {
+                    try {
+                        rootObject = invoke(baseObject, ((PropertyDescriptor) rootObject).getReadMethod());
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                    }
+                } else if (rootObject instanceof Method) {
+                    rootObject = ((Method) rootObject).getReturnType();
+                }
+
+                return call[0].length() + 1 + contextComplete(output, rootObject, call[1], i, list);
+            } else {
+                return -1;
+            }
+        } else {
+            String[] call = s.split("\\(", 2);
+
+            Map<String, List<Object>> matches = getContextMatches(output, baseObject, call[0]);
+
+            if (call.length == 2 && matches.containsKey(call[0])) {
+
+                int x = 0;
+                for (String key : matches.keySet()) {
+
+                    List<Object> matchList = matches.get(key);
+
+                    if (recomplete == 2) {
+                        List<Method> methods = new ArrayList<Method>();
+                        for (Object match : matchList) {
+                            if (match instanceof Method) {
+                                methods.add((Method) match);
+                            }
+                        }
+                        displaySignatures(output, baseObject, methods.toArray(new Method[methods.size()]));
+                        return -1;
+                    }
+
+                    for (Object match : matchList) {
+
+                        if (key.equals(call[0]) && match instanceof Method) {
+
+                            int result = completeParameters(baseObject, call[1], i, list, (Method) match); // x should be the same for all calls
+                            if (result > 0) {
+                                x = result;
+                            }
+                        }
+                    }
+                }
+                return call[0].length() + 1 + x;
+            }
+
+            if (matches.size() == 1 && matches.containsKey(call[0])) {
+                if (matches.get(call[0]).get(0) instanceof Method) {
+                    list.add("(" + (((Method) matches.get(call[0]).get(0)).getParameterTypes().length == 0 ? ")" : ""));
+                }
+                return call[0].length() + 1;
+            }
+
+            if (recomplete == 2) {
+                List<Method> methods = new ArrayList<Method>();
+                for (List<Object> matchList : matches.values()) {
+                    for (Object val : matchList) {
+                        if (val instanceof Method) {
+                            methods.add((Method) val);
+                        }
+                    }
+                }
+                displaySignatures(output, baseObject, methods.toArray(new Method[methods.size()]));
+            } else {
+                if (matches.size() == 1 && matches.values().iterator().next().get(0) instanceof Method) {
+                    list.add(matches.keySet().iterator().next()
+                        + "("
+                        + ((((Method) matches.values().iterator().next().get(0)).getParameterTypes().length == 0 ? ")"
+                            : "")));
+                } else {
+                    list.addAll(matches.keySet());
+                }
+            }
+            return 0;
+
+        }
+    }
+
+    private void displaySignatures(PrintWriter output, Object object, Method... methods) {
+        try {
+            String[][] signatures = new String[methods.length][];
+            int i = 0;
+            for (Method m : methods) {
+                signatures[i++] = getSignature(object, m).split(" ", 2);
+            }
+
+            int maxReturnLength = 0;
+            for (String[] sig : signatures) {
+                if (sig[0].length() > maxReturnLength)
+                    maxReturnLength = sig[0].length();
+            }
+
+            for (String[] sig : signatures) {
+                for (i = 0; i < (maxReturnLength - sig[0].length()); i++) {
+                    output.print(" ");
+                }
+
+                output.print(sig[0]);
+                output.print(" ");
+                output.print(sig[1]);
+                output.println();
+            }
+        } catch (Exception e) {
+            e.printStackTrace(output);
+        }
+    }
+
+    /**
+     * Split apart the parameters to a method call and complete the last parameter. If the last
+     * paramater has a valid value close that field with a "," for the next param or a ")" if is
+     * the last parameter. Does all machting according to the type of the parameters of the
+     * supplied method.
+     *
+     * @param baseObject
+     * @param params
+     * @param i
+     * @param list
+     * @param method
+     * @return
+     */
+    public int completeParameters(Object baseObject, String params, int i, List<String> list, Method method) {
+
+        String[] paramList = params.split(",");
+
+        Class<?>[] c = method.getParameterTypes();
+
+        String lastParam = paramList[paramList.length - 1];
+        int paramIndex = paramList.length - 1;
+        if (params.trim().endsWith(",")) {
+            lastParam = "";
+            paramIndex++;
+        }
+
+        int baseLength = 0;
+
+        for (int x = 0; x < paramIndex; x++) {
+            Object paramFound = context.getAttribute(paramList[x]);
+
+            if (paramFound != null && !c[x].isAssignableFrom(paramFound.getClass())) {
+                return -1;
+            }
+            baseLength += paramList[x].length() + 1;
+        }
+
+        if (paramIndex >= c.length) {
+            if (params.endsWith(")")) {
+                return -1;
+            } else {
+                list.add(params + ")");
+                return (params + ")").length();
+            }
+        } else {
+
+            if (baseObject instanceof Map && method.getName().equals("get") && method.getParameterTypes().length == 1) {
+                //unused Class<?> keyType = method.getParameterTypes()[0];
+                for (Object key : ((Map<?, ?>) baseObject).keySet()) {
+                    String lookupChoice = "\'" + String.valueOf(key) + "\'";
+                    if (lookupChoice.startsWith(lastParam)) {
+                        list.add(lookupChoice);
+                    }
+                }
+                if (list.size() == 1) {
+                    list.set(0, list.get(0) + ")");
+                }
+
+            } else {
+                Class<?> parameterType = c[paramIndex];
+
+                Map<String, Object> matches = getContextMatches(lastParam, parameterType);
+
+                if (matches.size() == 1 && matches.containsKey(lastParam)) {
+
+                    list.add(paramIndex == c.length - 1 ? ")" : ",");
+                    return baseLength + lastParam.length();
+                } else {
+                    list.addAll(matches.keySet());
+                }
+            }
+
+            return baseLength;
+        }
+    }
+
+    private Map<String, Object> getContextMatches(String start) {
+        Map<String, Object> found = new HashMap<String, Object>();
+        if (context != null) {
+            for (Integer scope : context.getScopes()) {
+                Bindings bindings = context.getBindings(scope);
+                for (String var : bindings.keySet()) {
+                    if (var.startsWith(start)) {
+                        found.put(var, bindings.get(var));
+                    }
+                }
+            }
+        }
+        
+        //this was originally part of the code completor that lived in the CLI
+        //I don't think we need it, because the services are present under the
+        //same names in the context. This code can never add any new matches.
+        /*
+        if (services != null) {
+            for (String var : services.keySet()) {
+                if (var.startsWith(start)) {
+                    found.put(var, services.get(var));
+                }
+            }
+        }
+        */
+        
+        return found;
+    }
+
+    /**
+     * Look through all available contexts to find bindings that both start with
+     * the supplied start and match the typeFilter.
+     * @param start
+     * @param typeFilter
+     * @return
+     */
+    private Map<String, Object> getContextMatches(String start, Class<?> typeFilter) {
+        Map<String, Object> found = new HashMap<String, Object>();
+        if (context != null) {
+            for (int scope : context.getScopes()) {
+                Bindings bindings = context.getBindings(scope);
+                for (String var : bindings.keySet()) {
+                    if (var.startsWith(start)) {
+
+                        if ((bindings.get(var) != null && typeFilter.isAssignableFrom(bindings.get(var).getClass()))
+                            || recomplete == 3) {
+                            found.put(var, bindings.get(var));
+                        }
+                    }
+                }
+            }
+
+            if (typeFilter.isEnum()) {
+                for (Object ec : typeFilter.getEnumConstants()) {
+                    Enum<?> e = (Enum<?>) ec;
+                    String code = typeFilter.getSimpleName() + "." + e.name();
+                    if (code.startsWith(start)) {
+                        found.put(typeFilter.getSimpleName() + "." + e.name(), e);
+                    }
+                }
+            }
+        }
+        return found;
+    }
+
+    private Map<String, List<Object>> getContextMatches(PrintWriter output, Object baseObject, String start) {
+        Map<String, List<Object>> found = new HashMap<String, List<Object>>();
+
+        Class<?> baseObjectClass = null;
+        if (baseObject instanceof Class) {
+            baseObjectClass = (Class<?>) baseObject;
+        } else {
+            baseObjectClass = baseObject.getClass();
+        }
+
+        try {
+            if (baseObjectClass.equals(Void.TYPE))
+                return found;
+
+            BeanInfo info = null;
+            if (baseObjectClass.isInterface() || baseObjectClass.equals(Object.class)) {
+                info = Introspector.getBeanInfo(baseObjectClass);
+            } else {
+                info = Introspector.getBeanInfo(baseObjectClass, Object.class);
+            }
+
+            Set<Method> methodsCovered = new HashSet<Method>();
+
+            PropertyDescriptor[] descriptors = info.getPropertyDescriptors();
+            for (PropertyDescriptor desc : descriptors) {
+                if (desc.getName().startsWith(start) && (!IGNORED_METHODS.contains(desc.getName()))) {
+
+                    List<Object> list = found.get(desc.getName());
+                    if (list == null) {
+                        list = new ArrayList<Object>();
+                        found.put(desc.getName(), list);
+                    }
+                    list.add(desc);
+
+                    methodsCovered.add(desc.getReadMethod());
+                    methodsCovered.add(desc.getWriteMethod());
+                }
+            }
+
+            MethodDescriptor[] methods = info.getMethodDescriptors();
+            for (MethodDescriptor desc : methods) {
+                if (desc.getName().startsWith(start) && !methodsCovered.contains(desc.getMethod())
+                    && !desc.getName().startsWith("_d") && !IGNORED_METHODS.contains(desc.getName())) {
+
+                    Method m = desc.getMethod();
+                    //TODO THIS IS SO WRONG - the methods are there but we just "forget" to
+                    //to mention them to the user.
+                    boolean isProxy = isProxyMethod(baseObject, m);
+                    Class<?>[] parameters = m.getParameterTypes();
+                    boolean startsWithSubject = ((parameters.length > 0) && isSubjectClass(parameters[0]));
+                    if ((isProxy && startsWithSubject) || !startsWithSubject) {
+
+                        List<Object> list = found.get(desc.getName());
+                        if (list == null) {
+                            list = new ArrayList<Object>();
+                            found.put(desc.getName(), list);
+                        }
+                        list.add(m);
+                    }
+                }
+            }
+
+        } catch (Exception e) {
+            e.printStackTrace(output);
+        }
+        return found;
+    }
+
+    private String getSignature(Object object, Method m) {
+
+        StringBuilder buf = new StringBuilder();
+        Type[] params = m.getGenericParameterTypes();
+        int i = 0;
+
+        buf.append(metadataProvider.getTypeName(m.getGenericReturnType(), false));
+        buf.append(" ");
+
+        buf.append(m.getName());
+        buf.append("(");
+        boolean first = true;
+        for (Type type : params) {
+            if (!first) {
+                buf.append(", ");
+            } else {
+                first = false;
+            }
+
+            String name = metadataProvider.getTypeName(type, false);
+            String paramName = metadataProvider.getParameterName(m, i);
+            if (paramName != null) {
+                name += " " + paramName;
+            }
+
+            buf.append(name);
+
+            i++;
+        }
+        buf.append(")");
+        return buf.toString();
+    }
+
+    private static boolean isProxyMethod(Object object, Method m) {
+        // TODO this has to be changed - we have the MetaDataProvider which should be able
+        // to provide enough info so that the completors don't have to go through these hoops.
+        return false;
+
+        //        boolean result = false;
+        //        if (object instanceof Proxy) {
+        //            if (Proxy.getInvocationHandler(object) instanceof RemoteClientProxy) {
+        //                try {
+        //                    m =
+        //                        ((RemoteClientProxy) Proxy.getInvocationHandler(object)).getRemoteInterface()
+        //                            .getDeclaredMethod(m.getName(), m.getParameterTypes());
+        //                } catch (NoSuchMethodException e) {
+        //                    result = true;
+        //                }
+        //            }
+        //        }
+        //        return result;
+    }
+
+    @Override
+    public void setScriptContext(ScriptContext context) {
+        this.context = context;
+    }
+
+    private static Object invoke(Object o, Method m) throws IllegalAccessException, InvocationTargetException {
+        boolean access = m.isAccessible();
+        m.setAccessible(true);
+        try {
+            return m.invoke(o);
+        } finally {
+            m.setAccessible(access);
+        }
+    }
+
+    private boolean isSubjectClass(Class<?> cls) {
+        while (cls != null) {
+            if (SUBJECT_CLASS_NAME.equals(cls.getName())) {
+                return true;
+            }
+
+            cls = cls.getSuperclass();
+        }
+        
+        return false;
+    }
+}
diff --git a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineProvider.java b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineProvider.java
index 984e5fc..02d54eb 100644
--- a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineProvider.java
+++ b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineProvider.java
@@ -42,8 +42,7 @@ public class JsEngineProvider implements ScriptEngineProvider {
 
     @Override
     public CodeCompletion getCodeCompletion() {
-        // TODO copy this over from the CLI
-        return null;
+        return new JavascriptCompletor();
     }
 
 }


commit 3b1e22ae89819d89a64c7d319099f53df85bfca3
Author: Ian Springer <ian.springer at redhat.com>
Date:   Tue Jun 19 15:20:09 2012 -0400

    add support for EAP 6.0.0 (GA) and remove support for all the EAP 6.0 ER's

diff --git a/modules/plugins/jboss-as-7/pom.xml b/modules/plugins/jboss-as-7/pom.xml
index e9f877a..16eb982 100644
--- a/modules/plugins/jboss-as-7/pom.xml
+++ b/modules/plugins/jboss-as-7/pom.xml
@@ -240,92 +240,12 @@
     </profile>
 
     <profile>
-      <id>eap600Beta1.itest.setup</id>
+      <id>eap600.itest.setup</id>
 
       <activation>
         <property>
           <name>as7.version</name>
-          <value>6.0.0.Beta1</value>
-        </property>
-      </activation>
-
-      <properties>
-        <as7.url>Please set the as7.url system property to the location of the EAP ${as7.version} distribution zipfile.</as7.url>
-        <jboss-as-arquillian-container-managed.version>7.1.1.Final</jboss-as-arquillian-container-managed.version>
-      </properties>
-    </profile>
-
-    <profile>
-      <id>eap600ER4.itest.setup</id>
-
-      <activation>
-        <property>
-          <name>as7.version</name>
-          <value>6.0.0.ER4</value>
-        </property>
-      </activation>
-
-      <properties>
-        <as7.url>Please set the as7.url system property to the location of the EAP ${as7.version} distribution zipfile.</as7.url>
-        <jboss-as-arquillian-container-managed.version>7.1.1.Final</jboss-as-arquillian-container-managed.version>
-      </properties>
-    </profile>
-
-    <profile>
-      <id>eap600ER5.itest.setup</id>
-
-      <activation>
-        <property>
-          <name>as7.version</name>
-          <value>6.0.0.ER5</value>
-        </property>
-      </activation>
-
-      <properties>
-        <as7.url>Please set the as7.url system property to the location of the EAP ${as7.version} distribution zipfile.</as7.url>
-        <jboss-as-arquillian-container-managed.version>7.1.1.Final</jboss-as-arquillian-container-managed.version>
-      </properties>
-    </profile>
-
-    <profile>
-      <id>eap600ER7.itest.setup</id>
-
-      <activation>
-        <property>
-          <name>as7.version</name>
-          <value>6.0.0.ER7</value>
-        </property>
-      </activation>
-
-      <properties>
-        <as7.url>Please set the as7.url system property to the location of the EAP ${as7.version} distribution zipfile.</as7.url>
-        <jboss-as-arquillian-container-managed.version>7.1.1.Final</jboss-as-arquillian-container-managed.version>
-      </properties>
-    </profile>
-
-    <profile>
-      <id>eap600ER8.itest.setup</id>
-
-      <activation>
-        <property>
-          <name>as7.version</name>
-          <value>6.0.0.ER8</value>
-        </property>
-      </activation>
-
-      <properties>
-        <as7.url>Please set the as7.url system property to the location of the EAP ${as7.version} distribution zipfile.</as7.url>
-        <jboss-as-arquillian-container-managed.version>7.1.1.Final</jboss-as-arquillian-container-managed.version>
-      </properties>
-    </profile>
-
-    <profile>
-      <id>eap600CR1.itest.setup</id>
-
-      <activation>
-        <property>
-          <name>as7.version</name>
-          <value>6.0.0.CR1</value>
+          <value>6.0.0</value>
         </property>
       </activation>
 
diff --git a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/AbstractServerComponentTest.java b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/AbstractServerComponentTest.java
index a1e26e2..f6f1502 100644
--- a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/AbstractServerComponentTest.java
+++ b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/AbstractServerComponentTest.java
@@ -61,13 +61,7 @@ public abstract class AbstractServerComponentTest extends AbstractJBossAS7Plugin
 
     private static final Map<String, String> EAP6_VERSION_TO_AS7_VERSION_MAP = new HashMap<String, String>();
     static {
-        EAP6_VERSION_TO_AS7_VERSION_MAP.put("6.0.0.Beta1", "7.1.0.Final-redhat-1");
-        EAP6_VERSION_TO_AS7_VERSION_MAP.put("6.0.0.ER4", "7.1.1.Final-redhat-1");
-        EAP6_VERSION_TO_AS7_VERSION_MAP.put("6.0.0.ER5", "7.1.1.Final-redhat-1");
-        EAP6_VERSION_TO_AS7_VERSION_MAP.put("6.0.0.ER6", "7.1.1.Final-redhat-1");
-        EAP6_VERSION_TO_AS7_VERSION_MAP.put("6.0.0.ER7", "7.1.1.Final-redhat-1");
-        EAP6_VERSION_TO_AS7_VERSION_MAP.put("6.0.0.ER8", "7.1.2.Final-redhat-1");
-        EAP6_VERSION_TO_AS7_VERSION_MAP.put("6.0.0.CR1", "7.1.2.Final-redhat-1");
+        EAP6_VERSION_TO_AS7_VERSION_MAP.put("6.0.0", "7.1.2.Final-redhat-1");
     }
 
     private static final String RELEASE_VERSION_TRAIT_NAME = "_skm:release-version";


commit 970df9f180e9de788b8e85d6a3f9ae6a01e3ec25
Author: Ian Springer <ian.springer at redhat.com>
Date:   Tue Jun 19 15:19:12 2012 -0400

    upgrade Arquillian bom from 1.0.0.Final to 1.0.1.Final

diff --git a/pom.xml b/pom.xml
index 4799e55..210b697 100644
--- a/pom.xml
+++ b/pom.xml
@@ -110,7 +110,7 @@
     <resteasy.version>2.3.3.Final</resteasy.version>
     <freemarker.version>2.3.18</freemarker.version>
     <powermock.version>1.4.11</powermock.version>
-    <arquillian.version>1.0.0.Final</arquillian.version>
+    <arquillian.version>1.0.1.Final</arquillian.version>
     <animal.sniffer.version>1.7</animal.sniffer.version>
     <xercesImpl.version>2.9.1-jbossas-2</xercesImpl.version> <!-- see BZ-820629 and CVE-2009-2625 -->
 


commit f2ab06c2f62a77655d37ddcdce82eb16fe06fd91
Author: Jirka Kremser <jkremser at redhat.com>
Date:   Tue Jun 19 10:50:45 2012 +0200

    [BZ 588507 - WAR file deployed against Tomcat shows an incorrect installation date] Instalation date is now taken from InstalledPackage instance instead of PackageVersion instance

diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/ListPackageHistoryUIBean.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/ListPackageHistoryUIBean.java
index 845c60d..da049a5 100644
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/ListPackageHistoryUIBean.java
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/ListPackageHistoryUIBean.java
@@ -124,8 +124,8 @@ public class ListPackageHistoryUIBean extends PagedDataTableUIBean {
 
         results.add(new PackageTableDataValue("SHA256", current.getPackageVersion().getSHA256(), ((old != null) ? old
             .getPackageVersion().getSHA256() : null)));
-        results.add(new PackageTableDataValue("Installation Date", dateToString(current.getPackageVersion()
-            .getFileCreatedDate()), dateToString((old != null) ? old.getPackageVersion().getFileCreatedDate() : null)));
+        results.add(new PackageTableDataValue("Installation Date", dateToString(current.getInstallationDate()),
+            dateToString((old != null) ? old.getInstallationDate() : null)));
         //Comment for now. This field is not even in the list of InstalledPackage fields
         //results.add(new PackageTableDataValue("Owner", (current.getUser() != null) ? current.getUser().toString()
         //    : null, (old != null) ? ((old.getUser() != null) ? old.getUser().toString() : null) : null));


commit 2918e9c7df1d792b2b91f2e412ef7d2187cd55d4
Author: Simeon Pinder <spinder at redhat.com>
Date:   Tue Jun 5 16:55:29 2012 -0400

    [BZ 826542] Adding support for security-domain child nodes (authentication=classic,authentication=jaspi,audit=classic,audit=classic,acl=classic,authorization=classic,identity-trust=classic,mapping=classic]. -Explicitly allows the creation of and update of N ModuleOptionType instances and support of N module options for each type instance.

diff --git a/.classpath b/.classpath
index fd400dc..76e080c 100644
--- a/.classpath
+++ b/.classpath
@@ -153,7 +153,7 @@
 	<classpathentry kind="src" path="modules/helpers/pluginAnnotations/src/main/java"/>
 	<classpathentry kind="src" path="modules/helpers/pluginGen/src/main/java"/>
 	<classpathentry kind="src" path="modules/helpers/perftest-support/src/main/java"/>
-    <classpathentry kind="src" path="modules/helpers/rtfilter/src/main/java"/>  
+	<classpathentry kind="src" path="modules/helpers/rtfilter/src/main/java"/>
 	<classpathentry kind="src" path="modules/core/plugin-container-itest/src/test/java"/>
 	<classpathentry kind="src" path="modules/core/plugin-test-util/src/main/java"/>
 	<classpathentry kind="src" path="modules/core/arquillian-integration/container/src/test/java"/>
@@ -241,7 +241,7 @@
 	<classpathentry exported="true" kind="var" path="M2_REPO/org/jboss/jbossws/jbossws-native-core/3.1.1.GA/jbossws-native-core-3.1.1.GA.jar"/>
 	<classpathentry exported="true" kind="var" path="M2_REPO/org/apache/maven/maven-project/2.0.8/maven-project-2.0.8.jar"/>
 	<classpathentry exported="true" kind="var" path="M2_REPO/org/apache/maven/maven-plugin-api/2.0.8/maven-plugin-api-2.0.8.jar"/>
-	<classpathentry exported="true" kind="var" path="M2_REPO/org/codehaus/swizzle/swizzle-confluence/1.6.1/swizzle-confluence-1.6.1.jar"/>
+	<classpathentry exported="true" kind="var" path="M2_REPO/org/codehaus/swizzle/1.6.1/swizzle-confluence-1.6.1.jar"/>
 	<classpathentry exported="true" kind="var" path="M2_REPO/org/jvnet/inflector/0.7.0/inflector-0.7.0.jar"/>
 	<classpathentry exported="true" kind="var" path="M2_REPO/net/augeas/augeas/0.0.2/augeas-0.0.2.jar"/>
 	<classpathentry exported="true" kind="var" path="M2_REPO/org/json/json/20080701/json-20080701.jar"/>
@@ -308,7 +308,7 @@
 	<classpathentry exported="true" kind="var" path="M2_REPO/org/jboss/arquillian/container/arquillian-container-spi/1.0.0.Final/arquillian-container-spi-1.0.0.Final.jar"/>
 	<classpathentry exported="true" kind="var" path="M2_REPO/org/jboss/arquillian/container/arquillian-container-test-api/1.0.0.Final/arquillian-container-test-api-1.0.0.Final.jar"/>
 	<classpathentry exported="true" kind="var" path="M2_REPO/org/jboss/arquillian/testng/arquillian-testng-core/1.0.0.Final/arquillian-testng-core-1.0.0.Final.jar"/>
-    <classpathentry exported="true" kind="var" path="M2_REPO/com/wordnik/swagger-annotations_2.9.1/1.1-SNAPSHOT/swagger-annotations_2.9.1-1.1-20120531.064118-1.jar"/>
-    <classpathentry exported="true" kind="var" path="M2_REPO/org/jboss/byteman/byteman/1.2.1/byteman-1.2.1.jar"/>    
+	<classpathentry exported="true" kind="var" path="M2_REPO/com/wordnik/swagger-annotations_2.9.1/1.1-SNAPSHOT/swagger-annotations_2.9.1-1.1-20120531.064118-1.jar"/>
+	<classpathentry exported="true" kind="var" path="M2_REPO/org/jboss/byteman/byteman/1.2.1/byteman-1.2.1.jar"/>
 	<classpathentry kind="output" path="eclipse-classes"/>
 </classpath>
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ModuleOptionsComponent.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ModuleOptionsComponent.java
new file mode 100644
index 0000000..d486542
--- /dev/null
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ModuleOptionsComponent.java
@@ -0,0 +1,867 @@
+package org.rhq.modules.plugins.jbossas7;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.codehaus.jackson.annotate.JsonProperty;
+import org.codehaus.jackson.map.annotate.JsonSerialize;
+import org.codehaus.jackson.map.annotate.JsonSerialize.Inclusion;
+
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.ConfigurationUpdateStatus;
+import org.rhq.core.domain.configuration.PropertyMap;
+import org.rhq.core.domain.configuration.PropertySimple;
+import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
+import org.rhq.core.domain.resource.CreateResourceStatus;
+import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.core.pluginapi.configuration.ConfigurationFacet;
+import org.rhq.core.pluginapi.configuration.ConfigurationUpdateReport;
+import org.rhq.core.pluginapi.inventory.CreateChildResourceFacet;
+import org.rhq.core.pluginapi.inventory.CreateResourceReport;
+import org.rhq.core.pluginapi.inventory.DeleteResourceFacet;
+import org.rhq.modules.plugins.jbossas7.json.Address;
+import org.rhq.modules.plugins.jbossas7.json.Operation;
+import org.rhq.modules.plugins.jbossas7.json.ReadAttribute;
+import org.rhq.modules.plugins.jbossas7.json.ReadChildrenNames;
+import org.rhq.modules.plugins.jbossas7.json.Result;
+import org.rhq.modules.plugins.jbossas7.json.WriteAttribute;
+
+/**
+ * Component class for Module Options. Necessary because Module Options are child 
+ * attributes of another as7 node attribute and cannot be created/updated without
+ * rewriting the parent attribute as well.  The following as7 node snippets shows how the
+ * 'login-modules' attribute contains both simple and complex child attributes.  The complex
+ * 'module-options' child attribute values can be numerous and can/may need to be modifiable 
+ * independently.
+ * Read:
+ * [standalone at localhost:9999 authentication=classic] :read-attribute(name=login-modules)
+ {
+    "outcome" => "success",
+    "result" => [{
+        "code" => "Ldap",
+        "flag" => "requisite",
+        "module-options" => [("bindDn"=>"uid=ldapUser,ou=People,dc=redat,dc=com")]
+    }]
+ }
+ * Write back:
+ [standalone at localhost:9999 authentication=classic] 
+ :write-attribute(name=login-modules,
+   value=[{"code"=>"Ldap","flag"=>"required", 
+       "module-options"=>[("bindDn"=>"uid=ldapSecureUser,ou=People,dc=redat,dc=com")]}])
+ {
+    "outcome" => "success",
+    "response-headers" => {
+        "operation-requires-reload" => true,
+        "process-state" => "reload-required"
+    }
+ }
+ * 
+ * @author Simeon Pinder
+ */
+public class ModuleOptionsComponent extends BaseComponent implements ConfigurationFacet, DeleteResourceFacet,
+    CreateChildResourceFacet {
+
+    //shared identifier for module-options attribute reused by all nodes with Module Options 
+    private static String moduleOptionsNode = ",module-options";
+
+    //Module Option type attribute identifiers
+    private static String loginModules = "login-modules";//Authentication (Classic,-Managed Server,-Profile)
+    private static String aclModules = "acl-modules";//Acl
+    private static String providerModules = "provider-modules";//Audit
+    private static String policyModules = "policy-modules";//Authorization
+    private static String trustModules = "trust-modules";//IdentityTrust
+    private static String mappingModules = "mapping-modules";//Mapping
+    private static String authModules = "auth-modules";//Authentication (Jaspi,-Managed Server,-Profile)
+
+    //Enumerates list of AS7 types that support module options.
+    public enum ModuleOptionType {
+        Acl(aclModules), Audit(providerModules), Authentication(loginModules), AuthenticationJaspi(authModules), Authorization(
+            policyModules), IdentityTrust(
+            trustModules), Mapping(mappingModules);
+        private String attribute = "";
+
+        //stores mapping of as7 attribute name to module option type mapping Ex. login-modules -> Authentication Module Option Type.
+        public static HashMap<String, ModuleOptionType> typeMap = new HashMap<String, ModuleOptionType>();
+        static {//populate all module option type mappings
+            for (ModuleOptionType type : ModuleOptionType.values()) {
+                typeMap.put(type.getAttribute(), type);
+            }
+        }
+        //Stores mapping of as7 attribute name to more user friendly Module option type
+        public static Map<String, String> readableNameMap = new HashMap<String, String>();
+        static {
+            readableNameMap.put(aclModules, "ACL Modules");
+            readableNameMap.put(providerModules, "Provider Modules");
+            readableNameMap.put(loginModules, "Login Modules");//Authentication=classic
+            readableNameMap.put(authModules, "Auth Modules");//Authentication=jaspi
+            readableNameMap.put(policyModules, "Policy Modules");
+            readableNameMap.put(trustModules, "Trust Modules");
+            readableNameMap.put(mappingModules, "Mapping Modules");
+        }
+
+        public String getAttribute() {
+            return attribute;
+        }
+
+        private ModuleOptionType(String attribute) {
+            this.attribute = attribute;
+        }
+    }
+
+    //Strings unique to nodes
+    private static String AUTH_CLASSIC_NODE = "Authentication (Classic";
+    private static String AUTH_JASPI_NODE = "Authentication (Jaspi";
+    private static String ACL_NODE = "ACL";
+    private static String AUDIT_NODE = "Audit";
+    private static String AUTHORIZATION_NODE = "Authorization";
+    private static String TRUST_NODE = "Identity Trust";
+    private static String MAPPING_NODE = "Mapping";
+    private static String[] supportedModuleOptionTypeNodes = { AUTH_CLASSIC_NODE, AUTH_JASPI_NODE, ACL_NODE,
+        AUDIT_NODE, AUTHORIZATION_NODE, TRUST_NODE, MAPPING_NODE };
+
+    //define operation/type mappings where specific plugin descriptor nodes map to specific 
+    // as7 node names.
+    public static HashMap<String, String> attributeMap = new HashMap<String, String>();
+    static {
+        attributeMap.put(AUTH_CLASSIC_NODE + ")", loginModules);
+        attributeMap.put(AUTH_CLASSIC_NODE + " - Managed Server)", loginModules);
+        attributeMap.put(AUTH_CLASSIC_NODE + " - Profile)", loginModules);
+        attributeMap.put(AUTH_JASPI_NODE + ")", authModules);
+        attributeMap.put(AUTH_JASPI_NODE + " - Managed Server)", authModules);
+        attributeMap.put(AUTH_JASPI_NODE + " - Profile)", authModules);
+        attributeMap.put(ACL_NODE, aclModules);
+        attributeMap.put(ACL_NODE + " (Managed Server)", aclModules);
+        attributeMap.put(ACL_NODE + " (Profile)", aclModules);
+        attributeMap.put(AUDIT_NODE, providerModules);
+        attributeMap.put(AUDIT_NODE + " (Managed Server)", providerModules);
+        attributeMap.put(AUDIT_NODE + " (Profile)", providerModules);
+        attributeMap.put(AUTHORIZATION_NODE, policyModules);
+        attributeMap.put(AUTHORIZATION_NODE + " (Managed Server)", policyModules);
+        attributeMap.put(AUTHORIZATION_NODE + " (Profile)", policyModules);
+        attributeMap.put(TRUST_NODE, trustModules);
+        attributeMap.put(TRUST_NODE + " (Managed Server)", trustModules);
+        attributeMap.put(TRUST_NODE + " (Profile)", trustModules);
+        attributeMap.put(MAPPING_NODE, mappingModules);
+        attributeMap.put(MAPPING_NODE + " (Managed Server)", mappingModules);
+        attributeMap.put(MAPPING_NODE + " (Profile)", mappingModules);
+    }
+
+    public static HashMap<String, String> newChildTypeMap = new HashMap<String, String>();
+    static {
+        newChildTypeMap.put(loginModules, "authentication=classic");
+        newChildTypeMap.put(authModules, "authentication=jaspi");
+        newChildTypeMap.put(aclModules, "acl=classic");
+        newChildTypeMap.put(providerModules, "audit=classic");
+        newChildTypeMap.put(policyModules, "authorization=classic");
+        newChildTypeMap.put(trustModules, "identity-trust=classic");
+        newChildTypeMap.put(mappingModules, "mapping=classic");
+    }
+    
+    @Override
+    public CreateResourceReport createResource(CreateResourceReport report) {
+
+        if (report.getPackageDetails() != null) { // Content deployment
+            return deployContent(report);
+        } else {
+            ASConnection connection = getASConnection();
+
+            // Check for the Highlander principle
+            boolean isSingleton = report.getResourceType().isSingleton();
+            if (isSingleton) {
+                // check if there is already a child with the desired type is present
+                Configuration pluginConfig = report.getPluginConfiguration();
+                PropertySimple pathProperty = pluginConfig.getSimple("path");
+                if (path == null || path.isEmpty()) {
+                    report.setErrorMessage("No path property found in plugin configuration");
+                    report.setStatus(CreateResourceStatus.INVALID_CONFIGURATION);
+                    return report;
+                }
+
+                ReadChildrenNames op = new ReadChildrenNames(address, pathProperty.getStringValue());
+                Result res = connection.execute(op);
+                if (res.isSuccess()) {
+                    List<String> entries = (List<String>) res.getResult();
+                    if (!entries.isEmpty()) {
+                        report.setErrorMessage("Resource is a singleton, but there are already children " + entries
+                            + " please remove them and retry");
+                        report.setStatus(CreateResourceStatus.FAILURE);
+                        return report;
+                    }
+                }
+            }
+
+            //determine type then attribute
+            ResourceType resourceType = report.getResourceType();
+            String attribute = attributeMap.get(resourceType.getName());
+            //determine new child name from attribute
+            String newChild = newChildTypeMap.get(attribute);
+
+            //get resourceConfig
+            Configuration configuration = report.getResourceConfiguration();
+            
+            if(attribute!=null){//create executed from SecurityDomain level
+
+                //retrieve the values passed in via config
+                Value loaded = loadCodeFlagType(configuration, attribute, null);
+
+                //populate the ModuleOptionType from the Configuration
+                List<Value> newAttributeState = new ArrayList<Value>();
+                newAttributeState.add(loaded);
+
+                //build the operation
+                //update the address to point to the new child being created
+                Address newChildLocation = new Address(path + "," + newChild);
+                Operation op = createAddModuleOptionTypeOperation(newChildLocation, attribute, newAttributeState);
+
+                Result result = connection.execute(op);
+                if (result.isSuccess()) {
+                    report.setStatus(CreateResourceStatus.SUCCESS);
+                    report.setResourceKey(newChildLocation.getPath());
+                    report.setResourceName(report.getResourceType().getName());
+                } else {
+                    report.setStatus(CreateResourceStatus.FAILURE);
+                    report.setErrorMessage(result.getFailureDescription());
+                }
+            }else{//Create executed from the 'Login Modules/Provider Modules/etc. level.
+                //retrieve the parent type to lookup attribute to write to
+                ResourceType parentType = (ResourceType) resourceType.getParentResourceTypes().toArray()[0];
+                attribute = attributeMap.get(parentType.getName());
+                
+                //retrieve existing attribute definition
+                //get the current attribute value
+                ReadAttribute op = new ReadAttribute(address, attribute);
+                Result result = getASConnection().execute(op);
+                if (result.isSuccess()) {
+                    //populate attribute values
+                    List<Value> currentAttributeState = new ArrayList<Value>();
+                    currentAttributeState = ModuleOptionsComponent.populateSecurityDomainModuleOptions(result,
+                        ModuleOptionsComponent.loadModuleOptionType(attribute));
+                   //populate new Module type data 
+                   //retrieve the values passed in via config
+                   Value loaded = loadCodeFlagType(configuration, attribute, null);
+
+                    //append new type information
+                    currentAttributeState.add(loaded);
+                    //write values back out.
+                    Operation write = new WriteAttribute(address);
+                    write.addAdditionalProperty("name", attribute);//attribute to execute on
+
+                    //now complete the write operation by updating the value
+                    write.addAdditionalProperty("value", (Object) currentAttributeState);
+                    result = connection.execute(write);
+                    if (result.isSuccess()) {
+                        report.setStatus(CreateResourceStatus.SUCCESS);
+                        //Ex. subsystem=security,security-domain=createOne,authentication=classic,login-modules:0
+                        report.setResourceKey(path + "," + attribute + ":" + (currentAttributeState.size() - 1));
+                        //Ex. Login Modules 0
+                        report.setResourceName(ModuleOptionType.readableNameMap.get(attribute) + " "
+                            + (currentAttributeState.size() - 1));
+                    } else {
+                        report.setStatus(CreateResourceStatus.FAILURE);
+                        report.setErrorMessage(result.getFailureDescription());
+                    }
+                }
+            }
+            return report;
+        }
+    }
+
+    @Override
+    public Configuration loadResourceConfiguration() throws Exception {
+        Configuration configuration = new Configuration();
+
+        //determine the component
+        ResourceType resourceType = context.getResourceType();
+        Set<ResourceType> nodeParentTypes = context.getResourceType().getParentResourceTypes();
+        ResourceType parentType = (ResourceType) nodeParentTypes.toArray()[0];
+        ResourceType grandParentType = (ResourceType) parentType.getParentResourceTypes().toArray()[0];
+
+        //For each Module Option type, like Authentication (Classic) and the immediate
+        // child node of each, the configuration is shared as it is in the AS7 node as well.
+        if (isSupportedModuleOptionTypeOrImmediateChildOf(parentType, resourceType)) {//Classic, Managed, Profile
+            boolean currentNodeIsModuleType = false;
+            //if the current resourceType is included in the attributeMap then it is an actual Module Option Type.
+            if (ModuleOptionsComponent.attributeMap.get(resourceType.getName()) != null) {
+                currentNodeIsModuleType = true;
+            }
+            //get type and lookup supported node and type
+            //retrieve the parent resource
+            String attribute = ModuleOptionsComponent.attributeMap.get(parentType.getName());
+            if (currentNodeIsModuleType) {//if is an actual Module Option Type then update attribute retrieved.
+                attribute = ModuleOptionsComponent.attributeMap.get(resourceType.getName());
+            }
+
+            //get the current attribute value
+            ReadAttribute op = new ReadAttribute(address, attribute);
+            Result result = getASConnection().execute(op);
+            if (result.isSuccess()) {
+                //populate attribute values
+                List<Value> currentAttributeState = new ArrayList<Value>();
+                currentAttributeState = ModuleOptionsComponent.populateSecurityDomainModuleOptions(result,
+                    ModuleOptionsComponent.loadModuleOptionType(attribute));
+                if (currentNodeIsModuleType) {//grab first available module type
+                    Value loaded = currentAttributeState.get(0);
+                    //populate configuration
+                    populateCodeFlagType(configuration, attribute, loaded);
+                } else {//Need to locate specific module type 
+                    //locate specific node and populate the config
+                    //Ex."login-modules:";
+                    String moduleTypeIdentifier = attribute + ":";
+                    int index = path.indexOf(moduleTypeIdentifier);
+                    String loginModuleIndex = path.substring(index + moduleTypeIdentifier.length());
+                    int lmi = Integer.valueOf(loginModuleIndex);//Ex 0,1,30
+                    if (currentAttributeState.size() > lmi) {//then retrieve.
+                        Value loaded = currentAttributeState.get(lmi);
+                        //populate configuration
+                        populateCodeFlagType(configuration, attribute, loaded);
+                    }
+                }
+            }
+            //read attribute
+            return configuration;
+        }
+        //Module Options child, Ex. 'Login Modules (Classic', ..-Managed, .. - Profile
+        else if (supportsLoginModuleOptionType(grandParentType)) {
+            //get type and lookup supported node and type
+            String attribute = ModuleOptionsComponent.attributeMap.get(grandParentType.getName());
+
+            //get the current attribute value
+            ReadAttribute op = new ReadAttribute(address, attribute);
+            Result result = getASConnection().execute(op);
+            if (result.isSuccess()) {
+                //populate attribute values
+                List<Value> currentAttributeState = new ArrayList<Value>();
+                currentAttributeState = ModuleOptionsComponent.populateSecurityDomainModuleOptions(result,
+                    ModuleOptionsComponent.loadModuleOptionType(attribute));
+
+                //locate specific node and populate the config
+                //Ex."login-modules:";
+                String moduleTypeIdentifier = attribute + ":";
+                int index = path.indexOf(moduleTypeIdentifier);
+                String loginModuleIndex = path.substring(index + moduleTypeIdentifier.length());
+                String[] split = loginModuleIndex.split(",");
+                int lmi = Integer.valueOf(split[0]);//Ex 0,1,30
+                if (lmi < currentAttributeState.size()) {//then proceed
+                    Value loaded = currentAttributeState.get(lmi);
+                    //populate configuration: module-options
+                    LinkedHashMap<String, Object> currentModuleOptions = loaded.getOptions();
+
+                    //This must match exactly the mapping identifier from descriptor, otherwise loadResource fails silently.
+                    String id = "Module Options";
+                    PropertyMap map = new PropertyMap(id);
+                    for (String key : currentModuleOptions.keySet()) {
+                        PropertySimple option = new PropertySimple(key, currentModuleOptions.get(key));
+                        map.put(option);
+                    }
+                    if (!currentModuleOptions.isEmpty()) {//check that keyset is non empty before adding to config.
+                        configuration.put(map);
+                    }
+                }
+            }
+            return configuration;
+        } else {//otherwise default subsystem discovery behavior.
+            ConfigurationDefinition configDef = context.getResourceType().getResourceConfigurationDefinition();
+            ConfigurationLoadDelegate delegate = new ConfigurationLoadDelegate(configDef, getASConnection(), address,
+                includeRuntime);
+            configuration = delegate.loadResourceConfiguration();
+
+            // Read server state
+            ReadAttribute op = new ReadAttribute(getAddress(), "name");
+            executeAndGenerateServerUpdateIfNecessary(configuration, op);
+            return configuration;
+        }
+    }
+
+    /** Looks up whether the current node supports the Module Options.
+     * 
+     * @param grandParentType
+     * @return
+     */
+    private boolean supportsLoginModuleOptionType(ResourceType grandParentType) {
+        boolean supportModuleOptionTypes = false;
+        if (grandParentType != null) {
+            for (String moduleOptionType : supportedModuleOptionTypeNodes) {
+                if (grandParentType.getName().indexOf(moduleOptionType) > -1) {
+                    supportModuleOptionTypes = true;
+                }
+            }
+        }
+        return supportModuleOptionTypes;
+    }
+
+    /**Iterates through the list of supported Module Option Type nodes
+     * to determine if the current node is i)supported Module option node or
+     * ii)the immediated child of a supported Module option node.
+     * 
+     * @param parentType
+     * @param resourceType
+     * @return
+     */
+    private boolean isSupportedModuleOptionTypeOrImmediateChildOf(ResourceType parentType, ResourceType resourceType) {
+        boolean loadThisConfiguration = false;
+        if ((parentType != null) && (resourceType != null)) {
+            for (String moduleOptionType : attributeMap.keySet()) {
+                if ((parentType.getName().equals(moduleOptionType))
+                    || (resourceType.getName().equals(moduleOptionType))) {
+                    loadThisConfiguration = true;
+                }
+            }
+
+        }
+        return loadThisConfiguration;
+    }
+
+    /** Handles the different types of configuration population based on the attribute value passed in.
+     * 
+     * @param configuration
+     * @param attribute 
+     * @param loaded
+     */
+    private void populateCodeFlagType(Configuration configuration, String attribute, Value loaded) {
+        if (attribute.equals(providerModules)) {//audit=classic. Ex. only code 
+            PropertySimple currentValue = new PropertySimple("code", loaded.getCode());
+            configuration.put(currentValue);
+        } else if (attribute.equals(mappingModules)) {//mapping=classic. Ex. code type
+            PropertySimple currentValue = new PropertySimple("code", loaded.getCode());
+            PropertySimple currentValue2 = new PropertySimple("type", loaded.getType());
+            configuration.put(currentValue);
+            configuration.put(currentValue2);
+        } else {//code flag
+            PropertySimple currentValue = new PropertySimple("code", loaded.getCode());
+            PropertySimple currentValue2 = new PropertySimple("flag", loaded.getFlag());
+            configuration.put(currentValue);
+            configuration.put(currentValue2);
+        }
+    }
+
+    /** Populates the Value instance passed in or returns new Value instance with values loaded.
+     * 
+     * @param configuration
+     * @param attribute
+     * @param loaded
+     * @return
+     */
+    private Value loadCodeFlagType(Configuration configuration, String attribute, Value loaded) {
+        //if required data is not present then return null.
+        if ((configuration == null) || attribute == null) {
+            return null;
+        }
+        if (loaded == null) {// initialize if null
+            loaded = new Value();
+        }
+        if (attribute.equals(providerModules)) {//audit=classic. Ex. only code
+            String code = configuration.getSimpleValue("code");
+            loaded.setCode(code);
+        } else if (attribute.equals(mappingModules)) {//mapping=classic. Ex. code type
+            String code = configuration.getSimpleValue("code");
+            String type = configuration.getSimpleValue("type");
+            loaded.setCode(code);
+            loaded.setType(type);
+        } else {//code flag
+            String code = configuration.getSimpleValue("code");
+            String flag = configuration.getSimpleValue("flag");
+            loaded.setCode(code);
+            loaded.setFlag(flag);
+        }
+        return loaded;
+    }
+
+    @Override
+    public void updateResourceConfiguration(ConfigurationUpdateReport report) {
+        //determine the component
+        ResourceType resourceType = context.getResourceType();
+        ConfigurationDefinition configDef = resourceType.getPluginConfigurationDefinition();
+        Set<ResourceType> nodeParentTypes = context.getResourceType().getParentResourceTypes();
+        ResourceType parentType = (ResourceType) nodeParentTypes.toArray()[0];
+        ResourceType grandParentType = (ResourceType) parentType.getParentResourceTypes().toArray()[0];
+        ///if child of SecurityDomain then
+        if (isSupportedModuleOptionTypeOrImmediateChildOf(parentType, resourceType)) {
+            boolean currentNodeIsModuleType = false;
+            if (ModuleOptionsComponent.attributeMap.get(resourceType.getName()) != null) {
+                currentNodeIsModuleType = true;
+            }
+            //get type and lookup supported node and type
+            //retreive the parent resource
+            String attribute = ModuleOptionsComponent.attributeMap.get(parentType.getName());
+            if (currentNodeIsModuleType) {
+                attribute = ModuleOptionsComponent.attributeMap.get(resourceType.getName());
+            }
+
+            //get the current attribute value. Will write module types back out exactly as read in with these new updates
+            ReadAttribute op = new ReadAttribute(address, attribute);
+            Result result = getASConnection().execute(op);
+            if (result.isSuccess()) {
+                List<String> entries = (List<String>) result.getResult();
+
+                //populate attribute values
+                List<Value> currentAttributeState = new ArrayList<Value>();
+                currentAttributeState = ModuleOptionsComponent.populateSecurityDomainModuleOptions(result,
+                    ModuleOptionsComponent.loadModuleOptionType(attribute));
+
+                //retrieve current config changes    
+                Configuration conf = report.getConfiguration();
+
+                if (currentNodeIsModuleType) {//grab first available module type
+                    Value loaded = currentAttributeState.get(0);
+                    //iterate over properties and update values appropriately
+                    for (String pKey : conf.getSimpleProperties().keySet()) {
+                        if (pKey.equals("flag")) {
+                            loaded.setFlag(conf.getSimpleProperties().get(pKey).getStringValue());
+                        } else if (pKey.equals("code")) {
+                            loaded.setCode(conf.getSimpleProperties().get(pKey).getStringValue());
+                        } else if (pKey.equals("type")) {
+                            loaded.setType(conf.getSimpleProperties().get(pKey).getStringValue());
+                        }
+                    }
+                    Operation write = new WriteAttribute(address);
+                    write.addAdditionalProperty("name", attribute);//attribute to execute on
+
+                    //now complete the write operation by updating the value
+                    write.addAdditionalProperty("value", (Object) currentAttributeState);
+                    executeWriteAndGenerateAs7ServerUpdate(report, conf, write);
+                } else {//Need to locate specific module type 
+
+                //locate specific node and populate the config
+                    String loginModuleIdentifier = attribute + ":";
+                int index = path.indexOf(loginModuleIdentifier);
+                String loginModuleIndex = path.substring(index + loginModuleIdentifier.length());
+                int lmi = Integer.valueOf(loginModuleIndex);//Ex 0,1,30
+                Value valueObject = currentAttributeState.get(lmi);
+
+                //iterate over properties and update values appropriately
+                for (String pKey : conf.getSimpleProperties().keySet()) {
+                    if (pKey.equals("flag")) {
+                        valueObject.setFlag(conf.getSimpleProperties().get(pKey).getStringValue());
+                    } else if (pKey.equals("code")) {
+                        valueObject.setCode(conf.getSimpleProperties().get(pKey).getStringValue());
+                        } else if (pKey.equals("type")) {
+                            valueObject.setType(conf.getSimpleProperties().get(pKey).getStringValue());
+                    }
+                }
+                Operation write = new WriteAttribute(address);
+                write.addAdditionalProperty("name", attribute);//attribute to execute on
+
+                //now complete the write operation by updating the value
+                write.addAdditionalProperty("value", (Object) currentAttributeState);
+                executeWriteAndGenerateAs7ServerUpdate(report, conf, write);
+                }
+            }
+        } else if (supportsLoginModuleOptionType(grandParentType)) {//Module Options child.
+            //get type and lookup supported node and type
+            String attribute = ModuleOptionsComponent.attributeMap.get(grandParentType.getName());
+
+            //get the current attribute value. Will write module types back out exactly as read in with these new updates
+            ReadAttribute op = new ReadAttribute(address, attribute);
+            Result result = getASConnection().execute(op);
+            if (result.isSuccess()) {
+
+                //populate attribute values
+                List<Value> currentAttributeState = new ArrayList<Value>();
+                currentAttributeState = ModuleOptionsComponent.populateSecurityDomainModuleOptions(result,
+                    ModuleOptionsComponent.loadModuleOptionType(attribute));
+
+                //locate specific node and populate the config
+                String loginModuleIdentifier = attribute + ":";
+                int index = path.indexOf(loginModuleIdentifier);
+                String loginModuleIndex = path.substring(index + loginModuleIdentifier.length());
+                String[] split = loginModuleIndex.split(",");
+                int lmi = Integer.valueOf(split[0]);//Ex 0,1,30
+                Value valueObject = currentAttributeState.get(lmi);
+
+                //retrieve current config changes    
+                Configuration conf = report.getConfiguration();
+                //list current conf stated being defined.
+                String mapKey = (String) conf.getMap().keySet().toArray()[0];
+                PropertyMap mapType = (PropertyMap) conf.getMap().get(mapKey);
+                //insert update logic.
+                //set this new state passed in as state of the attribute.
+                LinkedHashMap<String, Object> currentOptions = new LinkedHashMap<String, Object>();
+                for (String propertyKey : mapType.getMap().keySet()) {
+                    currentOptions.put(propertyKey, ((PropertySimple) mapType.get(propertyKey)).getStringValue());
+                }
+
+                //make these settings the new state for this part of the attribute.
+                valueObject.setOptions(currentOptions);
+                currentAttributeState.set(lmi, valueObject);
+
+                Operation write = new WriteAttribute(address);
+                write.addAdditionalProperty("name", attribute);//attribute to execute on
+
+                //now complete the write operation by updating the value
+                write.addAdditionalProperty("value", (Object) currentAttributeState);
+                executeWriteAndGenerateAs7ServerUpdate(report, conf, write);
+            }
+        } else {
+            ConfigurationWriteDelegate delegate = new ConfigurationWriteDelegate(configDef, getASConnection(), address);
+            delegate.updateResourceConfiguration(report);
+        }
+
+    }
+
+    /**Executes boilerplate finish for write operation.
+     * 
+     * @param report
+     * @param conf
+     * @param write
+     */
+    private void executeWriteAndGenerateAs7ServerUpdate(ConfigurationUpdateReport report, Configuration conf,
+        Operation write) {
+        Result result;
+        result = getASConnection().execute(write);
+        if (!result.isSuccess()) {
+            report.setStatus(ConfigurationUpdateStatus.FAILURE);
+            report.setErrorMessage(result.getFailureDescription());
+        } else {
+            report.setStatus(ConfigurationUpdateStatus.SUCCESS);
+            // signal "need reload"
+            if (result.isReloadRequired()) {
+                PropertySimple oobMessage = new PropertySimple("__OOB",
+                    "The server needs a reload for the latest changes to come effective.");
+                conf.put(oobMessage);
+            }
+            if (result.isRestartRequired()) {
+                PropertySimple oobMessage = new PropertySimple("__OOB",
+                    "The server needs a restart for the latest changes to come effective.");
+                conf.put(oobMessage);
+            }
+        }
+    }
+
+    /**Executes boilerplate finish for read operation.
+     * 
+     * @param report
+     * @param conf
+     * @param write
+     */
+    private void executeAndGenerateServerUpdateIfNecessary(Configuration configuration, ReadAttribute op) {
+        Result res = getASConnection().execute(op);
+        if (res.isReloadRequired()) {
+            PropertySimple oobMessage = new PropertySimple("__OOB",
+                "The server needs a reload for the latest changes to come effective.");
+            configuration.put(oobMessage);
+        }
+        if (res.isRestartRequired()) {
+            PropertySimple oobMessage = new PropertySimple("__OOB",
+                "The server needs a restart for the latest changes to come effective.");
+            configuration.put(oobMessage);
+        }
+    }
+
+    /** Locates the write ModuleOptionType mapped to the AS7Node attribute passed in.
+     *  Ex. 'login-modules' -> Authentication (Classic * type. One of three types.
+     * 
+     * @param attribute 
+     * @return
+     */
+    public static ModuleOptionType loadModuleOptionType(String attribute) {
+        ModuleOptionType located = ModuleOptionType.typeMap.get(attribute);
+        if (located == null) {
+            throw new IllegalArgumentException("Unknown node '" + attribute
+                + "' entered for which no valid ModuleOptionType could be found.");
+        }
+        return located;
+    }
+
+    /** Takes the result passed in(successful readAttribute for ModuleOptionType) and
+     *  parses the json to populate a json object of type List<Value> with the 
+     *  results.
+     *  Handles inconsistencies in model representation for login-modules vs. 
+     *  the other supported ModuleOptionTypes.
+     * 
+     * @param result json.Result type from successful read of attribute.
+     * @param type ModuleOptionType
+     * @return List<Value> type populated with moduleOption details.
+     */
+    public static List<Value> populateSecurityDomainModuleOptions(Result result, ModuleOptionType type) {
+        //initialize empty
+        List<Value> populated = new ArrayList<Value>();
+        //input validation
+        if ((result != null) && (result.isSuccess())) {
+
+            //parse json and populate the object.
+            Object rawResult = result.getResult();
+
+            if (rawResult instanceof ArrayList) {
+                //iterate over the module option type passed in.
+                ArrayList moduleOptionTypeChildrenList = (ArrayList) rawResult;
+                for (int i = 0; i < moduleOptionTypeChildrenList.size(); i++) {
+                    Value value = new Value();
+                    //stores current <module-options> defined.
+                    LinkedHashMap<String, Object> optionsMap = new LinkedHashMap<String, Object>();
+                    Object entryCheck = ((ArrayList) rawResult).get(i);
+
+                    if (entryCheck instanceof HashMap) {
+
+                        //this is the root attribute map for all children of the specific custom Security Domain 
+                        //type attributes.
+                        Map<String, Object> attributeMap = (HashMap<String, Object>) entryCheck;
+                        for (String key : attributeMap.keySet()) {
+
+                            //peek at contents to exclude empty values.
+                            String extracted = String.valueOf(attributeMap.get(key));
+                            if (!extracted.trim().isEmpty()) {
+                                if (key.equals("flag")) {
+                                    value.setFlag(extracted);
+                                } else if (key.equals("code")) {
+                                    value.setCode(extracted);
+                                } else if (key.equals("type")) {
+                                    value.setType(extracted);
+                                } else if (key.equals("module-options")) {
+                                    //Need to support both Map and List types here because of inconsistent representations.
+                                    Object optionEntity = attributeMap.get(key);
+                                    if (optionEntity instanceof HashMap) {
+                                        Map<String, Object> entryList = (HashMap<String, Object>) optionEntity;
+                                        for (String oKey : entryList.keySet()) {
+                                            //get key and value and populate ModuleEntries found.
+                                            optionsMap.put(oKey, String.valueOf(entryList.get(oKey)));
+                                        }
+                                    } else if (optionEntity instanceof ArrayList) {
+                                        Object listEntryCheck = ((ArrayList) optionEntity).get(0);
+                                        if (listEntryCheck instanceof HashMap) {
+                                            ArrayList list = (ArrayList) optionEntity;
+                                            for (Object listEntry : list) {//iterate over each instance to get all values.
+                                                Map<String, Object> entryList = (HashMap<String, Object>) listEntry;
+                                                for (String oKey : entryList.keySet()) {
+                                                    //get key and value and populate ModuleEntries found.
+                                                    optionsMap.put(oKey, String.valueOf(entryList.get(oKey)));
+                                                }
+                                            }
+                                        }
+                                    }//end of if/else
+                                }
+                            }//end of empty value check
+                        }
+                    }//end of HashMap for SecurityDomain child check
+                    value.setOptions(optionsMap);
+                    populated.add(value);
+                }//end of moduleOptionType iteration
+            }
+        }
+
+        return populated;
+    }
+
+    @JsonSerialize(include = Inclusion.NON_NULL)
+    public static class Value {
+        // no args for jackson.
+        public Value() {
+        };
+
+        /** Three possible flags can be set. c-> code f->flag t->type
+         * Acl                  c  f 
+         * Authentication       c  f
+         * Authentication(Jaspi)c  f
+         * Authorization        c  f
+         * Identity Trust       c  f
+         * Mapping              c  t
+         * Audit                c
+         * 
+         * @param code
+         * @param flag
+         * @param type
+         */
+        public Value(String code, String flag, String type) {
+            setCode(code);
+            if ((flag != null) && (!flag.trim().isEmpty())) {
+                setFlag(flag);
+            }
+            if ((type != null) && (!type.trim().isEmpty())) {
+                setType(type);
+            }
+        }
+
+        //default to empty string for case where specific attribute is not used.
+        @JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
+        private String flag;
+        private String code;
+        @JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
+        private String type;
+
+        public String getType() {
+            return type;
+        }
+
+        public void setType(String type) {
+            this.type = type;
+        }
+
+        public String getFlag() {
+            return flag;
+        }
+
+        public void setFlag(String flag) {
+            this.flag = flag;
+        }
+
+        public String getCode() {
+            return code;
+        }
+
+        public void setCode(String code) {
+            this.code = code;
+        }
+
+        //overrides the type name for serialization/deserialization.
+        @JsonProperty(value = "module-options")
+        @JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
+        private LinkedHashMap<String, Object> options = null;
+
+        @JsonProperty(value = "module-options")
+        public LinkedHashMap<String, Object> getOptions() {
+            if (options == null) {
+                options = new LinkedHashMap<String, Object>();
+            }
+            return options;
+        }
+
+        @JsonProperty(value = "module-options")
+        public void setOptions(LinkedHashMap<String, Object> options) {
+            this.options = options;
+        }
+
+        @Override
+        public String toString() {
+            String serialized = "";
+            serialized += "code=" + getCode() + ", ";
+            if (getFlag() != null) {
+                serialized += "flag=" + getFlag() + ", ";
+            } else if (getType() != null) {
+                serialized += "type=" + getType() + ", ";
+            }
+            String options = "module-options=";
+            if (getOptions().isEmpty()) {
+                options += " {}";
+            } else {
+                options += " {";
+                for (String key : getOptions().keySet()) {
+                    options += key + "=\"" + getOptions().get(key) + "\",";
+                }
+                options = options.substring(0, options.length() - 1);
+                options += "} ";
+            }
+            serialized += options;
+            return serialized;
+        }
+    }
+
+    /** Handles the creation of 
+     * 
+     * @param address
+     * @param attribute
+     * @param moduleTypeValue
+     * @return
+     */
+    public static Operation createAddModuleOptionTypeOperation(Address address, String attribute,
+        List<Value> moduleTypeValue) {
+        Operation add = null;
+        if ((address != null) & (attribute != null) & (moduleTypeValue != null)) {
+            add = new Operation("add", address);
+            add.addAdditionalProperty(attribute, moduleTypeValue);
+        }
+        return add;
+    }
+}
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ModuleOptionsDiscoveryComponent.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ModuleOptionsDiscoveryComponent.java
new file mode 100644
index 0000000..619d7d5
--- /dev/null
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ModuleOptionsDiscoveryComponent.java
@@ -0,0 +1,188 @@
+package org.rhq.modules.plugins.jbossas7;
+
+import java.util.HashSet;
+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.configuration.Configuration;
+import org.rhq.core.domain.configuration.PropertySimple;
+import org.rhq.core.pluginapi.inventory.DiscoveredResourceDetails;
+import org.rhq.core.pluginapi.inventory.InvalidPluginConfigurationException;
+import org.rhq.core.pluginapi.inventory.ResourceDiscoveryComponent;
+import org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext;
+import org.rhq.modules.plugins.jbossas7.ModuleOptionsComponent.Value;
+import org.rhq.modules.plugins.jbossas7.json.Address;
+import org.rhq.modules.plugins.jbossas7.json.ReadAttribute;
+import org.rhq.modules.plugins.jbossas7.json.ReadChildrenNames;
+import org.rhq.modules.plugins.jbossas7.json.ReadResource;
+import org.rhq.modules.plugins.jbossas7.json.Result;
+
+/**
+ * Discovery class for Module Options nodes. 
+ * 
+ * @author Simeon Pinder
+ */
+public class ModuleOptionsDiscoveryComponent implements ResourceDiscoveryComponent<BaseComponent<?>> {
+
+    private final Log log = LogFactory.getLog(this.getClass());
+
+    @Override
+    public Set<DiscoveredResourceDetails> discoverResources(ResourceDiscoveryContext<BaseComponent<?>> context)
+        throws InvalidPluginConfigurationException, Exception {
+
+        Set<DiscoveredResourceDetails> details = new HashSet<DiscoveredResourceDetails>();
+
+        BaseComponent parentComponent = context.getParentResourceComponent();
+        ASConnection connection = parentComponent.getASConnection();
+
+        Configuration config = context.getDefaultPluginConfiguration();
+        String confPath = config.getSimpleValue("path", "");
+        if (confPath == null || confPath.isEmpty()) {
+            log.error("Path plugin config is null for ResourceType [" + context.getResourceType().getName() + "].");
+            return details;
+        }
+
+        //locate parent component identifier via path
+        Configuration configParent = parentComponent.pluginConfiguration;
+        String parentConfPath = configParent.getSimpleValue("path", "");
+
+        //create relevant path and address details.
+        String path = confPath;//Ex. subsystem=security
+        //processing to retrieve parent for profile/domain mode.
+        if ((parentConfPath != null) && (!parentConfPath.isEmpty())) {
+            path = parentConfPath + "," + confPath;//Ex. profile=standalone-ha,subsystem=security
+        }
+
+        String name = "";//name=security
+        Address address = new Address(path);
+
+        //process the specific nodes
+        //Then we need to find out which of subchildren of ModOpsComponent is used i)security-domain=*
+        //ii)[Authentication*,etc] or iii)[ModOptions]
+
+        //path should already be right
+        if (path.endsWith("security-domain")) {//individual security domain entries
+            //ex. path => /subsystem=security/security-domain=(entry name)
+            //find all children and iterate over and update name appropriately
+            Address typeAddress = new Address(path);
+            String childType = "security-domain";
+            Result result = connection.execute(new ReadChildrenNames(typeAddress, childType));
+
+            if (result.isSuccess()) {
+
+                @SuppressWarnings("unchecked")
+                List<String> children = (List<String>) result.getResult();
+                for (String child : children) {
+                    //update the components for discovery
+                    name = child;//ex. basic, databaseDomain
+                    String currentChildPath = path + //ex. /subsystem=security,security-domain=jboss-web
+                        "=" + child;
+                    address = new Address(currentChildPath);
+                    addDiscoveredResource(context, details, connection, currentChildPath, name, address);
+                }
+            }
+        } else if (ifResourceIsSupportedModuleType(path)) {//is ModOptions map child
+            //ex. path => /subsystem=security/security-domain=(entry name)/authentication=classic/login-modules
+            //Ex. String attribute = "login-modules";
+            String attribute = lookupAttributeType(path);
+            //query all the module-options defined and discover them here
+            //Ex. String typeAddress = "subsystem=security,security-domain=testDomain2,authentication=classic";
+            String typeAddress = parentConfPath;
+            ReadAttribute readModuleOptionType = new ReadAttribute(new Address(typeAddress), attribute);
+            Result result = connection.execute(readModuleOptionType);
+            if (result.isSuccess()) {
+                List<Value> loadedLoginModuleTypes = ModuleOptionsComponent.populateSecurityDomainModuleOptions(result,
+                    ModuleOptionsComponent.loadModuleOptionType(attribute));
+                int moduleIndex = 0;
+                for (Value loginModule : loadedLoginModuleTypes) {
+                    //Ex. name = "Login Module " + moduleIndex;
+                    name = ModuleOptionsComponent.ModuleOptionType.readableNameMap.get(attribute) + " " + moduleIndex;
+                    //Ex. subsystem=security,security-domain=testDomain2,authentication=classic,login-modules:0
+                    String currentPath = path + ":" + moduleIndex++;
+                    //add the discovered resource
+                    addDiscoveredResource(context, details, connection, currentPath, name, address);
+                }
+            }
+        } else if (path.endsWith("module-options")) {//is ModOptions map child
+            //ex. path => /subsystem=security/security-domain=(entry name)/acl=classic/login-modules*module-options
+            //update name appropriately
+            name = "Module Options";
+            //add the discovered resource
+            addDiscoveredResource(context, details, connection, path, name, address);
+        } else {//[Authentication*,etc] children aka all others.
+                //ex. path => /subsystem=security/security-domain=(entry name)/authentication=classic
+                //update name appropriately
+            name = context.getResourceType().getName();//Authentication (Classic).  Singletons.
+            //add the discovered resource
+            addDiscoveredResource(context, details, connection, path, name, address);
+        }
+        return details;
+    }
+
+    private String lookupAttributeType(String path) {
+        String attribute = null;
+        if ((path != null) && (!path.trim().isEmpty())) {
+            //Ex. subsystem=security,security-domain=testDomain2,authentication=classic,login-modules
+            String[] segments = path.split(",");
+            //contents of last segment should be the 'attribute' value of one of the ModuleOptionTypes
+            if (segments.length > 1) {
+                String last = segments[segments.length - 1];
+                if (ModuleOptionsComponent.ModuleOptionType.typeMap.keySet().contains(last)) {
+                    attribute = last;
+                }
+            }
+        }
+        return attribute;
+    }
+
+    private boolean ifResourceIsSupportedModuleType(String path) {
+        boolean resourceIsSupported =false;
+        if ((path != null) && (!path.trim().isEmpty())) {
+            //Ex. subsystem=security,security-domain=testDomain2,authentication=classic,login-modules
+           String[] segments = path.split(",");
+           //contents of last segment should be the 'attribute' value of one of the ModuleOptionTypes
+            if (segments.length > 1) {
+                String last = segments[segments.length - 1];
+                if (ModuleOptionsComponent.ModuleOptionType.typeMap.keySet().contains(last)) {
+                    resourceIsSupported = true;
+                }
+            }
+        }
+        return resourceIsSupported;
+    }
+
+    /** Adds discovered resource.
+     * 
+     * @param context
+     * @param details
+     * @param connection
+     * @param path
+     * @param name
+     * @param address
+     */
+    private void addDiscoveredResource(ResourceDiscoveryContext context, Set<DiscoveredResourceDetails> details,
+        ASConnection connection, String path, String name, Address address) {
+        //ping the resource to determine if it's enabled and available.
+        ReadResource op = new ReadResource(address);
+        Result result = connection.execute(op);
+        if (result.isSuccess()) {
+
+            //include the config entry for the discovered node.
+            Configuration config2 = context.getDefaultPluginConfiguration();
+            //add path component to config as well.
+            PropertySimple pathProp = new PropertySimple("path", path);
+            config2.put(pathProp);
+
+            DiscoveredResourceDetails detail = new DiscoveredResourceDetails(context.getResourceType(), // DataType
+                path, // Key
+                name, // Name
+                null, // Version
+                context.getResourceType().getDescription(), // Description
+                config2, null);
+            details.add(detail);
+        }
+    }
+}
diff --git a/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml
index 956eed8..ecbaea2 100644
--- a/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml
@@ -768,6 +768,60 @@
       </resource-configuration>
 '>
 
+    <!ENTITY loginModuleResourceConfig '
+      <resource-configuration>
+             <c:simple-property name="code" required="true" type="string" readOnly="true"
+              description="Class name of the module to be instantiated.">
+                <c:property-options>
+                  <c:option value="AdvancedADLdap" />
+                  <c:option value="AdvancedLdap" />
+                  <c:option value="Certificate" />
+                  <c:option value="CertificateRoles" />
+                  <c:option value="CertificateUsers" />
+                  <c:option value="Client" />
+                  <c:option value="ConfigureIdentity" />
+                  <c:option value="Database" />
+                  <c:option value="DatabaseCertificate" />
+                  <c:option value="DatabaseUsers" />
+                  <c:option value="Identity" />
+                  <c:option value="Kerberos" />
+                  <c:option value="Ldap" />
+                  <c:option value="LdapExtended" />
+                  <c:option value="LdapUsers" />
+                  <c:option value="PropertiesUsers" />
+                  <c:option value="RoleMapping" />
+                  <c:option value="RunAs" />
+                  <c:option value="Simple" />
+                  <c:option value="SimpleUsers" />
+                  <c:option value="SPNEGOUsers" />
+                  <c:option value="UsersRoles" />
+                </c:property-options>
+              </c:simple-property>
+            <c:simple-property name="flag" required="true" type="string" readOnly="false" description="The flag controls how the module participates in the overall procedure. Allowed values are requisite, required, sufficient or optional.">
+              <c:property-options>
+                <c:option value="optional"/>
+                <c:option value="required"/>
+                <c:option value="requisite"/>
+                <c:option value="sufficient"/>
+              </c:property-options>
+            </c:simple-property>
+      </resource-configuration>
+'>
+
+    <!ENTITY flagModuleResourceConfig '
+	<resource-configuration>
+            <c:simple-property name="code" required="true" type="string" readOnly="false" description="Class name of the module to be instantiated."/>
+            <c:simple-property name="flag" required="true" type="string" readOnly="false" description="The flag controls how the module participates in the overall procedure. Allowed values are requisite, required, sufficient or optional.">
+              <c:property-options>
+                <c:option value="optional"/>
+                <c:option value="required"/>
+                <c:option value="requisite"/>
+                <c:option value="sufficient"/>
+              </c:property-options>
+            </c:simple-property>
+        </resource-configuration>
+'>
+
     ]>
 <plugin name="&pluginName;"
         displayName="JBoss Application Server 7.x"
@@ -3095,272 +3149,306 @@
          </c:simple-property>
         </resource-configuration>
 
-        <service name="ACL (Managed Server)"
-                 discovery="SubsystemDiscovery"
-                 class="BaseComponent"
-                 singleton="true">
+  <service name="ACL (Managed Server)" discovery="ModuleOptionsDiscoveryComponent" class="ModuleOptionsComponent"
+    singleton="true">
 
-          <plugin-configuration>
-            <c:simple-property name="path" readOnly="true" default="acl=classic"/>
-          </plugin-configuration>
+    <plugin-configuration>
+      <c:simple-property name="path" readOnly="true" default="acl=classic" />
+    </plugin-configuration>
 
-          <resource-configuration>
-            <c:list-property name="acl-modules" required="false" description="List of acl modules">
-              <c:map-property name="*" required="false">
-                <c:simple-property name="code" required="true" type="string" readOnly="true" description="Class name of the module to be instantiated."/>
-                <c:simple-property name="flag" required="true" type="string" readOnly="true" description="The flag controls how the module participates in the overall procedure. Allowed values are requisite, required, sufficient or optional.">
-                  <c:property-options>
-                    <c:option value="sufficient"/>
-                    <c:option value="requisite"/>
-                    <c:option value="optional"/>
-                    <c:option value="required"/>
-                  </c:property-options>
-                </c:simple-property>
-                <c:simple-property name="module" required="false" type="string" readOnly="true" description="Name of JBoss Module where the acl provider module code is located."/>
-                <c:simple-property name="module-options" required="false" type="string" readOnly="true" description="List of module options containing a name/value pair."/>
-              </c:map-property>
-            </c:list-property>
-          </resource-configuration>
-        </service>
+		&flagModuleResourceConfig;
+    <service name="Acl Modules (Managed Server)" discovery="ModuleOptionsDiscoveryComponent" class="ModuleOptionsComponent"
+      createDeletePolicy="both">
 
-        <service name="Audit (Managed Server)"
-                 discovery="SubsystemDiscovery"
-                 class="BaseComponent"
-                 singleton="true">
+      <plugin-configuration>
+        <c:simple-property name="path" readOnly="true" default="acl-modules" />
+      </plugin-configuration>
+		      &flagModuleResourceConfig;
 
-          <plugin-configuration>
-            <c:simple-property name="path" readOnly="true" default="audit=classic"/>
-          </plugin-configuration>
+      <service name="Module Options (Acl - Managed Server)" discovery="ModuleOptionsDiscoveryComponent" class="ModuleOptionsComponent"
+        singleton="true">
 
-          <resource-configuration>
-            <c:list-property name="provider-modules" required="false" description="List of provider modules">
-               <c:map-property name="*" required="false">
-                <c:simple-property name="code" required="true" type="string" readOnly="true" description="Class name of the module to be instantiated."/>
-                <c:simple-property name="module-options" required="false" type="string" readOnly="true" description="List of module options containing a name/value pair."/>
-              </c:map-property>
-            </c:list-property>
-          </resource-configuration>
-        </service>
+        <plugin-configuration>
+          <c:simple-property name="path" readOnly="true" default="module-options" />
+        </plugin-configuration>
 
-        <service name="Authentication (Classic - Managed Server)"
-                 discovery="SubsystemDiscovery"
-                 class="BaseComponent"
-                 singleton="true">
+        <resource-configuration>
+          <c:map-property name="Module Options" required="false" />
+        </resource-configuration>
+      </service><!-- End of Module Options (Acl - Managed Server) -->
+    </service><!-- End of Acl Modules (Managed Server) -->
+  </service>
 
-          <plugin-configuration>
-            <c:simple-property name="path" readOnly="true" default="authentication=classic"/>
-          </plugin-configuration>
+  <service name="Audit (Managed Server)" discovery="ModuleOptionsDiscoveryComponent" class="ModuleOptionsComponent"
+    singleton="true">
 
-          <resource-configuration>
-            <c:list-property name="login-modules" required="false" description="List of authentication modules">
-              <c:map-property name="*" required="false">
-               <c:simple-property name="code" required="true" type="string" readOnly="true"
-                description="Class name of the module to be instantiated.">
-                  <c:property-options>
-                    <c:option value="AdvancedADLdap" />
-                    <c:option value="AdvancedLdap" />
-                    <c:option value="Certificate" />
-                    <c:option value="CertificateRoles" />
-                    <c:option value="Client" />
-                    <c:option value="Database" />
-                    <c:option value="DatabaseCertificate" />
-                    <c:option value="DatabaseUsers" />
-                    <c:option value="Identity" />
-                    <c:option value="Kerberos" />
-                    <c:option value="Ldap" />
-                    <c:option value="LdapExtended" />
-                    <c:option value="RoleMapping" />
-                    <c:option value="Simple" />
-                    <c:option value="SPNEGOUsers" />
-                    <c:option value="UserRoles" />
-                  </c:property-options>
-                </c:simple-property>
-                <c:simple-property name="flag" required="true" type="string" readOnly="true" description="The flag controls how the module participates in the overall procedure. Allowed values are requisite, required, sufficient or optional.">
-                  <c:property-options>
-                    <c:option value="sufficient"/>
-                    <c:option value="requisite"/>
-                    <c:option value="optional"/>
-                    <c:option value="required"/>
-                  </c:property-options>
-                </c:simple-property>
-                <c:simple-property name="module" required="false" type="string" readOnly="true" description="Name of JBoss Module where the login module code is located."/>
-                <c:simple-property name="module-options" required="false" type="string" readOnly="true" description="List of module options containing a name/value pair."/>
-              </c:map-property>
-            </c:list-property>
-          </resource-configuration>
-        </service>
+    <plugin-configuration>
+      <c:simple-property name="path" readOnly="true" default="audit=classic" />
+    </plugin-configuration>
 
-        <service name="Authentication (Jaspi - Managed Server)"
-                 discovery="SubsystemDiscovery"
-                 class="BaseComponent"
-                 singleton="true">
+    <resource-configuration>
+      <c:simple-property name="code" required="true" type="string" readOnly="false"
+        description="Class name of the module to be instantiated." />
+    </resource-configuration>
+    <service name="Provider Modules (Managed Server)" discovery="ModuleOptionsDiscoveryComponent" class="ModuleOptionsComponent"
+      createDeletePolicy="both">
 
-          <plugin-configuration>
-              <c:simple-property name="path" readOnly="true" default="authentication=jaspi"/>
-          </plugin-configuration>
+      <plugin-configuration>
+        <c:simple-property name="path" readOnly="true" default="provider-modules" />
+      </plugin-configuration>
+      <resource-configuration>
+        <c:simple-property name="code" required="true" type="string" readOnly="false"
+          description="Class name of the module to be instantiated." />
+      </resource-configuration>
 
-          <resource-configuration>
-            <c:list-property name="auth-modules" required="true" description="List of authentication modules to be used." >
-                  <c:map-property name="*" required="false">
-                <c:simple-property name="code" required="true" type="string" readOnly="true" description="Class name of the module to be instantiated."/>
-                <c:simple-property name="flag" required="true" type="string" readOnly="true" description="The flag controls how the module participates in the overall procedure. Allowed values are requisite, required, sufficient or optional.">
-                  <c:property-options>
-                    <c:option value="sufficient"/>
-                    <c:option value="requisite"/>
-                    <c:option value="optional"/>
-                    <c:option value="required"/>
-                  </c:property-options>
-                </c:simple-property>
-                <c:simple-property name="module" required="false" type="string" readOnly="true" description="Name of JBoss Module where the auth module code is located."/>
-                <c:simple-property name="module-options" required="false" type="string" readOnly="true" description="List of module options containing a name/value pair."/>
-                <c:simple-property name="login-module-stack-ref" required="false" type="string" readOnly="true" description="Reference to a login module stack name previously configured in the same security domain."/>
-              </c:map-property>
-            </c:list-property>
-          </resource-configuration>
+      <service name="Module Options (Provider Modules - Managed Server)" discovery="ModuleOptionsDiscoveryComponent"
+        class="ModuleOptionsComponent" singleton="true">
 
-          <service name="Login Module Stack (Managed Server)"
-                   discovery="SubsystemDiscovery"
-                   class="BaseComponent">
+        <plugin-configuration>
+          <c:simple-property name="path" readOnly="true" default="module-options" />
+        </plugin-configuration>
 
-              <plugin-configuration>
-                  <c:simple-property name="path" readOnly="true" default="login-module-stack"/>
-              </plugin-configuration>
+        <resource-configuration>
+          <c:map-property name="Module Options" required="false" />
+        </resource-configuration>
+      </service><!-- End of Module Options (Provider Modules - Managed Server) -->
+    </service><!-- End of Provider Modules - Managed Server -->
+  </service>
 
-            <resource-configuration>
-              <c:list-property name="login-modules" required="true" description="List of authentication modules" >
-                <c:map-property name="*" required="false">
-                  <c:simple-property name="code" required="true" type="string" readOnly="true" description="Class name of the module to be instantiated."/>
-                  <c:simple-property name="flag" required="true" type="string" readOnly="true" description="The flag controls how the module participates in the overall procedure. Allowed values are requisite, required, sufficient or optional.">
-                    <c:property-options>
-                      <c:option value="sufficient"/>
-                      <c:option value="requisite"/>
-                      <c:option value="optional"/>
-                      <c:option value="required"/>
-                    </c:property-options>
-                  </c:simple-property>
-                  <c:simple-property name="module" required="false" type="string" readOnly="true" description="Name of JBoss Module where the login module code is located."/>
-                  <c:simple-property name="module-options" required="false" type="string" readOnly="true" description="List of module options containing a name/value pair."/>
-                </c:map-property>
-              </c:list-property>
-            </resource-configuration>
-          </service>
-        </service>
+  <service name="Authentication (Classic - Managed Server)" discovery="ModuleOptionsDiscoveryComponent" class="ModuleOptionsComponent"
+    singleton="true">
 
-        <service name="Authorization (Managed Server)"
-                 discovery="SubsystemDiscovery"
-                 class="BaseComponent"
-                 singleton="true">
+    <plugin-configuration>
+      <c:simple-property name="path" readOnly="true" default="authentication=classic" />
+    </plugin-configuration>
 
-          <plugin-configuration>
-            <c:simple-property name="path" readOnly="true" default="authorization=classic"/>
-          </plugin-configuration>
+    <service name="Login Modules (Classic - Managed Server)" discovery="ModuleOptionsDiscoveryComponent" class="ModuleOptionsComponent"
+      createDeletePolicy="both">
 
-          <resource-configuration>
-            <c:list-property name="policy-modules" required="false" description="List of authorization modules">
-                <c:map-property name="*" required="false">
-                  <c:simple-property name="code" required="true" type="string" readOnly="true" description="Class name of the module to be instantiated."/>
-                  <c:simple-property name="flag" required="true" type="string" readOnly="true" description="The flag controls how the module participates in the overall procedure. Allowed values are requisite, required, sufficient or optional.">
-                    <c:property-options>
-                      <c:option value="sufficient"/>
-                      <c:option value="requisite"/>
-                      <c:option value="optional"/>
-                      <c:option value="required"/>
-                    </c:property-options>
-                  </c:simple-property>
-                  <c:simple-property name="module" required="false" type="string" readOnly="true" description="Name of JBoss Module where the policy module code is located."/>
-                  <c:simple-property name="module-options" required="false" type="string" readOnly="true" description="List of module options containing a name/value pair."/>
-                </c:map-property>
-            </c:list-property>
-          </resource-configuration>
-        </service>
+      <plugin-configuration>
+        <c:simple-property name="path" readOnly="true" default="login-modules" />
+      </plugin-configuration>
+      
+            &loginModuleResourceConfig;
 
-        <service name="Identity Trust (Managed Server)"
-                 discovery="SubsystemDiscovery"
-                 class="BaseComponent"
-                 singleton="true">
+      <service name="Module Options (Classic - Managed Server)" discovery="ModuleOptionsDiscoveryComponent"
+        class="ModuleOptionsComponent" singleton="true">
 
-          <plugin-configuration>
-            <c:simple-property name="path" readOnly="true" default="identity-trust=classic"/>
-          </plugin-configuration>
+        <plugin-configuration>
+          <c:simple-property name="path" readOnly="true" default="module-options" />
+        </plugin-configuration>
 
-          <resource-configuration>
-            <c:list-property name="trust-modules" required="false" description="List of trust modules">
-              <c:map-property name="*" required="false">
-                <c:simple-property name="code" required="true" type="string" readOnly="true" description="Class name of the module to be instantiated."/>
-                <c:simple-property name="flag" required="true" type="string" readOnly="true" description="The flag controls how the module participates in the overall procedure. Allowed values are requisite, required, sufficient or optional.">
-                  <c:property-options>
-                    <c:option value="sufficient"/>
-                    <c:option value="requisite"/>
-                    <c:option value="optional"/>
-                    <c:option value="required"/>
-                  </c:property-options>
-                </c:simple-property>
-                <c:simple-property name="module" required="false" type="string" readOnly="true" description="Name of JBoss Module where the identity trust module code is located."/>
-                <c:simple-property name="module-options" required="false" type="string" readOnly="true" description="List of module options containing a name/value pair."/>
-              </c:map-property>
-            </c:list-property>
-          </resource-configuration>
-        </service>
+        <resource-configuration>
+          <c:map-property name="Module Options" required="false" />
+        </resource-configuration>
+      </service><!-- End of Module Options -->
+    </service><!-- End of Login Modules (Classic - Managed Server) -->
+  </service><!-- End of Authentication (Classic - Managed Server) -->
 
-        <service name="JSSE (Managed Server)"
-                 discovery="SubsystemDiscovery"
-                 class="BaseComponent">
+  <service name="Authentication (Jaspi - Managed Server)" discovery="ModuleOptionsDiscoveryComponent" class="ModuleOptionsComponent"
+    singleton="true">
 
-          <plugin-configuration>
-            <c:simple-property name="path" readOnly="true" default="jsse"/>
-          </plugin-configuration>
+    <plugin-configuration>
+      <c:simple-property name="path" readOnly="true" default="authentication=jaspi" />
+    </plugin-configuration>
 
-          <resource-configuration>
-            <c:simple-property name="cipher-suites" required="false" type="string" readOnly="true" description="Comma separated list of cipher suites to enable on SSLSockets."/>
-            <c:simple-property name="client-alias" required="false" type="string" readOnly="true" description="Preferred alias to use when the KeyManager chooses the client alias."/>
-            <c:simple-property name="client-auth" required="false" type="boolean" readOnly="true" description="Boolean attribute to indicate if client&apos;s certificates should also be authenticated on the server side."/>
-            <c:map-property name="key-manager" required="false" description="JSEE Key Manager factory">
-              <c:simple-property name="algorithm" required="false" type="string" readOnly="true" description="Algorithm to use when creating the KeyManagerFactory."/>
-              <c:simple-property name="provider" required="false" type="string" readOnly="true" description="Provider class name to use when creating the KeyManagerFactory."/>
-            </c:map-property>
-            <c:map-property name="keystore" required="false" description="Configures a JSSE key store">
-              <c:simple-property name="password" required="false" type="string" readOnly="true" description="Sets the password of the keystore. Either this or &apos;truststore&#45;password&apos; must be present otherwise the security domain will be useless."/>
-              <c:simple-property name="type" required="false" type="string" readOnly="true" description="Type of the keystore. If not set, type defaults to &apos;JKS&apos;."/>
-              <c:simple-property name="url" required="false" type="string" readOnly="true" description="URL of the keystore."/>
-              <c:simple-property name="provider" required="false" type="string" readOnly="true" description="Provider class name to use when creating the KeyStore."/>
-              <c:simple-property name="provider-argument" required="false" type="string" readOnly="true" description="String argument to pass to the keystore Provider constructor when instantiating it."/>
-            </c:map-property>
-            <c:simple-property name="protocols" required="false" type="string" readOnly="true" description="Comma separated list of protocols to enable on SSLSockets."/>
-            <c:simple-property name="server-alias" required="false" type="string" readOnly="true" description="Preferred alias to use when the KeyManager chooses the server alias."/>
-            <c:simple-property name="service-auth-token" required="false" type="string" readOnly="true" description="Token to retrieve PrivateKeys from the KeyStore."/>
-            <c:map-property name="trust-manager" required="false" description="JSEE Trust Manager factory">
-              <c:simple-property name="algorithm" required="false" type="string" readOnly="true" description="Algorithm to use when creating the TrustManagerFactory."/>
-              <c:simple-property name="provider" required="false" type="string" readOnly="true" description="Provider class name to use when creating the TrustManagerFactory."/>
-            </c:map-property>
-            <c:map-property name="truststore" required="false" description="Configures a JSSE trust store">
-              <c:simple-property name="password" required="false" type="string" readOnly="true" description="Sets the password of the truststore. Either this or &apos;keystore&#45;password&apos; must be present otherwise the security domain will be useless."/>
-              <c:simple-property name="type" required="false" type="string" readOnly="true" description="Type of the truststore. If not set, type defaults to &apos;JKS&apos;."/>
-              <c:simple-property name="url" required="false" type="string" readOnly="true" description="URL of the truststore."/>
-              <c:simple-property name="provider" required="false" type="string" readOnly="true" description="Provider class name to use when creating the truststore."/>
-              <c:simple-property name="provider-argument" required="false" type="string" readOnly="true" description="String argument to pass to the truststore Provider constructor when instantiating it."/>
-            </c:map-property>
-          </resource-configuration>
-        </service>
+          &loginModuleResourceConfig;
 
-        <service name="Mapping (Managed Server)"
-                 discovery="SubsystemDiscovery"
-                 class="BaseComponent"
-                 singleton="true">
+    <service name="Login Module Stack (Managed Server)" discovery="ModuleOptionsDiscoveryComponent" class="ModuleOptionsComponent">
 
-          <plugin-configuration>
-            <c:simple-property name="path" readOnly="true" default="mapping=classic"/>
-          </plugin-configuration>
+      <plugin-configuration>
+        <c:simple-property name="path" readOnly="true" default="login-module-stack" />
+      </plugin-configuration>
 
-          <resource-configuration>
-            <c:list-property name="mapping-modules" required="false" description="List of modules that map principal, role, and credential information">
-              <c:map-property name="*" required="false">
-                <c:simple-property name="code" required="true" type="string" readOnly="true" description="Class name of the module to be instantiated."/>
-                <c:simple-property name="type" required="true" type="string" readOnly="true" description="Type of mapping this module performs. Allowed values are principal, role, attribute or credential.."/>
-                <c:simple-property name="module-options" required="false" type="string" readOnly="true" description="List of module options containing a name/value pair."/>
-              </c:map-property>
-            </c:list-property>
-          </resource-configuration>
-        </service>
+	      &loginModuleResourceConfig;
+
+      <service name="Module Options (Login Module Stack (Managed Server))" discovery="ModuleOptionsDiscoveryComponent"
+        class="ModuleOptionsComponent" singleton="true">
+
+        <plugin-configuration>
+          <c:simple-property name="path" readOnly="true" default="module-options" />
+        </plugin-configuration>
+
+        <resource-configuration>
+          <c:map-property name="Module Options" required="false" />
+        </resource-configuration>
+      </service><!-- End of Module Options -->
+
+    </service>
+  </service>
+
+  <service name="Authorization (Managed Server)" discovery="ModuleOptionsDiscoveryComponent" class="ModuleOptionsComponent"
+    singleton="true">
+
+    <plugin-configuration>
+      <c:simple-property name="path" readOnly="true" default="authorization=classic" />
+    </plugin-configuration>
+
+	  &flagModuleResourceConfig;
+
+    <service name="Authorization Modules (Managed Server)" discovery="ModuleOptionsDiscoveryComponent" class="ModuleOptionsComponent"
+      createDeletePolicy="both">
+
+      <plugin-configuration>
+        <c:simple-property name="path" readOnly="true" default="policy-modules" />
+      </plugin-configuration>
+
+			&flagModuleResourceConfig;
+
+      <service name="Module Options (Authorization - Managed Server)" discovery="ModuleOptionsDiscoveryComponent"
+        class="ModuleOptionsComponent" singleton="true">
+
+        <plugin-configuration>
+          <c:simple-property name="path" readOnly="true" default="module-options" />
+        </plugin-configuration>
+
+        <resource-configuration>
+          <c:map-property name="Module Options" required="false" />
+        </resource-configuration>
+      </service><!-- End of Module Options (Authorization - Managed Server) -->
+    </service><!-- End of Authorization Modules (Managed Server) -->
+  </service>
+
+  <service name="Identity Trust (Managed Server)" discovery="ModuleOptionsDiscoveryComponent" class="ModuleOptionsComponent"
+    singleton="true">
+
+    <plugin-configuration>
+      <c:simple-property name="path" readOnly="true" default="identity-trust=classic" />
+    </plugin-configuration>
+
+	  &flagModuleResourceConfig;
+    <service name="Identity Trust Modules (Managed Server)" discovery="ModuleOptionsDiscoveryComponent" class="ModuleOptionsComponent"
+      createDeletePolicy="both">
+
+      <plugin-configuration>
+        <c:simple-property name="path" readOnly="true" default="trust-modules" />
+      </plugin-configuration>
+
+		      &flagModuleResourceConfig;
+
+      <service name="Module Options (Identity Trust - Managed Server)" discovery="ModuleOptionsDiscoveryComponent"
+        class="ModuleOptionsComponent" singleton="true">
+
+        <plugin-configuration>
+          <c:simple-property name="path" readOnly="true" default="module-options" />
+        </plugin-configuration>
+
+        <resource-configuration>
+          <c:map-property name="Module Options" required="false" />
+        </resource-configuration>
+      </service><!-- End of Module Options (Identity Trust - Managed Server) -->
+    </service><!-- End of Identity Trust Modules (Managed Server) -->
+  </service>
+
+  <service name="JSSE (Managed Server)" discovery="SubsystemDiscovery" class="BaseComponent">
+
+    <plugin-configuration>
+      <c:simple-property name="path" readOnly="true" default="jsse" />
+    </plugin-configuration>
+
+    <resource-configuration>
+      <c:simple-property name="cipher-suites" required="false" type="string" readOnly="true"
+        description="Comma separated list of cipher suites to enable on SSLSockets." />
+      <c:simple-property name="client-alias" required="false" type="string" readOnly="true"
+        description="Preferred alias to use when the KeyManager chooses the client alias." />
+      <c:simple-property name="client-auth" required="false" type="boolean" readOnly="true"
+        description="Boolean attribute to indicate if client&apos;s certificates should also be authenticated on the server side." />
+      <c:map-property name="key-manager" required="false" description="JSEE Key Manager factory">
+        <c:simple-property name="algorithm" required="false" type="string" readOnly="true"
+          description="Algorithm to use when creating the KeyManagerFactory." />
+        <c:simple-property name="provider" required="false" type="string" readOnly="true"
+          description="Provider class name to use when creating the KeyManagerFactory." />
+      </c:map-property>
+      <c:map-property name="keystore" required="false" description="Configures a JSSE key store">
+        <c:simple-property name="password" required="false" type="string" readOnly="true"
+          description="Sets the password of the keystore. Either this or &apos;truststore&#45;password&apos; must be present otherwise the security domain will be useless." />
+        <c:simple-property name="type" required="false" type="string" readOnly="true"
+          description="Type of the keystore. If not set, type defaults to &apos;JKS&apos;." />
+        <c:simple-property name="url" required="false" type="string" readOnly="true" description="URL of the keystore." />
+        <c:simple-property name="provider" required="false" type="string" readOnly="true"
+          description="Provider class name to use when creating the KeyStore." />
+        <c:simple-property name="provider-argument" required="false" type="string" readOnly="true"
+          description="String argument to pass to the keystore Provider constructor when instantiating it." />
+      </c:map-property>
+      <c:simple-property name="protocols" required="false" type="string" readOnly="true"
+        description="Comma separated list of protocols to enable on SSLSockets." />
+      <c:simple-property name="server-alias" required="false" type="string" readOnly="true"
+        description="Preferred alias to use when the KeyManager chooses the server alias." />
+      <c:simple-property name="service-auth-token" required="false" type="string" readOnly="true"
+        description="Token to retrieve PrivateKeys from the KeyStore." />
+      <c:map-property name="trust-manager" required="false" description="JSEE Trust Manager factory">
+        <c:simple-property name="algorithm" required="false" type="string" readOnly="true"
+          description="Algorithm to use when creating the TrustManagerFactory." />
+        <c:simple-property name="provider" required="false" type="string" readOnly="true"
+          description="Provider class name to use when creating the TrustManagerFactory." />
+      </c:map-property>
+      <c:map-property name="truststore" required="false" description="Configures a JSSE trust store">
+        <c:simple-property name="password" required="false" type="string" readOnly="true"
+          description="Sets the password of the truststore. Either this or &apos;keystore&#45;password&apos; must be present otherwise the security domain will be useless." />
+        <c:simple-property name="type" required="false" type="string" readOnly="true"
+          description="Type of the truststore. If not set, type defaults to &apos;JKS&apos;." />
+        <c:simple-property name="url" required="false" type="string" readOnly="true" description="URL of the truststore." />
+        <c:simple-property name="provider" required="false" type="string" readOnly="true"
+          description="Provider class name to use when creating the truststore." />
+        <c:simple-property name="provider-argument" required="false" type="string" readOnly="true"
+          description="String argument to pass to the truststore Provider constructor when instantiating it." />
+      </c:map-property>
+    </resource-configuration>
+  </service>
+
+  <service name="Mapping (Managed Server)" discovery="ModuleOptionsDiscoveryComponent" class="ModuleOptionsComponent"
+    singleton="true">
+
+    <plugin-configuration>
+      <c:simple-property name="path" readOnly="true" default="mapping=classic" />
+    </plugin-configuration>
+
+    <resource-configuration>
+      <c:simple-property name="code" required="true" type="string" readOnly="false"
+        description="Class name of the module to be instantiated." />
+      <c:simple-property name="type" required="true" type="string" readOnly="false"
+        description="Type of mapping this module performs. Allowed values are principal, role, attribute or credential..">
+        <c:property-options>
+          <c:option value="attribute" />
+          <c:option value="credential" />
+          <c:option value="principal" />
+          <c:option value="role" />
+        </c:property-options>
+      </c:simple-property>
+    </resource-configuration>
+    <service name="Mapping Modules (Managed Server)" discovery="ModuleOptionsDiscoveryComponent" class="ModuleOptionsComponent"
+      createDeletePolicy="both">
+
+      <plugin-configuration>
+        <c:simple-property name="path" readOnly="true" default="mapping-modules" />
+      </plugin-configuration>
+      <resource-configuration>
+        <c:simple-property name="code" required="true" type="string" readOnly="false"
+          description="Class name of the module to be instantiated." />
+        <c:simple-property name="type" required="true" type="string" readOnly="false"
+          description="Type of mapping this module performs. Allowed values are principal, role, attribute or credential..">
+          <c:property-options>
+            <c:option value="attribute" />
+            <c:option value="credential" />
+            <c:option value="principal" />
+            <c:option value="role" />
+          </c:property-options>
+        </c:simple-property>
+      </resource-configuration>
+
+      <service name="Module Options (Mapping - Managed Server)" discovery="ModuleOptionsDiscoveryComponent"
+        class="ModuleOptionsComponent" singleton="true">
+
+        <plugin-configuration>
+          <c:simple-property name="path" readOnly="true" default="module-options" />
+        </plugin-configuration>
+
+        <resource-configuration>
+          <c:map-property name="Module Options" required="false" />
+        </resource-configuration>
+      </service><!-- End of Module Options (Mapping - Managed Server) -->
+    </service><!-- End of Mapping Modules (Managed Server) -->
+  </service>
       </service>
 
       <service name="Vault (Managed Server)"
@@ -5863,8 +5951,8 @@
     </service>
 
     <service name="Security (Profile)"
-             discovery="SubsystemDiscovery"
-             class="BaseComponent"
+             discovery="ModuleOptionsDiscoveryComponent"
+             class="ModuleOptionsComponent"
              description="The configuration of the security subsystem."
              singleton="true">
 
@@ -5877,8 +5965,8 @@
       </resource-configuration>
 
       <service name="Security Domain (Profile)"
-               discovery="SubsystemDiscovery"
-               class="BaseComponent"
+               discovery="ModuleOptionsDiscoveryComponent"
+               class="ModuleOptionsComponent"
                createDeletePolicy="both">
 
         <plugin-configuration>
@@ -5894,281 +5982,305 @@
          </c:simple-property>
         </resource-configuration>
 
-        <service name="ACL (Profile)"
-                 discovery="SubsystemDiscovery"
-                 class="BaseComponent"
-                 singleton="true"
-                 createDeletePolicy="both">
+  <service name="ACL (Profile)" discovery="ModuleOptionsDiscoveryComponent" class="ModuleOptionsComponent"
+    singleton="true" createDeletePolicy="both">
 
-          <plugin-configuration>
-            <c:simple-property name="path" readOnly="true" default="acl=classic"/>
-          </plugin-configuration>
+    <plugin-configuration>
+      <c:simple-property name="path" readOnly="true" default="acl=classic" />
+    </plugin-configuration>
 
-          <resource-configuration>
-            <c:list-property name="acl-modules" required="false" description="List of acl modules">
-              <c:map-property name="*" required="false">
-                <c:simple-property name="code" required="true" type="string" readOnly="false" description="Class name of the module to be instantiated."/>
-                <c:simple-property name="flag" required="true" type="string" readOnly="false" description="The flag controls how the module participates in the overall procedure. Allowed values are requisite, required, sufficient or optional.">
-                  <c:property-options>
-                    <c:option value="sufficient"/>
-                    <c:option value="requisite"/>
-                    <c:option value="optional"/>
-                    <c:option value="required"/>
-                  </c:property-options>
-                </c:simple-property>
-                <c:simple-property name="module" required="false" type="string" readOnly="false" description="Name of JBoss Module where the acl provider module code is located."/>
-                <c:simple-property name="module-options" required="false" type="string" readOnly="false" description="List of module options containing a name/value pair."/>
-              </c:map-property>
-            </c:list-property>
-          </resource-configuration>
-        </service>
+		&flagModuleResourceConfig;
+    <service name="Acl Modules (Profile)" discovery="ModuleOptionsDiscoveryComponent" class="ModuleOptionsComponent"
+      createDeletePolicy="both">
 
-        <service name="Audit (Profile)"
-                 discovery="SubsystemDiscovery"
-                 class="BaseComponent"
-                 singleton="true"
-                 createDeletePolicy="both">
+      <plugin-configuration>
+        <c:simple-property name="path" readOnly="true" default="acl-modules" />
+      </plugin-configuration>
 
-          <plugin-configuration>
-            <c:simple-property name="path" readOnly="true" default="audit=classic"/>
-          </plugin-configuration>
+		      &flagModuleResourceConfig;
 
-          <resource-configuration>
-            <c:list-property name="provider-modules" required="false" description="List of provider modules">
-               <c:map-property name="*" required="false">
-                <c:simple-property name="code" required="true" type="string" readOnly="false" description="Class name of the module to be instantiated."/>
-                <c:simple-property name="module-options" required="false" type="string" readOnly="false" description="List of module options containing a name/value pair."/>
-              </c:map-property>
-            </c:list-property>
-          </resource-configuration>
-        </service>
+      <service name="Module Options (Acl - Profile)" discovery="ModuleOptionsDiscoveryComponent" class="ModuleOptionsComponent"
+        singleton="true">
 
-        <service name="Authentication (Classic - Profile)"
-                 discovery="SubsystemDiscovery"
-                 class="BaseComponent"
-                 singleton="true"
-                 createDeletePolicy="both">
+        <plugin-configuration>
+          <c:simple-property name="path" readOnly="true" default="module-options" />
+        </plugin-configuration>
 
-          <plugin-configuration>
-            <c:simple-property name="path" readOnly="true" default="authentication=classic"/>
-          </plugin-configuration>
+        <resource-configuration>
+          <c:map-property name="Module Options" required="false" />
+        </resource-configuration>
+      </service><!-- End of Module Options (Acl - Profile) -->
+    </service><!-- End of Acl Modules (Profile) -->
+  </service>
 
-          <resource-configuration>
-            <c:list-property name="login-modules" required="false" description="List of authentication modules">
-              <c:map-property name="*" required="false">
-               <c:simple-property name="code" required="true" type="string" readOnly="true"
-                description="Class name of the module to be instantiated.">
-                  <c:property-options>
-                    <c:option value="AdvancedADLdap" />
-                    <c:option value="AdvancedLdap" />
-                    <c:option value="Certificate" />
-                    <c:option value="CertificateRoles" />
-                    <c:option value="Client" />
-                    <c:option value="Database" />
-                    <c:option value="DatabaseCertificate" />
-                    <c:option value="DatabaseUsers" />
-                    <c:option value="Identity" />
-                    <c:option value="Kerberos" />
-                    <c:option value="Ldap" />
-                    <c:option value="LdapExtended" />
-                    <c:option value="RoleMapping" />
-                    <c:option value="Simple" />
-                    <c:option value="SPNEGOUsers" />
-                    <c:option value="UserRoles" />
-                  </c:property-options>
-                </c:simple-property>
-                <c:simple-property name="flag" required="true" type="string" readOnly="false" description="The flag controls how the module participates in the overall procedure. Allowed values are requisite, required, sufficient or optional.">
-                  <c:property-options>
-                    <c:option value="sufficient"/>
-                    <c:option value="requisite"/>
-                    <c:option value="optional"/>
-                    <c:option value="required"/>
-                  </c:property-options>
-                </c:simple-property>
-                <c:simple-property name="module" required="false" type="string" readOnly="false" description="Name of JBoss Module where the login module code is located."/>
-                <c:simple-property name="module-options" required="false" type="string" readOnly="false" description="List of module options containing a name/value pair."/>
-              </c:map-property>
-            </c:list-property>
-          </resource-configuration>
-        </service>
+  <service name="Audit (Profile)" discovery="ModuleOptionsDiscoveryComponent" class="ModuleOptionsComponent"
+    singleton="true" createDeletePolicy="both">
 
-        <service name="Authentication (Jaspi - Profile)"
-                 discovery="SubsystemDiscovery"
-                 class="BaseComponent"
-                 singleton="true"
-                 createDeletePolicy="both">
+    <plugin-configuration>
+      <c:simple-property name="path" readOnly="true" default="audit=classic" />
+    </plugin-configuration>
 
-          <plugin-configuration>
-              <c:simple-property name="path" readOnly="true" default="authentication=jaspi"/>
-          </plugin-configuration>
+    <resource-configuration>
+      <c:simple-property name="code" required="true" type="string" readOnly="false"
+        description="Class name of the module to be instantiated." />
+    </resource-configuration>
+    <service name="Provider Modules (Profile)" discovery="ModuleOptionsDiscoveryComponent" class="ModuleOptionsComponent"
+      createDeletePolicy="both">
 
-          <resource-configuration>
-            <c:list-property name="auth-modules" required="true" description="List of authentication modules to be used." >
-                  <c:map-property name="*" required="false">
-                <c:simple-property name="code" required="true" type="string" readOnly="false" description="Class name of the module to be instantiated."/>
-                <c:simple-property name="flag" required="true" type="string" readOnly="false" description="The flag controls how the module participates in the overall procedure. Allowed values are requisite, required, sufficient or optional.">
-                  <c:property-options>
-                    <c:option value="sufficient"/>
-                    <c:option value="requisite"/>
-                    <c:option value="optional"/>
-                    <c:option value="required"/>
-                  </c:property-options>
-                </c:simple-property>
-                <c:simple-property name="module" required="false" type="string" readOnly="false" description="Name of JBoss Module where the auth module code is located."/>
-                <c:simple-property name="module-options" required="false" type="string" readOnly="false" description="List of module options containing a name/value pair."/>
-                <c:simple-property name="login-module-stack-ref" required="false" type="string" readOnly="false" description="Reference to a login module stack name previously configured in the same security domain."/>
-              </c:map-property>
-            </c:list-property>
-          </resource-configuration>
+      <plugin-configuration>
+        <c:simple-property name="path" readOnly="true" default="provider-modules" />
+      </plugin-configuration>
+      <resource-configuration>
+        <c:simple-property name="code" required="true" type="string" readOnly="false"
+          description="Class name of the module to be instantiated." />
+      </resource-configuration>
 
-          <service name="Login Module Stack (Profile)"
-                   discovery="SubsystemDiscovery"
-                   class="BaseComponent"
-                   createDeletePolicy="both">
+      <service name="Module Options (Provider Modules - Profile)" discovery="ModuleOptionsDiscoveryComponent"
+        class="ModuleOptionsComponent" singleton="true">
 
-              <plugin-configuration>
-                  <c:simple-property name="path" readOnly="true" default="login-module-stack"/>
-              </plugin-configuration>
+        <plugin-configuration>
+          <c:simple-property name="path" readOnly="true" default="module-options" />
+        </plugin-configuration>
 
-            <resource-configuration>
-              <c:list-property name="login-modules" required="true" description="List of authentication modules" >
-                <c:map-property name="*" required="false">
-                  <c:simple-property name="code" required="true" type="string" readOnly="false" description="Class name of the module to be instantiated."/>
-                  <c:simple-property name="flag" required="true" type="string" readOnly="false" description="The flag controls how the module participates in the overall procedure. Allowed values are requisite, required, sufficient or optional.">
-                    <c:property-options>
-                      <c:option value="sufficient"/>
-                      <c:option value="requisite"/>
-                      <c:option value="optional"/>
-                      <c:option value="required"/>
-                    </c:property-options>
-                  </c:simple-property>
-                  <c:simple-property name="module" required="false" type="string" readOnly="false" description="Name of JBoss Module where the login module code is located."/>
-                  <c:simple-property name="module-options" required="false" type="string" readOnly="false" description="List of module options containing a name/value pair."/>
-                </c:map-property>
-              </c:list-property>
-            </resource-configuration>
-          </service>
-        </service>
+        <resource-configuration>
+          <c:map-property name="Module Options" required="false" />
+        </resource-configuration>
+      </service><!-- End of Module Options (Provider Modules - Profile) -->
+    </service><!-- End of Provider Modules (Profile) -->
+  </service>
 
-        <service name="Authorization (Profile)"
-                 discovery="SubsystemDiscovery"
-                 class="BaseComponent"
-                 singleton="true"
-                 createDeletePolicy="both">
+  <service name="Authentication (Classic - Profile)" discovery="ModuleOptionsDiscoveryComponent" class="ModuleOptionsComponent"
+    singleton="true" createDeletePolicy="both">
 
-          <plugin-configuration>
-            <c:simple-property name="path" readOnly="true" default="authorization=classic"/>
-          </plugin-configuration>
+    <plugin-configuration>
+      <c:simple-property name="path" readOnly="true" default="authentication=classic" />
+    </plugin-configuration>
 
-          <resource-configuration>
-            <c:list-property name="policy-modules" required="false" description="List of authorization modules">
-                <c:map-property name="*" required="false">
-                  <c:simple-property name="code" required="true" type="string" readOnly="false" description="Class name of the module to be instantiated."/>
-                  <c:simple-property name="flag" required="true" type="string" readOnly="false" description="The flag controls how the module participates in the overall procedure. Allowed values are requisite, required, sufficient or optional.">
-                    <c:property-options>
-                      <c:option value="sufficient"/>
-                      <c:option value="requisite"/>
-                      <c:option value="optional"/>
-                      <c:option value="required"/>
-                    </c:property-options>
-                  </c:simple-property>
-                  <c:simple-property name="module" required="false" type="string" readOnly="false" description="Name of JBoss Module where the policy module code is located."/>
-                  <c:simple-property name="module-options" required="false" type="string" readOnly="false" description="List of module options containing a name/value pair."/>
-                </c:map-property>
-            </c:list-property>
-          </resource-configuration>
-        </service>
+    <service name="Login Modules (Classic - Profile)" discovery="ModuleOptionsDiscoveryComponent" class="ModuleOptionsComponent"
+      createDeletePolicy="both">
 
-        <service name="Identity Trust (Profile)"
-                 discovery="SubsystemDiscovery"
-                 class="BaseComponent"
-                 singleton="true"
-                 createDeletePolicy="both">
+      <plugin-configuration>
+        <c:simple-property name="path" readOnly="true" default="login-modules" />
+      </plugin-configuration>
+      
+            &loginModuleResourceConfig;
 
-          <plugin-configuration>
-            <c:simple-property name="path" readOnly="true" default="identity-trust=classic"/>
-          </plugin-configuration>
+      <service name="Module Options (Classic - Profile)" discovery="ModuleOptionsDiscoveryComponent" class="ModuleOptionsComponent"
+        singleton="true">
 
-          <resource-configuration>
-            <c:list-property name="trust-modules" required="false" description="List of trust modules">
-              <c:map-property name="*" required="false">
-                <c:simple-property name="code" required="true" type="string" readOnly="false" description="Class name of the module to be instantiated."/>
-                <c:simple-property name="flag" required="true" type="string" readOnly="false" description="The flag controls how the module participates in the overall procedure. Allowed values are requisite, required, sufficient or optional.">
-                  <c:property-options>
-                    <c:option value="sufficient"/>
-                    <c:option value="requisite"/>
-                    <c:option value="optional"/>
-                    <c:option value="required"/>
-                  </c:property-options>
-                </c:simple-property>
-                <c:simple-property name="module" required="false" type="string" readOnly="false" description="Name of JBoss Module where the identity trust module code is located."/>
-                <c:simple-property name="module-options" required="false" type="string" readOnly="false" description="List of module options containing a name/value pair."/>
-              </c:map-property>
-            </c:list-property>
-          </resource-configuration>
-        </service>
+        <plugin-configuration>
+          <c:simple-property name="path" readOnly="true" default="module-options" />
+        </plugin-configuration>
 
-        <service name="JSSE (Profile)"
-                 discovery="SubsystemDiscovery"
-                 class="BaseComponent"
-                 createDeletePolicy="both">
+        <resource-configuration>
+          <c:map-property name="Module Options" required="false" />
+        </resource-configuration>
+      </service><!-- End of Module Options -->
+    </service><!-- End of Module Options -->
+  </service><!-- End of Authentication (Classic) -->
 
-          <plugin-configuration>
-            <c:simple-property name="path" readOnly="true" default="jsse"/>
-          </plugin-configuration>
+  <service name="Authentication (Jaspi - Profile)" discovery="ModuleOptionsDiscoveryComponent" class="ModuleOptionsComponent"
+    singleton="true" createDeletePolicy="both">
 
-          <resource-configuration>
-            <c:simple-property name="cipher-suites" required="false" type="string" readOnly="false" description="Comma separated list of cipher suites to enable on SSLSockets."/>
-            <c:simple-property name="client-alias" required="false" type="string" readOnly="false" description="Preferred alias to use when the KeyManager chooses the client alias."/>
-            <c:simple-property name="client-auth" required="false" type="boolean" readOnly="false" description="Boolean attribute to indicate if client&apos;s certificates should also be authenticated on the server side."/>
-            <c:map-property name="key-manager" required="false" description="JSEE Key Manager factory">
-              <c:simple-property name="algorithm" required="false" type="string" readOnly="false" description="Algorithm to use when creating the KeyManagerFactory."/>
-              <c:simple-property name="provider" required="false" type="string" readOnly="false" description="Provider class name to use when creating the KeyManagerFactory."/>
-            </c:map-property>
-            <c:map-property name="keystore" required="false" description="Configures a JSSE key store">
-              <c:simple-property name="password" required="false" type="string" readOnly="false" description="Sets the password of the keystore. Either this or &apos;truststore&#45;password&apos; must be present otherwise the security domain will be useless."/>
-              <c:simple-property name="type" required="false" type="string" readOnly="false" description="Type of the keystore. If not set, type defaults to &apos;JKS&apos;."/>
-              <c:simple-property name="url" required="false" type="string" readOnly="false" description="URL of the keystore."/>
-              <c:simple-property name="provider" required="false" type="string" readOnly="false" description="Provider class name to use when creating the KeyStore."/>
-              <c:simple-property name="provider-argument" required="false" type="string" readOnly="false" description="String argument to pass to the keystore Provider constructor when instantiating it."/>
-            </c:map-property>
-            <c:simple-property name="protocols" required="false" type="string" readOnly="false" description="Comma separated list of protocols to enable on SSLSockets."/>
-            <c:simple-property name="server-alias" required="false" type="string" readOnly="false" description="Preferred alias to use when the KeyManager chooses the server alias."/>
-            <c:simple-property name="service-auth-token" required="false" type="string" readOnly="false" description="Token to retrieve PrivateKeys from the KeyStore."/>
-            <c:map-property name="trust-manager" required="false" description="JSEE Trust Manager factory">
-              <c:simple-property name="algorithm" required="false" type="string" readOnly="false" description="Algorithm to use when creating the TrustManagerFactory."/>
-              <c:simple-property name="provider" required="false" type="string" readOnly="false" description="Provider class name to use when creating the TrustManagerFactory."/>
-            </c:map-property>
-            <c:map-property name="truststore" required="false" description="Configures a JSSE trust store">
-              <c:simple-property name="password" required="false" type="string" readOnly="false" description="Sets the password of the truststore. Either this or &apos;keystore&#45;password&apos; must be present otherwise the security domain will be useless."/>
-              <c:simple-property name="type" required="false" type="string" readOnly="false" description="Type of the truststore. If not set, type defaults to &apos;JKS&apos;."/>
-              <c:simple-property name="url" required="false" type="string" readOnly="false" description="URL of the truststore."/>
-              <c:simple-property name="provider" required="false" type="string" readOnly="false" description="Provider class name to use when creating the truststore."/>
-              <c:simple-property name="provider-argument" required="false" type="string" readOnly="false" description="String argument to pass to the truststore Provider constructor when instantiating it."/>
-            </c:map-property>
-          </resource-configuration>
-        </service>
+    <plugin-configuration>
+      <c:simple-property name="path" readOnly="true" default="authentication=jaspi" />
+    </plugin-configuration>
 
-        <service name="Mapping (Profile)"
-                 discovery="SubsystemDiscovery"
-                 class="BaseComponent"
-                 singleton="true"
-                 createDeletePolicy="both">
+          &loginModuleResourceConfig;
 
-          <plugin-configuration>
-            <c:simple-property name="path" readOnly="true" default="mapping=classic"/>
-          </plugin-configuration>
+    <service name="Login Module Stack (Profile)" discovery="ModuleOptionsDiscoveryComponent" class="ModuleOptionsComponent"
+      createDeletePolicy="both">
 
-          <resource-configuration>
-            <c:list-property name="mapping-modules" required="false" description="List of modules that map principal, role, and credential information">
-              <c:map-property name="*" required="false">
-                <c:simple-property name="code" required="true" type="string" readOnly="false" description="Class name of the module to be instantiated."/>
-                <c:simple-property name="type" required="true" type="string" readOnly="false" description="Type of mapping this module performs. Allowed values are principal, role, attribute or credential.."/>
-                <c:simple-property name="module-options" required="false" type="string" readOnly="false" description="List of module options containing a name/value pair."/>
-              </c:map-property>
-            </c:list-property>
-          </resource-configuration>
-        </service>
+      <plugin-configuration>
+        <c:simple-property name="path" readOnly="true" default="login-module-stack" />
+      </plugin-configuration>
+
+	      &loginModuleResourceConfig;
+
+      <service name="Module Options (Login Module Stack (Profile))" discovery="ModuleOptionsDiscoveryComponent"
+        class="ModuleOptionsComponent" singleton="true">
+
+        <plugin-configuration>
+          <c:simple-property name="path" readOnly="true" default="module-options" />
+        </plugin-configuration>
+
+        <resource-configuration>
+          <c:map-property name="Module Options" required="false" />
+        </resource-configuration>
+      </service><!-- End of Module Options -->
+
+    </service>
+  </service>
+
+  <service name="Authorization (Profile)" discovery="ModuleOptionsDiscoveryComponent" class="ModuleOptionsComponent"
+    singleton="true" createDeletePolicy="both">
+
+    <plugin-configuration>
+      <c:simple-property name="path" readOnly="true" default="authorization=classic" />
+    </plugin-configuration>
+
+	&flagModuleResourceConfig;
+    <service name="Authorization Modules (Profile)" discovery="ModuleOptionsDiscoveryComponent" class="ModuleOptionsComponent"
+      createDeletePolicy="both">
+
+      <plugin-configuration>
+        <c:simple-property name="path" readOnly="true" default="policy-modules" />
+      </plugin-configuration>
+			&flagModuleResourceConfig;
+
+      <service name="Module Options (Authorization - Profile)" discovery="ModuleOptionsDiscoveryComponent"
+        class="ModuleOptionsComponent" singleton="true">
+
+        <plugin-configuration>
+          <c:simple-property name="path" readOnly="true" default="module-options" />
+        </plugin-configuration>
+
+        <resource-configuration>
+          <c:map-property name="Module Options" required="false" />
+        </resource-configuration>
+      </service><!-- End of Module Options (Authorization - Profile) -->
+    </service><!-- End of Authorization Modules (Profile) -->
+  </service>
+
+  <service name="Identity Trust (Profile)" discovery="ModuleOptionsDiscoveryComponent" class="ModuleOptionsComponent"
+    singleton="true" createDeletePolicy="both">
+
+    <plugin-configuration>
+      <c:simple-property name="path" readOnly="true" default="identity-trust=classic" />
+    </plugin-configuration>
+
+	&flagModuleResourceConfig;
+    <service name="Identity Trust Modules (Profile)" discovery="ModuleOptionsDiscoveryComponent" class="ModuleOptionsComponent"
+      createDeletePolicy="both">
+
+      <plugin-configuration>
+        <c:simple-property name="path" readOnly="true" default="trust-modules" />
+      </plugin-configuration>
+		      &flagModuleResourceConfig;
+
+      <service name="Module Options (Identity Trust - Profile)" discovery="ModuleOptionsDiscoveryComponent"
+        class="ModuleOptionsComponent" singleton="true">
+
+        <plugin-configuration>
+          <c:simple-property name="path" readOnly="true" default="module-options" />
+        </plugin-configuration>
+
+        <resource-configuration>
+          <c:map-property name="Module Options" required="false" />
+        </resource-configuration>
+      </service><!-- End of Module Options (Identity Trust - Profile) -->
+    </service><!-- End of Identity Trust Modules (Profile) -->
+  </service>
+
+  <service name="JSSE (Profile)" discovery="SubsystemDiscovery" class="BaseComponent" createDeletePolicy="both">
+
+    <plugin-configuration>
+      <c:simple-property name="path" readOnly="true" default="jsse" />
+    </plugin-configuration>
+
+    <resource-configuration>
+      <c:simple-property name="cipher-suites" required="false" type="string" readOnly="false"
+        description="Comma separated list of cipher suites to enable on SSLSockets." />
+      <c:simple-property name="client-alias" required="false" type="string" readOnly="false"
+        description="Preferred alias to use when the KeyManager chooses the client alias." />
+      <c:simple-property name="client-auth" required="false" type="boolean" readOnly="false"
+        description="Boolean attribute to indicate if client&apos;s certificates should also be authenticated on the server side." />
+      <c:map-property name="key-manager" required="false" description="JSEE Key Manager factory">
+        <c:simple-property name="algorithm" required="false" type="string" readOnly="false"
+          description="Algorithm to use when creating the KeyManagerFactory." />
+        <c:simple-property name="provider" required="false" type="string" readOnly="false"
+          description="Provider class name to use when creating the KeyManagerFactory." />
+      </c:map-property>
+      <c:map-property name="keystore" required="false" description="Configures a JSSE key store">
+        <c:simple-property name="password" required="false" type="string" readOnly="false"
+          description="Sets the password of the keystore. Either this or &apos;truststore&#45;password&apos; must be present otherwise the security domain will be useless." />
+        <c:simple-property name="type" required="false" type="string" readOnly="false"
+          description="Type of the keystore. If not set, type defaults to &apos;JKS&apos;." />
+        <c:simple-property name="url" required="false" type="string" readOnly="false" description="URL of the keystore." />
+        <c:simple-property name="provider" required="false" type="string" readOnly="false"
+          description="Provider class name to use when creating the KeyStore." />
+        <c:simple-property name="provider-argument" required="false" type="string" readOnly="false"
+          description="String argument to pass to the keystore Provider constructor when instantiating it." />
+      </c:map-property>
+      <c:simple-property name="protocols" required="false" type="string" readOnly="false"
+        description="Comma separated list of protocols to enable on SSLSockets." />
+      <c:simple-property name="server-alias" required="false" type="string" readOnly="false"
+        description="Preferred alias to use when the KeyManager chooses the server alias." />
+      <c:simple-property name="service-auth-token" required="false" type="string" readOnly="false"
+        description="Token to retrieve PrivateKeys from the KeyStore." />
+      <c:map-property name="trust-manager" required="false" description="JSEE Trust Manager factory">
+        <c:simple-property name="algorithm" required="false" type="string" readOnly="false"
+          description="Algorithm to use when creating the TrustManagerFactory." />
+        <c:simple-property name="provider" required="false" type="string" readOnly="false"
+          description="Provider class name to use when creating the TrustManagerFactory." />
+      </c:map-property>
+      <c:map-property name="truststore" required="false" description="Configures a JSSE trust store">
+        <c:simple-property name="password" required="false" type="string" readOnly="false"
+          description="Sets the password of the truststore. Either this or &apos;keystore&#45;password&apos; must be present otherwise the security domain will be useless." />
+        <c:simple-property name="type" required="false" type="string" readOnly="false"
+          description="Type of the truststore. If not set, type defaults to &apos;JKS&apos;." />
+        <c:simple-property name="url" required="false" type="string" readOnly="false" description="URL of the truststore." />
+        <c:simple-property name="provider" required="false" type="string" readOnly="false"
+          description="Provider class name to use when creating the truststore." />
+        <c:simple-property name="provider-argument" required="false" type="string" readOnly="false"
+          description="String argument to pass to the truststore Provider constructor when instantiating it." />
+      </c:map-property>
+    </resource-configuration>
+  </service>
+
+  <service name="Mapping (Profile)" discovery="ModuleOptionsDiscoveryComponent" class="ModuleOptionsComponent"
+    singleton="true" createDeletePolicy="both">
+
+    <plugin-configuration>
+      <c:simple-property name="path" readOnly="true" default="mapping=classic" />
+    </plugin-configuration>
+
+    <resource-configuration>
+      <c:simple-property name="code" required="true" type="string" readOnly="false"
+        description="Class name of the module to be instantiated." />
+      <c:simple-property name="type" required="true" type="string" readOnly="false"
+        description="Type of mapping this module performs. Allowed values are principal, role, attribute or credential..">
+        <c:property-options>
+          <c:option value="attribute" />
+          <c:option value="credential" />
+          <c:option value="principal" />
+          <c:option value="role" />
+        </c:property-options>
+      </c:simple-property>
+    </resource-configuration>
+    <service name="Mapping Modules (Profile)" discovery="ModuleOptionsDiscoveryComponent" class="ModuleOptionsComponent"
+      createDeletePolicy="both">
+
+      <plugin-configuration>
+        <c:simple-property name="path" readOnly="true" default="mapping-modules" />
+      </plugin-configuration>
+      <resource-configuration>
+        <c:simple-property name="code" required="true" type="string" readOnly="false"
+          description="Class name of the module to be instantiated." />
+        <c:simple-property name="type" required="true" type="string" readOnly="false"
+          description="Type of mapping this module performs. Allowed values are principal, role, attribute or credential..">
+          <c:property-options>
+            <c:option value="attribute" />
+            <c:option value="credential" />
+            <c:option value="principal" />
+            <c:option value="role" />
+          </c:property-options>
+        </c:simple-property>
+      </resource-configuration>
+
+      <service name="Module Options (Mapping - Profile)" discovery="ModuleOptionsDiscoveryComponent" class="ModuleOptionsComponent"
+        singleton="true">
+
+        <plugin-configuration>
+          <c:simple-property name="path" readOnly="true" default="module-options" />
+        </plugin-configuration>
+
+        <resource-configuration>
+          <c:map-property name="Module Options" required="false" />
+        </resource-configuration>
+      </service><!-- End of Module Options (Mapping - Profile) -->
+    </service><!-- End of Mapping Modules (Managed Server) -->
+  </service>
       </service>
 
       <service name="Vault (Profile)"
@@ -6611,6 +6723,27 @@
             <c:simple-property name="routing-name" required="false" type="string" readOnly="false" description="Routing name of the divert"/>
             <c:simple-property name="transformer-class-name" required="false" type="string" readOnly="false" description="The name of a class used to transform the message&apos;s body or properties before it is diverted."/>
           </resource-configuration>
+
+	    <service name="Module Option"
+		     discovery="SubsystemDiscovery"
+		     class="BaseComponent"
+                     createDeletePolicy="both"
+		     description="The module options to be used."
+		     singleton="true">
+
+	      <plugin-configuration>
+		<c:simple-property name="path" readOnly="true" default="module-options"/>
+	      </plugin-configuration>
+
+	      <resource-configuration>
+                <c:list-property name="Modules Options" required="false" description="List of module options.">
+                  <c:map-property name="*" required="false">
+                    <c:simple-property name="name"/>
+                    <c:simple-property name="value"/>
+                  </c:map-property>
+                </c:list-property>
+	      </resource-configuration>
+            </service>
         </service>
 
         <service name="Queue (Profile)"
@@ -10323,8 +10456,8 @@
     </resource-configuration>
 
     <service name="Security Domain"
-             discovery="SubsystemDiscovery"
-             class="BaseComponent"
+             discovery="ModuleOptionsDiscoveryComponent"
+             class="ModuleOptionsComponent"
              createDeletePolicy="both">
 
       <plugin-configuration>
@@ -10352,219 +10485,200 @@
          </c:simple-property>
       </resource-configuration>
 
-      <service name="ACL"
-               discovery="SubsystemDiscovery"
-               class="BaseComponent"
-               singleton="true"
-               createDeletePolicy="both">
+  <service name="ACL" discovery="ModuleOptionsDiscoveryComponent" class="ModuleOptionsComponent" singleton="true"
+    createDeletePolicy="both">
+
+    <plugin-configuration>
+      <c:simple-property name="path" readOnly="true" default="acl=classic" />
+    </plugin-configuration>
+
+        &flagModuleResourceConfig;
+    <service name="Acl Modules" discovery="ModuleOptionsDiscoveryComponent" class="ModuleOptionsComponent"
+      createDeletePolicy="both">
+
+      <plugin-configuration>
+        <c:simple-property name="path" readOnly="true" default="acl-modules" />
+      </plugin-configuration>
+	&flagModuleResourceConfig;
+
+      <service name="Module Options (Acl)" discovery="ModuleOptionsDiscoveryComponent" class="ModuleOptionsComponent"
+        singleton="true">
 
         <plugin-configuration>
-          <c:simple-property name="path" readOnly="true" default="acl=classic"/>
+          <c:simple-property name="path" readOnly="true" default="module-options" />
         </plugin-configuration>
 
         <resource-configuration>
-          <c:list-property name="acl-modules" required="false" description="List of acl modules">
-            <c:map-property name="*" required="false">
-              <c:simple-property name="code" required="true" type="string" readOnly="false" description="Class name of the module to be instantiated."/>
-              <c:simple-property name="flag" required="true" type="string" readOnly="false" description="The flag controls how the module participates in the overall procedure. Allowed values are requisite, required, sufficient or optional.">
-                <c:property-options>
-                  <c:option value="sufficient"/>
-                  <c:option value="requisite"/>
-                  <c:option value="optional"/>
-                  <c:option value="required"/>
-                </c:property-options>
-              </c:simple-property>
-              <c:simple-property name="module" required="false" type="string" readOnly="false" description="Name of JBoss Module where the acl provider module code is located."/>
-              <c:simple-property name="module-options" required="false" type="string" readOnly="false" description="List of module options containing a name/value pair."/>
-            </c:map-property>
-          </c:list-property>
+          <c:map-property name="Module Options" required="false" />
         </resource-configuration>
-      </service>
+      </service><!-- End of Module Options (Acl) -->
+    </service><!-- End of Acl Modules -->
+  </service>
 
-      <service name="Audit"
-               discovery="SubsystemDiscovery"
-               class="BaseComponent"
-               singleton="true"
-               createDeletePolicy="both">
+  <service name="Audit" discovery="ModuleOptionsDiscoveryComponent" class="ModuleOptionsComponent" singleton="true"
+    createDeletePolicy="both">
+
+    <plugin-configuration>
+      <c:simple-property name="path" readOnly="true" default="audit=classic" />
+    </plugin-configuration>
+
+    <resource-configuration>
+      <c:simple-property name="code" required="true" type="string" readOnly="false"
+        description="Class name of the module to be instantiated." />
+    </resource-configuration>
+    <service name="Provider Modules" discovery="ModuleOptionsDiscoveryComponent" class="ModuleOptionsComponent"
+      createDeletePolicy="both">
+
+      <plugin-configuration>
+        <c:simple-property name="path" readOnly="true" default="provider-modules" />
+      </plugin-configuration>
+      <resource-configuration>
+        <c:simple-property name="code" required="true" type="string" readOnly="false"
+          description="Class name of the module to be instantiated." />
+      </resource-configuration>
+
+      <service name="Module Options (Provider Modules)" discovery="ModuleOptionsDiscoveryComponent" class="ModuleOptionsComponent"
+        singleton="true">
 
         <plugin-configuration>
-          <c:simple-property name="path" readOnly="true" default="audit=classic"/>
+          <c:simple-property name="path" readOnly="true" default="module-options" />
         </plugin-configuration>
 
         <resource-configuration>
-          <c:list-property name="provider-modules" required="false" description="List of provider modules">
-             <c:map-property name="*" required="false">
-              <c:simple-property name="code" required="true" type="string" readOnly="false" description="Class name of the module to be instantiated."/>
-              <c:simple-property name="module-options" required="false" type="string" readOnly="false" description="List of module options containing a name/value pair."/>
-            </c:map-property>
-          </c:list-property>
+          <c:map-property name="Module Options" required="false" />
         </resource-configuration>
-      </service>
+      </service><!-- End of Module Options (Provider Modules) -->
+    </service><!-- End of Provider Modules -->
+  </service>
 
-      <service name="Authentication (Classic)"
-               discovery="SubsystemDiscovery"
-               class="BaseComponent"
-               singleton="true"
-               createDeletePolicy="both">
+  <service name="Authentication (Classic)" discovery="ModuleOptionsDiscoveryComponent" class="ModuleOptionsComponent"
+    singleton="true" createDeletePolicy="both">
+
+    <plugin-configuration>
+      <c:simple-property name="path" readOnly="true" default="authentication=classic" />
+    </plugin-configuration>
+
+    &loginModuleResourceConfig;
+
+    <service name="Login Modules (Classic)" discovery="ModuleOptionsDiscoveryComponent" class="ModuleOptionsComponent"
+      createDeletePolicy="both">
+
+      <plugin-configuration>
+        <c:simple-property name="path" readOnly="true" default="login-modules" />
+      </plugin-configuration>
+
+      &loginModuleResourceConfig;
+
+      <service name="Module Options (Classic)" discovery="ModuleOptionsDiscoveryComponent" class="ModuleOptionsComponent"
+        singleton="true">
 
         <plugin-configuration>
-          <c:simple-property name="path" readOnly="true" default="authentication=classic"/>
+          <c:simple-property name="path" readOnly="true" default="module-options" />
         </plugin-configuration>
 
         <resource-configuration>
-          <c:list-property name="login-modules" required="false" description="List of authentication modules">
-            <c:map-property name="*" required="false">
-               <c:simple-property name="code" required="true" type="string" readOnly="true"
-                description="Class name of the module to be instantiated.">
-                  <c:property-options>
-                    <c:option value="AdvancedADLdap" />
-                    <c:option value="AdvancedLdap" />
-                    <c:option value="Certificate" />
-                    <c:option value="CertificateRoles" />
-                    <c:option value="Client" />
-                    <c:option value="Database" />
-                    <c:option value="DatabaseCertificate" />
-                    <c:option value="DatabaseUsers" />
-                    <c:option value="Identity" />
-                    <c:option value="Kerberos" />
-                    <c:option value="Ldap" />
-                    <c:option value="LdapExtended" />
-                    <c:option value="RoleMapping" />
-                    <c:option value="Simple" />
-                    <c:option value="SPNEGOUsers" />
-                    <c:option value="UserRoles" />
-                  </c:property-options>
-                </c:simple-property>
-              <c:simple-property name="flag" required="true" type="string" readOnly="false" description="The flag controls how the module participates in the overall procedure. Allowed values are requisite, required, sufficient or optional.">
-                <c:property-options>
-                  <c:option value="sufficient"/>
-                  <c:option value="requisite"/>
-                  <c:option value="optional"/>
-                  <c:option value="required"/>
-                </c:property-options>
-              </c:simple-property>
-              <c:simple-property name="module" required="false" type="string" readOnly="false" description="Name of JBoss Module where the login module code is located."/>
-              <c:simple-property name="module-options" required="false" type="string" readOnly="false" description="List of module options containing a name/value pair."/>
-            </c:map-property>
-          </c:list-property>
+          <c:map-property name="Module Options" required="false" />
         </resource-configuration>
-      </service>
+      </service><!-- End of Module Options -->
+    </service><!-- End of Login Modules (Classic) -->
+  </service><!-- End of Authentication (Classic) -->
 
-      <service name="Authentication (Jaspi)"
-               discovery="SubsystemDiscovery"
-               class="BaseComponent"
-               singleton="true"
-               createDeletePolicy="both">
+  <service name="Authentication (Jaspi)" discovery="ModuleOptionsDiscoveryComponent" class="ModuleOptionsComponent"
+    singleton="true" createDeletePolicy="both">
+
+    <plugin-configuration>
+      <c:simple-property name="path" readOnly="true" default="authentication=jaspi" />
+    </plugin-configuration>
+
+	&loginModuleResourceConfig;
+
+    <service name="Login Module Stack" discovery="ModuleOptionsDiscoveryComponent" class="ModuleOptionsComponent"
+      createDeletePolicy="both">
+
+      <plugin-configuration>
+        <c:simple-property name="path" readOnly="true" default="login-module-stack" />
+      </plugin-configuration>
+
+	 &loginModuleResourceConfig;
+
+      <service name="Module Options (Login Module Stack)" discovery="ModuleOptionsDiscoveryComponent" class="ModuleOptionsComponent"
+        singleton="true">
 
         <plugin-configuration>
-            <c:simple-property name="path" readOnly="true" default="authentication=jaspi"/>
+          <c:simple-property name="path" readOnly="true" default="module-options" />
         </plugin-configuration>
 
         <resource-configuration>
-          <c:list-property name="auth-modules" required="true" description="List of authentication modules to be used." >
-                <c:map-property name="*" required="false">
-              <c:simple-property name="code" required="true" type="string" readOnly="false" description="Class name of the module to be instantiated."/>
-              <c:simple-property name="flag" required="true" type="string" readOnly="false" description="The flag controls how the module participates in the overall procedure. Allowed values are requisite, required, sufficient or optional.">
-                <c:property-options>
-                  <c:option value="sufficient"/>
-                  <c:option value="requisite"/>
-                  <c:option value="optional"/>
-                  <c:option value="required"/>
-                </c:property-options>
-              </c:simple-property>
-              <c:simple-property name="module" required="false" type="string" readOnly="false" description="Name of JBoss Module where the auth module code is located."/>
-              <c:simple-property name="module-options" required="false" type="string" readOnly="false" description="List of module options containing a name/value pair."/>
-              <c:simple-property name="login-module-stack-ref" required="false" type="string" readOnly="false" description="Reference to a login module stack name previously configured in the same security domain."/>
-            </c:map-property>
-          </c:list-property>
+          <c:map-property name="Module Options" required="false" />
         </resource-configuration>
+      </service><!-- End of Module Options -->
 
-        <service name="Login Module Stack"
-                 discovery="SubsystemDiscovery"
-                 class="BaseComponent"
-                 createDeletePolicy="both">
+    </service>
+  </service>
 
-            <plugin-configuration>
-                <c:simple-property name="path" readOnly="true" default="login-module-stack"/>
-            </plugin-configuration>
+  <service name="Authorization" discovery="ModuleOptionsDiscoveryComponent" class="ModuleOptionsComponent"
+    singleton="true" createDeletePolicy="both">
 
-          <resource-configuration>
-            <c:list-property name="login-modules" required="true" description="List of authentication modules" >
-              <c:map-property name="*" required="false">
-                <c:simple-property name="code" required="true" type="string" readOnly="false" description="Class name of the module to be instantiated."/>
-                <c:simple-property name="flag" required="true" type="string" readOnly="false" description="The flag controls how the module participates in the overall procedure. Allowed values are requisite, required, sufficient or optional.">
-                  <c:property-options>
-                    <c:option value="sufficient"/>
-                    <c:option value="requisite"/>
-                    <c:option value="optional"/>
-                    <c:option value="required"/>
-                  </c:property-options>
-                </c:simple-property>
-                <c:simple-property name="module" required="false" type="string" readOnly="false" description="Name of JBoss Module where the login module code is located."/>
-                <c:simple-property name="module-options" required="false" type="string" readOnly="false" description="List of module options containing a name/value pair."/>
-              </c:map-property>
-            </c:list-property>
-          </resource-configuration>
-        </service>
-      </service>
+    <plugin-configuration>
+      <c:simple-property name="path" readOnly="true" default="authorization=classic" />
+    </plugin-configuration>
 
-      <service name="Authorization"
-               discovery="SubsystemDiscovery"
-               class="BaseComponent"
-               singleton="true"
-               createDeletePolicy="both">
+	&flagModuleResourceConfig;
+
+    <service name="Authorization Modules" discovery="ModuleOptionsDiscoveryComponent" class="ModuleOptionsComponent"
+      createDeletePolicy="both">
+
+      <plugin-configuration>
+        <c:simple-property name="path" readOnly="true" default="policy-modules" />
+      </plugin-configuration>
+		     
+                      &flagModuleResourceConfig;
+
+      <service name="Module Options (Authorization)" discovery="ModuleOptionsDiscoveryComponent" class="ModuleOptionsComponent"
+        singleton="true">
 
         <plugin-configuration>
-          <c:simple-property name="path" readOnly="true" default="authorization=classic"/>
+          <c:simple-property name="path" readOnly="true" default="module-options" />
         </plugin-configuration>
 
         <resource-configuration>
-          <c:list-property name="policy-modules" required="false" description="List of authorization modules">
-              <c:map-property name="*" required="false">
-                <c:simple-property name="code" required="true" type="string" readOnly="false" description="Class name of the module to be instantiated."/>
-                <c:simple-property name="flag" required="true" type="string" readOnly="false" description="The flag controls how the module participates in the overall procedure. Allowed values are requisite, required, sufficient or optional.">
-                  <c:property-options>
-                    <c:option value="sufficient"/>
-                    <c:option value="requisite"/>
-                    <c:option value="optional"/>
-                    <c:option value="required"/>
-                  </c:property-options>
-                </c:simple-property>
-                <c:simple-property name="module" required="false" type="string" readOnly="false" description="Name of JBoss Module where the policy module code is located."/>
-                <c:simple-property name="module-options" required="false" type="string" readOnly="false" description="List of module options containing a name/value pair."/>
-              </c:map-property>
-          </c:list-property>
+          <c:map-property name="Module Options" required="false" />
         </resource-configuration>
-      </service>
+      </service><!-- End of Module Options (Authorization) -->
+    </service><!-- End of Authorization Modules -->
+  </service>
 
-      <service name="Identity Trust"
-               discovery="SubsystemDiscovery"
-               class="BaseComponent"
-               singleton="true"
-               createDeletePolicy="both">
+  <service name="Identity Trust" discovery="ModuleOptionsDiscoveryComponent" class="ModuleOptionsComponent"
+    singleton="true" createDeletePolicy="both">
+
+    <plugin-configuration>
+      <c:simple-property name="path" readOnly="true" default="identity-trust=classic" />
+    </plugin-configuration>
+
+        &flagModuleResourceConfig;
+
+    <service name="Identity Trust Modules" discovery="ModuleOptionsDiscoveryComponent" class="ModuleOptionsComponent"
+      createDeletePolicy="both">
+
+      <plugin-configuration>
+        <c:simple-property name="path" readOnly="true" default="trust-modules" />
+      </plugin-configuration>
+
+        &flagModuleResourceConfig;
+
+      <service name="Module Options (Identity Trust)" discovery="ModuleOptionsDiscoveryComponent" class="ModuleOptionsComponent"
+        singleton="true">
 
         <plugin-configuration>
-          <c:simple-property name="path" readOnly="true" default="identity-trust=classic"/>
+          <c:simple-property name="path" readOnly="true" default="module-options" />
         </plugin-configuration>
 
         <resource-configuration>
-          <c:list-property name="trust-modules" required="false" description="List of trust modules">
-            <c:map-property name="*" required="false">
-              <c:simple-property name="code" required="true" type="string" readOnly="false" description="Class name of the module to be instantiated."/>
-              <c:simple-property name="flag" required="true" type="string" readOnly="false" description="The flag controls how the module participates in the overall procedure. Allowed values are requisite, required, sufficient or optional.">
-                <c:property-options>
-                  <c:option value="sufficient"/>
-                  <c:option value="requisite"/>
-                  <c:option value="optional"/>
-                  <c:option value="required"/>
-                </c:property-options>
-              </c:simple-property>
-              <c:simple-property name="module" required="false" type="string" readOnly="false" description="Name of JBoss Module where the identity trust module code is located."/>
-              <c:simple-property name="module-options" required="false" type="string" readOnly="false" description="List of module options containing a name/value pair."/>
-            </c:map-property>
-          </c:list-property>
+          <c:map-property name="Module Options" required="false" />
         </resource-configuration>
-      </service>
+      </service><!-- End of Module Options (Identity Trust) -->
+    </service><!-- End of Identity Trust Modules -->
+  </service>
 
       <service name="JSSE"
                discovery="SubsystemDiscovery"
@@ -10607,26 +10721,59 @@
         </resource-configuration>
       </service>
 
-      <service name="Mapping"
-               discovery="SubsystemDiscovery"
-               class="BaseComponent"
-               singleton="true"
-               createDeletePolicy="both">
+  <service name="Mapping" discovery="ModuleOptionsDiscoveryComponent" class="ModuleOptionsComponent" singleton="true"
+    createDeletePolicy="both">
+
+    <plugin-configuration>
+      <c:simple-property name="path" readOnly="true" default="mapping=classic" />
+    </plugin-configuration>
+
+    <resource-configuration>
+      <c:simple-property name="code" required="true" type="string" readOnly="false"
+        description="Class name of the module to be instantiated." />
+      <c:simple-property name="type" required="true" type="string" readOnly="false"
+        description="Type of mapping this module performs. Allowed values are principal, role, attribute or credential..">
+        <c:property-options>
+          <c:option value="attribute" />
+          <c:option value="credential" />
+          <c:option value="principal" />
+          <c:option value="role" />
+        </c:property-options>
+      </c:simple-property>
+    </resource-configuration>
+    <service name="Mapping Modules" discovery="ModuleOptionsDiscoveryComponent" class="ModuleOptionsComponent"
+      createDeletePolicy="both">
+
+      <plugin-configuration>
+        <c:simple-property name="path" readOnly="true" default="mapping-modules" />
+      </plugin-configuration>
+      <resource-configuration>
+        <c:simple-property name="code" required="true" type="string" readOnly="false"
+          description="Class name of the module to be instantiated." />
+        <c:simple-property name="type" required="true" type="string" readOnly="false"
+          description="Type of mapping this module performs. Allowed values are principal, role, attribute or credential..">
+          <c:property-options>
+            <c:option value="attribute" />
+            <c:option value="credential" />
+            <c:option value="principal" />
+            <c:option value="role" />
+          </c:property-options>
+        </c:simple-property>
+      </resource-configuration>
+
+      <service name="Module Options (Mapping)" discovery="ModuleOptionsDiscoveryComponent" class="ModuleOptionsComponent"
+        singleton="true">
 
         <plugin-configuration>
-          <c:simple-property name="path" readOnly="true" default="mapping=classic"/>
+          <c:simple-property name="path" readOnly="true" default="module-options" />
         </plugin-configuration>
 
         <resource-configuration>
-          <c:list-property name="mapping-modules" required="false" description="List of modules that map principal, role, and credential information">
-            <c:map-property name="*" required="false">
-              <c:simple-property name="code" required="true" type="string" readOnly="false" description="Class name of the module to be instantiated."/>
-              <c:simple-property name="type" required="true" type="string" readOnly="false" description="Type of mapping this module performs. Allowed values are principal, role, attribute or credential.."/>
-              <c:simple-property name="module-options" required="false" type="string" readOnly="false" description="List of module options containing a name/value pair."/>
-            </c:map-property>
-          </c:list-property>
+          <c:map-property name="Module Options" required="false" />
         </resource-configuration>
-      </service>
+      </service><!-- End of Module Options (Mapping) -->
+    </service><!-- End of Mapping Modules -->
+  </service>
     </service>
 
     <service name="Vault"
diff --git a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/SecurityModuleOptionsTest.java b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/SecurityModuleOptionsTest.java
new file mode 100644
index 0000000..49d8040
--- /dev/null
+++ b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/SecurityModuleOptionsTest.java
@@ -0,0 +1,319 @@
+/*
+ * 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 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.modules.plugins.jbossas7;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+
+import org.codehaus.jackson.JsonGenerationException;
+import org.codehaus.jackson.JsonNode;
+import org.codehaus.jackson.JsonProcessingException;
+import org.codehaus.jackson.map.JsonMappingException;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.codehaus.jackson.map.SerializationConfig;
+import org.testng.annotations.BeforeSuite;
+import org.testng.annotations.Test;
+
+import org.rhq.modules.plugins.jbossas7.ModuleOptionsComponent.ModuleOptionType;
+import org.rhq.modules.plugins.jbossas7.ModuleOptionsComponent.Value;
+import org.rhq.modules.plugins.jbossas7.json.Address;
+import org.rhq.modules.plugins.jbossas7.json.Operation;
+import org.rhq.modules.plugins.jbossas7.json.ReadAttribute;
+import org.rhq.modules.plugins.jbossas7.json.Remove;
+import org.rhq.modules.plugins.jbossas7.json.Result;
+import org.rhq.modules.plugins.jbossas7.json.WriteAttribute;
+
+/**
+ * Test exercising the subsystem=security/SecurityDomain/[Authentication, Authorization, Mapping, Audit, Acl, 
+ *      Identity-Trust]
+ * @author Simeon Pinder
+ */
+ at Test(groups = "unit")
+public class SecurityModuleOptionsTest extends AbstractConfigurationHandlingTest {
+
+    private static String user = "rhqadmin";
+    private static String pass = "as7";
+    private static String host = "localhost";
+    private static ASConnection con = null;
+    private static ObjectMapper mapper = null;
+    private ModuleOptionsComponent moc = null;
+
+    //Define some shared and reusable content
+    static HashMap<String, String> jsonMap = new HashMap<String, String>();
+    static {
+        jsonMap
+            .put(
+                "login-modules",
+                "[{\"flag\":\"required\", \"code\":\"Ldap\", \"module-options\":{\"bindDn\":\"uid=ldapSecureUser,ou=People,dc=redat,dc=com\", \"bindPw\":\"test126\", \"allowEmptyPasswords\":\"true\"}}]");
+        //              "[{\"flag\":\"required\", \"code\":\"Ldap\"}]");
+        jsonMap
+            .put(
+                "policy-modules",
+                "[{\"flag\":\"requisite\", \"code\":\"LdapExtended\", \"module-options\":{\"policy\":\"module\", \"policy1\":\"module1\"}}]");
+        jsonMap
+            .put("mapping-modules",
+                "[{\"code\":\"Test\", \"type\":\"attribute\", \"module-options\":{\"mapping\":\"module\", \"mapping1\":\"module1\"}}]");
+        jsonMap.put("provider-modules",
+            "[{\"code\":\"Providers\", \"module-options\":{\"provider\":\"module\", \"provider1\":\"module1\"}}]");
+    }
+
+    @BeforeSuite
+    private void initializeConnectionDetails() {
+        con = new ASConnection(host, 9990, user, pass);
+        mapper = new ObjectMapper();
+        mapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true);
+
+        moc = new ModuleOptionsComponent();
+    }
+
+    public static void main(String[] args) {
+        SecurityModuleOptionsTest test = new SecurityModuleOptionsTest();
+        try {
+            test.initializeConnectionDetails();
+            test.testPopulateModuleOptionsAndTypes();
+        } catch (Exception e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+
+    }
+
+    /**The test reads the existing property values, deserializes them and writes the same 
+     * contents back out to a running instance for all known ModuleOptionTypes.
+     * 
+     * @throws Exception
+     */
+    public void testPopulateModuleOptionsAndTypes() throws Exception {
+
+        //as7 node details.
+        String securityDomainId = "testDomain";
+        //TODO: spinder 6-6-12: this cannot run as a standalone itest until JIRA https://issues.jboss.org/browse/AS7-4951
+        //      is addressed as there is no way to automate setup of the information being tested.
+        String address = "subsystem=security,security-domain=" + securityDomainId + ",authentication=classic";
+        boolean verboseOutput = true;
+        boolean executeOperation = true;
+        for (ModuleOptionType t : ModuleOptionType.values()) {
+            String attribute = t.getAttribute();
+            if (verboseOutput) {
+                System.out.println("======= Running with ModuleOptionType:" + t + " attribute:" + attribute + ":");
+            }
+            if (attribute.equals("policy-modules")) {
+                address = "subsystem=security,security-domain=" + securityDomainId + ",authorization=classic";
+            } else if (attribute.equals("acl-modules")) {
+                address = "subsystem=security,security-domain=" + securityDomainId + ",acl=classic";
+            } else if (attribute.equals("mapping-modules")) {
+                address = "subsystem=security,security-domain=" + securityDomainId + ",mapping=classic";
+            } else if (attribute.equals("trust-modules")) {
+                address = "subsystem=security,security-domain=" + securityDomainId + ",identity-trust=classic";
+            } else if (attribute.equals("provider-modules")) {
+                address = "subsystem=security,security-domain=" + securityDomainId + ",audit=classic";
+            } else if (attribute.equals("login-modules")) {
+                address = "subsystem=security,security-domain=" + securityDomainId + ",authentication=classic";
+            } else {
+                assert false : "An unknown attribute '" + attribute
+                    + "' was found. Is there a new type to be supported?";
+            }
+
+            //test operation- read property always available.
+            Operation op = null;
+
+            //read the login-modules attribute
+            op = new ReadAttribute(new Address(address), attribute);
+            Result result = exerciseOperation(op, true, verboseOutput);
+            assert result.isSuccess() == true : "The operation '" + op + "' failed to read the resource."
+                + result.getFailureDescription();
+            //extract current results
+            Object rawResult = result.getResult();
+            assert rawResult != null : "Read of attribute'" + attribute + "' from address '" + address
+                + "' has returned no value. Are those values in the model?";
+
+            List<Value> list2 = new ArrayList<Value>();
+            //populate the Value component complete with module Options.
+            list2 = moc.populateSecurityDomainModuleOptions(result,
+                ModuleOptionsComponent.loadModuleOptionType(attribute));
+            if (verboseOutput) {
+                if (rawResult != null) {
+                    System.out.println("Raw Result is:" + rawResult + " and of type:" + rawResult.getClass());
+                } else {
+                    System.out.println("Read of attribute'" + attribute + "' from address '" + address
+                        + "' has returned no value. Are those values in the model?");
+                }
+            }
+            //write the login-modules attribute
+            op = new WriteAttribute(new Address(address));
+            op.addAdditionalProperty("name", attribute);//attribute to execute on
+            op.addAdditionalProperty("value", list2);
+
+            //Now test the operation
+            result = exerciseOperation(op, executeOperation, verboseOutput);
+            assert ((result.isSuccess() == true) || (result.getOutcome() == null)) : "The operation '" + op
+                + "' failed to write the resource.." + result.getFailureDescription();
+
+            //read the login-modules attribute
+            op = new ReadAttribute(new Address(address), attribute);
+            result = exerciseOperation(op, true, verboseOutput);
+            assert (result.isSuccess() == true) : "The operation '" + op + "' failed to read the resource."
+                + result.getFailureDescription();
+        }
+        if (verboseOutput) {
+            System.out.println("Successfully detected,read and wrote out attribute values for:");
+            for (ModuleOptionType type : ModuleOptionType.values()) {
+                System.out.println("\n" + type.ordinal() + " " + type.name());
+            }
+        }
+    }
+
+    /**Attempts to create a new Authentication node(authentication=classic) with a
+     * 'login-modules' attribute complete with 'code':'Ldap' and 'flag':'required' 
+     *  and some sample 'module-options' values.
+     *  
+     */
+    @Test(enabled = true)
+    public void testCreateSecurityDomainChildLoginModules() {
+        boolean execute = true;
+        boolean verboseOutput = false;
+        String address = "subsystem=security,security-domain=testDomain3,authentication=classic";
+        String attribute = ModuleOptionType.Authentication.getAttribute();
+
+        //test operation- read property always available.
+        Operation op = null;
+
+        //read the login-modules attribute
+        op = new ReadAttribute(new Address(address), attribute);
+        Result result = exerciseOperation(op, execute, verboseOutput);
+        assert result.isSuccess() == true : "The operation '" + op + "' failed to read the resource."
+            + result.getFailureDescription();
+
+        //extract current results
+        Object rawResult = result.getResult();
+
+        //#### Have to create new content for the new node.
+        List<Value> moduleTypeValue = new ArrayList<Value>();
+        try {
+            // loading 'login-module'
+            JsonNode node = mapper.readTree(jsonMap.get(attribute));
+            result.setResult(mapper.treeToValue(node, Object.class));
+        } catch (JsonProcessingException e) {
+            e.printStackTrace();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+
+        //populate the Value component complete with module Options.
+        moduleTypeValue = ModuleOptionsComponent.populateSecurityDomainModuleOptions(result,
+            ModuleOptionsComponent.loadModuleOptionType(attribute));
+
+        //add the login-modules attribute
+        op = ModuleOptionsComponent
+            .createAddModuleOptionTypeOperation(new Address(address), attribute, moduleTypeValue);
+
+        result = exerciseOperation(op, execute, verboseOutput);
+        assert ((result.isSuccess() == true) || (result.getOutcome() == null)) : "The operation '" + op
+            + "' failed to write the resource.." + result.getFailureDescription();
+
+        //read the login-modules attribute
+        op = new ReadAttribute(new Address(address), attribute);
+        result = exerciseOperation(op, execute, verboseOutput);
+        assert result.isSuccess() == true : "The operation '" + op + "' failed to read the resource."
+            + result.getFailureDescription();
+
+        //exercise values retrieved from read
+        List<Value> serverResponse = ModuleOptionsComponent.populateSecurityDomainModuleOptions(result,
+            ModuleOptionsComponent.loadModuleOptionType(attribute));
+        Value serverState = serverResponse.get(0);
+        assert serverState.getFlag().equals("required") : "Incorrect state retrieved for 'flag'. Expected 'required'.";
+        assert serverState.getCode().equals("Ldap") : "Incorrect state retrieved for 'code'. Expected 'Ldap'.";
+        LinkedHashMap<String, Object> options = serverState.getOptions();
+        assert options.size() == 3 : "Invalid number of module options returned. Expected 3.";
+        int found = 0;
+        for (String key : options.keySet()) {
+            if (key.equals("bindPw")) {
+                assert "test126".equals(options.get(key)) : "Module option value not correct for key '" + key + "'.";
+                found++;
+            } else if (key.equals("bindDn")) {
+                assert "uid=ldapSecureUser,ou=People,dc=redat,dc=com".equals(options.get(key)) : "Module option value not correct for key '"
+                    + key + "'.";
+                found++;
+            } else if (key.equals("allowEmptyPasswords")) {
+                assert "true".equals(options.get(key)) : "Module option value not correct for key '" + key + "'.";
+                found++;
+            }
+        }
+        assert found == 3 : "All module options were not loaded.";
+
+        //remove the original node to reset for next run.
+        op = new Remove(new Address(address));
+        result = exerciseOperation(op, execute, verboseOutput);
+        assert result.isSuccess() == true : "The operation '" + op + "' failed to remove the resource."
+            + result.getFailureDescription();
+    }
+
+    /** For each operation 
+     *   - will write verbose json and operation details to system.out if verboseOutput = true;
+     *   - will execute the operation against running server if execute = true.
+     * 
+     * @param op
+     * @param execute
+     * @param verboseOutput
+     * @return
+     */
+    public static Result exerciseOperation(Operation op, boolean execute, boolean verboseOutput) {
+        //display operation as AS7 plugin will build it
+        if (verboseOutput) {
+            System.out.println("\tOperation is:" + op);
+        }
+
+        String jsonToSend = "";
+        try {
+            //            jsonToSend = mapper.writeValueAsString(op);
+            jsonToSend = mapper.defaultPrettyPrintingWriter().writeValueAsString(op);
+        } catch (JsonGenerationException e) {
+            e.printStackTrace();
+        } catch (JsonMappingException e) {
+            e.printStackTrace();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        //As generated by jackson mapper
+        if (verboseOutput) {
+            System.out.println("@@@@ OUTBOUND JSON#\n" + jsonToSend + "#");
+        }
+
+        //Execute the operation
+        Result result = new Result();
+        if (execute) {
+            result = con.execute(op);
+        } else {
+            if (verboseOutput) {
+                System.out.println("**** NOTE: Execution disabled . NOT exercising write-attribute operation. **** ");
+            }
+        }
+        if (verboseOutput) {
+            //result wrapper details 
+            System.out.println("\tResult:" + result);
+            //detailed results
+            System.out.println("\tValue:" + result.getResult());
+            System.out.println("-----------------------------------------------------\n");
+        }
+        return result;
+    }
+}


commit a580f69b6dbf05df46c766daec53982365dac52e
Author: Lukas Krejci <lkrejci at redhat.com>
Date:   Tue Jun 19 13:15:37 2012 +0200

    [BZ 801551] - Make sure the server name is not editable when upgrading
    existing server in the installer.

diff --git a/modules/enterprise/gui/installer-war/src/main/java/org/rhq/enterprise/installer/ConfigurationBean.java b/modules/enterprise/gui/installer-war/src/main/java/org/rhq/enterprise/installer/ConfigurationBean.java
index 2af8f15..e06dbe8 100644
--- a/modules/enterprise/gui/installer-war/src/main/java/org/rhq/enterprise/installer/ConfigurationBean.java
+++ b/modules/enterprise/gui/installer-war/src/main/java/org/rhq/enterprise/installer/ConfigurationBean.java
@@ -895,6 +895,12 @@ public class ConfigurationBean {
         return ((null != registeredServerNames) && !registeredServerNames.isEmpty());
     }
 
+    public boolean isInstallationSettingsConfigurable() {
+        String selectedServer = getSelectedRegisteredServerName();
+        return selectedServer == null || selectedServer.isEmpty()
+            || selectedServer.equals(I18Nmsg.getMsg(InstallerI18NResourceKeys.NEW_SERVER_SELECT_ITEM));
+    }
+
     public List<SelectItem> getRegisteredServerNames() {
         List<SelectItem> result = new ArrayList<SelectItem>(0);
 
@@ -925,6 +931,7 @@ public class ConfigurationBean {
     // should not call getServerConfiguration.setValue()
     public void setSelectedRegisteredServerName(String selectedRegisteredServerName) {
         this.selectedRegisteredServerName = selectedRegisteredServerName;
+        setHaServerName(selectedRegisteredServerName);
     }
 
     public String getHaServerName() {
diff --git a/modules/enterprise/gui/installer-war/src/main/webapp/start.jsp b/modules/enterprise/gui/installer-war/src/main/webapp/start.jsp
index ad0219e..7bbb55c 100644
--- a/modules/enterprise/gui/installer-war/src/main/webapp/start.jsp
+++ b/modules/enterprise/gui/installer-war/src/main/webapp/start.jsp
@@ -210,7 +210,8 @@
                                             document.getElementById('propForm:haendpointport').value = '';
                                             document.getElementById('propForm:haendpointsecureport').value = '';
                                             if (document.getElementById('propForm:haaffinitygroup') != null) {
-                                               document.getElementById('propForm:haaffinitygroup').value = ''; }
+                                               document.getElementById('propForm:haaffinitygroup').value = ''; 
+                                            }
                                             submit(); }" >
                   <f:selectItems value="#{configurationBean.registeredServerNames}" />
                </h:selectOneMenu>
@@ -233,7 +234,7 @@
                <h:outputText value="#{bundle.propertyHighAvailabilityName}" />
             </h:outputLink>
             <h:inputText id="haservername" size="#{configurationBean.propHaServerName.itemDefinition.fieldSize}"
-                         value="#{configurationBean.haServerName}" >
+                         value="#{configurationBean.haServerName}" readonly="#{not configurationBean.installationSettingsConfigurable}">
             </h:inputText>
             <h:outputText value="#{bundle.yesString}" rendered="#{configurationBean.propHaServerName.itemDefinition.requiresRestart}" />
             <h:outputText value="#{bundle.noString}" rendered="#{!configurationBean.propHaServerName.itemDefinition.requiresRestart}" />


commit 36085bd4268ab11fb394a69d92a12e7889a607b2
Author: Heiko W. Rupp <hwr at redhat.com>
Date:   Tue Jun 19 10:31:36 2012 +0200

    Improve support for resource operation scheduling

diff --git a/modules/enterprise/gui/rest-war/src/main/webapp/index.html b/modules/enterprise/gui/rest-war/src/main/webapp/index.html
index 00d615f..1cb29eb 100644
--- a/modules/enterprise/gui/rest-war/src/main/webapp/index.html
+++ b/modules/enterprise/gui/rest-war/src/main/webapp/index.html
@@ -17,6 +17,7 @@ mobile client (Android) of the API.
     <li><a href="1/alert/">Alerts</a></li>
     <li><a href="1/status.html">System status</a> </li>
     <li><a href="1/user/favorites/resource">Favorite resources</a></li>
+    <li><a href="1/operation/history">Operation histories</a></li>
 </ul>
 <hr/>
 <h2>Misc examples (using <a href="https://github.com/mbostock/d3">D3.js</a>)</h2>
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java
index 73a4ebb..cb233f8 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java
@@ -27,14 +27,22 @@ import java.util.Set;
 import javax.ejb.EJB;
 import javax.ejb.Stateless;
 import javax.interceptor.Interceptors;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.core.CacheControl;
 import javax.ws.rs.core.EntityTag;
 import javax.ws.rs.core.GenericEntity;
 import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Request;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriBuilder;
 import javax.ws.rs.core.UriInfo;
 
+import com.wordnik.swagger.annotations.ApiOperation;
+import com.wordnik.swagger.annotations.ApiParam;
+
 import org.rhq.core.domain.configuration.Configuration;
 import org.rhq.core.domain.configuration.Property;
 import org.rhq.core.domain.configuration.PropertySimple;
@@ -45,10 +53,12 @@ import org.rhq.core.domain.criteria.ResourceOperationHistoryCriteria;
 import org.rhq.core.domain.operation.HistoryJobId;
 import org.rhq.core.domain.operation.JobId;
 import org.rhq.core.domain.operation.OperationDefinition;
+import org.rhq.core.domain.operation.OperationRequestStatus;
 import org.rhq.core.domain.operation.ResourceOperationHistory;
 import org.rhq.core.domain.operation.bean.ResourceOperationSchedule;
 import org.rhq.core.domain.resource.Resource;
 import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.core.domain.util.PageOrdering;
 import org.rhq.enterprise.server.operation.OperationManagerLocal;
 import org.rhq.enterprise.server.resource.ResourceManagerLocal;
 import org.rhq.enterprise.server.rest.domain.Link;
@@ -139,7 +149,7 @@ public class OperationsHandlerBean extends AbstractRestBean implements Operation
     }
 
     @Override
-    public Response getOperationDefinitions(Integer resourceId, UriInfo uriInfo, Request request) {
+    public Response getOperationDefinitions(Integer resourceId, UriInfo uriInfo, Request request, HttpHeaders httpHeaders) {
 
         if (resourceId == null)
             throw new ParameterMissingException("resourceId");
@@ -281,8 +291,9 @@ public class OperationsHandlerBean extends AbstractRestBean implements Operation
     }
 
     @Override
-    public Response outcome(String jobName, UriInfo uriInfo) {
+    public Response outcome(String jobName, UriInfo uriInfo, Request request, HttpHeaders httpHeaders) {
 
+        MediaType mediaType = httpHeaders.getAcceptableMediaTypes().get(0);
 
         ResourceOperationHistoryCriteria criteria = new ResourceOperationHistoryCriteria();
         criteria.addFilterJobId(new JobId(jobName));
@@ -295,6 +306,68 @@ public class OperationsHandlerBean extends AbstractRestBean implements Operation
         }
 
         history = list.get(0);
+        OperationHistoryRest hist = historyToHistoryRest(history, uriInfo);
+        Response.ResponseBuilder builder;
+        if (mediaType.equals(MediaType.TEXT_HTML_TYPE)) {
+            builder = Response.ok(renderTemplate("operationHistory.ftl",hist));
+        } else {
+            builder = Response.ok(hist);
+        }
+        if (history.getStatus()== OperationRequestStatus.SUCCESS) {
+            // add a long time cache header
+            CacheControl cc = new CacheControl();
+            cc.setMaxAge(1200);
+            builder.cacheControl(cc);
+        }
+
+        return builder.build();
+
+    }
+
+    public Response listHistory(int resourceId, UriInfo uriInfo, Request request, HttpHeaders httpHeaders) {
+
+        ResourceOperationHistoryCriteria criteria = new ResourceOperationHistoryCriteria();
+        if (resourceId>0)
+            criteria.addFilterResourceIds(resourceId);
+
+        criteria.addSortEndTime(PageOrdering.DESC);
+
+        List<ResourceOperationHistory> list = opsManager.findResourceOperationHistoriesByCriteria(caller,criteria);
+
+        List<OperationHistoryRest> result = new ArrayList<OperationHistoryRest>(list.size());
+        for (ResourceOperationHistory roh : list) {
+            OperationHistoryRest historyRest = historyToHistoryRest(roh,uriInfo);
+            result.add(historyRest);
+        }
+
+        MediaType mediaType = httpHeaders.getAcceptableMediaTypes().get(0);
+        Response.ResponseBuilder builder;
+        if (mediaType.equals(MediaType.TEXT_HTML_TYPE)) {
+            builder = Response.ok(renderTemplate("listOperationHistory.ftl", result));
+        } else {
+            GenericEntity<List<OperationHistoryRest>> res = new GenericEntity<List<OperationHistoryRest>>(result) {};
+            builder = Response.ok(res);
+        }
+        return builder.build();
+    }
+
+    @Override
+    public Response deleteOperationHistoryItem(String jobName) {
+
+        ResourceOperationHistoryCriteria criteria = new ResourceOperationHistoryCriteria();
+        criteria.addFilterJobId(new JobId(jobName));
+        List<ResourceOperationHistory> list = opsManager.findResourceOperationHistoriesByCriteria(caller,criteria);
+        if ((list != null && !list.isEmpty())) {
+
+            ResourceOperationHistory history = list.get(0);
+            opsManager.deleteOperationHistory(caller,history.getId(),false);
+        }
+        return Response.noContent().build();
+
+    }
+
+
+    private OperationHistoryRest historyToHistoryRest(ResourceOperationHistory history, UriInfo uriInfo) {
         String status;
         if (history.getStatus()==null)
             status = " - no information yet -";
@@ -303,6 +376,10 @@ public class OperationsHandlerBean extends AbstractRestBean implements Operation
 
         OperationHistoryRest hist = new OperationHistoryRest();
         hist.setStatus(status);
+        if (history.getResource()!=null)
+            hist.setResourceName(history.getResource().getName());
+        hist.setOperationName(history.getOperationDefinition().getName());
+        hist.lastModified(history.getModifiedTime());
         if (history.getErrorMessage()!=null)
             hist.setErrorMessage(history.getErrorMessage());
         if (history.getResults()!=null) {
@@ -317,14 +394,17 @@ public class OperationsHandlerBean extends AbstractRestBean implements Operation
             }
         }
 
+        String jobName = history.getJobName();
+        String jobGroup = history.getJobGroup();
+        JobId jobId = new JobId(jobName, jobGroup);
+        hist.setJobId(jobId.toString());
+
         UriBuilder uriBuilder = uriInfo.getBaseUriBuilder();
         uriBuilder.path("/operation/history/{id}");
-        URI url = uriBuilder.build(new JobId(jobName));
+        URI url = uriBuilder.build(jobId);
         Link self = new Link("self",url.toString());
         hist.getLinks().add(self);
-
-
-        return Response.ok(hist).build();
-
+        return hist;
     }
-}
+
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerLocal.java
index a4268b7..8cce452 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerLocal.java
@@ -70,7 +70,8 @@ public interface OperationsHandlerLocal {
     public Response getOperationDefinitions(
             @ApiParam(value = "Id of the resource",required = true) @QueryParam("resourceId") Integer resourceId,
                                             @Context UriInfo uriInfo,
-                                            @Context Request request
+                                            @Context Request request,
+                                            @Context HttpHeaders httpHeaders
     );
 
     @POST
@@ -104,7 +105,27 @@ public interface OperationsHandlerLocal {
     @GET
     @Path("history/{id}")
     @ApiOperation("Return the outcome of the scheduled operation")
+    @Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML,MediaType.TEXT_HTML})
     public Response outcome(
             @ApiParam("Name of the submitted job.") @PathParam("id") String jobName,
-            @Context UriInfo uriInfo);
+            @Context UriInfo uriInfo,
+            @Context Request request,
+            @Context HttpHeaders httpHeaders);
+
+    @GET
+    @Path("history")
+    @ApiOperation("Return the outcome of the scheduled operations")
+    @Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML,MediaType.TEXT_HTML})
+    public Response listHistory(
+            @ApiParam("Id of a resource to limit to") @QueryParam("resourceId") int resourceId,
+            @Context UriInfo uriInfo,
+            @Context Request request,
+            @Context HttpHeaders httpHeaders);
+
+
+    @DELETE
+    @Path("history/{id}")
+    @ApiOperation(value = "Delete the operation history item with the passed id")
+    public Response deleteOperationHistoryItem(
+            @ApiParam("Name fo the submitted job") @PathParam("id") String jobId);
 }
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/OperationHistoryRest.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/OperationHistoryRest.java
index 8249db6..10967df 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/OperationHistoryRest.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/OperationHistoryRest.java
@@ -32,8 +32,12 @@ import javax.xml.bind.annotation.XmlRootElement;
 @XmlRootElement
 public class OperationHistoryRest {
 
+    String operationName;
+    String resourceName;
+    long lastModified;
     String status;
     String errorMessage;
+    String jobId;
 
     Map<String,Object> result = new HashMap<String, Object>();
     List<Link> links = new ArrayList<Link>();
@@ -69,4 +73,36 @@ public class OperationHistoryRest {
     public void setLinks(List<Link> links) {
         this.links = links;
     }
+
+    public String getOperationName() {
+        return operationName;
+    }
+
+    public void setOperationName(String operationName) {
+        this.operationName = operationName;
+    }
+
+    public String getResourceName() {
+        return resourceName;
+    }
+
+    public void setResourceName(String resourceName) {
+        this.resourceName = resourceName;
+    }
+
+    public long getLastModified() {
+        return lastModified;
+    }
+
+    public void lastModified(long date) {
+        this.lastModified = date;
+    }
+
+    public String getJobId() {
+        return jobId;
+    }
+
+    public void setJobId(String jobId) {
+        this.jobId = jobId;
+    }
 }
diff --git a/modules/enterprise/server/jar/src/main/resources/rest_templates/listGroupDefinition.ftl b/modules/enterprise/server/jar/src/main/resources/rest_templates/listGroupDefinition.ftl
index 15e8272..8e8acc3 100644
--- a/modules/enterprise/server/jar/src/main/resources/rest_templates/listGroupDefinition.ftl
+++ b/modules/enterprise/server/jar/src/main/resources/rest_templates/listGroupDefinition.ftl
@@ -21,17 +21,17 @@
 -->
 <#-- @ftlvariable name="var" type="java.util.List<org.rhq.enterprise.server.rest.domain.GroupDefinitionRest>" -->
 <html>
+<#if (var?size>0) >
 <ul>
-    <#-- the next looks odd, but the incoming var is a list -->
-    <#if (var?size>0) >
+<#-- the next looks odd, but the incoming var is a list -->
     <#list var as var>
     <li>
         <#include "groupDefinition.ftl"/>
     </li>
     </#list>
-    <#else>
-       <strong>No Definitions have been set up</strong>
-    </#if>
 
 </ul>
+<#else>
+   <strong>No Definitions have been set up</strong>
+</#if>
 <html>
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/main/resources/rest_templates/listMetricSchedule.ftl b/modules/enterprise/server/jar/src/main/resources/rest_templates/listMetricSchedule.ftl
index b351644..a104675 100644
--- a/modules/enterprise/server/jar/src/main/resources/rest_templates/listMetricSchedule.ftl
+++ b/modules/enterprise/server/jar/src/main/resources/rest_templates/listMetricSchedule.ftl
@@ -21,12 +21,18 @@
 -->
 <#-- @ftlvariable name="var" type="java.util.List<org.rhq.enterprise.server.rest.domain.MetricSchedule>" -->
 <html>
+<#if (var?size>0) >
 <ul>
     <#-- the next looks odd, but the incoming var is a list -->
+
     <#list var as var>
     <li>
         <#include "metricSchedule.ftl"/>
     </li>
     </#list>
+
 </ul>
+<#else>
+   <strong>No Schedules have been set up</strong>
+</#if>
 <html>
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/main/resources/rest_templates/listOperationHistory.ftl b/modules/enterprise/server/jar/src/main/resources/rest_templates/listOperationHistory.ftl
new file mode 100644
index 0000000..60fee92
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/resources/rest_templates/listOperationHistory.ftl
@@ -0,0 +1,37 @@
+<#ftl >
+<#--
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 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.
+ */
+-->
+<#-- @ftlvariable name="var" type="java.util.List<org.rhq.enterprise.server.rest.domain.OperationHistoryRest>" -->
+<html>
+<#if (var?size>0) >
+<ul>
+
+    <#-- the next looks odd, but the incoming var is a list -->
+    <#list var as var>
+    <li>
+        <#include "operationHistory.ftl"/>
+    </li>
+    </#list>
+</ul>
+<#else>
+   <strong>No Operations have been run</strong>
+</#if>
+<html>
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/main/resources/rest_templates/operationHistory.ftl b/modules/enterprise/server/jar/src/main/resources/rest_templates/operationHistory.ftl
new file mode 100644
index 0000000..b1141e7
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/resources/rest_templates/operationHistory.ftl
@@ -0,0 +1,56 @@
+<#ftl >
+<#--
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 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.
+ */
+-->
+<#-- @ftlvariable name="var" type="org.rhq.enterprise.server.rest.domain.OperationHistoryRest" -->
+<html>
+
+<table>
+    <tr>
+        <td>Operation Name</td>
+        <td>${var.operationName}</td>
+    </tr>
+    <tr>
+        <td>Resource Name</td>
+        <td>${var.resourceName}</td>
+    </tr>
+    <tr>
+        <td>Outcome</td>
+        <td>${var.status}</td>
+    </tr>
+    <#if var.errorMessage?has_content>
+        <tr>
+            <td>Error</td>
+            <td>${var.errorMessage}</td>
+        </tr>
+    </#if>
+    <#if var.result?has_content>
+    <tr>
+        <td>Result Parameters</td>
+        <td>
+            <#assign result=var.result/>
+            <#list result?keys as p>
+                ${p} : ${result[p]}<br/>
+            </#list>
+        </td>
+    </tr>
+    </#if>
+</table>
+</html>
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/main/resources/rest_templates/resourceWithType.ftl b/modules/enterprise/server/jar/src/main/resources/rest_templates/resourceWithType.ftl
index f4bfa15..c95c8ba 100644
--- a/modules/enterprise/server/jar/src/main/resources/rest_templates/resourceWithType.ftl
+++ b/modules/enterprise/server/jar/src/main/resources/rest_templates/resourceWithType.ftl
@@ -50,4 +50,5 @@
     <a href="/rest/1/resource/${var.resourceId}/schedules.html">Schedules</a><br/>
     <a href="/rest/1/resource/${var.resourceId}/availability.html">Current availability</a><br/>
     <a href="/rest/1/resource/${var.resourceId}/availability/history.html">Availability History</a><br/>
-    <a href="/rest/1/alert.html?resourceId=${var.resourceId}">Up to 20 Alerts for this resource</a>
+    <a href="/rest/1/alert.html?resourceId=${var.resourceId}">Up to 20 Alerts for this resource</a><br/>
+    <a href="/rest/1/operation/history.html?resourceId=${var.resourceId}">Operations history</a>


commit ed6b6c2a7666218a08c35eee6bd18f1f28b4409a
Author: Stefan Negrea <snegrea at redhat.com>
Date:   Mon Jun 18 15:24:31 2012 -0500

    Add one more no-argument operation to the list of ignored operations.

diff --git a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/ResourcesStandaloneServerTest.java b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/ResourcesStandaloneServerTest.java
index f2d601c..bd904b9 100644
--- a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/ResourcesStandaloneServerTest.java
+++ b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/ResourcesStandaloneServerTest.java
@@ -108,6 +108,8 @@ public class ResourcesStandaloneServerTest extends AbstractJBossAS7PluginTest  {
         //ignored because this is not a true operation, it is handled
         //internally by a configuration property change
         ignoredOperations.add("enable");
+        //ignored because the Osgi subsystem not configured out of box
+        ignoredOperations.add("subsystem:activate");
 
         Resource platform = this.pluginContainer.getInventoryManager().getPlatform();
         Resource server = getResourceByTypeAndKey(platform, StandaloneServerComponentTest.RESOURCE_TYPE,


commit 755964e1ac732505f8ef2261e9ed601205679f29
Author: Stefan Negrea <snegrea at redhat.com>
Date:   Mon Jun 18 15:23:59 2012 -0500

    [BZ 833187] Updates to support nullable lists. If a nullable list is empty then send back to the AS7 the null value instead of an empty list.

diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ConfigurationWriteDelegate.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ConfigurationWriteDelegate.java
index d6d7329..366f840 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ConfigurationWriteDelegate.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ConfigurationWriteDelegate.java
@@ -520,6 +520,18 @@ public class ConfigurationWriteDelegate implements ConfigurationFacet {
 
         PropertyDefinition memberDef = propertyDefinition.getMemberDefinition();
         List<Property> embeddedProps = property.getList();
+
+
+        String propertyName = property.getName();
+
+        if (propertyName.endsWith(":nullable")) {
+            propertyName = propertyName.substring(0, propertyName.indexOf(":nullable"));
+
+            if (embeddedProps.isEmpty()) {
+                return new SimpleEntry<String, List<Object>>(propertyName, null);
+            }
+        }
+
         List<Object> values = new ArrayList<Object>();
         for (Property inner : embeddedProps) {
             if (memberDef instanceof PropertyDefinitionSimple) {
@@ -539,9 +551,9 @@ public class ConfigurationWriteDelegate implements ConfigurationFacet {
             }
         }
 
-        String name = stripNumberIdentifier(property.getName());
+        propertyName = stripNumberIdentifier(property.getName());
 
-        return new SimpleEntry<String, List<Object>>(name, values);
+        return new SimpleEntry<String, List<Object>>(propertyName, values);
     }
 
 
diff --git a/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml
index 68d5a36..956eed8 100644
--- a/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml
@@ -3638,7 +3638,7 @@
           <c:simple-property name="persist-delivery-count-before-delivery" required="false" type="boolean" readOnly="true" defaultValue="false" description="Whether the delivery count is persisted before delivery. False means that this only happens after a message has been cancelled. The default value is false."/>
           <c:simple-property name="persist-id-cache" required="false" type="boolean" readOnly="true" defaultValue="true" description="Whether IDs are persisted to the journal. The default value is true."/>
           <c:simple-property name="persistence-enabled" required="false" type="boolean" readOnly="true" defaultValue="true" description="Whether the server will use the file based journal for persistence. The default value is true."/>
-          <c:list-property name="remoting-interceptors" required="false" readOnly="true" description="The list of interceptor classes used by this server." >
+          <c:list-property name="remoting-interceptors:nullable" required="false" readOnly="true" description="The list of interceptor classes used by this server." >
               <c:simple-property name="remoting-interceptors" readOnly="true"/>
           </c:list-property>
           <c:simple-property name="run-sync-speed-test" required="false" type="boolean" readOnly="true" defaultValue="false" description="Whether on startup to perform a diagnostic test on how fast your disk can sync. Useful when determining performance issues. The default value is false."/>
@@ -4604,7 +4604,7 @@
             <c:simple-property name="reconnect-attempts" required="false" type="integer" readOnly="true" defaultValue="&#45;1" description="The total number of reconnect attempts the bridge will make before giving up and shutting down. A value of &#45;1 signifies an unlimited number of attempts. The default value is &#45;1."/>
             <c:simple-property name="retry-interval" required="false" type="long" readOnly="true" defaultValue="500" description="The period in milliseconds between subsequent reconnection attempts, if the connection to the target server has failed. The default value is 500."/>
             <c:simple-property name="retry-interval-multiplier" required="false" type="double" readOnly="true" defaultValue="1.0" description="A multiplier to apply to the time since the last retry to compute the time to the next retry. This allows you to implement an exponential backoff between retry attempts. The default value is 1.0."/>
-            <c:list-property name="static-connectors" required="false" readOnly="true" description="The statically defined list of connectors to which this cluster connection will make connections. Must be undefined (null) if &apos;discovery&#45;group&#45;name&apos; is defined." >
+            <c:list-property name="static-connectors:nullable" required="false" readOnly="true" description="The statically defined list of connectors to which this cluster connection will make connections. Must be undefined (null) if &apos;discovery&#45;group&#45;name&apos; is defined." >
                 <c:simple-property name="static-connectors" readOnly="true"/>
             </c:list-property>
             <c:simple-property name="use-duplicate-detection" required="false" type="boolean" readOnly="true" defaultValue="true" description="Whether the bridge will automatically insert a duplicate id property into each message that it forwards. The default value is true."/>
@@ -4727,7 +4727,7 @@
             <c:simple-property name="reconnect-attempts" required="false" type="integer" readOnly="true" defaultValue="&#45;1" description="The total number of reconnect attempts the bridge will make before giving up and shutting down. A value of &#45;1 signifies an unlimited number of attempts. The default value is &#45;1."/>
             <c:simple-property name="retry-interval" required="false" type="long" readOnly="true" defaultValue="2000" description="The period in milliseconds between subsequent reconnection attempts, if the connection to the target server has failed. The default value is 2000."/>
             <c:simple-property name="retry-interval-multiplier" required="false" type="double" readOnly="true" defaultValue="1.0" description="A multiplier to apply to the time since the last retry to compute the time to the next retry. This allows you to implement an exponential backoff between retry attempts. The default value is 1.0."/>
-            <c:list-property name="static-connectors" required="false" description="A list of names of statically defined connectors used by this bridge. Must be undefined (null) if &apos;discovery&#45;group&#45;name&apos; is defined." >
+            <c:list-property name="static-connectors:nullable" required="false" description="A list of names of statically defined connectors used by this bridge. Must be undefined (null) if &apos;discovery&#45;group&#45;name&apos; is defined." >
               <c:simple-property name="static-connectors" />
             </c:list-property>
             <c:simple-property name="transformer-class-name" required="false" type="string" readOnly="true" description="The name of a user&#45;defined class which implements the org.hornetq.core.server.cluster.Transformer interface."/>
@@ -6253,7 +6253,7 @@
           <c:simple-property name="persist-delivery-count-before-delivery" required="false" type="boolean" readOnly="false" defaultValue="false" description="Whether the delivery count is persisted before delivery. False means that this only happens after a message has been cancelled. The default value is false."/>
           <c:simple-property name="persist-id-cache" required="false" type="boolean" readOnly="false" defaultValue="true" description="Whether IDs are persisted to the journal. The default value is true."/>
           <c:simple-property name="persistence-enabled" required="false" type="boolean" readOnly="false" defaultValue="true" description="Whether the server will use the file based journal for persistence. The default value is true."/>
-          <c:list-property name="remoting-interceptors" required="false" description="The list of interceptor classes used by this server." >
+          <c:list-property name="remoting-interceptors:nullable" required="false" description="The list of interceptor classes used by this server." >
               <c:simple-property name="remoting-interceptors" />
           </c:list-property>
           <c:simple-property name="run-sync-speed-test" required="false" type="boolean" readOnly="false" defaultValue="false" description="Whether on startup to perform a diagnostic test on how fast your disk can sync. Useful when determining performance issues. The default value is false."/>
@@ -6689,7 +6689,7 @@
             <c:simple-property name="reconnect-attempts" required="false" type="integer" readOnly="false" defaultValue="&#45;1" description="The total number of reconnect attempts the bridge will make before giving up and shutting down. A value of &#45;1 signifies an unlimited number of attempts. The default value is &#45;1."/>
             <c:simple-property name="retry-interval" required="false" type="long" readOnly="false" defaultValue="500" description="The period in milliseconds between subsequent reconnection attempts, if the connection to the target server has failed. The default value is 500."/>
             <c:simple-property name="retry-interval-multiplier" required="false" type="double" readOnly="false" defaultValue="1.0" description="A multiplier to apply to the time since the last retry to compute the time to the next retry. This allows you to implement an exponential backoff between retry attempts. The default value is 1.0."/>
-            <c:list-property name="static-connectors" required="false" description="The statically defined list of connectors to which this cluster connection will make connections. Must be undefined (null) if &apos;discovery&#45;group&#45;name&apos; is defined." >
+            <c:list-property name="static-connectors:nullable" required="false" description="The statically defined list of connectors to which this cluster connection will make connections. Must be undefined (null) if &apos;discovery&#45;group&#45;name&apos; is defined." >
                 <c:simple-property name="static-connectors" />
             </c:list-property>
             <c:simple-property name="use-duplicate-detection" required="false" type="boolean" readOnly="false" defaultValue="true" description="Whether the bridge will automatically insert a duplicate id property into each message that it forwards. The default value is true."/>
@@ -6778,7 +6778,7 @@
             <c:simple-property name="reconnect-attempts" required="false" type="integer" readOnly="false" defaultValue="&#45;1" description="The total number of reconnect attempts the bridge will make before giving up and shutting down. A value of &#45;1 signifies an unlimited number of attempts. The default value is &#45;1."/>
             <c:simple-property name="retry-interval" required="false" type="long" readOnly="false" defaultValue="2000" description="The period in milliseconds between subsequent reconnection attempts, if the connection to the target server has failed. The default value is 2000."/>
             <c:simple-property name="retry-interval-multiplier" required="false" type="double" readOnly="false" defaultValue="1.0" description="A multiplier to apply to the time since the last retry to compute the time to the next retry. This allows you to implement an exponential backoff between retry attempts. The default value is 1.0."/>
-            <c:list-property name="static-connectors" required="false" description="A list of names of statically defined connectors used by this bridge. Must be undefined (null) if &apos;discovery&#45;group&#45;name&apos; is defined." >
+            <c:list-property name="static-connectors:nullable" required="false" description="A list of names of statically defined connectors used by this bridge. Must be undefined (null) if &apos;discovery&#45;group&#45;name&apos; is defined." >
               <c:simple-property name="static-connectors" />
             </c:list-property>
             <c:simple-property name="transformer-class-name" required="false" type="string" readOnly="false" description="The name of a user&#45;defined class which implements the org.hornetq.core.server.cluster.Transformer interface."/>
@@ -9195,7 +9195,7 @@
         <c:simple-property name="persist-delivery-count-before-delivery" required="false" type="boolean" readOnly="false" defaultValue="false" description="Whether the delivery count is persisted before delivery. False means that this only happens after a message has been cancelled. The default value is false."/>
         <c:simple-property name="persist-id-cache" required="false" type="boolean" readOnly="false" defaultValue="true" description="Whether IDs are persisted to the journal. The default value is true."/>
         <c:simple-property name="persistence-enabled" required="false" type="boolean" readOnly="false" defaultValue="true" description="Whether the server will use the file based journal for persistence. The default value is true."/>
-        <c:list-property name="remoting-interceptors" required="false" description="The list of interceptor classes used by this server.">
+        <c:list-property name="remoting-interceptors:nullable" required="false" description="The list of interceptor classes used by this server.">
           <c:simple-property name="remoting-interceptors"/>
         </c:list-property>
         <c:simple-property name="run-sync-speed-test" required="false" type="boolean" readOnly="false" defaultValue="false" description="Whether on startup to perform a diagnostic test on how fast your disk can sync. Useful when determining performance issues. The default value is false."/>
@@ -11775,7 +11775,7 @@
         <c:simple-property name="persist-delivery-count-before-delivery" required="false" type="boolean" readOnly="false" defaultValue="false" description="Whether the delivery count is persisted before delivery. False means that this only happens after a message has been cancelled. The default value is false."/>
         <c:simple-property name="persist-id-cache" required="false" type="boolean" readOnly="false" defaultValue="true" description="Whether IDs are persisted to the journal. The default value is true."/>
         <c:simple-property name="persistence-enabled" required="false" type="boolean" readOnly="false" defaultValue="true" description="Whether the server will use the file based journal for persistence. The default value is true."/>
-        <c:list-property name="remoting-interceptors" required="false" description="The list of interceptor classes used by this server.">
+        <c:list-property name="remoting-interceptors:nullable" required="false" description="The list of interceptor classes used by this server.">
           <c:simple-property name="remoting-interceptors"/>
         </c:list-property>
         <c:simple-property name="run-sync-speed-test" required="false" type="boolean" readOnly="false" defaultValue="false" description="Whether on startup to perform a diagnostic test on how fast your disk can sync. Useful when determining performance issues. The default value is false."/>
@@ -12742,7 +12742,7 @@
           <c:simple-property name="reconnect-attempts" required="false" type="integer" readOnly="false" defaultValue="&#45;1" description="The total number of reconnect attempts the bridge will make before giving up and shutting down. A value of &#45;1 signifies an unlimited number of attempts. The default value is &#45;1."/>
           <c:simple-property name="retry-interval" required="false" type="long" readOnly="false" defaultValue="500" description="The period in milliseconds between subsequent reconnection attempts, if the connection to the target server has failed. The default value is 500."/>
           <c:simple-property name="retry-interval-multiplier" required="false" type="double" readOnly="false" defaultValue="1.0" description="A multiplier to apply to the time since the last retry to compute the time to the next retry. This allows you to implement an exponential backoff between retry attempts. The default value is 1.0."/>
-          <c:list-property name="static-connectors" required="false" description="The statically defined list of connectors to which this cluster connection will make connections. Must be undefined (null) if &apos;discovery&#45;group&#45;name&apos; is defined.">
+          <c:list-property name="static-connectors:nullable" required="false" description="The statically defined list of connectors to which this cluster connection will make connections. Must be undefined (null) if &apos;discovery&#45;group&#45;name&apos; is defined.">
             <c:simple-property name="static-connectors"/>
           </c:list-property>
           <c:simple-property name="use-duplicate-detection" required="false" type="boolean" readOnly="false" defaultValue="true" description="Whether the bridge will automatically insert a duplicate id property into each message that it forwards. The default value is true."/>
@@ -12865,7 +12865,7 @@
           <c:simple-property name="reconnect-attempts" required="false" type="integer" readOnly="false" defaultValue="&#45;1" description="The total number of reconnect attempts the bridge will make before giving up and shutting down. A value of &#45;1 signifies an unlimited number of attempts. The default value is &#45;1."/>
           <c:simple-property name="retry-interval" required="false" type="long" readOnly="false" defaultValue="2000" description="The period in milliseconds between subsequent reconnection attempts, if the connection to the target server has failed. The default value is 2000."/>
           <c:simple-property name="retry-interval-multiplier" required="false" type="double" readOnly="false" defaultValue="1.0" description="A multiplier to apply to the time since the last retry to compute the time to the next retry. This allows you to implement an exponential backoff between retry attempts. The default value is 1.0."/>
-          <c:list-property name="static-connectors" required="false" description="A list of names of statically defined connectors used by this bridge. Must be undefined (null) if &apos;discovery&#45;group&#45;name&apos; is defined.">
+          <c:list-property name="static-connectors:nullable" required="false" description="A list of names of statically defined connectors used by this bridge. Must be undefined (null) if &apos;discovery&#45;group&#45;name&apos; is defined.">
             <c:simple-property name="static-connectors"/>
           </c:list-property>
           <c:simple-property name="transformer-class-name" required="false" type="string" readOnly="false" description="The name of a user&#45;defined class which implements the org.hornetq.core.server.cluster.Transformer interface."/>


commit 5a8b4196beed872022861c0d4110a652c0f5c013
Author: Jay Shaughnessy <jshaughn at redhat.com>
Date:   Mon Jun 18 11:18:13 2012 -0400

    [831152 - Repositories Delete Selected Repository button leads to exception page when no permission is given]
    A private repo should be able to be deleted by its owner, even if the owner
    does not have MANAGE_REPOSITORIES permission.

diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/RepoManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/RepoManagerBean.java
index 4a7c2f2..72d7bee 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/RepoManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/RepoManagerBean.java
@@ -20,8 +20,6 @@ package org.rhq.enterprise.server.content;
 
 import java.text.ParseException;
 import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -78,10 +76,8 @@ import org.rhq.enterprise.server.auth.SubjectManagerLocal;
 import org.rhq.enterprise.server.authz.AuthorizationManagerLocal;
 import org.rhq.enterprise.server.authz.PermissionException;
 import org.rhq.enterprise.server.authz.RequiredPermission;
-import org.rhq.enterprise.server.plugin.pc.content.ContentProvider;
 import org.rhq.enterprise.server.plugin.pc.content.ContentProviderManager;
 import org.rhq.enterprise.server.plugin.pc.content.ContentServerPluginContainer;
-import org.rhq.enterprise.server.plugin.pc.content.PackageSource;
 import org.rhq.enterprise.server.plugin.pc.content.PackageTypeBehavior;
 import org.rhq.enterprise.server.plugin.pc.content.RepoDetails;
 import org.rhq.enterprise.server.plugin.pc.content.RepoGroupDetails;
@@ -150,7 +146,7 @@ public class RepoManagerBean implements RepoManagerLocal, RepoManagerRemote {
         }
 
         // remove any unused, orphaned package versions
-        contentSourceManager.purgeOrphanedPackageVersions(subject);
+        contentSourceManager.purgeOrphanedPackageVersions(subjectManager.getOverlord());
     }
 
     @RequiredPermission(Permission.MANAGE_REPOSITORIES)


commit c7dd1545b7a5264274a9f97289ee62c8dec76eee
Author: Stefan Negrea <snegrea at redhat.com>
Date:   Mon Jun 18 10:16:29 2012 -0500

    [BZ 833089] Remove more unneeded properties from Local Cache resource.

diff --git a/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml
index 01f9c40..68d5a36 100644
--- a/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml
@@ -2003,29 +2003,22 @@
           </plugin-configuration>
 
           <resource-configuration>
-            <c:simple-property name="start" required="false" type="string" readOnly="false" default="LAZY" description="The cache start mode, which can be EAGER (immediate start) or LAZY (on-demand start).">
+            <c:simple-property name="start" required="false" type="string" readOnly="true" default="LAZY" description="The cache start mode, which can be EAGER (immediate start) or LAZY (on-demand start).">
               <c:property-options>
                 <c:option value="LAZY"/>
                 <c:option value="EAGER"/>
               </c:property-options>
             </c:simple-property>
-            <c:simple-property name="batching" required="false" type="boolean" readOnly="false" default="false" description="If enabled, the invocation batching API will be made available for this cache."/>
-            <c:simple-property name="indexing" required="false" type="string" readOnly="false" default="NONE" description="If enabled, entries will be indexed when they are added to the cache. Indexes will be updated as entries change or are removed.">
+            <c:simple-property name="batching" required="false" type="boolean" readOnly="true" default="false" description="If enabled, the invocation batching API will be made available for this cache."/>
+            <c:simple-property name="indexing" required="false" type="string" readOnly="true" default="NONE" description="If enabled, entries will be indexed when they are added to the cache. Indexes will be updated as entries change or are removed.">
               <c:property-options>
                 <c:option value="NONE"/>
                 <c:option value="LOCAL"/>
                 <c:option value="ALL"/>
               </c:property-options>
             </c:simple-property>
-            <c:simple-property name="jndi-name" required="false" type="string" readOnly="false" description="The jndi-name to which to bind this cache instance."/>
-            <c:simple-property name="queue-size" required="false" type="integer" readOnly="false" default="0" description="In ASYNC mode, this attribute can be used to trigger flushing of the queue when it reaches a specific threshold."/>
-            <c:simple-property name="queue-flush-interval" required="false" type="long" readOnly="false" default="10" description="In ASYNC mode, this attribute controls how often the asynchronous thread used to flush the replication queue runs. This should be a positive integer which represents thread wakeup time in milliseconds."/>
-            <c:simple-property name="remote-timeout" required="false" type="long" readOnly="false" default="17500" description="In SYNC mode, the timeout (in ms) used to wait for an acknowledgment when making a remote call, after which the call is aborted and an exception is thrown."/>
-            <c:simple-property name="async-marshalling" required="false" type="boolean" readOnly="false" defaultValue="false" description="If enabled, this will cause marshalling of entries to be performed asynchronously. The default value is false."/>
-            <c:simple-property name="l1-lifespan" required="false" type="long" readOnly="false" defaultValue="600000" description="Maximum lifespan of an entry placed in the L1 cache. This element configures the L1 cache behavior in &apos;distributed&apos; caches instances. In any other cache modes, this element is ignored. The default value is 600000."/>
-            <c:simple-property name="module" required="false" type="string" readOnly="false" description="The module whose class loader should be used when building this cache&apos;s configuration."/>
-            <c:simple-property name="owners" required="false" type="integer" readOnly="false" defaultValue="2" description="Number of cluster&#45;wide replicas for each cache entry. The default value is 2."/>
-            <c:simple-property name="virtual-nodes" required="false" type="integer" readOnly="false" defaultValue="1" description="Controls the number of virtual nodes per &apos;real&apos; node. If numVirtualNodes is 1, then virtual nodes are disabled. The topology aware consistent hash must be used if you wish to take advantage of virtual nodes. A default of 1 is used. The default value is 1."/>
+            <c:simple-property name="jndi-name" required="false" type="string" readOnly="true" description="The jndi-name to which to bind this cache instance."/>
+            <c:simple-property name="module" required="false" type="string" readOnly="true" description="The module whose class loader should be used when building this cache&apos;s configuration."/>
           </resource-configuration>
         </service>
 
@@ -11263,14 +11256,7 @@
             </c:property-options>
           </c:simple-property>
           <c:simple-property name="jndi-name" required="false" type="string" readOnly="false" description="The jndi-name to which to bind this cache instance."/>
-          <c:simple-property name="queue-size" required="false" type="integer" readOnly="false" default="0" description="In ASYNC mode, this attribute can be used to trigger flushing of the queue when it reaches a specific threshold."/>
-          <c:simple-property name="queue-flush-interval" required="false" type="long" readOnly="false" default="10" description="In ASYNC mode, this attribute controls how often the asynchronous thread used to flush the replication queue runs. This should be a positive integer which represents thread wakeup time in milliseconds."/>
-          <c:simple-property name="remote-timeout" required="false" type="long" readOnly="false" default="17500" description="In SYNC mode, the timeout (in ms) used to wait for an acknowledgment when making a remote call, after which the call is aborted and an exception is thrown."/>
-          <c:simple-property name="async-marshalling" required="false" type="boolean" readOnly="false" defaultValue="false" description="If enabled, this will cause marshalling of entries to be performed asynchronously. The default value is false."/>
-          <c:simple-property name="l1-lifespan" required="false" type="long" readOnly="false" defaultValue="600000" description="Maximum lifespan of an entry placed in the L1 cache. This element configures the L1 cache behavior in &apos;distributed&apos; caches instances. In any other cache modes, this element is ignored. The default value is 600000."/>
           <c:simple-property name="module" required="false" type="string" readOnly="false" description="The module whose class loader should be used when building this cache&apos;s configuration."/>
-          <c:simple-property name="owners" required="false" type="integer" readOnly="false" defaultValue="2" description="Number of cluster&#45;wide replicas for each cache entry. The default value is 2."/>
-          <c:simple-property name="virtual-nodes" required="false" type="integer" readOnly="false" defaultValue="1" description="Controls the number of virtual nodes per &apos;real&apos; node. If numVirtualNodes is 1, then virtual nodes are disabled. The topology aware consistent hash must be used if you wish to take advantage of virtual nodes. A default of 1 is used. The default value is 1."/>
         </resource-configuration>
       </service>
 


commit b2f94df78ce141bed4167ed833547c37b8b89598
Author: Stefan Negrea <snegrea at redhat.com>
Date:   Mon Jun 18 09:59:49 2012 -0500

    [BZ 833089] Created a separate Local Cache resource descriptor with properties only applicable to this resource type.

diff --git a/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml
index 4e3f4da..01f9c40 100644
--- a/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml
@@ -1939,7 +1939,7 @@
                  class="TemplatedComponent">
 
           <plugin-configuration>
-            <c:simple-property name="path" readOnly="true" default="distributed-cache|local-cache|invalidation-cache|replicated-cache"/>
+            <c:simple-property name="path" readOnly="true" default="distributed-cache|invalidation-cache|replicated-cache"/>
           </plugin-configuration>
 
           <resource-configuration>
@@ -1975,15 +1975,11 @@
 
             <c:simple-property name="__type" displayName="Type of cache" required="true" readOnly="true" default="local-cache" description="Type of cache">
               <c:property-options>
-                <c:option value="local-cache"/>
                 <c:option value="invalidation-cache"/>
                 <c:option value="distributed-cache"/>
                 <c:option value="replicated-cache"/>
               </c:property-options>
             </c:simple-property>
-            <c:template name="Local Cache" description="Local Cache">
-              <c:simple-property name="__type" readOnly="true" default="local-cache"/>
-            </c:template>
             <c:template name="Invalidation Cache" description="Invalidation Cache">
               <c:simple-property name="__type" readOnly="true" default="invalidation-cache"/>
             </c:template>
@@ -1996,6 +1992,43 @@
           </resource-configuration>
         </service>
 
+        <service name="Local Cache (Managed Server)"
+                 discovery="SubsystemDiscovery"
+                 class="BaseComponent"
+                 createDeletePolicy="both"
+                 creationDataType="configuration">
+
+          <plugin-configuration>
+            <c:simple-property name="path" readOnly="true" default="local-cache"/>
+          </plugin-configuration>
+
+          <resource-configuration>
+            <c:simple-property name="start" required="false" type="string" readOnly="false" default="LAZY" description="The cache start mode, which can be EAGER (immediate start) or LAZY (on-demand start).">
+              <c:property-options>
+                <c:option value="LAZY"/>
+                <c:option value="EAGER"/>
+              </c:property-options>
+            </c:simple-property>
+            <c:simple-property name="batching" required="false" type="boolean" readOnly="false" default="false" description="If enabled, the invocation batching API will be made available for this cache."/>
+            <c:simple-property name="indexing" required="false" type="string" readOnly="false" default="NONE" description="If enabled, entries will be indexed when they are added to the cache. Indexes will be updated as entries change or are removed.">
+              <c:property-options>
+                <c:option value="NONE"/>
+                <c:option value="LOCAL"/>
+                <c:option value="ALL"/>
+              </c:property-options>
+            </c:simple-property>
+            <c:simple-property name="jndi-name" required="false" type="string" readOnly="false" description="The jndi-name to which to bind this cache instance."/>
+            <c:simple-property name="queue-size" required="false" type="integer" readOnly="false" default="0" description="In ASYNC mode, this attribute can be used to trigger flushing of the queue when it reaches a specific threshold."/>
+            <c:simple-property name="queue-flush-interval" required="false" type="long" readOnly="false" default="10" description="In ASYNC mode, this attribute controls how often the asynchronous thread used to flush the replication queue runs. This should be a positive integer which represents thread wakeup time in milliseconds."/>
+            <c:simple-property name="remote-timeout" required="false" type="long" readOnly="false" default="17500" description="In SYNC mode, the timeout (in ms) used to wait for an acknowledgment when making a remote call, after which the call is aborted and an exception is thrown."/>
+            <c:simple-property name="async-marshalling" required="false" type="boolean" readOnly="false" defaultValue="false" description="If enabled, this will cause marshalling of entries to be performed asynchronously. The default value is false."/>
+            <c:simple-property name="l1-lifespan" required="false" type="long" readOnly="false" defaultValue="600000" description="Maximum lifespan of an entry placed in the L1 cache. This element configures the L1 cache behavior in &apos;distributed&apos; caches instances. In any other cache modes, this element is ignored. The default value is 600000."/>
+            <c:simple-property name="module" required="false" type="string" readOnly="false" description="The module whose class loader should be used when building this cache&apos;s configuration."/>
+            <c:simple-property name="owners" required="false" type="integer" readOnly="false" defaultValue="2" description="Number of cluster&#45;wide replicas for each cache entry. The default value is 2."/>
+            <c:simple-property name="virtual-nodes" required="false" type="integer" readOnly="false" defaultValue="1" description="Controls the number of virtual nodes per &apos;real&apos; node. If numVirtualNodes is 1, then virtual nodes are disabled. The topology aware consistent hash must be used if you wish to take advantage of virtual nodes. A default of 1 is used. The default value is 1."/>
+          </resource-configuration>
+        </service>
+
         <service name="Transport (Managed Server)"
                  discovery="SubsystemDiscovery"
                  class="BaseComponent"
@@ -11151,7 +11184,7 @@
                creationDataType="configuration">
 
         <plugin-configuration>
-          <c:simple-property name="path" readOnly="true" default="distributed-cache|local-cache|invalidation-cache|replicated-cache"/>
+          <c:simple-property name="path" readOnly="true" default="distributed-cache|invalidation-cache|replicated-cache"/>
         </plugin-configuration>
 
         <resource-configuration>
@@ -11187,15 +11220,11 @@
 
           <c:simple-property name="__type" displayName="Type of cache" required="true" readOnly="true" default="local-cache" description="Type of cache">
             <c:property-options>
-              <c:option value="local-cache"/>
               <c:option value="invalidation-cache"/>
               <c:option value="distributed-cache"/>
               <c:option value="replicated-cache"/>
             </c:property-options>
           </c:simple-property>
-          <c:template name="Local Cache" description="Local Cache">
-            <c:simple-property name="__type" readOnly="true" default="local-cache"/>
-          </c:template>
           <c:template name="Invalidation Cache" description="Invalidation Cache">
             <c:simple-property name="__type" readOnly="true" default="invalidation-cache"/>
           </c:template>
@@ -11208,6 +11237,43 @@
         </resource-configuration>
       </service>
 
+      <service name="Local Cache"
+               discovery="SubsystemDiscovery"
+               class="BaseComponent"
+               createDeletePolicy="both"
+               creationDataType="configuration">
+
+        <plugin-configuration>
+          <c:simple-property name="path" readOnly="true" default="local-cache"/>
+        </plugin-configuration>
+
+        <resource-configuration>
+          <c:simple-property name="start" required="false" type="string" readOnly="false" default="LAZY" description="The cache start mode, which can be EAGER (immediate start) or LAZY (on-demand start).">
+            <c:property-options>
+              <c:option value="LAZY"/>
+              <c:option value="EAGER"/>
+            </c:property-options>
+          </c:simple-property>
+          <c:simple-property name="batching" required="false" type="boolean" readOnly="false" default="false" description="If enabled, the invocation batching API will be made available for this cache."/>
+          <c:simple-property name="indexing" required="false" type="string" readOnly="false" default="NONE" description="If enabled, entries will be indexed when they are added to the cache. Indexes will be updated as entries change or are removed.">
+            <c:property-options>
+              <c:option value="NONE"/>
+              <c:option value="LOCAL"/>
+              <c:option value="ALL"/>
+            </c:property-options>
+          </c:simple-property>
+          <c:simple-property name="jndi-name" required="false" type="string" readOnly="false" description="The jndi-name to which to bind this cache instance."/>
+          <c:simple-property name="queue-size" required="false" type="integer" readOnly="false" default="0" description="In ASYNC mode, this attribute can be used to trigger flushing of the queue when it reaches a specific threshold."/>
+          <c:simple-property name="queue-flush-interval" required="false" type="long" readOnly="false" default="10" description="In ASYNC mode, this attribute controls how often the asynchronous thread used to flush the replication queue runs. This should be a positive integer which represents thread wakeup time in milliseconds."/>
+          <c:simple-property name="remote-timeout" required="false" type="long" readOnly="false" default="17500" description="In SYNC mode, the timeout (in ms) used to wait for an acknowledgment when making a remote call, after which the call is aborted and an exception is thrown."/>
+          <c:simple-property name="async-marshalling" required="false" type="boolean" readOnly="false" defaultValue="false" description="If enabled, this will cause marshalling of entries to be performed asynchronously. The default value is false."/>
+          <c:simple-property name="l1-lifespan" required="false" type="long" readOnly="false" defaultValue="600000" description="Maximum lifespan of an entry placed in the L1 cache. This element configures the L1 cache behavior in &apos;distributed&apos; caches instances. In any other cache modes, this element is ignored. The default value is 600000."/>
+          <c:simple-property name="module" required="false" type="string" readOnly="false" description="The module whose class loader should be used when building this cache&apos;s configuration."/>
+          <c:simple-property name="owners" required="false" type="integer" readOnly="false" defaultValue="2" description="Number of cluster&#45;wide replicas for each cache entry. The default value is 2."/>
+          <c:simple-property name="virtual-nodes" required="false" type="integer" readOnly="false" defaultValue="1" description="Controls the number of virtual nodes per &apos;real&apos; node. If numVirtualNodes is 1, then virtual nodes are disabled. The topology aware consistent hash must be used if you wish to take advantage of virtual nodes. A default of 1 is used. The default value is 1."/>
+        </resource-configuration>
+      </service>
+
       <service name="Transport"
                discovery="SubsystemDiscovery"
                class="BaseComponent"


commit 7ac429112405857b728cacbc767ab71bdd809292
Author: John Sanda <jsanda at redhat.com>
Date:   Mon Jun 18 09:44:17 2012 -0400

    [BZ 786614] Add some error logging  if we cannot find a resource container
    
    We should not be in state where the method getAbsoluteBaseDirectory is
    passed a resource id that does not have a corresponding resource
    container in the local inventory. If that does happen, we will now log
    an error message that includes the resource id and drift definition to
    facilitate further debugging. Then an IllegalArgumentException is
    thrown.

diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftManager.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftManager.java
index 0a4f5c3..0924288 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftManager.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/drift/DriftManager.java
@@ -664,6 +664,15 @@ public class DriftManager extends AgentService implements DriftAgentService, Dri
         // get the resource entity stored in our local inventory
         InventoryManager im = getInventoryManager();
         ResourceContainer container = im.getResourceContainer(resourceId);
+
+        if (container == null) {
+            log.error("Cannot determine base directory for " + driftDefinition + ". No resource container found " +
+                "for resource id " + resourceId + ". You may want to restart the agent with the -u option so that " +
+                "the agent's local inventory is synchronized with and consistent with the server's inventory.");
+            throw new IllegalArgumentException("Cannot determine base directory for " + driftDefinition +
+                ". No resource container found for resource id " + resourceId);
+        }
+
         Resource resource = container.getResource();
 
         // find out the type of base location that is specified by the drift def


commit 5c2899d3522c7caa886c8355d88fc41a3076c4a8
Author: Stefan Negrea <snegrea at redhat.com>
Date:   Mon Jun 18 08:40:35 2012 -0500

    Updates for generic integration tests. Moved generic code to base classes and added more ignored resources due to open JIRAs and BZs.

diff --git a/modules/core/plugin-test-util/src/main/java/org/rhq/core/plugin/testutil/AbstractAgentPluginTest.java b/modules/core/plugin-test-util/src/main/java/org/rhq/core/plugin/testutil/AbstractAgentPluginTest.java
index 97f3f9a..e60349c 100644
--- a/modules/core/plugin-test-util/src/main/java/org/rhq/core/plugin/testutil/AbstractAgentPluginTest.java
+++ b/modules/core/plugin-test-util/src/main/java/org/rhq/core/plugin/testutil/AbstractAgentPluginTest.java
@@ -18,19 +18,29 @@
  */
 package org.rhq.core.plugin.testutil;
 
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
 import java.io.File;
 import java.io.FilenameFilter;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.EnumSet;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import java.util.Queue;
 import java.util.Set;
 import java.util.TreeSet;
 
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.mockito.Mockito;
@@ -44,7 +54,9 @@ import org.jboss.shrinkwrap.resolver.api.DependencyResolvers;
 import org.jboss.shrinkwrap.resolver.api.maven.MavenDependencyResolver;
 
 import org.rhq.core.clientapi.agent.PluginContainerException;
+import org.rhq.core.clientapi.agent.configuration.ConfigurationUpdateRequest;
 import org.rhq.core.clientapi.agent.configuration.ConfigurationUtility;
+import org.rhq.core.clientapi.server.configuration.ConfigurationUpdateResponse;
 import org.rhq.core.clientapi.server.discovery.InventoryReport;
 import org.rhq.core.domain.configuration.Configuration;
 import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
@@ -63,6 +75,7 @@ import org.rhq.core.domain.util.MeasurementDefinitionFilter;
 import org.rhq.core.domain.util.ResourceTypeUtility;
 import org.rhq.core.pc.PluginContainer;
 import org.rhq.core.pc.PluginContainerConfiguration;
+import org.rhq.core.pc.configuration.ConfigurationManager;
 import org.rhq.core.pc.inventory.ResourceContainer;
 import org.rhq.core.pc.util.FacetLockType;
 import org.rhq.core.pluginapi.availability.AvailabilityFacet;
@@ -79,11 +92,6 @@ import org.rhq.test.arquillian.FakeServerInventory;
 import org.rhq.test.arquillian.MockingServerServices;
 import org.rhq.test.shrinkwrap.RhqAgentPluginArchive;
 
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertNull;
-import static org.testng.Assert.assertTrue;
-
 /**
  * The base class for an Agent plugin integration test class.
  *
@@ -91,6 +99,8 @@ import static org.testng.Assert.assertTrue;
  */
 public abstract class AbstractAgentPluginTest extends Arquillian {
 
+    private Log log = LogFactory.getLog(this.getClass());
+
     @ArquillianResource
     protected MockingServerServices serverServices;
 
@@ -589,4 +599,123 @@ public abstract class AbstractAgentPluginTest extends Arquillian {
         return serverInventory;
     }
 
+    /**
+     * Test that loads a resource configuration and then immediately updates the resource
+     * with the exact same loaded settings.
+     *
+     * Notes:
+     * 1) load/update is not executed on the root resource provided.
+     * 2) if a resource is ignored then all of subresource of that resources are ignored
+     *
+     * @param rootResource root resource
+     * @param ignoredResources resources to be ignored
+     * @return number of errors
+     * @throws InterruptedException
+     * @throws PluginContainerException
+     */
+    protected int loadUpdateConfigChildResources(Resource rootResource, List<String> ignoredResources)
+        throws InterruptedException, PluginContainerException {
+
+        ignoredResources = (ignoredResources == null) ? new ArrayList<String>() : ignoredResources;
+
+        ConfigurationManager configManager = this.pluginContainer.getConfigurationManager();
+        configManager.initialize();
+        Thread.sleep(10 * 1000L);
+
+        Queue<Resource> unparsedResources = new LinkedList<Resource>();
+        addCommitedChildrenToCollection(unparsedResources, rootResource, ignoredResources);
+
+        int errorCount = 0;
+
+        while (!unparsedResources.isEmpty()) {
+            Resource resourceUnderTest = unparsedResources.poll();
+
+            addCommitedChildrenToCollection(unparsedResources, resourceUnderTest, ignoredResources);
+
+            if (resourceUnderTest.getResourceType().getResourceConfigurationDefinition() != null) {
+                Configuration configUnderTest = configManager.loadResourceConfiguration(resourceUnderTest.getId());
+
+                ConfigurationUpdateRequest updateRequest = new ConfigurationUpdateRequest(1, configUnderTest,
+                    resourceUnderTest.getId());
+                ConfigurationUpdateResponse updateResponse = configManager
+                    .executeUpdateResourceConfigurationImmediately(updateRequest);
+
+                if (updateResponse == null) {
+                    errorCount++;
+                    log.error("------------------------------");
+                    log.error(resourceUnderTest);
+                    log.error("Update Response is NULL!!!!");
+                    log.error("------------------------------\n");
+                }
+                if (updateResponse.getErrorMessage() != null) {
+                    errorCount++;
+                    log.error("------------------------------");
+                    log.error(resourceUnderTest);
+                    log.error(updateResponse.getErrorMessage());
+                    log.error("------------------------------\n");
+                }
+            }
+        }
+
+        return errorCount;
+    }
+
+    /**
+     * Test that executes all the no arg operations for all the subresources of a provided resource.
+     * Notes:
+     * 1) no operations are executed on the root resource provided.
+     * 2) if a resource is ignored then all of subresource of that resources are ignored
+     *
+     * @param rootResource root resource
+     * @param ignoredResources resources to be ignored
+     * @param ignoredOperations operations to be ignored
+     * @throws PluginContainerException
+     */
+    protected void executeNoArgOperations(Resource rootResource, List<String> ignoredResources,
+        List<String> ignoredOperations) throws PluginContainerException {
+
+        ignoredResources = (ignoredResources == null) ? new ArrayList<String>() : ignoredResources;
+        ignoredOperations = (ignoredOperations == null) ? new ArrayList<String>() : ignoredOperations;
+
+        Queue<Resource> unparsedResources = new LinkedList<Resource>();
+        addCommitedChildrenToCollection(unparsedResources, rootResource, ignoredResources);
+
+        while (!unparsedResources.isEmpty()) {
+            Resource resourceUnderTest = unparsedResources.poll();
+
+            addCommitedChildrenToCollection(unparsedResources, resourceUnderTest, ignoredResources);
+
+            for (OperationDefinition operationUnderTest : resourceUnderTest.getResourceType().getOperationDefinitions()) {
+                if (!ignoredOperations.contains(operationUnderTest.getName())) {
+                    if (operationUnderTest.getParametersConfigurationDefinition() == null
+                        || operationUnderTest.getParametersConfigurationDefinition().getPropertyDefinitions().isEmpty()) {
+                        this.invokeOperationAndAssertSuccess(resourceUnderTest, operationUnderTest.getName(),
+                            new Configuration());
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Adds direct subresources of resources to a collection.
+     *
+     * @param accumulatorCollection accumulator collection
+     * @param rootResource root resource
+     * @param ignoredResources resources to be ignored
+     */
+    private void addCommitedChildrenToCollection(Collection<Resource> accumulatorCollection, Resource rootResource,
+        List<String> ignoredResources) {
+        for (Resource childResource : rootResource.getChildResources()) {
+            if (childResource.getInventoryStatus().equals(InventoryStatus.COMMITTED)) {
+                if( !ignoredResources.contains(childResource.getResourceType().getName())) {
+                    accumulatorCollection.add(childResource);
+                }
+            } else {
+                log.info("Resource NOT COMMITTED --> not added to collection!! - " + childResource + " - "
+                    + childResource.getInventoryStatus());
+            }
+        }
+    }
+
 }
diff --git a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/ResourcesStandaloneServerTest.java b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/ResourcesStandaloneServerTest.java
index d11e7ab..f2d601c 100644
--- a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/ResourcesStandaloneServerTest.java
+++ b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/ResourcesStandaloneServerTest.java
@@ -24,22 +24,15 @@ import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertNotNull;
 
 import java.util.ArrayList;
-import java.util.LinkedList;
 import java.util.List;
-import java.util.Queue;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.testng.Assert;
 import org.testng.annotations.Test;
 
-import org.rhq.core.clientapi.agent.configuration.ConfigurationUpdateRequest;
-import org.rhq.core.clientapi.server.configuration.ConfigurationUpdateResponse;
-import org.rhq.core.domain.configuration.Configuration;
-import org.rhq.core.domain.operation.OperationDefinition;
 import org.rhq.core.domain.resource.InventoryStatus;
 import org.rhq.core.domain.resource.Resource;
-import org.rhq.core.pc.configuration.ConfigurationManager;
 import org.rhq.core.pc.inventory.InventoryManager;
 import org.rhq.core.pc.inventory.ResourceContainer;
 import org.rhq.modules.plugins.jbossas7.itest.AbstractJBossAS7PluginTest;
@@ -69,7 +62,7 @@ public class ResourcesStandaloneServerTest extends AbstractJBossAS7PluginTest  {
             StandaloneServerComponentTest.RESOURCE_KEY);
         inventoryManager.activateResource(server, platformContainer, false);
 
-        Thread.sleep(20 * 1000L);
+        Thread.sleep(40 * 1000L);
     }
 
 
@@ -81,103 +74,46 @@ public class ResourcesStandaloneServerTest extends AbstractJBossAS7PluginTest  {
         //works well with real agent
         ignoredResources.add("VHost");
 
-        //ignored because the settings different when started with arquillian, inet-address is not set correctly
-        //works well with real agent
+        //created JIRA AS7-5011
+        //server is started with the configuration but unable to write it back as is
+        //due to marshaling error
         ignoredResources.add("Network Interface");
 
+        //created JIRA AS7-5012
+        //default value for  is float but the resource only accepts integers
+        ignoredResources.add("Load Metric");
+
+        //will revisit after BZ 826542 is resolved
+        ignoredResources.add("Authentication (Classic)");
+
         Resource platform = this.pluginContainer.getInventoryManager().getPlatform();
         Resource server = getResourceByTypeAndKey(platform, StandaloneServerComponentTest.RESOURCE_TYPE,
             StandaloneServerComponentTest.RESOURCE_KEY);
 
-        ConfigurationManager configurationManager = this.pluginContainer.getConfigurationManager();
-        configurationManager.initialize();
-        Thread.sleep(40 * 1000L);
-
-        Queue<Resource> unparsedResources = new LinkedList<Resource>();
-        for (Resource topLevelResource : server.getChildResources()) {
-            if (topLevelResource.getInventoryStatus().equals(InventoryStatus.COMMITTED)) {
-                unparsedResources.add(topLevelResource);
-            } else {
-                log.info("Subsystem not COMMITTED " + topLevelResource + " - " + topLevelResource.getInventoryStatus());
-            }
-        }
-
-        int errorCount = 0;
-
-        while (!unparsedResources.isEmpty()) {
-            Resource resourceUnderTest = unparsedResources.poll();
-
-            for (Resource childResource : resourceUnderTest.getChildResources()) {
-                if (childResource.getInventoryStatus().equals(InventoryStatus.COMMITTED)) {
-                    unparsedResources.add(childResource);
-                } else {
-                    log.info("Subsystem not COMMITTED " + childResource + " - " + childResource.getInventoryStatus());
-                }
-            }
-
-            if (resourceUnderTest.getResourceType().getResourceConfigurationDefinition() != null
-                && !ignoredResources.contains(resourceUnderTest.getResourceType().getName())) {
-                Configuration configUnderTest = configurationManager
-                    .loadResourceConfiguration(resourceUnderTest.getId());
-
-                ConfigurationUpdateRequest updateRequest = new ConfigurationUpdateRequest(1, configUnderTest,
-                    resourceUnderTest.getId());
-                ConfigurationUpdateResponse updateResponse = configurationManager
-                    .executeUpdateResourceConfigurationImmediately(updateRequest);
-
-                Assert.assertNotNull(updateResponse);
-                if (updateResponse.getErrorMessage() != null) {
-                    errorCount++;
-                    log.error("------------------------------");
-                    log.error(resourceUnderTest);
-                    log.error(updateResponse.getErrorMessage());
-                    log.error("------------------------------");
-                }
-            }
-        }
-
+        int errorCount = loadUpdateConfigChildResources(server, ignoredResources);
         Assert.assertEquals(errorCount, 0);
     }
 
     @Test(priority = 11)
-    public void executeNoArgOperations() throws Exception {
+    public void standaloneExecuteNoArgOperations() throws Exception {
         List<String> ignoredSubsystems = new ArrayList<String>();
+
+        //ignored because mod_cluster is not setup in default server configuration
+        //to be more specific, there is no server to fail-over to
         ignoredSubsystems.add("ModCluster Standalone Service");
 
         List<String> ignoredOperations = new ArrayList<String>();
+        //ignored because there is no other server to fail-over to
         ignoredOperations.add("subsystem:force-failover");
+        //ignored because this is not a true operation, it is handled
+        //internally by a configuration property change
         ignoredOperations.add("enable");
 
         Resource platform = this.pluginContainer.getInventoryManager().getPlatform();
         Resource server = getResourceByTypeAndKey(platform, StandaloneServerComponentTest.RESOURCE_TYPE,
             StandaloneServerComponentTest.RESOURCE_KEY);
 
-        Queue<Resource> unparsedResources = new LinkedList<Resource>();
-        for (Resource topLevelResource : server.getChildResources()) {
-            if (topLevelResource.getInventoryStatus().equals(InventoryStatus.COMMITTED)
-                && !ignoredSubsystems.contains(topLevelResource.getResourceType().getName())) {
-                unparsedResources.add(topLevelResource);
-            }
-        }
-
-        while (!unparsedResources.isEmpty()) {
-            Resource resourceUnderTest = unparsedResources.poll();
-
-            for (Resource childResource : resourceUnderTest.getChildResources()) {
-                if (childResource.getInventoryStatus().equals(InventoryStatus.COMMITTED)) {
-                    unparsedResources.add(childResource);
-                }
-            }
-
-            for (OperationDefinition operationUnderTest : resourceUnderTest.getResourceType().getOperationDefinitions()) {
-                if (!ignoredOperations.contains(operationUnderTest.getName())) {
-                    if (operationUnderTest.getParametersConfigurationDefinition() == null
-                        || operationUnderTest.getParametersConfigurationDefinition().getPropertyDefinitions().isEmpty()) {
-                        this.invokeOperationAndAssertSuccess(resourceUnderTest, operationUnderTest.getName(),
-                            new Configuration());
-                    }
-                }
-            }
-        }
+        executeNoArgOperations(server, ignoredSubsystems, ignoredOperations);
     }
+
 }


commit 9c27510ac57d09e8283841810f4a889a33760e5f
Author: Heiko W. Rupp <hwr at redhat.com>
Date:   Mon Jun 18 15:21:00 2012 +0200

    Improvements in operation scheduling.

diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java
index 8b827b8..73a4ebb 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java
@@ -1,6 +1,6 @@
 /*
  * RHQ Management Platform
- * Copyright (C) 2005-2011 Red Hat, Inc.
+ * Copyright (C) 2005-2012 Red Hat, Inc.
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
@@ -30,7 +30,6 @@ import javax.interceptor.Interceptors;
 import javax.ws.rs.core.EntityTag;
 import javax.ws.rs.core.GenericEntity;
 import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Request;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriBuilder;
@@ -41,6 +40,7 @@ import org.rhq.core.domain.configuration.Property;
 import org.rhq.core.domain.configuration.PropertySimple;
 import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
 import org.rhq.core.domain.configuration.definition.PropertyDefinition;
+import org.rhq.core.domain.configuration.definition.PropertyDefinitionSimple;
 import org.rhq.core.domain.criteria.ResourceOperationHistoryCriteria;
 import org.rhq.core.domain.operation.HistoryJobId;
 import org.rhq.core.domain.operation.JobId;
@@ -55,6 +55,7 @@ import org.rhq.enterprise.server.rest.domain.Link;
 import org.rhq.enterprise.server.rest.domain.OperationDefinitionRest;
 import org.rhq.enterprise.server.rest.domain.OperationHistoryRest;
 import org.rhq.enterprise.server.rest.domain.OperationRest;
+import org.rhq.enterprise.server.rest.domain.SimplePropDef;
 
 /**
  * Deal with operations
@@ -96,6 +97,8 @@ public class OperationsHandlerBean extends AbstractRestBean implements Operation
             odr.setId(def.getId());
             odr.setName(def.getName());
 
+            copyParamsForDefinition(def, odr);
+
             builder=Response.ok(odr);
 
             // Add some links
@@ -115,6 +118,26 @@ public class OperationsHandlerBean extends AbstractRestBean implements Operation
 
     }
 
+    private void copyParamsForDefinition(OperationDefinition def, OperationDefinitionRest odr) {
+        ConfigurationDefinition cd = def.getParametersConfigurationDefinition();
+        if (cd==null)
+            return;
+
+        for (Map.Entry<String,PropertyDefinition> entry : cd.getPropertyDefinitions().entrySet()) {
+            PropertyDefinition pd = entry.getValue();
+            if (pd instanceof PropertyDefinitionSimple) {
+                PropertyDefinitionSimple pds = (PropertyDefinitionSimple) pd;
+                SimplePropDef prop = new SimplePropDef();
+                prop.setName(pds.getName());
+                prop.setRequired(pds.isRequired());
+                prop.setType(pds.getType());
+                prop.setDefaultValue(pds.getDefaultValue());
+                odr.addParam(prop);
+            }
+            log.debug("copyParams: " + pd.getName() + " not yet supported");
+        }
+    }
+
     @Override
     public Response getOperationDefinitions(Integer resourceId, UriInfo uriInfo, Request request) {
 
@@ -139,6 +162,9 @@ public class OperationsHandlerBean extends AbstractRestBean implements Operation
                 OperationDefinitionRest odr = new OperationDefinitionRest();
                 odr.setId(def.getId());
                 odr.setName(def.getName());
+
+                copyParamsForDefinition(def,odr);
+
                 UriBuilder uriBuilder = uriInfo.getBaseUriBuilder();
                 uriBuilder.path("/operation/definition/{id}");
                 uriBuilder.queryParam("resourceId",resourceId);
@@ -174,7 +200,7 @@ public class OperationsHandlerBean extends AbstractRestBean implements Operation
         }
         OperationRest operationRest = new OperationRest(resourceId,definitionId);
         operationRest.setId((int)System.currentTimeMillis()); // TODO better id (?)(we need one for pUT later on)
-        operationRest.setState("creating");
+        operationRest.setReadyToSubmit(false);
         operationRest.setName(opDef.getName());
         ConfigurationDefinition paramDefinition = opDef.getParametersConfigurationDefinition();
         if (paramDefinition != null) {
@@ -208,11 +234,11 @@ public class OperationsHandlerBean extends AbstractRestBean implements Operation
     @Override
     public Response updateOperation(int operationId, OperationRest operation, UriInfo uriInfo) {
 
-        if (operation.getState().equals("creating") && operation.getDefinitionId()>0 && !operation.getName().isEmpty()) {
+        if (!operation.isReadyToSubmit() && operation.getDefinitionId()>0 && !operation.getName().isEmpty()) {
             // TODO check all the required parameters for presence before allowing to submit
-            operation.setState("ready");
+            operation.setReadyToSubmit(true);
         }
-        if (operation.getState().equals("ready")) {
+        if (operation.isReadyToSubmit()) {
             // todo check params
 
             // submit
@@ -222,7 +248,7 @@ public class OperationsHandlerBean extends AbstractRestBean implements Operation
                 parameters.put(new PropertySimple(entry.getKey(),entry.getValue())); // TODO honor more types
             }
             ResourceOperationSchedule sched = opsManager.scheduleResourceOperation(caller,operation.getResourceId(),operation.getName(),0,0,0,-1,
-                    parameters,"TEst");
+                    parameters,"Test");
             JobId jobId = new JobId(sched.getJobName(),sched.getJobGroup());
             UriBuilder uriBuilder = uriInfo.getBaseUriBuilder();
             uriBuilder.path("/operation/history/{id}");
@@ -271,7 +297,7 @@ public class OperationsHandlerBean extends AbstractRestBean implements Operation
         history = list.get(0);
         String status;
         if (history.getStatus()==null)
-            status = " - no infomation yet -";
+            status = " - no information yet -";
         else
             status = history.getStatus().getDisplayName();
 
@@ -282,7 +308,12 @@ public class OperationsHandlerBean extends AbstractRestBean implements Operation
         if (history.getResults()!=null) {
             Configuration results = history.getResults();
             for (Property p : results.getProperties()) {
-                hist.getResult().put(p.getName(),p.toString());
+                String val;
+                if (p instanceof PropertySimple)
+                    val = ((PropertySimple)p).getStringValue();
+                else
+                    val = p.toString();
+                hist.getResult().put(p.getName(),val);
             }
         }
 
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/OperationDefinitionRest.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/OperationDefinitionRest.java
index 70f1a97..06cbbcf 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/OperationDefinitionRest.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/OperationDefinitionRest.java
@@ -1,7 +1,9 @@
 package org.rhq.enterprise.server.rest.domain;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 import javax.xml.bind.annotation.XmlElementRef;
 import javax.xml.bind.annotation.XmlRootElement;
@@ -18,7 +20,7 @@ public class OperationDefinitionRest {
     String name;
     int id;
     List<Link> links = new ArrayList<Link>();
-    // TODO add parameters
+    List<SimplePropDef> params = new ArrayList<SimplePropDef>();
 
     public String getName() {
         return name;
@@ -49,4 +51,15 @@ public class OperationDefinitionRest {
         links.add(link);
     }
 
+    public List<SimplePropDef> getParams() {
+        return params;
+    }
+
+    public void setParams(List<SimplePropDef> params) {
+        this.params = params;
+    }
+
+    public void addParam(SimplePropDef prop) {
+        params.add(prop);
+    }
 }
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/OperationRest.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/OperationRest.java
index 50332ae..31f51dc 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/OperationRest.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/OperationRest.java
@@ -16,7 +16,7 @@ public class OperationRest {
 
     int id;
     String name;
-    String state; // TODO Convert to enum
+    boolean readyToSubmit;
     int resourceId;
     int definitionId;
     Map<String,Object> params = new HashMap<String, Object>();
@@ -46,12 +46,12 @@ public class OperationRest {
         this.name = name;
     }
 
-    public String getState() {
-        return state;
+    public boolean isReadyToSubmit() {
+        return readyToSubmit;
     }
 
-    public void setState(String state) {
-        this.state = state;
+    public void setReadyToSubmit(boolean readyToSubmit) {
+        this.readyToSubmit = readyToSubmit;
     }
 
     public int getResourceId() {
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/SimplePropDef.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/SimplePropDef.java
new file mode 100644
index 0000000..08527fd
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/SimplePropDef.java
@@ -0,0 +1,72 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 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.rest.domain;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.rhq.core.domain.configuration.definition.PropertySimpleType;
+
+/**
+ * Simple property definition
+ * @author Heiko W. Rupp
+ */
+ at XmlRootElement
+public class SimplePropDef {
+
+    String name;
+    boolean required;
+    PropertySimpleType type;
+    String defaultValue;
+
+    public SimplePropDef() {
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public boolean isRequired() {
+        return required;
+    }
+
+    public void setRequired(boolean required) {
+        this.required = required;
+    }
+
+    public PropertySimpleType getType() {
+        return type;
+    }
+
+    public void setType(PropertySimpleType type) {
+        this.type = type;
+    }
+
+    public String getDefaultValue() {
+        return defaultValue;
+    }
+
+    public void setDefaultValue(String defaultValue) {
+        this.defaultValue = defaultValue;
+    }
+}


commit d35d0f2fb6ae66ed339dbe2099a9d475a3d0cea6
Merge: 6bd2fa8 bc0ab10
Author: Lukas Krejci <lkrejci at redhat.com>
Date:   Mon Jun 18 13:05:37 2012 +0200

    Merge branch 'master' into lkrejci/modular-scripting

diff --cc modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java
index 5021434,99595ab..7ebe141
--- a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java
+++ b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java
@@@ -22,11 -22,7 +22,8 @@@
   */
  package org.rhq.enterprise.client;
  
- import gnu.getopt.Getopt;
- import gnu.getopt.LongOpt;
- 
  import java.io.ByteArrayInputStream;
 +import java.io.File;
  import java.io.IOException;
  import java.io.InputStreamReader;
  import java.io.PrintWriter;
@@@ -37,9 -32,14 +34,9 @@@ import java.util.HashMap
  import java.util.List;
  import java.util.Map;
  
- import javax.script.ScriptEngine;
- import javax.script.ScriptException;
 -import org.rhq.core.domain.auth.Subject;
 -import org.rhq.enterprise.client.commands.ClientCommand;
 -import org.rhq.enterprise.client.commands.ScriptCommand;
 -import org.rhq.enterprise.client.script.CommandLineParseException;
 -import org.rhq.enterprise.clientapi.RemoteClient;
 -
+ import gnu.getopt.Getopt;
+ import gnu.getopt.LongOpt;
 +
  import jline.ArgumentCompletor;
  import jline.Completor;
  import jline.ConsoleReader;
@@@ -47,14 -47,6 +44,12 @@@ import jline.MultiCompletor
  import jline.SimpleCompletor;
  import mazz.i18n.Msg;
  
- import org.rhq.bindings.ScriptEngineFactory;
- import org.rhq.bindings.util.PackageFinder;
 +import org.rhq.core.domain.auth.Subject;
 +import org.rhq.enterprise.client.commands.ClientCommand;
 +import org.rhq.enterprise.client.commands.ScriptCommand;
 +import org.rhq.enterprise.client.script.CommandLineParseException;
 +import org.rhq.enterprise.clientapi.RemoteClient;
 +
  /**
   * @author Greg Hinkle
   * @author Simeon Pinder


commit bc0ab1018da30382a30d19aa1907837c0ad121ae
Author: Ian Springer <ian.springer at redhat.com>
Date:   Sat Jun 16 10:49:16 2012 -0400

    add needed stuff to get JBoss Nexus to accept the artifact

diff --git a/etc/rhq-ircBot/pom.xml b/etc/rhq-ircBot/pom.xml
index c747084..40b6952 100644
--- a/etc/rhq-ircBot/pom.xml
+++ b/etc/rhq-ircBot/pom.xml
@@ -13,6 +13,28 @@
 
   <name>RHQ IRC Bot</name>
   <description>an IRC bot for doing helpful stuff on the Freenode #rhq channel</description>
+  <url>http://www.jboss.org/rhq/</url>
+
+  <scm>
+    <connection>scm:git:git://git.fedorahosted.org/rhq/rhq.git</connection>
+    <developerConnection>scm:git:ssh://git.fedorahosted.org/git/rhq/rhq.git</developerConnection>
+    <url>http://git.fedorahosted.org/git/rhq/rhq.git</url>
+  </scm>
+
+  <licenses>
+    <license>
+      <name>GPL</name>
+      <url>http://www.gnu.org/licenses/gpl.html</url>
+    </license>
+  </licenses>
+
+  <developers>
+    <developer>
+      <name>Ian Springer</name>
+      <timezone>-5</timezone>
+      <url>http://freshjava.blogspot.com/</url>
+    </developer>
+  </developers>
 
   <dependencies>
 
@@ -72,10 +94,37 @@
         </executions>
       </plugin>
 
-    </plugins>
+      <plugin>
+        <artifactId>maven-source-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>attach-sources</id>
+            <goals>
+              <goal>jar</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
 
+    </plugins>
 
   </build>
 
+  <distributionManagement>
+
+    <snapshotRepository>
+      <id>jboss-snapshots-repository</id>
+      <name>JBoss Snapshots Repository</name>
+      <url>https://repository.jboss.org/nexus/content/repositories/snapshots/</url>
+    </snapshotRepository>
+
+    <repository>
+      <id>jboss-releases-repository</id>
+      <name>JBoss Releases Repository</name>
+      <url>https://repository.jboss.org/nexus/service/local/staging/deploy/maven2/</url>
+    </repository>
+
+  </distributionManagement>
+
 </project>
 


commit a8af1970fd5bec8e03a8e186f4b43f46becd207e
Author: Heiko W. Rupp <hwr at redhat.com>
Date:   Sat Jun 16 15:17:00 2012 +0200

    Display availability history.

diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
index b76d7d1..c0efed4 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
@@ -1,6 +1,6 @@
 /*
  * RHQ Management Platform
- * Copyright (C) 2005-2011 Red Hat, Inc.
+ * Copyright (C) 2005-2012 Red Hat, Inc.
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
@@ -47,6 +47,7 @@ import javax.ws.rs.core.UriInfo;
 
 import org.rhq.core.domain.alert.Alert;
 import org.rhq.core.domain.criteria.AlertCriteria;
+import org.rhq.core.domain.criteria.AvailabilityCriteria;
 import org.rhq.core.domain.discovery.AvailabilityReport;
 import org.rhq.core.domain.measurement.Availability;
 import org.rhq.core.domain.measurement.AvailabilityType;
@@ -59,6 +60,7 @@ import org.rhq.core.domain.resource.Resource;
 import org.rhq.core.domain.resource.ResourceCategory;
 import org.rhq.core.domain.resource.ResourceType;
 import org.rhq.core.domain.util.PageControl;
+import org.rhq.core.domain.util.PageOrdering;
 import org.rhq.enterprise.server.RHQConstants;
 import org.rhq.enterprise.server.alert.AlertManagerLocal;
 import org.rhq.enterprise.server.core.AgentManagerLocal;
@@ -207,6 +209,47 @@ public class ResourceHandlerBean extends AbstractRestBean implements ResourceHan
     }
 
     @Override
+    public Response getAvailabilityHistory(int resourceId, long start, long end, HttpHeaders headers) {
+        if (end==0)
+            end = System.currentTimeMillis();
+
+        if (start==0)
+            start = end - (30*86400*1000L); // 30 days
+
+        AvailabilityCriteria criteria = new AvailabilityCriteria();
+        criteria.addFilterInterval(start,end);
+        criteria.addFilterResourceId(resourceId);
+        criteria.addSortStartTime(PageOrdering.DESC);
+        List<Availability> points = availMgr.findAvailabilityByCriteria(caller,criteria);
+        List<AvailabilityRest> ret = new ArrayList<AvailabilityRest>(points.size());
+        for (Availability avail : points) {
+            AvailabilityRest availabilityRest;
+            if (avail.getAvailabilityType() != null) {
+                availabilityRest = new AvailabilityRest(avail.getAvailabilityType(), avail.getStartTime(), avail
+                    .getResource().getId());
+            }
+            else {
+                availabilityRest = new AvailabilityRest(avail.getStartTime(), resourceId);
+            }
+            if (avail.getEndTime()!=null)
+                availabilityRest.setUntil(avail.getEndTime());
+            ret.add(availabilityRest);
+        }
+        MediaType mediaType = headers.getAcceptableMediaTypes().get(0);
+        Response.ResponseBuilder builder;
+
+        if (mediaType.equals(MediaType.TEXT_HTML_TYPE)) {
+            builder = Response.ok(renderTemplate("listAvailability.ftl",ret), mediaType);
+        } else {
+            GenericEntity<List<AvailabilityRest>> availabilityRest = new GenericEntity<List<AvailabilityRest>>(ret) {};
+            builder = Response.ok(availabilityRest);
+        }
+        return builder.build();
+
+    }
+
+
+    @Override
     public void reportAvailability(int resourceId, AvailabilityRest avail) {
         if (avail.getResourceId() != resourceId)
             throw new IllegalArgumentException("Resource Ids do not match");
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerLocal.java
index 7ae0c0b..867a0e4 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerLocal.java
@@ -1,6 +1,6 @@
 /*
  * RHQ Management Platform
- * Copyright (C) 2005-2011 Red Hat, Inc.
+ * Copyright (C) 2005-2012 Red Hat, Inc.
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
@@ -90,7 +90,6 @@ public interface ResourceHandlerLocal {
     ResourceWithChildren getHierarchy(
             @ApiParam("Id of the resource to start with") @PathParam("id")int baseResourceId);
 
-    @LinkResource(rel = "availability", value = AvailabilityRest.class)
     @GET
     @Path("/{id}/availability")
     @ApiError(code = 404, reason = NO_RESOURCE_FOR_ID)
@@ -98,6 +97,17 @@ public interface ResourceHandlerLocal {
     Response getAvailability(
             @ApiParam("Id of the resource to query") @PathParam("id") int resourceId, @Context HttpHeaders headers);
 
+    @GET
+    @Path("/{id}/availability/history")
+    @ApiError(code = 404, reason = NO_RESOURCE_FOR_ID)
+    @ApiOperation(value = "Return the availability history for the passed resource", responseClass = "AvailabilityRest", multiValueResponse = true)
+    Response getAvailabilityHistory(
+            @ApiParam("Id of the resource to query") @PathParam("id") int resourceId,
+            @ApiParam(value="Start time", defaultValue = "30 days ago") @QueryParam("start") long start,
+            @ApiParam(value="End time", defaultValue = "Now") @QueryParam("end") long end,
+
+             @Context HttpHeaders headers);
+
     @PUT
     @Path("/{id}/availability")
     @ApiOperation("Set the current availability of the passed resource")
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/AvailabilityRest.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/AvailabilityRest.java
index 2534198..2710660 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/AvailabilityRest.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/AvailabilityRest.java
@@ -35,6 +35,7 @@ public class AvailabilityRest {
 
     long since;
     String type;
+    Long until;
 
     int resourceId;
 
@@ -80,4 +81,12 @@ public class AvailabilityRest {
     public void setResourceId(int resourceId) {
         this.resourceId = resourceId;
     }
+
+    public Long getUntil() {
+        return until;
+    }
+
+    public void setUntil(Long until) {
+        this.until = until;
+    }
 }
diff --git a/modules/enterprise/server/jar/src/main/resources/rest_templates/availability.ftl b/modules/enterprise/server/jar/src/main/resources/rest_templates/availability.ftl
index d02558a..388d761 100644
--- a/modules/enterprise/server/jar/src/main/resources/rest_templates/availability.ftl
+++ b/modules/enterprise/server/jar/src/main/resources/rest_templates/availability.ftl
@@ -22,5 +22,9 @@
 <#-- @ftlvariable name="var" type="org.rhq.enterprise.server.rest.domain.AvailabilityRest" -->
 
 State: ${var.type}<br/>
-Since: ${var.since?number_to_time}
+Since: ${var.since?number_to_datetime}
+<#if var.until?has_content>
+ until ${var.until?number_to_datetime}
+</#if>
+<br/>
 <a href="/rest/1/resource/${var.resourceId?c}.html">Back to Resource</a>
diff --git a/modules/enterprise/server/jar/src/main/resources/rest_templates/listAvailability.ftl b/modules/enterprise/server/jar/src/main/resources/rest_templates/listAvailability.ftl
new file mode 100644
index 0000000..128ea65
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/resources/rest_templates/listAvailability.ftl
@@ -0,0 +1,32 @@
+<#ftl >
+<#--
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 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.
+ */
+-->
+<#-- @ftlvariable name="var" type="java.util.List<org.rhq.enterprise.server.rest.domain.AvailabilityRest>" -->
+<html>
+<ul>
+    <#-- the next looks odd, but the incoming var is a list -->
+    <#list var as var>
+    <li>
+        <#include "availability.ftl"/>
+    </li>
+    </#list>
+</ul>
+<html>
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/main/resources/rest_templates/resourceWithType.ftl b/modules/enterprise/server/jar/src/main/resources/rest_templates/resourceWithType.ftl
index 7e96a11..f4bfa15 100644
--- a/modules/enterprise/server/jar/src/main/resources/rest_templates/resourceWithType.ftl
+++ b/modules/enterprise/server/jar/src/main/resources/rest_templates/resourceWithType.ftl
@@ -48,5 +48,6 @@
     </table>
     <a href="/rest/1/resource/${var.resourceId}/children.html">Children</a><br/>
     <a href="/rest/1/resource/${var.resourceId}/schedules.html">Schedules</a><br/>
-    <a href="/rest/1/resource/${var.resourceId}/availability.html">Availability</a><br/>
+    <a href="/rest/1/resource/${var.resourceId}/availability.html">Current availability</a><br/>
+    <a href="/rest/1/resource/${var.resourceId}/availability/history.html">Availability History</a><br/>
     <a href="/rest/1/alert.html?resourceId=${var.resourceId}">Up to 20 Alerts for this resource</a>


commit fdb022dd24ced74d9682314d32c1a63e35159dba
Author: Heiko W. Rupp <hwr at redhat.com>
Date:   Sat Jun 16 09:43:18 2012 +0200

    Allow to limit alerts by prio and resource. Add linking from/to resource. Fix a bug in the genericString template.

diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerBean.java
index a9bcc4e..074199c 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerBean.java
@@ -47,6 +47,7 @@ import org.rhq.core.domain.criteria.Criteria;
 import org.rhq.core.domain.resource.Resource;
 import org.rhq.core.domain.util.PageControl;
 import org.rhq.core.domain.util.PageList;
+import org.rhq.core.domain.util.PageOrdering;
 import org.rhq.enterprise.server.alert.AlertDefinitionManagerLocal;
 import org.rhq.enterprise.server.alert.AlertManagerLocal;
 import org.rhq.enterprise.server.rest.domain.*;
@@ -69,7 +70,9 @@ public class AlertHandlerBean extends AbstractRestBean implements AlertHandlerLo
 
 
     @Override
-    public Response listAlerts(int page, String status, boolean slim, Long since, Request request, UriInfo uriInfo, HttpHeaders headers) {
+    public Response listAlerts(int page, String prio, boolean slim, Long since, Integer resourceId, Request request,
+                               UriInfo uriInfo,
+                               HttpHeaders headers) {
 
 
         AlertCriteria criteria = new AlertCriteria();
@@ -77,6 +80,17 @@ public class AlertHandlerBean extends AbstractRestBean implements AlertHandlerLo
         if (since!=null) {
             criteria.addFilterStartTime(since);
         }
+
+        if (resourceId!=null) {
+            criteria.addFilterResourceIds(resourceId);
+        }
+
+        if (!prio.equals("All")) {
+            AlertPriority alertPriority = AlertPriority.valueOf(prio.toUpperCase());
+            criteria.addFilterPriorities(alertPriority);
+        }
+        criteria.addSortCtime(PageOrdering.DESC);
+
         PageList<Alert> alerts = alertManager.findAlertsByCriteria(caller,criteria);
         List<AlertRest> ret = new ArrayList<AlertRest>(alerts.size());
         for (Alert al : alerts) {
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerLocal.java
index 5fd7506..4912ca1 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerLocal.java
@@ -59,11 +59,13 @@ public interface AlertHandlerLocal {
     @ApiOperation(value = "List all alerts", multiValueResponse = true, responseClass = "List<AlertRest")
     Response listAlerts(
             @ApiParam(value = "Page number", defaultValue = "0") @QueryParam("page") int page,
-            @ApiParam(value = "Limit to status, UNUSED AT THE MOMENT ") @QueryParam("status") String status,
+            @ApiParam(value = "Limit to priority", allowableValues = "High, Medium, Low, All") @DefaultValue("All") @QueryParam("prio") String prio,
             @ApiParam(value = "Should full resources and definitions be sent") @QueryParam("slim") @DefaultValue(
                     "false") boolean slim,
-            @ApiParam(value = "If non-null only send alerts that have fired after this time, time is millisecond since epoch")
-                @QueryParam("since") Long since,
+            @ApiParam(
+                    value = "If non-null only send alerts that have fired after this time, time is millisecond since epoch")
+            @QueryParam("since") Long since,
+            @ApiParam(value = "Id of a resource to limit search for") @QueryParam("resourceId") Integer resourceId,
             @Context Request request, @Context UriInfo uriInfo, @Context HttpHeaders headers);
 
     @GET
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/UserHandlerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/UserHandlerLocal.java
index 05ef280..9893e8e 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/UserHandlerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/UserHandlerLocal.java
@@ -1,6 +1,6 @@
 /*
  * RHQ Management Platform
- * Copyright (C) 2005-2011 Red Hat, Inc.
+ * Copyright (C) 2005-2012 Red Hat, Inc.
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
@@ -21,7 +21,6 @@ package org.rhq.enterprise.server.rest;
 import javax.ejb.Local;
 import javax.ws.rs.DELETE;
 import javax.ws.rs.GET;
-import javax.ws.rs.POST;
 import javax.ws.rs.PUT;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
@@ -51,7 +50,7 @@ public interface UserHandlerLocal {
 
     @GET
     @Path("favorites/resource")
-    @ApiOperation(value = "Return a list of favorite resources of the caller", multiValueResponse = true)
+    @ApiOperation(value = "Return a list of favorite resources of the caller", multiValueResponse = true, responseClass = "ResourceWithType")
     Response getFavorites(@Context UriInfo uriInfo, at Context HttpHeaders headers);
 
     @PUT
diff --git a/modules/enterprise/server/jar/src/main/resources/rest_templates/alert.ftl b/modules/enterprise/server/jar/src/main/resources/rest_templates/alert.ftl
index 60be9fc..fe60590 100644
--- a/modules/enterprise/server/jar/src/main/resources/rest_templates/alert.ftl
+++ b/modules/enterprise/server/jar/src/main/resources/rest_templates/alert.ftl
@@ -31,7 +31,7 @@
     </tr>
     <tr>
         <td>Id</td>
-        <td>${var.id}</td>
+        <td>${var.id?c}</td>
     </tr>
     <tr>
         <td>Description</td>
@@ -55,3 +55,4 @@
 <a href="/rest/1/alert/${var.id?c}/definition.html">Alert Definition</a>
 <a href="/rest/1/alert/${var.id?c}/conditions.html">Condition Logs</a>
 <a href="/rest/1/alert/${var.id?c}/notifications.html">Notification Logs</a>
+<a href="/rest/1/resource/${var.resource.getResourceId()}.html">Resource</a>
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/main/resources/rest_templates/genericStringList.ftl b/modules/enterprise/server/jar/src/main/resources/rest_templates/genericStringList.ftl
index d0ad8a2..af116af 100644
--- a/modules/enterprise/server/jar/src/main/resources/rest_templates/genericStringList.ftl
+++ b/modules/enterprise/server/jar/src/main/resources/rest_templates/genericStringList.ftl
@@ -21,7 +21,7 @@
 -->
 <#-- @ftlvariable name="var" type="java.util.List<String>" -->
 <ul>
-    <#if var.isEmpty()>
+    <#if (var?size==0)>
         <i>Nothing to display</i>
     <#else>
         <#list var as line>
diff --git a/modules/enterprise/server/jar/src/main/resources/rest_templates/resourceWithType.ftl b/modules/enterprise/server/jar/src/main/resources/rest_templates/resourceWithType.ftl
index bb8f717..7e96a11 100644
--- a/modules/enterprise/server/jar/src/main/resources/rest_templates/resourceWithType.ftl
+++ b/modules/enterprise/server/jar/src/main/resources/rest_templates/resourceWithType.ftl
@@ -49,3 +49,4 @@
     <a href="/rest/1/resource/${var.resourceId}/children.html">Children</a><br/>
     <a href="/rest/1/resource/${var.resourceId}/schedules.html">Schedules</a><br/>
     <a href="/rest/1/resource/${var.resourceId}/availability.html">Availability</a><br/>
+    <a href="/rest/1/alert.html?resourceId=${var.resourceId}">Up to 20 Alerts for this resource</a>


commit 66fd59f643fdf8f39f199129711d77dfbd5ccbc7
Author: John Mazzitelli <mazz at redhat.com>
Date:   Fri Jun 15 17:29:41 2012 -0400

    [BZ 535514] remote client will not connect to the server if the server is not supported. for this commit, "not supported" means the server and cli/remote client aren't the same version.

diff --git a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/LoginCommand.java b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/LoginCommand.java
index 97221af..17cf94e 100644
--- a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/LoginCommand.java
+++ b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/LoginCommand.java
@@ -24,7 +24,6 @@ import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
 import org.rhq.core.domain.auth.Subject;
-import org.rhq.core.domain.common.ProductInfo;
 import org.rhq.enterprise.client.ClientMain;
 import org.rhq.enterprise.client.script.CommandLineParseException;
 import org.rhq.enterprise.clientapi.RemoteClient;
@@ -111,8 +110,7 @@ public class LoginCommand implements ClientCommand {
 
         Subject subject = remoteClient.login(username, password);
 
-        ProductInfo info = remoteClient.getSystemManager().getProductInfo(subject);
-        String version = info.getVersion() + " (" + info.getBuildNumber() + ")";
+        String version = remoteClient.getServerVersion() + " (" + remoteClient.getServerBuildNumber() + ")";
         client.getPrintWriter().println("Remote server version is: " + version);
 
         // this call has the side effect of setting bindings for the new remote client and its subject
diff --git a/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RemoteClient.java b/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RemoteClient.java
index 0ec565e..d0fb529 100644
--- a/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RemoteClient.java
+++ b/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RemoteClient.java
@@ -24,6 +24,7 @@ import java.util.Map;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.apache.maven.artifact.versioning.ComparableVersion;
 
 import org.jboss.remoting.Client;
 import org.jboss.remoting.InvokerLocator;
@@ -33,6 +34,7 @@ import org.jboss.remoting.transport.http.ssl.HTTPSClientInvoker;
 import org.rhq.bindings.client.RhqFacade;
 import org.rhq.bindings.client.RhqManagers;
 import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.common.ProductInfo;
 import org.rhq.enterprise.communications.util.SecurityUtil;
 import org.rhq.enterprise.server.alert.AlertDefinitionManagerRemote;
 import org.rhq.enterprise.server.alert.AlertManagerRemote;
@@ -89,6 +91,7 @@ public class RemoteClient implements RhqFacade {
     private Subject subject;
     private Client remotingClient;
     private String subsystem = null;
+    private ProductInfo serverInfo = null;
 
     /**
      * Creates a client that will communicate with the server running on the given host
@@ -422,6 +425,24 @@ public class RemoteClient implements RhqFacade {
         return this.remotingClient;
     }
 
+    /**
+     * If the client is connected, this is version of the server that the client is talking to.
+     *
+     * @return remote server version
+     */
+    public String getServerVersion() {
+        return (this.serverInfo != null) ? this.serverInfo.getVersion() : null;
+    }
+
+    /**
+     * If the client is connected, this is build number of the server that the client is talking to.
+     *
+     * @return remote server build number
+     */
+    public String getServerBuildNumber() {
+        return (this.serverInfo != null) ? this.serverInfo.getBuildNumber() : null;
+    }
+
     private void doDisconnect() {
         try {
             if (this.remotingClient != null && this.remotingClient.isConnected()) {
@@ -431,6 +452,7 @@ public class RemoteClient implements RhqFacade {
             LOG.warn(e); // TODO what to do here?
         } finally {
             this.remotingClient = null;
+            this.serverInfo = null;
         }
     }
 
@@ -446,6 +468,16 @@ public class RemoteClient implements RhqFacade {
         Map<String, String> remotingConfig = buildRemotingConfig(locatorURI);
         this.remotingClient = new Client(locator, subsystem, remotingConfig);
         this.remotingClient.connect();
+
+        // make sure the remote server can support this client
+        this.serverInfo = getSystemManager().getProductInfo(subject);
+        try {
+            checkServerSupported(this.serverInfo);
+        } catch (Exception e) {
+            // our client cannot be supported by the server - disconnect and rethrow the exception
+            doDisconnect();
+            throw e;
+        }
     }
 
     private Map<String, String> buildRemotingConfig(String locatorURI) {
@@ -503,4 +535,43 @@ public class RemoteClient implements RhqFacade {
         }
         return;
     }
+
+    /**
+     * Checks to see if the server (whose version information is passed in) supports this client.
+     * This performs version checks and throws an IllegalStateException if the server does not
+     * support this client.
+     *
+     * @param serverVersionInfo the information about the remote server
+     *
+     * @throws IllegalStateException if the remote server does not support this client
+     */
+    private void checkServerSupported(ProductInfo serverVersionInfo) throws IllegalStateException {
+        boolean supported;
+        String clientVersionString;
+        String serverVersionString;
+
+        try {
+            clientVersionString = getClass().getPackage().getImplementationVersion();
+            serverVersionString = this.serverInfo.getVersion();
+            ComparableVersion clientVersion = new ComparableVersion(clientVersionString);
+            ComparableVersion serverVersion = new ComparableVersion(serverVersionString);
+            supported = clientVersion.equals(serverVersion);
+        } catch (Exception e) {
+            throw new IllegalStateException("Cannot determine if server version is supported.", e); // assume we can't talk to it
+        }
+
+        if (!supported) {
+            String errMsg = "This client [" + clientVersionString + "] does not support the remote server ["
+                + serverVersionString + "]";
+
+            final String propName = "rhq.client.version-check";
+            String versionCheckProp = System.getProperty(propName, "true");
+            if (versionCheckProp.equalsIgnoreCase("true")) {
+                throw new IllegalStateException(errMsg);
+            } else {
+                LOG.error(errMsg + " - '" + propName
+                    + "' was not set to true so this client will be allowed to continue but expect errors");
+            }
+        }
+    }
 }
\ No newline at end of file


commit 350b123ae5afb4248eb2936656744112c3950359
Author: Jay Shaughnessy <jshaughn at redhat.com>
Date:   Fri Jun 15 15:53:37 2012 -0400

    [831272 - remove all attempts at pluralization to fix i18n messages]
    Get rid of the bogus message construction. Also, fix up some I18N stuff.

diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/roles/RolesView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/roles/RolesView.java
index e3ff089..795c55e 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/roles/RolesView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/roles/RolesView.java
@@ -18,12 +18,16 @@
  */
 package org.rhq.enterprise.gui.coregui.client.admin.roles;
 
+import java.util.ArrayList;
+import java.util.List;
+
 import com.smartgwt.client.types.SelectionStyle;
 import com.smartgwt.client.widgets.Canvas;
 import com.smartgwt.client.widgets.grid.ListGridField;
 import com.smartgwt.client.widgets.grid.ListGridRecord;
 import com.smartgwt.client.widgets.grid.events.CellClickEvent;
 import com.smartgwt.client.widgets.grid.events.CellClickHandler;
+
 import org.rhq.enterprise.gui.coregui.client.IconEnum;
 import org.rhq.enterprise.gui.coregui.client.admin.AdministrationView;
 import org.rhq.enterprise.gui.coregui.client.components.table.EscapedHtmlCellFormatter;
@@ -32,9 +36,6 @@ import org.rhq.enterprise.gui.coregui.client.components.table.TableSection;
 import org.rhq.enterprise.gui.coregui.client.components.view.HasViewName;
 import org.rhq.enterprise.gui.coregui.client.components.view.ViewName;
 
-import java.util.ArrayList;
-import java.util.List;
-
 /**
  * A table that lists all roles and provides the ability to view details of or delete those roles and to create new
  * roles. 
@@ -49,7 +50,6 @@ public class RolesView extends TableSection<RolesDataSource> implements HasViewN
     public static final String VIEW_PATH = AdministrationView.VIEW_ID + "/"
         + AdministrationView.SECTION_SECURITY_VIEW_ID + "/" + VIEW_ID;
 
-
     private boolean hasManageSecurity;
 
     public RolesView(String locatorId, boolean hasManageSecurity) {
@@ -58,10 +58,10 @@ public class RolesView extends TableSection<RolesDataSource> implements HasViewN
         final RolesDataSource datasource = RolesDataSource.getInstance();
         setDataSource(datasource);
         setEscapeHtmlInDetailsLinkColumn(true);
-        
+
         this.hasManageSecurity = hasManageSecurity;
     }
-    
+
     @Override
     protected void configureTable() {
         updateSelectionStyle();
@@ -161,13 +161,8 @@ public class RolesView extends TableSection<RolesDataSource> implements HasViewN
     }
 
     @Override
-    protected String getDataTypeName() {
-        return MSG.common_label_role();
-    }
-
-    @Override
-    protected String getDataTypeNamePlural() {
-        return MSG.common_label_roles();
+    protected String getDeleteConfirmMessage() {
+        return MSG.common_msg_deleteConfirm(MSG.common_label_roles());
     }
 
     @Override
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/users/UsersView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/users/UsersView.java
index 6d094e9..e4485bd 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/users/UsersView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/users/UsersView.java
@@ -18,6 +18,9 @@
  */
 package org.rhq.enterprise.gui.coregui.client.admin.users;
 
+import java.util.ArrayList;
+import java.util.List;
+
 import com.google.gwt.user.client.rpc.AsyncCallback;
 import com.smartgwt.client.types.SelectionStyle;
 import com.smartgwt.client.widgets.Canvas;
@@ -25,6 +28,7 @@ import com.smartgwt.client.widgets.grid.ListGridField;
 import com.smartgwt.client.widgets.grid.ListGridRecord;
 import com.smartgwt.client.widgets.grid.events.CellClickEvent;
 import com.smartgwt.client.widgets.grid.events.CellClickHandler;
+
 import org.rhq.core.domain.authz.Permission;
 import org.rhq.enterprise.gui.coregui.client.CoreGUI;
 import org.rhq.enterprise.gui.coregui.client.IconEnum;
@@ -38,9 +42,6 @@ import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
 import org.rhq.enterprise.gui.coregui.client.gwt.SubjectGWTServiceAsync;
 import org.rhq.enterprise.gui.coregui.client.util.message.Message;
 
-import java.util.ArrayList;
-import java.util.List;
-
 /**
  * A table that lists all users and provides the ability to view or edit details of users, delete users, or create new
  * users. For the logged in user to view or edit a user other than themselves, they must possess the
@@ -227,13 +228,8 @@ public class UsersView extends TableSection<UsersDataSource> implements HasViewN
     }
 
     @Override
-    protected String getDataTypeName() {
-        return MSG.common_label_user();
-    }
-
-    @Override
-    protected String getDataTypeNamePlural() {
-        return MSG.common_label_users();
+    protected String getDeleteConfirmMessage() {
+        return MSG.common_msg_deleteConfirm(MSG.common_label_users());
     }
 
     @Override
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/carousel/Carousel.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/carousel/Carousel.java
index 42403da..a89e1e2 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/carousel/Carousel.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/carousel/Carousel.java
@@ -864,17 +864,6 @@ public abstract class Carousel extends LocatableHLayout implements RefreshableVi
         }
     }
 
-    protected String getDataTypeName() {
-        return "item";
-    }
-
-    protected String getDataTypeNamePlural() {
-        return "items";
-    }
-
-    protected String getDeleteConfirmMessage() {
-        return MSG.common_msg_deleteConfirm(getDataTypeNamePlural());
-    }
 
     // -------------- Inner utility classes ------------- //
 
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/table/Table.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/table/Table.java
index 70e29d4..27692b8 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/table/Table.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/table/Table.java
@@ -1111,10 +1111,9 @@ public class Table<DS extends RPCDataSource> extends LocatableHLayout implements
                     }
                     if (deletedRecordNames.size() == selectedRecordCount) {
                         // all selected schedules were successfully deleted.
-                        Message message = new Message(MSG.widget_recordEditor_info_recordsDeletedConcise(
-                            String.valueOf(deletedRecordNames.size()), getDataTypeNamePlural()), MSG
-                            .widget_recordEditor_info_recordsDeletedDetailed(String.valueOf(deletedRecordNames.size()),
-                                getDataTypeNamePlural(), deletedRecordNames.toString()));
+                        String deletedMessage = getDeletedMessage(deletedRecordNames.size());
+                        String deletedMessageDetail = deletedMessage + ": [" + deletedRecordNames.toString() + "]";
+                        Message message = new Message(deletedMessage, deletedMessageDetail);
                         CoreGUI.getMessageCenter().notify(message);
                         refresh();
                     }
@@ -1124,20 +1123,18 @@ public class Table<DS extends RPCDataSource> extends LocatableHLayout implements
         }, requestProperties);
     }
 
-    protected String getDataTypeName() {
-        return "item";
-    }
-
-    protected String getDataTypeNamePlural() {
-        return "items";
-    }
-
     protected String getTitleFieldName() {
         return FIELD_NAME;
     }
 
+    protected String getDeletedMessage(int numDeleted) {
+        String num = String.valueOf(numDeleted);
+        String thing = (1 == numDeleted) ? MSG.common_label_item() : MSG.common_label_items();
+        return MSG.common_msg_deleted(num, thing);
+    }
+
     protected String getDeleteConfirmMessage() {
-        return MSG.common_msg_deleteConfirm(getDataTypeNamePlural());
+        return MSG.common_msg_deleteConfirm(MSG.common_label_items());
     }
 
     protected void hideField(ListGridField field) {
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
index 8d228e8..e8d267b 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
@@ -83,6 +83,7 @@ common_msg_areYouSure = Are You Sure?
 common_msg_asyncTimeout = {0}. This occurred because the server is taking a long time to complete this request. Please be aware that the server may still be processing your request and it may complete shortly. You can check the server logs to see if any abnormal errors occurred.
 common_msg_changeAutoDetected = Change auto-detected
 common_msg_deleteConfirm = Are you sure you want to delete the # selected {0}?
+common_msg_deleted = {0} {1} deleted.
 common_msg_emphasizedNotePrefix = NOTE:
 common_msg_loading = Loading...
 common_msg_noItemsToShow = No items to show
@@ -2000,8 +2001,6 @@ widget_recordEditor_info_recordCreatedConcise = {0} created.
 widget_recordEditor_info_recordCreatedDetailed = {0} [{1}] created.
 widget_recordEditor_info_recordUpdatedConcise = {0} updated.
 widget_recordEditor_info_recordUpdatedDetailed = {0} [{1}] updated.
-widget_recordEditor_info_recordsDeletedConcise = {0} {1} deleted.
-widget_recordEditor_info_recordsDeletedDetailed = {0} {1} deleted: {2}.
 widget_recordEditor_title_edit = Edit {0} [{1}]
 widget_recordEditor_title_new = Create New {0}
 widget_recordEditor_title_view = View {0} [{1}]
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
index edf2e50..f02b83b 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
@@ -106,6 +106,7 @@ common_msg_areYouSure = Jste si jistí?
 common_msg_asyncTimeout = {0}. Stalo se to, protože serveru trvalo příliš dlouho k vyřízení požadavku. Prosím, vemte na vědomí, že server může stále vyřizovat Váš požadavek. Můžete zkontrolovat logy serveru, zda nenajdete něco neobvyklého.
 common_msg_changeAutoDetected = Změnit automaticky detekované
 common_msg_deleteConfirm = Jste si jistí, že chcete smazat # vybraných {0}?
+common_msg_deleted = {0} {1} smazáno.
 common_msg_emphasizedNotePrefix = POZNÁMKA:
 common_msg_loading = Nahrávám...
 common_msg_noItemsToShow = Žádné položky k zobrazení
@@ -1562,6 +1563,7 @@ view_inventory_resources_deleteFailed = Nepodařilo se odstranit vybrané zdroje
 view_inventory_resources_deleteSuccessful = Požadavek na smazání zdroje byl úspěšně předán všem agentům.
 view_inventory_resources_disableConfirm = Jste si jisti, že chcete zneplatnit vybrané zdroje? Při zneplatnění jsou hlášení o dostupnosti zdroje ignorovány. Zneplatňování může být užitečné při údržbě systému, kdy se předpokládá, že zdroje nebudou fungovat (plánovaný restart apod.)
 view_inventory_resources_disableFailed = Nepodařilo se zneplatnit vybrané zdroje.
+view_inventory_resources_disableSuccessful = Úspěšně jste zneplatnil vybrané zdroje a jejich potomky, [{0}] zdrojů
 view_inventory_resources_enableConfirm = Jste si jisti, že chcete povolit vybrané zdroje? Při povolení se dostupnost nastaví na neznámou (UNKNOWN) dokud neproběhne další agentovo hlášení o dostupnosti zdrojů. Agenti budou požádáni o tento report co nejdříve.
 view_inventory_resources_enableFailed = Nepodařilo se povolit vybrané zdroje.
 view_inventory_resources_enableSuccessful = Úspěšně jste povolili vybrané zdroje a jejich potomky, [{0}] zdrojů.
@@ -1979,7 +1981,6 @@ view_upload_tooltip_1b = Vyberte soubor k uploadu a klikněte na Další
 view_upload_tooltip_2 = Upload souboru minule selhal
 view_upload_upload = Upload
 view_upload_uploadFile = Upload souboru
-vview_inventory_resources_disableSuccessful = Úspěšně jste zneplatnil vybrané zdroje a jejich potomky, [{0}] zdrojů
 widget_colorPicker_tooltip = Klikněte pro výběr nové barvy
 widget_durationItem_inputUnitLessThanTargetUnit = Vstupní jednotka je menší než cílová jednotka.
 widget_durationItem_unitTypeNotSupported = Typ jednotek [{0}] není podporován třídou DurationItem.
@@ -2018,8 +2019,6 @@ widget_recordEditor_info_recordCreatedConcise = {0} vytvořeno.
 widget_recordEditor_info_recordCreatedDetailed = {0} [{1}] vytvořeno.
 widget_recordEditor_info_recordUpdatedConcise = {0} změněno.
 widget_recordEditor_info_recordUpdatedDetailed = {0} [{1}] změněno.
-widget_recordEditor_info_recordsDeletedConcise = {0} {1} smazáno.
-widget_recordEditor_info_recordsDeletedDetailed = {0} {1} smazáno: {2}.
 widget_recordEditor_title_edit = Editovat {0} [{1}]
 widget_recordEditor_title_new = Vytvořit nový {0}
 widget_recordEditor_title_view = Zobrazit {0} [{1}]
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
index 3806dd5..4de4df2 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
@@ -86,6 +86,7 @@ common_msg_areYouSure = Sind Sie sicher?
 common_msg_asyncTimeout = {0}. Dies ist aufgetreten weil der Server lange Zeit für die Bearbeitung der Anfrage benötigt. Bitte beachten Sie, dass der Serer eventuell Ihre Anfrage immer noch bearbeitet und bald fertig sein kann. Sie können die Server-Logs überprüfen, um zu sehen, ob abnormale Bedingungen aufgetreten sind.
 common_msg_changeAutoDetected = Änderungen gefunden
 ##common_msg_deleteConfirm = Are you sure you want to delete the # selected {0}?
+common_msg_deleted = {0} {1} gelöscht.
 common_msg_emphasizedNotePrefix = Achtung:
 common_msg_loading = Laden...
 common_msg_noItemsToShow = Keine Einträge vorhanden
@@ -1341,6 +1342,7 @@ view_inventory_problemGroups = Gruppen mit Problemen
 ##view_inventory_resources_deleteConfirm = Are you sure you want to delete the selected resources?
 ##view_inventory_resources_deleteFailed = Failed to delete the selected resources
 ##view_inventory_resources_deleteSuccessful = A request to perform the resource deletion has been submitted successfully to the agent(s).
+##view_inventory_resources_disableSuccessful = You have successfully disabled the selected resources and their children, [{0}] resources.
 ##view_inventory_resources_loadFailed = Failed to load resource composite data
 ##view_inventory_resources_members = Member Resources
 view_inventory_sectionHelp = In diesem Abschnitt können neu gefundene Ressourcen, sowie Ressourcen und Gruppen im Inventar angesehen und verwaltet werden.
@@ -1780,8 +1782,6 @@ widget_recordEditor_info_recordCreatedConcise = {0} angelegt.
 widget_recordEditor_info_recordCreatedDetailed = {0} [{1}] angelegt.
 widget_recordEditor_info_recordUpdatedConcise = {0} aktualisiert.
 widget_recordEditor_info_recordUpdatedDetailed = {0} [{1}] aktualisiert.
-widget_recordEditor_info_recordsDeletedConcise = {0} {1} gelöscht.
-widget_recordEditor_info_recordsDeletedDetailed = {0} {1} gelöscht: {2}.
 widget_recordEditor_title_edit = Bearbeiten {0} [{1}]
 widget_recordEditor_title_new = Neue {0} anlegen
 widget_recordEditor_title_view = Anzeigen {0} [{1}]
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
index 42b166f..ea692e6 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
@@ -86,6 +86,7 @@ common_msg_areYouSure = よろしいですか?
 common_msg_asyncTimeout = {0}. これが発生したのはサーバーがこのリクエストを完了するのに長時間経過したからです。サーバーがそのリクエストをまだ処理中で短時間で完了可能かどうか注意してください。サーバーログを調べることで異常なエラーが発生したかどうかがわかります。
 common_msg_changeAutoDetected = 変更が自動検出されました
 common_msg_deleteConfirm = 選択された {0} を削除してもよろしいですか
+common_msg_deleted = {0} {1} が削除されました。
 common_msg_emphasizedNotePrefix = 注意:
 common_msg_loading = ロード中...
 common_msg_noItemsToShow = 表示する項目はありません
@@ -1987,8 +1988,6 @@ widget_recordEditor_info_recordCreatedConcise = {0} が作成されました。
 widget_recordEditor_info_recordCreatedDetailed = {0} [{1}] が作成されました。
 widget_recordEditor_info_recordUpdatedConcise = {0} が更新されました。
 widget_recordEditor_info_recordUpdatedDetailed = {0} [{1}] が更新されました。
-widget_recordEditor_info_recordsDeletedConcise = {0} {1} が削除されました。
-widget_recordEditor_info_recordsDeletedDetailed = {0} {1} が削除されました: {2}.
 widget_recordEditor_title_edit = 編集 {0} [{1}]
 widget_recordEditor_title_new = 新規作成 {0}
 widget_recordEditor_title_view = 閲覧 {0} [{1}]
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
index a755166..26f3ab8 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
@@ -84,6 +84,7 @@ common_msg_areYouSure = Tem certeza?
 common_msg_asyncTimeout = {0}. Isso ocorre porque o servidor est\u00E1 levando muito tempo para atender esta requisi\u00E7\u00E3o. Favor atentar para o fato de que o servidor ainda esteja processando sua requisi\u00E7\u00E3o e pode concluir dentro de mais alguns instantes. Voc\u00EA ainda pode verificar os logs do servidor para identificar se algum erro anormal ocorreu.
 common_msg_changeAutoDetected = Mudan\u00E7as detectadas automaticamente
 common_msg_deleteConfirm = Tem certeza de que deseja excluir o # selecionado {0}?
+common_msg_deleted = {0} {1} exclu\u00EDdo.
 common_msg_emphasizedNotePrefix = NOTA:
 common_msg_loading = Carregando...
 common_msg_noItemsToShow = N\u00E3o existem itens para apresentar
@@ -2103,8 +2104,6 @@ widget_recordEditor_info_recordCreatedConcise = {0} criado.
 widget_recordEditor_info_recordCreatedDetailed = {0} [{1}] criado.
 widget_recordEditor_info_recordUpdatedConcise = {0} atualizado.
 widget_recordEditor_info_recordUpdatedDetailed = {0} [{1}] atualizado.
-widget_recordEditor_info_recordsDeletedConcise = {0} {1} exclu\u00EDdo.
-widget_recordEditor_info_recordsDeletedDetailed = {0} {1} exclu\u00EDdo: {2}.
 widget_recordEditor_title_edit = Editar {0} [{1}]
 widget_recordEditor_title_new = Criar Novo {0}
 widget_recordEditor_title_view = Visualizar {0} [{1}]
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
index c572c62..394ecc9 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
@@ -2093,7 +2093,10 @@ common_label_users = пользователи
 common_label_week = неделя
 common_label_yesterday = Вчера
 common_msg_areYouSure = Вы уверены?
+##common_msg_asyncTimeout = {0}. This occurred because the server is taking a long time to complete this request. Please be aware that the server may still be processing your request and it may complete shortly. You can check the server logs to see if any abnormal errors occurred.
 common_msg_changeAutoDetected = Автообнаружение изменений
+##common_msg_deleteConfirm = Are you sure you want to delete the # selected {0}?
+##common_msg_deleted = {0} {1} deleted.
 common_msg_emphasizedNotePrefix = Примечание\:
 common_msg_loading = Загрузка...
 common_msg_noItemsToShow = Отсутствуют элементы для отображения
@@ -2456,6 +2459,7 @@ view_admin_downloads_cli_version = Версия CLI
 ##view_bundle_revertWizard_getInfoStep_revertDeployDescFull = [REVERT From] {0} [REVERT To] {1}
 ##view_configEdit_property = Property
 ##view_configEdit_unset = Unset?
+##view_inventory_resources_disableSuccessful = You have successfully disabled the selected resources and their children, [{0}] resources.
 ##view_messageCenter_messageRootCause = Root Cause
 ##view_operationHistoryList_cancelConfirm = Are you sure you want to cancel the selected operations? NOTE: Only those selected operations that are currently "in progress" will be attempted to be canceled.
 ##view_operationHistoryList_cancelFailure = The cancel request failed for the operation with the history ID of [{0}].
@@ -2464,3 +2468,7 @@ view_admin_downloads_cli_version = Версия CLI
 ##view_operationHistoryList_deleteFailure = Failed to delete operation history [{0}].
 ##view_operationHistoryList_deletePartialSuccess = Deleted [{0}] operation history items, but failed to delete the items with the following IDs: {1}
 ##view_operationHistoryList_deleteSuccess = Deleted [{0}] operation history items.
+##widget_recordEditor_info_recordCreatedConcise = {0} created.
+##widget_recordEditor_info_recordCreatedDetailed = {0} [{1}] created.
+##widget_recordEditor_info_recordUpdatedConcise = {0} updated.
+##widget_recordEditor_info_recordUpdatedDetailed = {0} [{1}] updated.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
index 8d22ea6..dff469a 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
@@ -83,6 +83,7 @@ common_msg_areYouSure = \u4f60\u786e\u5b9a?
 common_msg_asyncTimeout = {0}. \u56e0\u4e3a\u670d\u52a1\u5668\u54cd\u5e94\u65f6\u95f4\u592a\u957f. \u8bf7\u6ce8\u610f\u670d\u52a1\u5668\u53ef\u80fd\u4ecd\u5728\u5904\u7406\u60a8\u7684\u8bf7\u6c42\uff0c\u5e76\u53ef\u80fd\u5728\u77ed\u671f\u5185\u5b8c\u6210. \u4f60\u53ef\u4ee5\u68c0\u67e5\u670d\u52a1\u5668\u65e5\u5fd7\uff0c\u67e5\u770b\u662f\u5426\u51fa\u73b0\u4efb\u4f55\u4e0d\u6b63\u5e38\u7684\u9519\u8bef.
 ##common_msg_changeAutoDetected = Change auto-detected
 common_msg_deleteConfirm = \u4f60\u786e\u5b9a\u8981\u5220\u9664# selected {0}?
+##common_msg_deleted = {0} {1} deleted.
 common_msg_emphasizedNotePrefix = \u6ce8\u610f:
 common_msg_loading = \u52a0\u8f7d\u4e2d...
 common_msg_noItemsToShow = \u6ca1\u6709\u6761\u76ee\u663e\u793a
@@ -1982,12 +1983,10 @@ widget_recordEditor_error_operation = \u64cd\u4f5c\u5931\u8d25.\u6709\u9519\u8be
 widget_recordEditor_error_operationInvalidValues = \u64cd\u4f5c\u5931\u8d25-\u4e00\u4e2a\u6216\u591a\u4e2a\u5b57\u6bb5\u7684\u503c\u65e0\u6548
 widget_recordEditor_error_permissionCreate = \u4f60\u6ca1\u6709\u521b\u5efa\u65b0[{0}]\u7684\u6743\u9650
 widget_recordEditor_error_unsupportedOperationType = \u4e0d\u652f\u6301\u7684\u64cd\u4f5c\u7c7b\u578b: [{0}]
-widget_recordEditor_info_recordCreatedConcise = {0} created.
-widget_recordEditor_info_recordCreatedDetailed = {0} [{1}] created.
-widget_recordEditor_info_recordUpdatedConcise = {0} updated.
-widget_recordEditor_info_recordUpdatedDetailed = {0} [{1}] updated.
-widget_recordEditor_info_recordsDeletedConcise = {0} {1} deleted.
-widget_recordEditor_info_recordsDeletedDetailed = {0} {1} deleted: {2}.
+##widget_recordEditor_info_recordCreatedConcise = {0} created.
+##widget_recordEditor_info_recordCreatedDetailed = {0} [{1}] created.
+##widget_recordEditor_info_recordUpdatedConcise = {0} updated.
+##widget_recordEditor_info_recordUpdatedDetailed = {0} [{1}] updated.
 widget_recordEditor_title_edit = \u7f16\u8f91{0} [{1}]
 widget_recordEditor_title_new = \u65b0\u5efa{0}
 widget_recordEditor_title_view = \u67e5\u770b{0} [{1}]


commit ac7fe40163f22ed7b634d1ec8138fb0182e1617d
Author: Lukas Krejci <lkrejci at redhat.com>
Date:   Fri Jun 15 17:35:38 2012 +0200

    [BZ 832090] - adding an integration test for checking that all the PC
    subsystems obtain the synced resource after manual add.

diff --git a/modules/core/arquillian-integration/container/src/main/java/org/rhq/test/arquillian/FakeServerInventory.java b/modules/core/arquillian-integration/container/src/main/java/org/rhq/test/arquillian/FakeServerInventory.java
index 0b7b043..37e4ff2 100644
--- a/modules/core/arquillian-integration/container/src/main/java/org/rhq/test/arquillian/FakeServerInventory.java
+++ b/modules/core/arquillian-integration/container/src/main/java/org/rhq/test/arquillian/FakeServerInventory.java
@@ -41,6 +41,7 @@ import org.mockito.stubbing.Answer;
 import org.rhq.core.clientapi.agent.upgrade.ResourceUpgradeRequest;
 import org.rhq.core.clientapi.agent.upgrade.ResourceUpgradeResponse;
 import org.rhq.core.clientapi.server.discovery.InventoryReport;
+import org.rhq.core.domain.discovery.MergeResourceResponse;
 import org.rhq.core.domain.discovery.ResourceSyncInfo;
 import org.rhq.core.domain.resource.InventoryStatus;
 import org.rhq.core.domain.resource.Resource;
@@ -186,6 +187,24 @@ public class FakeServerInventory {
         return discoveryChecker;
     }
 
+    public synchronized Answer<MergeResourceResponse> addResource() {
+        return new Answer<MergeResourceResponse>() {
+            @Override
+            public MergeResourceResponse answer(InvocationOnMock invocation) throws Throwable {
+                Resource r = (Resource) invocation.getArguments()[0];
+                int subjectId = (Integer) invocation.getArguments()[1];
+                
+                LOG.debug("A request to add a resource [" + r + "] made by subject with id " + subjectId);
+                
+                boolean exists = getResourceStore().containsKey(r.getUuid());
+
+                r = fakePersist(r, InventoryStatus.COMMITTED, new HashSet<String>());
+
+                return new MergeResourceResponse(r.getId(), exists);
+            }
+        };
+    }
+
     public synchronized Answer<ResourceSyncInfo> mergeInventoryReport(final InventoryStatus requiredInventoryStatus) {
         return new Answer<ResourceSyncInfo>() {
             @Override
diff --git a/modules/core/plugin-container-itest/src/test/java/org/rhq/core/pc/inventory/DiscoveryTest.java b/modules/core/plugin-container-itest/src/test/java/org/rhq/core/pc/inventory/DiscoveryTest.java
index 474c5c9..8880b92 100644
--- a/modules/core/plugin-container-itest/src/test/java/org/rhq/core/pc/inventory/DiscoveryTest.java
+++ b/modules/core/plugin-container-itest/src/test/java/org/rhq/core/pc/inventory/DiscoveryTest.java
@@ -19,11 +19,17 @@
 package org.rhq.core.pc.inventory;
 
 import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
 import static org.mockito.Mockito.when;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotEquals;
+import static org.testng.Assert.assertTrue;
 
 import java.util.HashMap;
 import java.util.Map;
 
+import org.mockito.Mockito;
 import org.testng.Assert;
 import org.testng.annotations.Test;
 
@@ -34,13 +40,22 @@ import org.jboss.arquillian.testng.Arquillian;
 import org.jboss.shrinkwrap.api.ShrinkWrap;
 
 import org.rhq.core.clientapi.server.discovery.InventoryReport;
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.PropertySimple;
+import org.rhq.core.domain.discovery.MergeResourceResponse;
 import org.rhq.core.domain.resource.InventoryStatus;
 import org.rhq.core.domain.resource.Resource;
 import org.rhq.core.domain.resource.ResourceType;
 import org.rhq.core.pc.PluginContainer;
 import org.rhq.core.pc.PluginContainerConfiguration;
+import org.rhq.core.pc.availability.AvailabilityContextImpl;
+import org.rhq.core.pc.content.ContentContextImpl;
+import org.rhq.core.pc.event.EventContextImpl;
+import org.rhq.core.pc.inventory.testplugin.ManualAddDiscoveryComponent;
 import org.rhq.core.pc.inventory.testplugin.TestResourceComponent;
 import org.rhq.core.pc.inventory.testplugin.TestResourceDiscoveryComponent;
+import org.rhq.core.pc.operation.OperationContextImpl;
+import org.rhq.core.pluginapi.inventory.ResourceContext;
 import org.rhq.test.arquillian.AfterDiscovery;
 import org.rhq.test.arquillian.BeforeDiscovery;
 import org.rhq.test.arquillian.FakeServerInventory;
@@ -58,7 +73,7 @@ public class DiscoveryTest extends Arquillian {
     public static RhqAgentPluginArchive getTestPlugin() {
         RhqAgentPluginArchive pluginJar = ShrinkWrap.create(RhqAgentPluginArchive.class, "test-plugin.jar");
         return pluginJar.setPluginDescriptor("test-great-grandchild-discovery-plugin.xml").addClasses(
-            TestResourceDiscoveryComponent.class, TestResourceComponent.class);
+            TestResourceDiscoveryComponent.class, TestResourceComponent.class, ManualAddDiscoveryComponent.class);
     }
 
     @ArquillianResource
@@ -122,6 +137,57 @@ public class DiscoveryTest extends Arquillian {
                 + flaggedExecutionCountsByResourceType);
     }
 
+    @Test(groups = "pc.itest.discovery", priority = 10)
+    public void testResourceSyncedWithServerAfterManualAdd() throws Exception {
+        Mockito.when(serverServices.getDiscoveryServerService().addResource(any(Resource.class), anyInt())).then(
+            fakeServerInventory.addResource());
+
+        InventoryManager inventoryManager = pluginContainer.getInventoryManager();
+
+        Resource platform = inventoryManager.getPlatform();
+
+        Configuration myPluginConfig = new Configuration();
+        myPluginConfig.put(new PropertySimple("test", "value"));
+
+        ResourceType resourceType = pluginContainer.getPluginManager().getMetadataManager()
+            .getType("Manual Add Server", "test");
+
+        MergeResourceResponse response = inventoryManager.manuallyAddResource(resourceType, platform.getId(),
+            myPluginConfig, -1);
+
+        assertFalse(response.resourceAlreadyExisted(), "The manual add resource shouldn't have existed");
+        assertNotEquals(response.getResourceId(), 0, "The manual add resource should have had its resource id set");
+
+        ResourceContainer resourceContainer = inventoryManager.getResourceContainer(response.getResourceId());
+        ResourceContext<?> resourceContext = resourceContainer.getResourceContext();
+
+        assertEquals(resourceContext.getPluginConfiguration(), myPluginConfig,
+            "The manual add resource doesn't have the expected plugin config.");
+
+        assertTrue(resourceContext.getAvailabilityContext() instanceof AvailabilityContextImpl,
+            "Unexpected implementation clas of the AvailabilityContext, please fix this test.");
+        assertEquals(((AvailabilityContextImpl) resourceContext.getAvailabilityContext()).getResource().getId(),
+            response.getResourceId(),
+            "Availability subsystem isn't aware of the correct resource id for manual add resource");
+
+        assertTrue(resourceContext.getContentContext() instanceof ContentContextImpl,
+            "Unexpected implementation class of ContentContext, please fix this test");
+        assertEquals(((ContentContextImpl) resourceContext.getContentContext()).getResourceId(),
+            response.getResourceId(),
+            "Content subsystem isn't aware of the correct resource id for manual add resource");
+
+        assertTrue(resourceContext.getEventContext() instanceof EventContextImpl,
+            "Unexpected implementation clas of the EventContext, please fix this test.");
+        assertEquals(((EventContextImpl) resourceContext.getEventContext()).getResource().getId(),
+            response.getResourceId(), "Event subsystem isn't aware of the correct resource id for manual add resource");
+
+        assertTrue(resourceContext.getOperationContext() instanceof OperationContextImpl,
+            "Unexpected implementation clas of the OperationContext, please fix this test.");
+        assertEquals(((OperationContextImpl) resourceContext.getOperationContext()).getResourceId(),
+            response.getResourceId(),
+            "Operation subsystem isn't aware of the correct resource id for manual add resource");
+    }
+    
     private void validatePluginContainerInventory() throws Exception {
         System.out.println("Validating PC inventory...");
 
diff --git a/modules/core/plugin-container-itest/src/test/java/org/rhq/core/pc/inventory/testplugin/ManualAddDiscoveryComponent.java b/modules/core/plugin-container-itest/src/test/java/org/rhq/core/pc/inventory/testplugin/ManualAddDiscoveryComponent.java
new file mode 100644
index 0000000..95701b2
--- /dev/null
+++ b/modules/core/plugin-container-itest/src/test/java/org/rhq/core/pc/inventory/testplugin/ManualAddDiscoveryComponent.java
@@ -0,0 +1,34 @@
+package org.rhq.core.pc.inventory.testplugin;
+
+import java.util.Collections;
+import java.util.Set;
+
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.core.pluginapi.inventory.DiscoveredResourceDetails;
+import org.rhq.core.pluginapi.inventory.InvalidPluginConfigurationException;
+import org.rhq.core.pluginapi.inventory.ManualAddFacet;
+import org.rhq.core.pluginapi.inventory.ResourceComponent;
+import org.rhq.core.pluginapi.inventory.ResourceDiscoveryComponent;
+import org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext;
+
+public class ManualAddDiscoveryComponent implements ResourceDiscoveryComponent<ResourceComponent<?>>,
+    ManualAddFacet<ResourceComponent<?>> {
+
+    @Override
+    public DiscoveredResourceDetails discoverResource(Configuration pluginConfiguration,
+        ResourceDiscoveryContext<ResourceComponent<?>> context) throws InvalidPluginConfigurationException {
+
+        ResourceType resourceType = context.getResourceType();
+
+        return new DiscoveredResourceDetails(resourceType, "SINGLETON", resourceType.getName(), "1.0",
+            resourceType.getDescription(), pluginConfiguration, null);
+    }
+
+    @Override
+    public Set<DiscoveredResourceDetails> discoverResources(ResourceDiscoveryContext<ResourceComponent<?>> context)
+        throws InvalidPluginConfigurationException, Exception {
+        return Collections.emptySet();
+    }
+
+}
diff --git a/modules/core/plugin-container-itest/src/test/java/org/rhq/core/pc/inventory/testplugin/TestResourceComponent.java b/modules/core/plugin-container-itest/src/test/java/org/rhq/core/pc/inventory/testplugin/TestResourceComponent.java
index d56d598..20ccf76 100644
--- a/modules/core/plugin-container-itest/src/test/java/org/rhq/core/pc/inventory/testplugin/TestResourceComponent.java
+++ b/modules/core/plugin-container-itest/src/test/java/org/rhq/core/pc/inventory/testplugin/TestResourceComponent.java
@@ -18,15 +18,49 @@
  */
 package org.rhq.core.pc.inventory.testplugin;
 
+import java.io.InputStream;
+import java.util.List;
+import java.util.Set;
+
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.content.PackageType;
+import org.rhq.core.domain.content.transfer.DeployPackageStep;
+import org.rhq.core.domain.content.transfer.DeployPackagesResponse;
+import org.rhq.core.domain.content.transfer.RemovePackagesResponse;
+import org.rhq.core.domain.content.transfer.ResourcePackageDetails;
 import org.rhq.core.domain.measurement.AvailabilityType;
+import org.rhq.core.domain.measurement.MeasurementReport;
+import org.rhq.core.domain.measurement.MeasurementScheduleRequest;
+import org.rhq.core.pluginapi.bundle.BundleDeployRequest;
+import org.rhq.core.pluginapi.bundle.BundleDeployResult;
+import org.rhq.core.pluginapi.bundle.BundleFacet;
+import org.rhq.core.pluginapi.bundle.BundlePurgeRequest;
+import org.rhq.core.pluginapi.bundle.BundlePurgeResult;
+import org.rhq.core.pluginapi.configuration.ConfigurationFacet;
+import org.rhq.core.pluginapi.configuration.ConfigurationUpdateReport;
+import org.rhq.core.pluginapi.content.ContentFacet;
+import org.rhq.core.pluginapi.content.ContentServices;
+import org.rhq.core.pluginapi.inventory.CreateChildResourceFacet;
+import org.rhq.core.pluginapi.inventory.CreateResourceReport;
+import org.rhq.core.pluginapi.inventory.DeleteResourceFacet;
 import org.rhq.core.pluginapi.inventory.InvalidPluginConfigurationException;
 import org.rhq.core.pluginapi.inventory.ResourceComponent;
 import org.rhq.core.pluginapi.inventory.ResourceContext;
+import org.rhq.core.pluginapi.measurement.MeasurementFacet;
+import org.rhq.core.pluginapi.operation.OperationFacet;
+import org.rhq.core.pluginapi.operation.OperationResult;
+import org.rhq.core.pluginapi.support.SnapshotReportRequest;
+import org.rhq.core.pluginapi.support.SnapshotReportResults;
+import org.rhq.core.pluginapi.support.SupportFacet;
 
 /**
+ * This resource component implements most (all?) of the facets so that all the plugin container subsystems can work
+ * with it.
+ *  
  * @author Ian Springer
  */
-public class TestResourceComponent implements ResourceComponent<ResourceComponent<?>> {
+public class TestResourceComponent implements ResourceComponent<ResourceComponent<?>>, OperationFacet, ContentFacet,
+    ConfigurationFacet, MeasurementFacet, DeleteResourceFacet, CreateChildResourceFacet, BundleFacet, SupportFacet {
 
     private ResourceContext<ResourceComponent<?>> resourceContext;
 
@@ -46,4 +80,71 @@ public class TestResourceComponent implements ResourceComponent<ResourceComponen
         return;
     }
 
+    @Override
+    public SnapshotReportResults getSnapshotReport(SnapshotReportRequest request) throws Exception {
+        return null;
+    }
+
+    @Override
+    public BundleDeployResult deployBundle(BundleDeployRequest request) {
+        return null;
+    }
+
+    @Override
+    public BundlePurgeResult purgeBundle(BundlePurgeRequest request) {
+        return null;
+    }
+
+    @Override
+    public CreateResourceReport createResource(CreateResourceReport report) {
+        return null;
+    }
+
+    @Override
+    public void deleteResource() throws Exception {
+    }
+
+    @Override
+    public void getValues(MeasurementReport report, Set<MeasurementScheduleRequest> metrics) throws Exception {
+    }
+
+    @Override
+    public Configuration loadResourceConfiguration() throws Exception {
+        return null;
+    }
+
+    @Override
+    public void updateResourceConfiguration(ConfigurationUpdateReport report) {
+    }
+
+    @Override
+    public List<DeployPackageStep> generateInstallationSteps(ResourcePackageDetails packageDetails) {
+        return null;
+    }
+
+    @Override
+    public DeployPackagesResponse deployPackages(Set<ResourcePackageDetails> packages, ContentServices contentServices) {
+        return null;
+    }
+
+    @Override
+    public RemovePackagesResponse removePackages(Set<ResourcePackageDetails> packages) {
+        return null;
+    }
+
+    @Override
+    public Set<ResourcePackageDetails> discoverDeployedPackages(PackageType type) {
+        return null;
+    }
+
+    @Override
+    public InputStream retrievePackageBits(ResourcePackageDetails packageDetails) {
+        return null;
+    }
+
+    @Override
+    public OperationResult invokeOperation(String name, Configuration parameters) throws InterruptedException,
+        Exception {
+        return null;
+    }
 }
diff --git a/modules/core/plugin-container-itest/src/test/resources/test-great-grandchild-discovery-plugin.xml b/modules/core/plugin-container-itest/src/test/resources/test-great-grandchild-discovery-plugin.xml
index 477b3c9..a1e222a 100644
--- a/modules/core/plugin-container-itest/src/test/resources/test-great-grandchild-discovery-plugin.xml
+++ b/modules/core/plugin-container-itest/src/test/resources/test-great-grandchild-discovery-plugin.xml
@@ -27,4 +27,34 @@
          </service>
       </service>
    </server>
+   
+   <server name="Manual Add Server"
+           discovery="ManualAddDiscoveryComponent"
+           class="TestResourceComponent">
+      <plugin-configuration>
+         <c:simple-property name="test" />
+      </plugin-configuration>
+      <operation name="test" />      
+      <metric property="test" />      
+      <event name="test" />            
+      <content name="test" category="executableScript" />
+      <resource-configuration>
+         <c:simple-property name="test" />
+      </resource-configuration>
+      
+      <drift-definition name="test">
+        <basedir>
+            <value-context>fileSystem</value-context>
+            <value-name>test</value-name>
+        </basedir>
+      </drift-definition>
+      
+      <bundle-target>
+         <destination-base-dir name="test">
+            <value-context>fileSystem</value-context>
+            <value-name>test</value-name>
+         </destination-base-dir>
+      </bundle-target>
+      
+   </server>
 </plugin>
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/availability/AvailabilityContextImpl.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/availability/AvailabilityContextImpl.java
index f34d673..32fb361 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/availability/AvailabilityContextImpl.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/availability/AvailabilityContextImpl.java
@@ -79,4 +79,11 @@ public class AvailabilityContextImpl implements AvailabilityContext {
     public void enable() {
         PluginContainer.getInstance().getInventoryManager().setResourceEnablement(resource.getId(), true);
     }
+
+    /**
+     * Only used in tests
+     */
+    public Resource getResource() {
+        return resource;
+    }
 }
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/event/EventContextImpl.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/event/EventContextImpl.java
index a50a658..fd360cf 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/event/EventContextImpl.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/event/EventContextImpl.java
@@ -108,6 +108,13 @@ public class EventContextImpl implements EventContext {
         return getEventManager().getSigar();
     }
 
+    /**
+     * Only used for testing purposes.
+     */
+    public Resource getResource() {
+        return resource;
+    }
+
     private void registerEventPollerInternal(final EventPoller poller, int pollingInterval, final String sourceLocation) {
         EventDefinition eventDefinition = EventUtility.getEventDefinition(poller.getEventType(),
             this.resource.getResourceType());


commit 13663106e701a2390f7dc06a778718994318a4c4
Author: Lukas Krejci <lkrejci at redhat.com>
Date:   Fri Jun 15 14:14:01 2012 +0200

    Trivial - code formatting

diff --git a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/DeploymentTest.java b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/DeploymentTest.java
index 655b0a3..6f84e34 100644
--- a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/DeploymentTest.java
+++ b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/DeploymentTest.java
@@ -64,32 +64,32 @@ import org.rhq.test.arquillian.ServerServicesSetup;
 @Test(groups = { "integration", "pc", "standalone" }, singleThreaded = true)
 public class DeploymentTest extends AbstractJBossAS7PluginTest {
 
-	private enum TestDeployments {
-		DEPLOYMENT_1("test-simple.war"), DEPLOYMENT_2("test-simple-2.war");
-		
-		private String deploymentName;
-		private String resourcePath;
-		private byte[] hash;
-		
-		private TestDeployments(String warName) {
-			this.deploymentName = warName;
-			this.resourcePath = "itest/" + warName;
-			hash = computeHash(DeploymentTest.class.getClassLoader().getResourceAsStream(resourcePath));
-		}
-		
-		public String getDeploymentName() {
-			return deploymentName;
-		}
-		
-		public String getResourcePath() {
-			return resourcePath;
-		}
-		
-		public byte[] getHash() {
-			return hash;
-		}
-	}
-	
+    private enum TestDeployments {
+        DEPLOYMENT_1("test-simple.war"), DEPLOYMENT_2("test-simple-2.war");
+
+        private String deploymentName;
+        private String resourcePath;
+        private byte[] hash;
+
+        private TestDeployments(String warName) {
+            this.deploymentName = warName;
+            this.resourcePath = "itest/" + warName;
+            hash = computeHash(DeploymentTest.class.getClassLoader().getResourceAsStream(resourcePath));
+        }
+
+        public String getDeploymentName() {
+            return deploymentName;
+        }
+
+        public String getResourcePath() {
+            return resourcePath;
+        }
+
+        public byte[] getHash() {
+            return hash;
+        }
+    }
+
     @ResourceComponentInstances(plugin = PLUGIN_NAME, resourceType = "JBossAS7 Standalone Server")
     private Set<StandaloneASComponent> standalones;
 
@@ -102,7 +102,7 @@ public class DeploymentTest extends AbstractJBossAS7PluginTest {
     private Set<Resource> deploymentResources;
 
     private static TestDeployments DEPLOYMENT_TO_SERVE = TestDeployments.DEPLOYMENT_1;
-    
+
     private static long copyStreamAndReturnCount(InputStream in, OutputStream out) throws IOException {
         int data;
         long cnt = 0;
@@ -115,7 +115,7 @@ public class DeploymentTest extends AbstractJBossAS7PluginTest {
 
         return cnt;
     }
-    
+
     //this is no test method
     @ServerServicesSetup
     @Test(enabled = false)
@@ -126,16 +126,20 @@ public class DeploymentTest extends AbstractJBossAS7PluginTest {
             new Answer<Long>() {
                 @Override
                 public Long answer(InvocationOnMock invocation) throws Throwable {
-                    InputStream str = getClass().getClassLoader().getResourceAsStream(DEPLOYMENT_TO_SERVE.getResourcePath());
+                    InputStream str = getClass().getClassLoader().getResourceAsStream(
+                        DEPLOYMENT_TO_SERVE.getResourcePath());
                     OutputStream out = (OutputStream) invocation.getArguments()[invocation.getArguments().length - 1];
                     return copyStreamAndReturnCount(str, out);
                 }
             });
-        
-        Mockito.when(serverServices.getContentServerService().downloadPackageBitsGivenResource(Mockito.anyInt(), Mockito.any(PackageDetailsKey.class), Mockito.any(OutputStream.class))).then(new Answer<Long>() {
+
+        Mockito.when(
+            serverServices.getContentServerService().downloadPackageBitsGivenResource(Mockito.anyInt(),
+                Mockito.any(PackageDetailsKey.class), Mockito.any(OutputStream.class))).then(new Answer<Long>() {
             @Override
             public Long answer(InvocationOnMock invocation) throws Throwable {
-                InputStream str = getClass().getClassLoader().getResourceAsStream(DEPLOYMENT_TO_SERVE.getResourcePath());
+                InputStream str = getClass().getClassLoader()
+                    .getResourceAsStream(DEPLOYMENT_TO_SERVE.getResourcePath());
                 OutputStream out = (OutputStream) invocation.getArguments()[invocation.getArguments().length - 1];
                 return copyStreamAndReturnCount(str, out);
             }
@@ -167,8 +171,8 @@ public class DeploymentTest extends AbstractJBossAS7PluginTest {
         request.setResourceName(packageDetails.getName());
         request.setResourceTypeName("Deployment");
 
-        CreateResourceResponse response =
-            pluginContainer.getResourceFactoryManager().executeCreateResourceImmediately(request);
+        CreateResourceResponse response = pluginContainer.getResourceFactoryManager().executeCreateResourceImmediately(
+            request);
 
         assert response.getStatus() == CreateResourceStatus.SUCCESS : "The deoloyment failed with an error mesasge: "
             + response.getErrorMessage();
@@ -181,16 +185,17 @@ public class DeploymentTest extends AbstractJBossAS7PluginTest {
         Resource deployment = deploymentResources.iterator().next();
 
         assert TestDeployments.DEPLOYMENT_1.getDeploymentName().equals(deployment.getName()) : "The deployment doesn't seem to have the expected name";
-        
-        ContentDiscoveryReport report = pluginContainer.getContentManager().executeResourcePackageDiscoveryImmediately(deployment.getId(), "file");
-        
+
+        ContentDiscoveryReport report = pluginContainer.getContentManager().executeResourcePackageDiscoveryImmediately(
+            deployment.getId(), "file");
+
         Set<ResourcePackageDetails> details = report.getDeployedPackages();
-        
+
         assert details != null && details.size() == 1 : "The archived deployment should be backed by exactly 1 package.";
-        
+
         ResourcePackageDetails actualDetails = details.iterator().next();
         ResourcePackageDetails expectedDetails = getTestDeploymentPackageDetails(TestDeployments.DEPLOYMENT_1);
-        
+
         //we don't expect the resource details to be equal, because the version field
         //will be different - the test code simplistically just assigns "1.0"
         //but the actual code assigns a sha256, because the test war doesn't contain
@@ -200,39 +205,42 @@ public class DeploymentTest extends AbstractJBossAS7PluginTest {
         String actualType = actualDetails.getPackageTypeName();
         String expectedName = expectedDetails.getName();
         String expectedType = expectedDetails.getPackageTypeName();
-        
-        Assert.assertEquals(actualName, expectedName, "The deployment's package details are called differently than expected.");
-        Assert.assertEquals(actualType, expectedType, "The deployment's package details have different type than expected.");
+
+        Assert.assertEquals(actualName, expectedName,
+            "The deployment's package details are called differently than expected.");
+        Assert.assertEquals(actualType, expectedType,
+            "The deployment's package details have different type than expected.");
     }
 
     @Test(priority = 13)
     public void testDeploymentContentRetrieval() throws Exception {
-    	testContentRetrieval(TestDeployments.DEPLOYMENT_1);
+        testContentRetrieval(TestDeployments.DEPLOYMENT_1);
     }
 
     @Test(priority = 14)
     public void testRedeploy() throws Exception {
-    	Resource deployment = deploymentResources.iterator().next();
-    	//we are updating the deployment 1. So provide a key to the first deployment but later on actually
-    	//deliver bits of the deployment 2, so that we get the update we "wanted".
-    	ResourcePackageDetails packageDetails = getTestDeploymentPackageDetails(TestDeployments.DEPLOYMENT_1);
-    	
-    	//this is what our mocked serverside is going to serve the package bits for
-    	TestDeployments origServedDeployemnt = DEPLOYMENT_TO_SERVE;
-    	DEPLOYMENT_TO_SERVE = TestDeployments.DEPLOYMENT_2;
-    	
-    	try {
-	    	DeployPackagesRequest request = new DeployPackagesRequest(1, deployment.getId(), Collections.singleton(packageDetails));
-	    	    	
-	    	DeployPackagesResponse response = pluginContainer.getContentManager().deployPackagesImmediately(request);
-	    		    	
-	    	testContentRetrieval(TestDeployments.DEPLOYMENT_2);
-    	} finally {
-    		//switch the served deployment back, so that other tests aren't affected
-    		DEPLOYMENT_TO_SERVE = origServedDeployemnt;
-    	}
+        Resource deployment = deploymentResources.iterator().next();
+        //we are updating the deployment 1. So provide a key to the first deployment but later on actually
+        //deliver bits of the deployment 2, so that we get the update we "wanted".
+        ResourcePackageDetails packageDetails = getTestDeploymentPackageDetails(TestDeployments.DEPLOYMENT_1);
+
+        //this is what our mocked serverside is going to serve the package bits for
+        TestDeployments origServedDeployemnt = DEPLOYMENT_TO_SERVE;
+        DEPLOYMENT_TO_SERVE = TestDeployments.DEPLOYMENT_2;
+
+        try {
+            DeployPackagesRequest request = new DeployPackagesRequest(1, deployment.getId(),
+                Collections.singleton(packageDetails));
+
+            DeployPackagesResponse response = pluginContainer.getContentManager().deployPackagesImmediately(request);
+
+            testContentRetrieval(TestDeployments.DEPLOYMENT_2);
+        } finally {
+            //switch the served deployment back, so that other tests aren't affected
+            DEPLOYMENT_TO_SERVE = origServedDeployemnt;
+        }
     }
-    
+
     @Test(priority = 15)
     public void testUndeploy() throws Exception {
         Resource deployment = deploymentResources.iterator().next();
@@ -240,7 +248,7 @@ public class DeploymentTest extends AbstractJBossAS7PluginTest {
         getServerInventory().removeResource(deployment);
         pluginContainer.getResourceFactoryManager().deleteResource(request);
     }
-    
+
     private void testContentRetrieval(final TestDeployments deployment) throws Exception {
         final boolean[] lockAndTestResult = new boolean[2];
 
@@ -269,8 +277,8 @@ public class DeploymentTest extends AbstractJBossAS7PluginTest {
 
         //setup the content retrieval request and execute it
         Resource deploymentResource = deploymentResources.iterator().next();
-        RetrievePackageBitsRequest request =
-            new RetrievePackageBitsRequest(0, deploymentResource.getId(), getTestDeploymentPackageDetails(deployment));
+        RetrievePackageBitsRequest request = new RetrievePackageBitsRequest(0, deploymentResource.getId(),
+            getTestDeploymentPackageDetails(deployment));
         pluginContainer.getContentManager().retrievePackageBits(request);
 
         //the content retrieval is async so wait in the test method until the mocked server-side
@@ -282,14 +290,15 @@ public class DeploymentTest extends AbstractJBossAS7PluginTest {
             assert lockAndTestResult[1] : "The data obtained from the deployment are different to what should have been deployed.";
         }
     }
-    
+
     private ResourcePackageDetails getTestDeploymentPackageDetails(TestDeployments deployment) {
-        ResourcePackageDetails details = new ResourcePackageDetails(new PackageDetailsKey(deployment.getDeploymentName(), "1.0", "file", "noarch"));
+        ResourcePackageDetails details = new ResourcePackageDetails(new PackageDetailsKey(
+            deployment.getDeploymentName(), "1.0", "file", "noarch"));
         details.setFileName(deployment.getDeploymentName());
         details.setDeploymentTimeConfiguration(new Configuration());
-        
+
         return details;
-        
+
     }
 
     private static byte[] computeHash(InputStream str) {


commit 19f7fabd25d7beda27499e57a52a3f313c47a343
Author: John Mazzitelli <mazz at redhat.com>
Date:   Fri Jun 15 11:25:33 2012 -0400

    provide more information to the user when the security token is bad

diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/CoreServerServiceImpl.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/CoreServerServiceImpl.java
index 851937b..c976f5a 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/CoreServerServiceImpl.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/CoreServerServiceImpl.java
@@ -137,11 +137,8 @@ public class CoreServerServiceImpl implements CoreServerService {
                 if (agentByName != null) {
                     // the agent request provided a name that already is in use by an agent. However, the request
                     // provided a security token that was not assigned to any agent! How can this be? Something is fishy.
-                    String msg = "The agent asking for registration under the name ["
-                        + request.getName()
-                        + "] provided an invalid security token. This request will fail. "
-                        + "Please consult an administrator to obtain the agent's proper security token "
-                        + "and restart the agent with the option \"-Drhq.agent.security-token=<the valid security token>\"";
+                    String msg = "The agent asking for registration under the name [" + request.getName()
+                        + "] provided an invalid security token. This request will fail. " + securityTokenMessage();
                     throw new AgentRegistrationException(msg);
                 }
                 Agent agentByAddressPort = getAgentManager().getAgentByAddressAndPort(request.getAddress(),
@@ -176,11 +173,8 @@ public class CoreServerServiceImpl implements CoreServerService {
                         + " and same security token.";
                     throw new AgentRegistrationException(msg);
                 } else {
-                    String msg = "The agent ["
-                        + request.getName()
-                        + "] is attempting to re-register without a security token. "
-                        + "Please consult an administrator to obtain the agent's proper security token "
-                        + "and restart the agent with the option \"-Drhq.agent.security-token=<the valid security token>\"";
+                    String msg = "The agent [" + request.getName()
+                        + "] is attempting to re-register without a security token. " + securityTokenMessage();
                     throw new AgentRegistrationException(msg);
 
                 }
@@ -192,8 +186,7 @@ public class CoreServerServiceImpl implements CoreServerService {
                     String msg = "An agent is trying to register with an existing agent name ["
                         + request.getName()
                         + "] without providing a valid security token. If you are attempting to re-register this agent, "
-                        + "please consult an administrator to obtain the agent's proper security token "
-                        + "and restart the agent with the option \"-Drhq.agent.security-token=<the valid security token>\"";
+                        + "you will need the agent's security token. " + securityTokenMessage();
                     throw new AgentRegistrationException(msg);
                 }
             }
@@ -274,6 +267,15 @@ public class CoreServerServiceImpl implements CoreServerService {
         return results;
     }
 
+    private String securityTokenMessage() {
+        return "Please consult an administrator to obtain the agent's proper security token "
+            + "and restart the agent with the option \"-Drhq.agent.security-token=<the valid security token>\". "
+            + "An administrator can find the agent's security token by navigating to the GUI page "
+            + "\"Administration (Topology) > Agents\" and drilling down to this specific agent. "
+            + "You will see the long security token string there. For more information, read: "
+            + "https://docs.jboss.org/author/display/RHQ/Agent+Registration";
+    }
+
     /**
      * @see CoreServerService#connectAgent(ConnectAgentRequest)
      */


commit 544aba9cb75ea85b9dd2ceecb56047290856eab7
Author: John Mazzitelli <mazz at redhat.com>
Date:   Thu Jun 14 17:06:29 2012 -0400

    [BZ 832204] protect against npe when the message bar disappears but user still has the root cause context menu option and selects it

diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/message/MessageBar.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/message/MessageBar.java
index 0aba1ba..a2d76e5 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/message/MessageBar.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/util/message/MessageBar.java
@@ -85,14 +85,19 @@ public class MessageBar extends LocatableHLayout implements MessageCenter.Messag
         showRootCauseMenuItem.addClickHandler(new ClickHandler() {
             @Override
             public void onClick(MenuItemClickEvent event) {
-                String rootCause = MessageBar.this.currentMessage.getRootCauseMessage();
-                SC.say(MSG.view_messageCenter_messageRootCause(), rootCause);
+                Message msg = MessageBar.this.currentMessage;
+                if (msg != null) {
+                    String rootCause = msg.getRootCauseMessage();
+                    if (rootCause != null) {
+                        SC.say(MSG.view_messageCenter_messageRootCause(), rootCause);
+                    }
+                }
             }
         });
         showRootCauseMenuItem.setEnableIfCondition(new MenuItemIfFunction() {
             public boolean execute(Canvas target, Menu menu, MenuItem item) {
-                return MessageBar.this.currentMessage != null
-                    && MessageBar.this.currentMessage.getRootCauseMessage() != null;
+                Message msg = MessageBar.this.currentMessage;
+                return msg != null && msg.getRootCauseMessage() != null;
             }
         });
 


commit 0cdd1e4fd3e738b275a59751e0fb0a07bcd1a626
Author: Stefan Negrea <snegrea at redhat.com>
Date:   Thu Jun 14 15:29:43 2012 -0500

    Adding ignored resources along with reason for ignoring them to the load/update integration test.

diff --git a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/ResourcesStandaloneServerTest.java b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/ResourcesStandaloneServerTest.java
index 4eb3519..d11e7ab 100644
--- a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/ResourcesStandaloneServerTest.java
+++ b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/ResourcesStandaloneServerTest.java
@@ -39,8 +39,6 @@ import org.rhq.core.domain.configuration.Configuration;
 import org.rhq.core.domain.operation.OperationDefinition;
 import org.rhq.core.domain.resource.InventoryStatus;
 import org.rhq.core.domain.resource.Resource;
-import org.rhq.core.domain.resource.ResourceCategory;
-import org.rhq.core.domain.resource.ResourceType;
 import org.rhq.core.pc.configuration.ConfigurationManager;
 import org.rhq.core.pc.inventory.InventoryManager;
 import org.rhq.core.pc.inventory.ResourceContainer;
@@ -77,20 +75,26 @@ public class ResourcesStandaloneServerTest extends AbstractJBossAS7PluginTest  {
 
     @Test(priority = 12)
     public void loadUpdateTemplatedResourceConfiguration() throws Exception {
+        List<String> ignoredResources = new ArrayList<String>();
+
+        //ignored because of differences between test plugin container and real application
+        //works well with real agent
+        ignoredResources.add("VHost");
+
+        //ignored because the settings different when started with arquillian, inet-address is not set correctly
+        //works well with real agent
+        ignoredResources.add("Network Interface");
+
         Resource platform = this.pluginContainer.getInventoryManager().getPlatform();
         Resource server = getResourceByTypeAndKey(platform, StandaloneServerComponentTest.RESOURCE_TYPE,
             StandaloneServerComponentTest.RESOURCE_KEY);
 
         ConfigurationManager configurationManager = this.pluginContainer.getConfigurationManager();
         configurationManager.initialize();
-        Thread.sleep(100 * 1000L);
+        Thread.sleep(40 * 1000L);
 
         Queue<Resource> unparsedResources = new LinkedList<Resource>();
         for (Resource topLevelResource : server.getChildResources()) {
-            ResourceType resourceType = new ResourceType(topLevelResource.getResourceType().getName(), PLUGIN_NAME,
-                ResourceCategory.SERVICE, null);
-            topLevelResource = getResourceByTypeAndKey(server, resourceType, topLevelResource.getResourceKey());
-
             if (topLevelResource.getInventoryStatus().equals(InventoryStatus.COMMITTED)) {
                 unparsedResources.add(topLevelResource);
             } else {
@@ -111,7 +115,8 @@ public class ResourcesStandaloneServerTest extends AbstractJBossAS7PluginTest  {
                 }
             }
 
-            if (resourceUnderTest.getResourceType().getResourceConfigurationDefinition() != null) {
+            if (resourceUnderTest.getResourceType().getResourceConfigurationDefinition() != null
+                && !ignoredResources.contains(resourceUnderTest.getResourceType().getName())) {
                 Configuration configUnderTest = configurationManager
                     .loadResourceConfiguration(resourceUnderTest.getId());
 


commit 6b4d1b0baf4d1d95d51d14fc7387fbc78cbf97fe
Author: Jay Shaughnessy <jshaughn at redhat.com>
Date:   Thu Jun 14 16:24:46 2012 -0400

    [830158 - java.sql.BatchUpdateException when you uninventory everything right after importing it]
    The exception is due to badness when trying to uninventory a platform that is
    actively merging in new resources.  This is an unlikely use case.  This commit
    does not try to prevent the problem but rather adds some exception handling
    and an improved log message indicating the probably scenario, and suggesting the
    user retry after waiting for the resources to be merged.

diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java
index 468f619..79c7935 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java
@@ -276,101 +276,116 @@ public class ResourceManagerBean implements ResourceManagerLocal, ResourceManage
             throw new PermissionException("You do not have permission to uninventory resource [" + resourceId + "]");
         }
 
-        // if the resource has no parent, its a top root resource and its agent should be purged too
-        // test code does not always follow this rule, so catch and continue.
+        // if the resource has no parent, its a platform resource and its agent should be purged too
         Agent doomedAgent = null;
-        if (resource.getParentResource() == null) {
-            try {
+        try {
+            if (resource.getParentResource() == null) {
                 // note, this needs to be done before the marking because the agent reference is going to be set to null
                 doomedAgent = agentManager.getAgentByResourceId(subjectManager.getOverlord(), resourceId);
-            } catch (Exception e) {
-                doomedAgent = null;
-                log.warn("This warning should occur in TEST code only! " + e);
+
+                // note - test code does not always provide the agent, if not found, just warn
+                if (doomedAgent == null) {
+                    log.warn("Platform resource had no associated agent. This warning should occur in TEST code only!");
+                }
             }
-        }
 
-        AgentClient agentClient = null;
-        try {
-            // The test code does not always generate agents for the resources. Catch and log any problem but continue
-            agentClient = agentManager.getAgentClient(subjectManager.getOverlord(), resourceId);
-        } catch (Throwable t) {
-            log.warn("No AgentClient found for resource [" + resource
-                + "]. Unable to inform agent of inventory removal (this may be ok): " + t);
-        }
+            AgentClient agentClient = null;
+            try {
+                // The test code does not always generate agents for the resources. Catch and log any problem but continue
+                agentClient = agentManager.getAgentClient(subjectManager.getOverlord(), resourceId);
+            } catch (Throwable t) {
+                log.warn("No AgentClient found for resource [" + resource
+                    + "]. Unable to inform agent of inventory removal (this may be ok): " + t);
+            }
 
-        // since we delete the resource asynchronously now, we need to make sure we remove things that would cause
-        // system side effects after markForDeletion completed but before the resource was actually removed from the DB
-        Subject overlord = subjectManager.getOverlord();
+            // since we delete the resource asynchronously now, we need to make sure we remove things that would cause
+            // system side effects after markForDeletion completed but before the resource was actually removed from the DB
+            Subject overlord = subjectManager.getOverlord();
 
-        // delete the resource and all its children
-        log.info("User [" + user + "] is marking resource [" + resource + "] for asynchronous uninventory");
+            // delete the resource and all its children
+            log.info("User [" + user + "] is marking resource [" + resource + "] for asynchronous uninventory");
 
-        // set agent references null
-        // foobar the resourceKeys
-        // update the inventory status to UNINVENTORY
-        Query toBeDeletedQuery = entityManager.createNamedQuery(Resource.QUERY_FIND_DESCENDANTS);
-        toBeDeletedQuery.setParameter("resourceId", resourceId);
-        List<Integer> toBeDeletedResourceIds = toBeDeletedQuery.getResultList();
+            // set agent references null
+            // foobar the resourceKeys
+            // update the inventory status to UNINVENTORY
+            Query toBeDeletedQuery = entityManager.createNamedQuery(Resource.QUERY_FIND_DESCENDANTS);
+            toBeDeletedQuery.setParameter("resourceId", resourceId);
+            List<Integer> toBeDeletedResourceIds = toBeDeletedQuery.getResultList();
 
-        int i = 0;
-        log.debug("== total size : " + toBeDeletedResourceIds.size());
+            int i = 0;
+            log.debug("== total size : " + toBeDeletedResourceIds.size());
+
+            while (i < toBeDeletedResourceIds.size()) {
+                int j = i + 1000;
+                if (j > toBeDeletedResourceIds.size())
+                    j = toBeDeletedResourceIds.size();
+                List<Integer> idsToDelete = toBeDeletedResourceIds.subList(i, j);
+                log.debug("== Bounds " + i + ", " + j);
+
+                boolean hasErrors = uninventoryResourcesBulkDelete(overlord, idsToDelete);
+                if (hasErrors) {
+                    throw new IllegalArgumentException("Could not remove resources from their containing groups");
+                }
+                i = j;
+            }
 
-        while (i < toBeDeletedResourceIds.size()) {
-            int j = i + 1000;
-            if (j > toBeDeletedResourceIds.size())
-                j = toBeDeletedResourceIds.size();
-            List<Integer> idsToDelete = toBeDeletedResourceIds.subList(i, j);
-            log.debug("== Bounds " + i + ", " + j);
+            // QUERY_MARK_RESOURCES_FOR_ASYNC_DELETION is an expensive recursive query
+            // But luckily we have already (through such a recursive query above) determined the doomed resources
+            //        Query markDeletedQuery = entityManager.createNamedQuery(Resource.QUERY_MARK_RESOURCES_FOR_ASYNC_DELETION);
+            //        markDeletedQuery.setParameter("resourceId", resourceId);
+            //        markDeletedQuery.setParameter("status", InventoryStatus.UNINVENTORIED);
+            //        int resourcesDeleted = markDeletedQuery.executeUpdate();
 
-            boolean hasErrors = uninventoryResourcesBulkDelete(overlord, idsToDelete);
-            if (hasErrors) {
-                throw new IllegalArgumentException("Could not remove resources from their containing groups");
+            i = 0;
+            int resourcesDeleted = 0;
+            while (i < toBeDeletedResourceIds.size()) {
+                int j = i + 1000;
+                if (j > toBeDeletedResourceIds.size())
+                    j = toBeDeletedResourceIds.size();
+                List<Integer> idsToDelete = toBeDeletedResourceIds.subList(i, j);
+
+                Query markDeletedQuery = entityManager
+                    .createNamedQuery(Resource.QUERY_MARK_RESOURCES_FOR_ASYNC_DELETION_QUICK);
+                markDeletedQuery.setParameter("resourceIds", idsToDelete);
+                markDeletedQuery.setParameter("status", InventoryStatus.UNINVENTORIED);
+                resourcesDeleted += markDeletedQuery.executeUpdate();
+                i = j;
             }
-            i = j;
-        }
 
-        // QUERY_MARK_RESOURCES_FOR_ASYNC_DELETION is an expensive recursive query
-        // But luckily we have already (through such a recursive query above) determined the doomed resources
-        //        Query markDeletedQuery = entityManager.createNamedQuery(Resource.QUERY_MARK_RESOURCES_FOR_ASYNC_DELETION);
-        //        markDeletedQuery.setParameter("resourceId", resourceId);
-        //        markDeletedQuery.setParameter("status", InventoryStatus.UNINVENTORIED);
-        //        int resourcesDeleted = markDeletedQuery.executeUpdate();
+            if (resourcesDeleted != toBeDeletedResourceIds.size()) {
+                log.error("Tried to uninventory " + toBeDeletedResourceIds.size()
+                    + " resources, but actually uninventoried " + resourcesDeleted);
+            }
 
-        i = 0;
-        int resourcesDeleted = 0;
-        while (i < toBeDeletedResourceIds.size()) {
-            int j = i + 1000;
-            if (j > toBeDeletedResourceIds.size())
-                j = toBeDeletedResourceIds.size();
-            List<Integer> idsToDelete = toBeDeletedResourceIds.subList(i, j);
+            // still need to tell the agent about the removed resources so it stops avail reports
+            if (agentClient != null) {
+                try {
+                    agentClient.getDiscoveryAgentService().uninventoryResource(resourceId);
+                } catch (Exception e) {
+                    log.warn(" Unable to inform agent of inventory removal for resource [" + resourceId + "]", e);
+                }
+            }
 
-            Query markDeletedQuery = entityManager
-                .createNamedQuery(Resource.QUERY_MARK_RESOURCES_FOR_ASYNC_DELETION_QUICK);
-            markDeletedQuery.setParameter("resourceIds", idsToDelete);
-            markDeletedQuery.setParameter("status", InventoryStatus.UNINVENTORIED);
-            resourcesDeleted += markDeletedQuery.executeUpdate();
-            i = j;
-        }
+            // now remove the dommed agent. Call flush() to force out any problems with agent removal
+            // so that we can catch them and report a better exception. 
+            if (doomedAgent != null) {
+                agentManager.deleteAgent(doomedAgent);
+                entityManager.flush();
+            }
 
-        if (resourcesDeleted != toBeDeletedResourceIds.size()) {
-            log.error("Tried to uninventory " + toBeDeletedResourceIds.size()
-                + " resources, but actually uninventoried " + resourcesDeleted);
-        }
+            return toBeDeletedResourceIds;
 
-        // still need to tell the agent about the removed resources so it stops avail reports
-        if (agentClient != null) {
-            try {
-                agentClient.getDiscoveryAgentService().uninventoryResource(resourceId);
-            } catch (Exception e) {
-                log.warn(" Unable to inform agent of inventory removal for resource [" + resourceId + "]", e);
+        } catch (RuntimeException e) {
+            if (doomedAgent != null) {
+                // The most likely reason for a failure, although unlikely in itself, is that newly discovered resources
+                // are currently being merged into the platform, and associated with the doomed agent.  In this case
+                // the user must wait until the merge is complete.  Make sure the caller knows about this possibility.
+                throw new IllegalStateException(
+                    "Failed to uninventory platform. This can happen if new resources were actively being imported. Please wait and try again shortly.");
             }
-        }
 
-        if (doomedAgent != null) {
-            agentManager.deleteAgent(doomedAgent);
+            throw e;
         }
-
-        return toBeDeletedResourceIds;
     }
 
     @SuppressWarnings("unchecked")


commit f33a3aca5c5915df31276bdebe287d81c7f9942d
Author: John Mazzitelli <mazz at redhat.com>
Date:   Thu Jun 14 15:16:27 2012 -0400

    [BZ 825338] fix the doc links to point to the new jboss.org RHQ confluence docs

diff --git a/etc/m2/settings.xml b/etc/m2/settings.xml
index 0464376..8bb17aa 100644
--- a/etc/m2/settings.xml
+++ b/etc/m2/settings.xml
@@ -248,7 +248,7 @@
         <!--<rhq.containerDir>C:/home/bob/rhq-dev-container</rhq.containerDir>-->
 
         <!-- set browser(s) to compile the GWT stuff for
-          ~~ See http://rhq-project.org/display/RHQ/Advanced+Build+Notes#AdvancedBuildNotes-GWTCompilationForDifferentBrowsers
+          ~~ See https://docs.jboss.org/author/display/RHQ/Advanced+Build+Notes#AdvancedBuildNotes-GWTCompilationForDifferentBrowsers
           ~~ for details and browser versions
           ~~ Possible values are: ie6,ie8,ie9,gecko,gecko1_8,safari,opera
         -->
@@ -277,8 +277,8 @@
     <profile>
       <id>publish</id>
       <properties>
-        <confluenceUrl>http://rhq-project.org/</confluenceUrl>
-        <confluenceSpace>JOPR2</confluenceSpace>
+        <confluenceUrl>https://docs.jboss.org/author/display/</confluenceUrl>
+        <confluenceSpace>RHQ</confluenceSpace>
         <confluenceParentPageTitle>Managed Resources</confluenceParentPageTitle>
         <confluenceUserName>SET_ME</confluenceUserName>
         <confluencePassword>SET_ME</confluencePassword>
diff --git a/etc/m2/smartgwt-war-archetype/pom.xml b/etc/m2/smartgwt-war-archetype/pom.xml
index 19ef9be..fdec67d 100644
--- a/etc/m2/smartgwt-war-archetype/pom.xml
+++ b/etc/m2/smartgwt-war-archetype/pom.xml
@@ -16,7 +16,7 @@
 
   <name>smartgwt-war-archetype</name>
   <description>archetype for a Maven project for a SmartGWT web application (WAR)</description>
-  <url>http://rhq-project.org/</url>
+  <url>http://www.jboss.org/rhq/</url>
 
   <licenses>
     <license>
diff --git a/modules/core/plugindoc/src/main/java/org/rhq/core/tool/plugindoc/PluginDocGenerator.java b/modules/core/plugindoc/src/main/java/org/rhq/core/tool/plugindoc/PluginDocGenerator.java
index 605b644..dbf047d 100644
--- a/modules/core/plugindoc/src/main/java/org/rhq/core/tool/plugindoc/PluginDocGenerator.java
+++ b/modules/core/plugindoc/src/main/java/org/rhq/core/tool/plugindoc/PluginDocGenerator.java
@@ -115,8 +115,8 @@ public class PluginDocGenerator {
     }
 
     public void loadProperties(Properties props) {
-        this.confluenceUrl = props.getProperty("confluenceUrl", "http://rhq-project.org/");
-        this.confluenceSpace = props.getProperty("confluenceSpace", "JOPR2");
+        this.confluenceUrl = props.getProperty("confluenceUrl", "https://docs.jboss.org/author/display/");
+        this.confluenceSpace = props.getProperty("confluenceSpace", "RHQ");
         this.confluenceParentPageTitle = props.getProperty("confluenceParentPageTitle", "Management Plugins");
         this.confluenceUserName = props.getProperty("confluenceUserName");
         this.confluencePassword = props.getProperty("confluencePassword");
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/DashboardsView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/DashboardsView.java
index 52e3a8f..cae2d20 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/DashboardsView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/DashboardsView.java
@@ -323,7 +323,8 @@ public class DashboardsView extends LocatableVLayout implements DashboardContain
 
         DashboardPortlet news = new DashboardPortlet(MashupPortlet.NAME, MashupPortlet.KEY, 300);
         if (isRHQ) {
-            news.getConfiguration().put(new PropertySimple("address", "http://rhq-project.org/display/RHQ/Home"));
+            news.getConfiguration()
+                .put(new PropertySimple("address", "https://docs.jboss.org/author/display/RHQ/Home"));
         } else {
             news.getConfiguration().put(
                 new PropertySimple("address",
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/MessageConstants.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/MessageConstants.properties
index 5f4e2d9..c3b641e 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/MessageConstants.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/MessageConstants.properties
@@ -33,17 +33,17 @@ view_help_section_1_title       = Documentation
 view_help_section_1_item_count  = 3
 
 view_help_section_1_propTitle_1 = Frequently Asked Questions (FAQ) 
-view_help_section_1_propUrl_1   = http://www.rhq-project.org/display/JOPR2/FAQ
+view_help_section_1_propUrl_1   = https://docs.jboss.org/author/display/RHQ/FAQ
 view_help_section_1_propTitle_2 = Documentation Set 
-view_help_section_1_propUrl_2   = http://www.rhq-project.org/display/JOPR2/Home
+view_help_section_1_propUrl_2   = https://docs.jboss.org/author/display/RHQ/Home
 view_help_section_1_propTitle_3 = API Javadoc 
-view_help_section_1_propUrl_3   = http://www.rhq-project.org/display/JOPR2/API+Documentation
+view_help_section_1_propUrl_3   = https://docs.jboss.org/author/display/RHQ/API+Documentation
 
 view_help_section_2_title       = Tutorial
 view_help_section_2_item_count  = 4
 
 view_help_section_2_propTitle_1 = Demo: All Demos 
-view_help_section_2_propUrl_1   = http://www.rhq-project.org/display/JOPR2/Demos
+view_help_section_2_propUrl_1   = https://docs.jboss.org/author/display/RHQ/Demos
 view_help_section_2_propTitle_2 = Demo: Bundle Provisioning 
 view_help_section_2_propUrl_2   = http://management-platform.blogspot.com/2011/01/bundle-provisioning-via-rhq.html 
 view_help_section_2_propTitle_3 = How to build Group Definitions 
@@ -51,4 +51,4 @@ view_help_section_2_propIcon_3  = [SKIN]/../actions/help.png
 view_help_section_2_propUrl_3   = http://docs.redhat.com/docs/en-US/JBoss_Operations_Network/2.4/html/Basic_Admin_Guide/sect-Basic_Admin_Guide-Managing_Groups.html#sect-Basic_Admin_Guide-Managing_Groups-Tutorial
 view_help_section_2_propTitle_4 = How to use the Search Bar 
 view_help_section_2_propIcon_4  = [SKIN]/../actions/help.png
-view_help_section_2_propUrl_4   = http://www.rhq-project.org/display/JOPR2/Search
+view_help_section_2_propUrl_4   = https://docs.jboss.org/author/display/RHQ/Search
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
index 0e948cd..8d228e8 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
@@ -3,7 +3,7 @@
 #
 # Developers: See the following wiki page for how to work with this file:
 #
-#   http://rhq-project.org/display/RHQ/Working+with+the+Resource+Bundles
+#   https://docs.jboss.org/author/display/RHQ/Working+with+the+Resource+Bundles
 #
 ###################################
 common_alert_high = High
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
index a5d71dd..edf2e50 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
@@ -26,7 +26,7 @@
 #
 # Developers: See the following wiki page for how to work with this file:
 #
-#   http://rhq-project.org/display/RHQ/Working+with+the+Resource+Bundles
+#   https://docs.jboss.org/author/display/RHQ/Working+with+the+Resource+Bundles
 #
 ###################################
 common_alert_high = Vysoká
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
index 57ffe8d..3806dd5 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
@@ -6,7 +6,7 @@
 #
 # Developers: See the following wiki page for how to work with this file:
 #
-#   http://rhq-project.org/display/RHQ/Working+with+the+Resource+Bundles
+#   https://docs.jboss.org/author/display/RHQ/Working+with+the+Resource+Bundles
 #
 ###################################
 common_alert_high = HOCH
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
index 0644243..42b166f 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
@@ -6,7 +6,7 @@
 #
 # Developers: See the following wiki page for how to work with this file:
 #
-#   http://rhq-project.org/display/RHQ/Working+with+the+Resource+Bundles
+#   https://docs.jboss.org/author/display/RHQ/Working+with+the+Resource+Bundles
 #
 ###################################
 common_alert_high = 高
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
index 923ace3..a755166 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
@@ -3,7 +3,7 @@
 #
 # Developers: See the following wiki page for how to work with this file:
 #
-#   http://rhq-project.org/display/RHQ/Working+with+the+Resource+Bundles
+#   https://docs.jboss.org/author/display/RHQ/Working+with+the+Resource+Bundles
 #
 ###################################
 F3view_admin_systemSettings_BaselineDataSet_desc = Quantidade de dados mensurados que ser\u00E1 utilizada para determinar um baseline. Valor especificado em dias.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
index f34cb82..c572c62 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
@@ -3,7 +3,7 @@
 ##
 ## Developers: See the following wiki page for how to work with this file:
 ##
-##   http://rhq-project.org/display/RHQ/Working+with+the+Resource+Bundles
+##   https://docs.jboss.org/author/display/RHQ/Working+with+the+Resource+Bundles
 ##
 ####################################
 #common_alert_high = High
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
index bafb045..8d22ea6 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
@@ -3,7 +3,7 @@
 #
 # Developers: See the following wiki page for how to work with this file:
 #
-#   http://rhq-project.org/display/RHQ/Working+with+the+Resource+Bundles
+#   https://docs.jboss.org/author/display/RHQ/Working+with+the+Resource+Bundles
 #
 ###################################
 common_alert_high = High
diff --git a/modules/enterprise/gui/installer-war/pom.xml b/modules/enterprise/gui/installer-war/pom.xml
index ba0518f..e26a864 100644
--- a/modules/enterprise/gui/installer-war/pom.xml
+++ b/modules/enterprise/gui/installer-war/pom.xml
@@ -25,16 +25,16 @@
     <product.shortName>RHQ</product.shortName>
     <product.name>RHQ</product.name>
     <product.fullName>RHQ</product.fullName>
-    <product.url.domain>rhq-project.org</product.url.domain>
+    <product.url.domain>jboss.org</product.url.domain>
     <product.sales.email>rhq-users at lists.fedorahosted.org</product.sales.email>
     <product.support.email>rhq-users at lists.fedorahosted.org</product.support.email>
     <product.version>${project.version}</product.version>
-    <product.help.doc.root>http://www.rhq-project.org/display/JOPR2/</product.help.doc.root>
+    <product.help.doc.root>https://docs.jboss.org/author/display/RHQ/</product.help.doc.root>
     <product.help.installation>Installation</product.help.installation>
     <product.help.guide.server>Running+the+RHQ+Server</product.help.guide.server>
     <product.help.guide.agent>Running+the+RHQ+Agent</product.help.guide.agent>
     <product.help.FAQ>FAQ</product.help.FAQ>
-    <product.help.config.props>http://www.rhq-project.org/display/JOPR2/Startup+Properties#StartupProperties-</product.help.config.props>
+    <product.help.config.props>https://docs.jboss.org/author/display/RHQ/Startup+Properties#StartupProperties-</product.help.config.props>
   </properties>
 
   <dependencies>
diff --git a/modules/enterprise/gui/installer-war/src/main/resources/InstallerMessages_ko.properties b/modules/enterprise/gui/installer-war/src/main/resources/InstallerMessages_ko.properties
index f206aef..719a354 100644
--- a/modules/enterprise/gui/installer-war/src/main/resources/InstallerMessages_ko.properties
+++ b/modules/enterprise/gui/installer-war/src/main/resources/InstallerMessages_ko.properties
@@ -1,10 +1,3 @@
-product.shortName=RHQ
-product.name=RHQ
-product.fullName=RHQ
-product.url=http://rhq-project.org/
-product.sales.email=sales at rhq-project.org
-product.support.email=info at rhq-project.org
-helpDocRoot=http://support.rhq-project.org/display/JOPR2/
 createDatabaseUserTitle=\uc0dd\uc131 \ub370\uc774\ud130\ubca0\uc774\uc2a4/\uc0ac\uc6a9\uc790
 createDatabaseUserHelp=\uc5ec\uae30\uc5d0 \ub370\uc774\ud130\ubca0\uc774\uc2a4 \uad00\ub9ac\uc790 \uc815\ubcf4\ub97c \uc785\ub825\ud558\uace0 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc640 \uc0ac\uc6a9\uc790\ub97c \ub9cc\ub4e4 \uc218 \uc788\ub294 \ubc84\ud2bc\uc744 \ub204\ub974\uc2ed\uc2dc\uc624.
 adminConnectionUrl=DB \uc5f0\uacb0 URL
@@ -156,7 +149,6 @@ helpDocRHQAgentUsersGuide=Running+the+RHQ+Agent
 helpDocRHQAgentUsersGuideLabel=RHQ \uc5d0\uc774\uc804\ud2b8 \uc0ac\uc6a9\uc790 \uac00\uc774\ub4dc
 helpDocFaq=FAQ
 helpDocFaqLabel=\uc790\uc8fc \ubb3b\ub294 \uc9c8\ubb38
-helpDocRHQServerPropParentPage=http://support.rhq-project.org/display/JOPR2/Startup+Properties#ConfiguringtheServer
 newServerSelectItem=\uc2e0\uaddc \uc11c\ubc84
 registeredServersLabel=\ub4f1\ub85d\ub41c \uc11c\ubc84:
 propertyHighAvailabilityName=\uc11c\ubc84 \uc774\ub984
diff --git a/modules/enterprise/gui/installer-war/src/main/resources/InstallerMessages_pt.properties b/modules/enterprise/gui/installer-war/src/main/resources/InstallerMessages_pt.properties
index c3af5ba..d5845f4 100644
--- a/modules/enterprise/gui/installer-war/src/main/resources/InstallerMessages_pt.properties
+++ b/modules/enterprise/gui/installer-war/src/main/resources/InstallerMessages_pt.properties
@@ -1,4 +1,3 @@
-helpDocRoot=http://support.rhq-project.org/display/RHQ/
 createDatabaseUserTitle=Criar Base de Dados/Usu\u00E1rio
 createDatabaseUserHelp=Entre com as informa\u00E7\u00F5es do administrador do banco de dados e clique no bot\u00E3o para criar o baco de dados e o usu\u00E1rio.
 adminConnectionUrl=URL de conex\u00E3o com BD
@@ -59,7 +58,6 @@ helpDocRHQGuiConsoleUsersGuideLabel=RHQ GUI Console - Guia do Usu\u00E1rio
 helpDocRHQServerUsersGuideLabel=RHQ Server - Guia do Usu\u00E1rio
 helpDocRHQAgentUsersGuideLabel=RHQ Agent - Guia do Usu\u00E1rio
 helpDocFaqLabel=Perguntas Frequentes (FAQ)
-helpDocRHQServerPropParentPage=http://support.rhq-project.org/display/RHQ/Configuring+the+Server#ConfiguringtheServer
 newServerSelectItem=Novo Servidor
 registeredServersLabel=Servidores Registrados
 propertyHighAvailabilityName=Nome do Servidor
diff --git a/modules/enterprise/gui/installer-war/src/main/resources/InstallerMessages_zh.properties b/modules/enterprise/gui/installer-war/src/main/resources/InstallerMessages_zh.properties
index e392202..8878300 100644
--- a/modules/enterprise/gui/installer-war/src/main/resources/InstallerMessages_zh.properties
+++ b/modules/enterprise/gui/installer-war/src/main/resources/InstallerMessages_zh.properties
@@ -150,7 +150,6 @@ helpDocRHQAgentUsersGuide=Running+the+RHQ+Agent
 helpDocRHQAgentUsersGuideLabel=RHQ Agent\u7528\u6237\u6307\u5357
 helpDocFaq=FAQ
 helpDocFaqLabel=\u7591\u96be\u89e3\u7b54
-helpDocRHQServerPropParentPage=http://support.rhq-project.org/display/JOPR2/Startup+Properties#ConfiguringtheServer
 newServerSelectItem=\u65b0\u670d\u52a1\u5668
 registeredServersLabel=\u6ce8\u518c\u7684\u670d\u52a1\u5668:
 propertyHighAvailabilityName=\u670d\u52a1\u5668\u540d\u79f0
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp-filtered/WEB-INF/classes/ApplicationResources.properties b/modules/enterprise/gui/portal-war/src/main/webapp-filtered/WEB-INF/classes/ApplicationResources.properties
index fd3edea..96c0e3b 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp-filtered/WEB-INF/classes/ApplicationResources.properties
+++ b/modules/enterprise/gui/portal-war/src/main/webapp-filtered/WEB-INF/classes/ApplicationResources.properties
@@ -88,7 +88,7 @@ common.field.value=Value
 
 common.marketing.FeatureDisabled=This feature is unavailable, please contact sales to upgrade
 
-common.url.help=http://www.rhq-project.org/display/JOPR2
+common.url.help=https://docs.jboss.org/author/display/RHQ/User+Documentation
 
 common.error.invalid.oid=OID specified is invalid, please enter OID in form of 1.2.3.4
 
@@ -2952,7 +2952,7 @@ software.common.InstallPreview.PatchTitle=Title
 software.common.InstallPreview.StepDescription=Step Description
 software.common.InstallPreview.ShortDescription=Short Description
 software.common.InstallPreview.LongDescription=Detailed Description
-software.common.InstallPreview.TopMessage=Clicking the [Install] button will begin the execution of the steps listed below.  Review each step carefully before proceeding with the update installation.<br/><ul><li>Prior to installing this update, if you have applied any one-off fixes to this instance, please check the update description to see that they are included in the fixes that make up this update. If they are not included then this update may overwrite the one-off fix and leave your instance in an unstable state.</li><li>When updating a JBoss instance that shares a common server configuration, follow the instructions documented in the wiki\: <a href\="http://www.rhq-project.org/display/JOPR2/Demos#Demos-ContentSubsystem" target\="_new">Installing a Patch</a>. Please contact support for more information.</li></ul>
+software.common.InstallPreview.TopMessage=Clicking the [Install] button will begin the execution of the steps listed below.  Review each step carefully before proceeding with the update installation.<br/><ul><li>Prior to installing this update, if you have applied any one-off fixes to this instance, please check the update description to see that they are included in the fixes that make up this update. If they are not included then this update may overwrite the one-off fix and leave your instance in an unstable state.</li><li>When updating a JBoss instance that shares a common server configuration, follow the instructions documented in the wiki\: <a href\="https://docs.jboss.org/author/display/RHQ/Demos#Demos-ContentSubsystem" target\="_new">Installing a Patch</a>. Please contact support for more information.</li></ul>
 software.common.InstallPreview.NotAllowedToInstall=This user doesn't have the appropriate rights to install an update. Only users that can control a resource may install an update.
 
 software.common.ManualUninstall.TableTitle=Manual Update Uninstallation
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/common/menu/menu.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/common/menu/menu.xhtml
index c855e67..010d29d 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/common/menu/menu.xhtml
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/common/menu/menu.xhtml
@@ -625,7 +625,7 @@ v        <rich:menuItem submitMode="none"
     </p>
 
     <p>
-        <a href="http://rhq-project.org/">
+        <a href="http://www.jboss.org/rhq">
             <h:graphicImage value="/images/logo_icon.png" style="vertical-align:middle" />
             RHQ Project
         </a>
diff --git a/modules/enterprise/server/container/src/main/downloadable-resources/connectors/README.txt b/modules/enterprise/server/container/src/main/downloadable-resources/connectors/README.txt
index e0e10d5..c1dc783 100644
--- a/modules/enterprise/server/container/src/main/downloadable-resources/connectors/README.txt
+++ b/modules/enterprise/server/container/src/main/downloadable-resources/connectors/README.txt
@@ -18,5 +18,5 @@ required for earlier versions of Tomcat, since they already include that jar.
 For details on how to deploy the filter to various versions of JBoss AS and
 Tomcat, see:
 
-http://rhq-project.org/display/JOPR2/Managed+Product+Configuration
+https://docs.jboss.org/author/display/RHQ/Managed+Product+Configuration
 
diff --git a/modules/enterprise/server/container/src/main/resources/etc/RHQ-mib.txt b/modules/enterprise/server/container/src/main/resources/etc/RHQ-mib.txt
index 20bb110..ced6071 100644
--- a/modules/enterprise/server/container/src/main/resources/etc/RHQ-mib.txt
+++ b/modules/enterprise/server/container/src/main/resources/etc/RHQ-mib.txt
@@ -13,12 +13,12 @@ IMPORTS
 rhqMIB MODULE-IDENTITY
     LAST-UPDATED    "201112200000Z"
     ORGANIZATION    "RHQ-Project"
-    CONTACT-INFO    "http://www.rhq-project.org/"
+    CONTACT-INFO    "http://www.jboss.org/rhq"
     DESCRIPTION
         "The MIB module for RHQ alerts.
 
         This file is part of the RHQ management platform
-        Copyright (C) 2005-2011 Red Hat, Inc.
+        Copyright (C) 2005-2012 Red Hat, Inc.
         All rights reserved.
     "
 
diff --git a/modules/enterprise/server/plugins/validate-all-serverplugins/pom.xml b/modules/enterprise/server/plugins/validate-all-serverplugins/pom.xml
index 4d68e6e..1f996f5 100644
--- a/modules/enterprise/server/plugins/validate-all-serverplugins/pom.xml
+++ b/modules/enterprise/server/plugins/validate-all-serverplugins/pom.xml
@@ -30,7 +30,7 @@
                            <classpath>
                               <pathelement path="${test.classpath}" />
                               
-                              <!-- See also: http://rhq-project.org/display/RHQ/Design-Server+Side+Plugins#Design-ServerSidePlugins-xmlschemas -->
+                              <!-- See also: https://docs.jboss.org/author/display/RHQ/Design-Server+Side+Plugins#Design-ServerSidePlugins-xmlschemas -->
                               
                               <pathelement location="../disk/target/rhq-serverplugin-disk-${project.version}.jar" />
                               <pathelement location="../jboss-software/target/rhq-serverplugin-jboss-software-${project.version}.jar" />
diff --git a/modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/ServerPluginDescriptorUtil.java b/modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/ServerPluginDescriptorUtil.java
index 1e3bae0..3f36ee8 100644
--- a/modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/ServerPluginDescriptorUtil.java
+++ b/modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/ServerPluginDescriptorUtil.java
@@ -73,7 +73,7 @@ public abstract class ServerPluginDescriptorUtil {
     static {
         // maps all xsd files to their generated package names for all known server plugin types;
         // if a new plugin type is ever added, you must ensure you add the new plugin type's xsd/package here
-        // See also: http://rhq-project.org/display/RHQ/Design-Server+Side+Plugins#Design-ServerSidePlugins-xmlschemas
+        // See also: https://docs.jboss.org/author/display/RHQ/Design-Server+Side+Plugins#Design-ServerSidePlugins-xmlschemas
         PLUGIN_SCHEMA_PACKAGES = new HashMap<String, String>();
         PLUGIN_SCHEMA_PACKAGES.put(XmlSchemas.XSD_SERVERPLUGIN, XmlSchemas.PKG_SERVERPLUGIN);
         PLUGIN_SCHEMA_PACKAGES.put(XmlSchemas.XSD_SERVERPLUGIN_GENERIC, XmlSchemas.PKG_SERVERPLUGIN_GENERIC);
diff --git a/modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/XmlSchemas.java b/modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/XmlSchemas.java
index ce46022..9141ae8 100644
--- a/modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/XmlSchemas.java
+++ b/modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/XmlSchemas.java
@@ -28,7 +28,7 @@ import org.rhq.core.clientapi.descriptor.DescriptorPackages;
  * Defines constants related to the server-side XML Schemas, including their JAXB generated package names
  * and their .xsd files, as found in the server's classpath.
  * 
- * See also: http://rhq-project.org/display/RHQ/Design-Server+Side+Plugins#Design-ServerSidePlugins-xmlschemas
+ * See also: https://docs.jboss.org/author/display/RHQ/Design-Server+Side+Plugins#Design-ServerSidePlugins-xmlschemas
  *
  * @author John Mazzitelli
  */
diff --git a/pom.xml b/pom.xml
index b023384..4799e55 100644
--- a/pom.xml
+++ b/pom.xml
@@ -11,7 +11,7 @@
 
   <name>RHQ</name>
   <description>RHQ is a server management and monitoring suite primarily targeted at JBoss software.</description>
-  <url>http://rhq-project.org/</url>
+  <url>http://www.jboss.org/rhq/</url>
   <inceptionYear>2008</inceptionYear>
 
   <organization>
@@ -47,12 +47,12 @@
     <product.shortName>RHQ</product.shortName>
     <product.name>RHQ</product.name>
     <product.fullName>RHQ</product.fullName>
-    <product.url>http://www.rhq-project.org/</product.url>
-    <product.urlDomain>rhq-project.org</product.urlDomain>
+    <product.url>http://www.jboss.org/rhq</product.url>
+    <product.urlDomain>jboss.org</product.urlDomain>
     <product.salesEmail>rhq-users at lists.fedorahosted.org</product.salesEmail>
     <product.supportEmail>rhq-users at lists.fedorahosted.org</product.supportEmail>
     <product.version>${project.version}</product.version>
-    <product.helpDocRoot>http://www.rhq-project.org/display/JOPR2/</product.helpDocRoot>
+    <product.helpDocRoot>https://docs.jboss.org/author/display/RHQ/User+Documentation</product.helpDocRoot>
     <product.buildPropertiesFile>target/build.properties</product.buildPropertiesFile>
 
     <doUpdate>false</doUpdate>


commit e6b9967525abb459a5f365528813ca17f37e9133
Author: Heiko W. Rupp <hwr at redhat.com>
Date:   Thu Jun 14 17:27:05 2012 +0200

    Don't require a special jsonp media type as jQuery seems to have issues. Rename parameter name to that clashes are less likely.

diff --git a/modules/enterprise/gui/rest-war/src/main/java/org/rhq/enterprise/rest/JsonPFilter.java b/modules/enterprise/gui/rest-war/src/main/java/org/rhq/enterprise/rest/JsonPFilter.java
index 5d812dc..3a785fd 100644
--- a/modules/enterprise/gui/rest-war/src/main/java/org/rhq/enterprise/rest/JsonPFilter.java
+++ b/modules/enterprise/gui/rest-war/src/main/java/org/rhq/enterprise/rest/JsonPFilter.java
@@ -63,8 +63,7 @@ public class JsonPFilter implements Filter {
         HttpServletRequest httpRequest = (HttpServletRequest) request;
         HttpServletResponse httpResponse = (HttpServletResponse) response;
 
-        String requestedType = httpRequest.getHeader("accept");
-        if ("application/jsonp".equals(requestedType) && hasCallback(httpRequest)) {
+        if (hasCallback(httpRequest)) {
 
             String callback = getCallback(httpRequest);
 
diff --git a/modules/enterprise/gui/rest-war/src/main/webapp/WEB-INF/web.xml b/modules/enterprise/gui/rest-war/src/main/webapp/WEB-INF/web.xml
index 7e5d52e..11597bb 100644
--- a/modules/enterprise/gui/rest-war/src/main/webapp/WEB-INF/web.xml
+++ b/modules/enterprise/gui/rest-war/src/main/webapp/WEB-INF/web.xml
@@ -29,8 +29,8 @@
       <filter-class>org.rhq.enterprise.rest.JsonPFilter</filter-class>
       <init-param>
         <param-name>filter.jsonp.callback</param-name>
-        <param-value>callback</param-value>
-        <description>Name of the callback to use for JsonP (?callback=...)</description>
+        <param-value>jsonp</param-value>
+        <description>Name of the callback to use for JsonP (?jsonp=...)</description>
       </init-param>
     </filter>
 


commit 662d3ef2ad7ac1b49257565b08c7c7f61187d3a2
Author: Lukas Krejci <lkrejci at redhat.com>
Date:   Thu Jun 14 15:40:49 2012 +0200

    [BZ 832090] - Make sure to activate the resource only after it has been
    synced with the server during manual add so that the subsystems dependent
    on the resource id get the correct one.

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 30680d5..8cd3859 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
@@ -694,7 +694,6 @@ public class InventoryManager extends AgentService implements ContainerService,
         MergeResourceResponse mergeResourceResponse;
         Resource resource = null;
         boolean resourceAlreadyExisted = false;
-        Throwable startError = null;
 
         try {
             ResourceContainer parentResourceContainer = getResourceContainer(parentResourceId);
@@ -805,14 +804,6 @@ public class InventoryManager extends AgentService implements ContainerService,
             if (log.isDebugEnabled()) {
                 log.debug("Activating resource [" + resource + "]...");
             }
-            // if it fails to start keep going, we already have the resource in inventory and
-            // need to coordinate with the server. The new resource will be unavailable but at least
-            // it will be accessible and editable by the user. Report the start exception at the end.
-            try {
-                activateResource(resource, resourceContainer, newPluginConfig);
-            } catch (Throwable t) {
-                startError = t;
-            }
 
             // NOTE: We don't mess with inventory status - that's the server's responsibility.
 
@@ -829,11 +820,19 @@ public class InventoryManager extends AgentService implements ContainerService,
             postProcessNewlyCommittedResources(newResources);
             performServiceScan(resource.getId());
 
-            if (null != startError) {
-                handleInvalidPluginConfigurationResourceError(resource, startError);
+            // Note that it is important to activate the resource *AFTER* it has been synced with the
+            // server so that the resource has a valid id (which is needed by at least the content
+            // subsystem).
+            try {
+                activateResource(resource, resourceContainer, newPluginConfig);
+            } catch (Throwable t) {
+                // if it fails to start keep going, we already have the resource in inventory and
+                // we are in sync with the server. The new resource will be unavailable but at least
+                // it will be accessible and editable by the user. Report the start exception at the end.
+                handleInvalidPluginConfigurationResourceError(resource, t);
                 throw new PluginContainerException("The resource [" + resource
                     + "] has been added but could not be started. Verify the supplied configuration values: ",
-                    startError);
+                    t);
             }
         }
 


commit b8a19a54ca7e0ca3aa44082cb48004c1fbc3ed56
Author: John Sanda <jsanda at redhat.com>
Date:   Thu Jun 14 07:12:22 2012 -0400

    [BZ 831603] Do not allow plugin defined templates to be deleted
    
    DriftTemplateManagerBean now throws an IllegalArgumentException if you
    try to delete a plugin defined template. The delete action in the
    templates ui is now disabled for plugin defined templates.

diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/DriftDefinitionTemplatesView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/DriftDefinitionTemplatesView.java
index a3ffed1..ab60c35 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/DriftDefinitionTemplatesView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/DriftDefinitionTemplatesView.java
@@ -167,7 +167,7 @@ public class DriftDefinitionTemplatesView extends TableSection<DriftDefinitionTe
                         for (ListGridRecord record : selection) {
                             if (!record.getAttributeAsBoolean(DriftDefinitionTemplateDataSource.ATTR_IS_USER_DEFINED)
                                 .booleanValue()) {
-                                break;
+                                return false;
                             }
                         }
                         result = true;
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/drift/DriftTemplateManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/drift/DriftTemplateManagerBean.java
index 9a1c980..528fd7a 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/drift/DriftTemplateManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/drift/DriftTemplateManagerBean.java
@@ -19,11 +19,26 @@
 
 package org.rhq.enterprise.server.drift;
 
+import static javax.ejb.TransactionAttributeType.NEVER;
+import static org.rhq.core.domain.common.EntityContext.forResource;
+import static org.rhq.core.domain.drift.DriftChangeSetCategory.COVERAGE;
+import static org.rhq.core.domain.drift.DriftConfigurationDefinition.DriftHandlingMode.normal;
+
+import javax.ejb.EJB;
+import javax.ejb.Stateless;
+import javax.ejb.TransactionAttribute;
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+
 import org.rhq.core.domain.auth.Subject;
 import org.rhq.core.domain.authz.Permission;
 import org.rhq.core.domain.criteria.DriftDefinitionCriteria;
 import org.rhq.core.domain.criteria.DriftDefinitionTemplateCriteria;
-import org.rhq.core.domain.drift.*;
+import org.rhq.core.domain.drift.DriftDefinition;
+import org.rhq.core.domain.drift.DriftDefinitionComparator;
+import org.rhq.core.domain.drift.DriftDefinitionTemplate;
+import org.rhq.core.domain.drift.DriftSnapshot;
+import org.rhq.core.domain.drift.DriftSnapshotRequest;
 import org.rhq.core.domain.drift.dto.DriftChangeSetDTO;
 import org.rhq.core.domain.resource.ResourceType;
 import org.rhq.core.domain.util.PageList;
@@ -34,17 +49,6 @@ import org.rhq.enterprise.server.resource.ResourceTypeNotFoundException;
 import org.rhq.enterprise.server.util.CriteriaQueryGenerator;
 import org.rhq.enterprise.server.util.CriteriaQueryRunner;
 
-import javax.ejb.EJB;
-import javax.ejb.Stateless;
-import javax.ejb.TransactionAttribute;
-import javax.persistence.EntityManager;
-import javax.persistence.PersistenceContext;
-
-import static javax.ejb.TransactionAttributeType.NEVER;
-import static org.rhq.core.domain.common.EntityContext.forResource;
-import static org.rhq.core.domain.drift.DriftChangeSetCategory.COVERAGE;
-import static org.rhq.core.domain.drift.DriftConfigurationDefinition.DriftHandlingMode.normal;
-
 @Stateless
 public class DriftTemplateManagerBean implements DriftTemplateManagerLocal, DriftTemplateManagerRemote {
 
@@ -164,6 +168,10 @@ public class DriftTemplateManagerBean implements DriftTemplateManagerLocal, Drif
     @Override
     public void deleteTemplate(Subject subject, int templateId) {
         DriftDefinitionTemplate template = entityMgr.find(DriftDefinitionTemplate.class, templateId);
+        if (!template.isUserDefined()) {
+            throw new IllegalArgumentException(template.getName() + " is a plugin defined template. Plugin defined " +
+                "templates cannot be deleted.");
+        }
         for (DriftDefinition defintion : template.getDriftDefinitions()) {
             if (defintion.isAttached()) {
                 driftMgr.deleteDriftDefinition(subject, forResource(defintion.getResource().getId()), defintion


commit 5e503eee3759b30bc4209c9695a9a9ab68cf2b31
Author: Heiko W. Rupp <hwr at redhat.com>
Date:   Thu Jun 14 11:44:37 2012 +0200

    More improvements especially in the area of linking between resources.

diff --git a/modules/enterprise/gui/rest-war/src/main/webapp/index.html b/modules/enterprise/gui/rest-war/src/main/webapp/index.html
index 0ab715a..00d615f 100644
--- a/modules/enterprise/gui/rest-war/src/main/webapp/index.html
+++ b/modules/enterprise/gui/rest-war/src/main/webapp/index.html
@@ -16,6 +16,7 @@ mobile client (Android) of the API.
     <li><a href="1/group/definitions">Group Definitions</a></li>
     <li><a href="1/alert/">Alerts</a></li>
     <li><a href="1/status.html">System status</a> </li>
+    <li><a href="1/user/favorites/resource">Favorite resources</a></li>
 </ul>
 <hr/>
 <h2>Misc examples (using <a href="https://github.com/mbostock/d3">D3.js</a>)</h2>
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerBean.java
index 024b084..a9bcc4e 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerBean.java
@@ -18,18 +18,29 @@
  */
 package org.rhq.enterprise.server.rest;
 
+import java.net.URI;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Set;
 
 import javax.ejb.EJB;
 import javax.ejb.Stateless;
 import javax.interceptor.Interceptors;
+import javax.ws.rs.core.EntityTag;
+import javax.ws.rs.core.GenericEntity;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Request;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
 import javax.ws.rs.core.UriInfo;
 
 import org.rhq.core.domain.alert.Alert;
+import org.rhq.core.domain.alert.AlertCondition;
+import org.rhq.core.domain.alert.AlertConditionLog;
 import org.rhq.core.domain.alert.AlertDefinition;
 import org.rhq.core.domain.alert.AlertPriority;
+import org.rhq.core.domain.alert.notification.AlertNotificationLog;
 import org.rhq.core.domain.criteria.AlertCriteria;
 import org.rhq.core.domain.criteria.AlertDefinitionCriteria;
 import org.rhq.core.domain.criteria.Criteria;
@@ -38,9 +49,7 @@ import org.rhq.core.domain.util.PageControl;
 import org.rhq.core.domain.util.PageList;
 import org.rhq.enterprise.server.alert.AlertDefinitionManagerLocal;
 import org.rhq.enterprise.server.alert.AlertManagerLocal;
-import org.rhq.enterprise.server.rest.domain.AlertRest;
-import org.rhq.enterprise.server.rest.domain.AlertDefinitionRest;
-import org.rhq.enterprise.server.rest.domain.ResourceWithType;
+import org.rhq.enterprise.server.rest.domain.*;
 
 /**
  * Deal with alert related stuff
@@ -60,22 +69,36 @@ public class AlertHandlerBean extends AbstractRestBean implements AlertHandlerLo
 
 
     @Override
-    public List<AlertRest> listAlerts(int page, String status, Request request, UriInfo uriInfo) {
+    public Response listAlerts(int page, String status, boolean slim, Long since, Request request, UriInfo uriInfo, HttpHeaders headers) {
 
 
         AlertCriteria criteria = new AlertCriteria();
         criteria.setPaging(page,20); // TODO implement linking to next page
+        if (since!=null) {
+            criteria.addFilterStartTime(since);
+        }
         PageList<Alert> alerts = alertManager.findAlertsByCriteria(caller,criteria);
         List<AlertRest> ret = new ArrayList<AlertRest>(alerts.size());
         for (Alert al : alerts) {
-            AlertRest ar = alertToDomain(al, uriInfo);
+            AlertRest ar = alertToDomain(al, uriInfo, slim);
             ret.add(ar);
         }
-        return ret;
+
+        MediaType type = headers.getAcceptableMediaTypes().get(0);
+        Response.ResponseBuilder builder;
+
+        if (type.equals(MediaType.TEXT_HTML_TYPE)) {
+            builder = Response.ok(renderTemplate("listAlerts.ftl",ret),type);
+        } else {
+            GenericEntity<List<AlertRest>> entity = new GenericEntity<List<AlertRest>>(ret) {};
+            builder = Response.ok(entity);
+        }
+
+        return builder.build();
     }
 
     @Override
-    public int countAlerts() {
+    public int countAlerts(Long since) {
         AlertCriteria criteria = new AlertCriteria();
         criteria.setPageControl(PageControl.getUnlimitedInstance());
         criteria.fetchAlertDefinition(false);
@@ -83,6 +106,9 @@ public class AlertHandlerBean extends AbstractRestBean implements AlertHandlerLo
         criteria.fetchRecoveryAlertDefinition(false);
         criteria.fetchNotificationLogs(false);
         criteria.setRestriction(Criteria.Restriction.COUNT_ONLY);
+        if (since!=null) {
+            criteria.addFilterStartTime(since);
+        }
         PageList<Alert> alerts = alertManager.findAlertsByCriteria(caller,criteria);
         int count = alerts.getTotalSize();
 
@@ -90,27 +116,114 @@ public class AlertHandlerBean extends AbstractRestBean implements AlertHandlerLo
     }
 
     @Override
-    public AlertRest getAlert(int id, UriInfo uriInfo) {
+    public Response getAlert(int id, boolean slim, UriInfo uriInfo, Request request, HttpHeaders headers) {
 
         Alert al = findAlertWithId(id);
-        AlertRest ar = alertToDomain(al, uriInfo);
-        return ar;
+        MediaType type = headers.getAcceptableMediaTypes().get(0);
+
+        EntityTag eTag = new EntityTag(Integer.toHexString(al.hashCode()));
+        Response.ResponseBuilder builder = request.evaluatePreconditions(eTag);
+        if (builder==null) {
+            AlertRest ar = alertToDomain(al, uriInfo, slim);
+            if (type.equals(MediaType.TEXT_HTML_TYPE)) {
+                builder = Response.ok(renderTemplate("alert.ftl",ar),type);
+            } else {
+                builder = Response.ok(ar);
+            }
+        }
+        builder.tag(eTag);
+
+        return builder.build();
     }
 
+    @Override
+    public Response getConditionLogs(int id, Request request, UriInfo uriInfo, HttpHeaders headers) {
+
+        Alert al = findAlertWithId(id);
+        Set<AlertConditionLog> conditions =  al.getConditionLogs();
+        MediaType type = headers.getAcceptableMediaTypes().get(0);
+        Response.ResponseBuilder builder;
+
+        if (type.equals(MediaType.APPLICATION_XML_TYPE)) {
+            List<StringValue> result = new ArrayList<StringValue>(conditions.size());
+            for (AlertConditionLog log : conditions) {
+                AlertCondition condition = log.getCondition();
+                String entry = String.format("category='%s', name='%s', comparator='%s', threshold='%s', option='%s' : %s",
+                        condition.getCategory(), condition.getName(), condition.getComparator(), condition.getThreshold(), condition.getOption(), log.getValue() );
+                StringValue sv = new StringValue(entry);
+                result.add(sv);
+            }
+            GenericEntity<List<StringValue>> entity = new GenericEntity<List<StringValue>>(result){};
+            builder = Response.ok(entity);
+        }
+        else {
+            List<String> result = new ArrayList<String>(conditions.size());
+
+            for (AlertConditionLog log : conditions) {
+                AlertCondition condition = log.getCondition();
+                String entry = String.format("category='%s', name='%s', comparator='%s', threshold='%s', option='%s' : %s",
+                        condition.getCategory(), condition.getName(), condition.getComparator(), condition.getThreshold(), condition.getOption(), log.getValue() );
+                result.add(entry);
+            }
+            if (type.equals(MediaType.TEXT_HTML_TYPE)) {
+                builder = Response.ok(renderTemplate("genericStringList.ftl",result),type);
+            } else {
+                builder = Response.ok(result);
+            }
+        }
+
+        return builder.build();
+
+    }
+
+    @Override
+    public Response getNotificationLogs(int id, Request request, UriInfo uriInfo, HttpHeaders headers) {
+        Alert al = findAlertWithId(id);
+        MediaType type = headers.getAcceptableMediaTypes().get(0);
+        Response.ResponseBuilder builder;
+
+        List<AlertNotificationLog> notifications =  al.getAlertNotificationLogs();
+        if (type.equals(MediaType.APPLICATION_XML_TYPE)) {
+            List<StringValue> result = new ArrayList<StringValue>(notifications.size());
+            for (AlertNotificationLog log : notifications) {
+                String entry = log.getSender() + ": " + log.getResultState() + ": " + log.getMessage();
+                StringValue sv = new StringValue(entry);
+                result.add(sv);
+            }
+
+            GenericEntity<List<StringValue>> entity = new GenericEntity<List<StringValue>>(result){};
+            builder = Response.ok(entity);
+        } else {
+            List<String> result = new ArrayList<String>(notifications.size());
+            for (AlertNotificationLog log : notifications) {
+                String entry = log.getSender() + ": " + log.getResultState() + ": " + log.getMessage();
+                result.add(entry);
+            }
+            if (type.equals(MediaType.TEXT_HTML_TYPE)) {
+                builder = Response.ok(renderTemplate("genericStringList.ftl",result),type);
+            } else {
+                builder = Response.ok(result);
+            }
+        }
 
+        return builder.build();
+    }
 
     @Override
     public AlertRest ackAlert(int id, UriInfo uriInfo) {
         findAlertWithId(id); // Ensure the alert exists
-        alertManager.acknowledgeAlerts(caller,new int[]{id});
+        int count = alertManager.acknowledgeAlerts(caller,new int[]{id});
+
+        // TODO this is not reliable due to Tx constraints ( the above may only run after this ackAlert() method has finished )
+
         Alert al = findAlertWithId(id);
-        AlertRest ar = alertToDomain(al, uriInfo);
+        AlertRest ar = alertToDomain(al, uriInfo, true);
         return ar;
     }
 
     @Override
     public void purgeAlert(int id) {
-        alertManager.deleteAlerts(caller,new int[]{id});
+        alertManager.deleteAlerts(caller, new int[]{id});
 
     }
 
@@ -127,7 +240,7 @@ public class AlertHandlerBean extends AbstractRestBean implements AlertHandlerLo
 
         AlertDefinitionCriteria criteria = new AlertDefinitionCriteria();
         criteria.setPaging(page,20); // TODO add link to next page
-        List<AlertDefinition> defs = alertDefinitionManager.findAlertDefinitionsByCriteria(caller,criteria);
+        List<AlertDefinition> defs = alertDefinitionManager.findAlertDefinitionsByCriteria(caller, criteria);
         List<AlertDefinitionRest> ret = new ArrayList<AlertDefinitionRest>(defs.size());
         for (AlertDefinition def : defs) {
             AlertDefinitionRest adr = definitionToDomain(def);
@@ -137,17 +250,25 @@ public class AlertHandlerBean extends AbstractRestBean implements AlertHandlerLo
     }
 
     @Override
-    public AlertDefinitionRest getAlertDefinition(int definitionId) {
+    public Response getAlertDefinition(int definitionId, Request request) {
 
         AlertDefinition def = alertDefinitionManager.getAlertDefinition(caller,definitionId);
         if (def==null)
             throw new StuffNotFoundException("AlertDefinition with id " + definitionId );
-        AlertDefinitionRest adr = definitionToDomain(def);
-        return adr;
+
+        EntityTag eTag = new EntityTag(Integer.toHexString(def.hashCode()));
+        Response.ResponseBuilder builder = request.evaluatePreconditions(eTag);
+        if (builder==null) {
+            AlertDefinitionRest adr = definitionToDomain(def);
+            builder = Response.ok(adr);
+        }
+        builder.tag(eTag);
+
+        return builder.build();
     }
 
     @Override
-    public AlertDefinitionRest updateDefinition(int definitionId, AlertDefinitionRest definitionRest, Request request) {
+    public Response updateDefinition(int definitionId, AlertDefinitionRest definitionRest, Request request) {
         AlertDefinition def = alertDefinitionManager.getAlertDefinition(caller,definitionId);
         if (def==null)
             throw new StuffNotFoundException("AlertDefinition with id " + definitionId);
@@ -157,9 +278,14 @@ public class AlertHandlerBean extends AbstractRestBean implements AlertHandlerLo
 
         def = alertDefinitionManager.updateAlertDefinition(caller,def.getId(),def,false);
 
-        definitionRest = definitionToDomain(def);
+        EntityTag eTag = new EntityTag(Integer.toHexString(def.hashCode()));
+        AlertDefinitionRest adr = definitionToDomain(def);
+
+        Response.ResponseBuilder builder = Response.ok(adr);
+        builder.tag(eTag);
+
+        return builder.build();
 
-        return definitionRest;
     }
 
     private AlertDefinitionRest definitionToDomain(AlertDefinition def) {
@@ -187,26 +313,53 @@ public class AlertHandlerBean extends AbstractRestBean implements AlertHandlerLo
         return alerts.get(0);
     }
 
-    public AlertRest alertToDomain(Alert al, UriInfo uriInfo) {
+    public AlertRest alertToDomain(Alert al, UriInfo uriInfo, boolean slim) {
         AlertRest ret = new AlertRest();
         ret.setId(al.getId());
         AlertDefinition alertDefinition = al.getAlertDefinition();
         ret.setName(alertDefinition.getName());
-        ret.setAlertDefinition(definitionToDomain(alertDefinition));
+        AlertDefinitionRest alertDefinitionRest;
+        if (slim) {
+            alertDefinitionRest = new AlertDefinitionRest(alertDefinition.getId());
+        } else {
+            alertDefinitionRest = definitionToDomain(alertDefinition);
+        }
+        ret.setAlertDefinition(alertDefinitionRest);
         ret.setDefinitionEnabled(alertDefinition.getEnabled());
         if (al.getAcknowledgingSubject()!=null) {
             ret.setAckBy(al.getAcknowledgingSubject());
             ret.setAckTime(al.getAcknowledgeTime());
         }
         ret.setAlertTime(al.getCtime());
-
         ret.setDescription(alertManager.prettyPrintAlertConditions(al,false));
 
         Resource r = fetchResource(alertDefinition.getResource().getId());
-        ResourceWithType rwt = fillRWT(r,uriInfo);
-
+        ResourceWithType rwt;
+        if (slim) {
+            rwt = new ResourceWithType(r.getName(),r.getId());
+        } else {
+            rwt = fillRWT(r,uriInfo);
+        }
         ret.setResource(rwt);
 
+        // add some links
+        UriBuilder builder = uriInfo.getBaseUriBuilder();
+        builder.path("/alert/{id}/conditions");
+        URI uri = builder.build(al.getId());
+        Link link = new Link("conditions",uri.toString());
+        ret.addLink(link);
+        builder = uriInfo.getBaseUriBuilder();
+        builder.path("/alert/{id}/notifications");
+        uri = builder.build(al.getId());
+        link = new Link("notification",uri.toString());
+        ret.addLink(link);
+        builder = uriInfo.getBaseUriBuilder();
+        builder.path("/alert/{id}/definition");
+        uri = builder.build(al.getId());
+        link = new Link("definition",uri.toString());
+        ret.addLink(link);
+
+
         return ret;
     }
 }
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerLocal.java
index b255db3..5fd7506 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerLocal.java
@@ -22,6 +22,7 @@ import java.util.List;
 
 import javax.ejb.Local;
 import javax.ws.rs.DELETE;
+import javax.ws.rs.DefaultValue;
 import javax.ws.rs.GET;
 import javax.ws.rs.PUT;
 import javax.ws.rs.Path;
@@ -29,15 +30,16 @@ import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
 import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.Request;
+import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriInfo;
 
 import com.wordnik.swagger.annotations.Api;
 import com.wordnik.swagger.annotations.ApiOperation;
 import com.wordnik.swagger.annotations.ApiParam;
 
-import org.jboss.resteasy.links.AddLinks;
-import org.jboss.resteasy.links.LinkResource;
+import org.jboss.resteasy.annotations.cache.Cache;
 
 import org.rhq.enterprise.server.rest.domain.AlertRest;
 import org.rhq.enterprise.server.rest.domain.AlertDefinitionRest;
@@ -54,28 +56,48 @@ public interface AlertHandlerLocal {
 
     @GET
     @Path("/")
-    @AddLinks
-    @LinkResource(value = AlertRest.class)
-    @ApiOperation("List all alerts")
-    List<AlertRest> listAlerts(
+    @ApiOperation(value = "List all alerts", multiValueResponse = true, responseClass = "List<AlertRest")
+    Response listAlerts(
             @ApiParam(value = "Page number", defaultValue = "0") @QueryParam("page") int page,
             @ApiParam(value = "Limit to status, UNUSED AT THE MOMENT ") @QueryParam("status") String status,
-            @Context Request request, @Context UriInfo uriInfo);
+            @ApiParam(value = "Should full resources and definitions be sent") @QueryParam("slim") @DefaultValue(
+                    "false") boolean slim,
+            @ApiParam(value = "If non-null only send alerts that have fired after this time, time is millisecond since epoch")
+                @QueryParam("since") Long since,
+            @Context Request request, @Context UriInfo uriInfo, @Context HttpHeaders headers);
 
     @GET
     @Path("count")
     @ApiOperation("Return a count of alerts in the system depending on criteria")
-    int countAlerts(); // TODO add some limiting to new  / old / ....
+    int countAlerts(@ApiParam(value = "If non-null only send alerts that have fired after this time, time is millisecond since epoch")
+                    @QueryParam("since") Long since);
 
     @GET
+    @Cache(maxAge = 60)
     @Path("/{id}")
-    @AddLinks
-    @ApiOperation("Get one alert with the passed id")
-    AlertRest getAlert(@ApiParam("Id of the alert to retrieve") @PathParam("id") int id, @Context UriInfo uriInfo);
+    @ApiOperation(value = "Get one alert with the passed id", responseClass = "AlertRest")
+    Response getAlert(
+        @ApiParam("Id of the alert to retrieve") @PathParam("id") int id,
+        @ApiParam(value = "Should full resources and definitions be sent") @QueryParam("slim") @DefaultValue("false") boolean slim,
+        @Context UriInfo uriInfo, @Context Request request, @Context HttpHeaders headers);
+
+    @GET
+    @Path("/{id}/conditions")
+    @Cache(maxAge = 300)
+    @ApiOperation(value = "Return the notification logs for the given alert")
+    Response getConditionLogs(@ApiParam("Id of the alert to retrieve") @PathParam("id") int id,
+                              @Context Request request, @Context UriInfo uriInfo, @Context HttpHeaders headers);
+
+    @GET
+    @Path("/{id}/notifications")
+    @Cache(maxAge = 60)
+    @ApiOperation(value = "Return the notification logs for the given alert")
+    Response getNotificationLogs(@ApiParam("Id of the alert to retrieve") @PathParam("id") int id,
+                                 @Context Request request, @Context UriInfo uriInfo, @Context HttpHeaders headers);
 
     @PUT
     @Path("/{id}")
-    @ApiOperation(value = "Mark the alert as acknowledged (by the caller)")
+    @ApiOperation(value = "Mark the alert as acknowledged (by the caller)", notes = "Returns a slim version of the alert")
     AlertRest ackAlert(
             @ApiParam(value = "Id of the alert to acknowledge") @PathParam("id") int id, @Context UriInfo uriInfo);
 
@@ -86,6 +108,7 @@ public interface AlertHandlerLocal {
             @ApiParam(value = "Id of the alert to remove") @PathParam("id") int id);
 
     @GET
+    @Cache(maxAge = 300)
     @Path("/{id}/definition")
     @ApiOperation("Get the alert definition (basics) for the alert")
     AlertDefinitionRest getDefinitionForAlert(@ApiParam("Id of the alert to show the definition") @PathParam("id") int alertId);
@@ -100,12 +123,13 @@ public interface AlertHandlerLocal {
 
     @GET
     @Path("/definition/{id}")
-    @ApiOperation("Get one AlertDefinition by id")
-    AlertDefinitionRest getAlertDefinition(@ApiParam("Id of the alert definition to retrieve") @PathParam("id") int definitionId);
+    @ApiOperation(value = "Get one AlertDefinition by id", responseClass = "AlertDefinitionRest")
+    Response getAlertDefinition(@ApiParam("Id of the alert definition to retrieve") @PathParam("id") int definitionId,
+        @Context Request request);
 
     @PUT
     @Path("/definition/{id}")
     @ApiOperation(value = "Update the alert definition (priority, enablement)", notes = "Priority must be HIGH,LOW,MEDIUM")
-    AlertDefinitionRest updateDefinition(@ApiParam("Id of the alert definition to update") @PathParam("id") int definitionId,
+    Response updateDefinition(@ApiParam("Id of the alert definition to update") @PathParam("id") int definitionId,
                                          AlertDefinitionRest definition, @Context Request request);
 }
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
index 1f9594b..b76d7d1 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
@@ -255,6 +255,11 @@ public class ResourceHandlerBean extends AbstractRestBean implements ResourceHan
                             uri = uriBuilder.build(schedule.getId());
                             Link metricLink = new Link("metric", uri.toString());
                             ms.addLink(metricLink);
+                            uriBuilder = uriInfo.getBaseUriBuilder();
+                            uriBuilder.path("/metric/data/{id}/raw");
+                            uri = uriBuilder.build(schedule.getId());
+                            metricLink = new Link("metric-raw", uri.toString());
+                            ms.addLink(metricLink);
                         }
                         // create link to the resource
                         uriBuilder = uriInfo.getBaseUriBuilder();
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/UserHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/UserHandlerBean.java
index a980f17..c4bf673 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/UserHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/UserHandlerBean.java
@@ -1,6 +1,6 @@
 /*
  * RHQ Management Platform
- * Copyright (C) 2005-2011 Red Hat, Inc.
+ * Copyright (C) 2005-2012 Red Hat, Inc.
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
@@ -27,21 +27,14 @@ import java.util.TreeSet;
 import javax.ejb.EJB;
 import javax.ejb.Stateless;
 import javax.interceptor.Interceptors;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.GET;
-import javax.ws.rs.PUT;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.core.CacheControl;
 import javax.ws.rs.core.EntityTag;
+import javax.ws.rs.core.GenericEntity;
 import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Request;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriInfo;
 
-import com.wordnik.swagger.annotations.ApiParam;
-
 import org.rhq.core.domain.auth.Subject;
 import org.rhq.core.domain.configuration.Configuration;
 import org.rhq.core.domain.configuration.PropertySimple;
@@ -83,26 +76,34 @@ public class UserHandlerBean extends AbstractRestBean implements UserHandlerLoca
     ResourceManagerLocal resourceManager;
 
     @Override
-    @GET
-    @Path("favorites/r")
-    public List<ResourceWithType> getFavorites(UriInfo uriInfo) {
+    public Response getFavorites(UriInfo uriInfo, HttpHeaders httpHeaders) {
 
         Set<Integer> favIds = getResourceIdsForFavorites();
         List<ResourceWithType> ret = new ArrayList<ResourceWithType>();
+
+        MediaType mediaType = httpHeaders.getAcceptableMediaTypes().get(0);
         for (Integer id : favIds) {
             Resource res = resourceManager.getResource(caller,id);
 
             ResourceWithType rwt = fillRWT(res,uriInfo);
             ret.add(rwt);
         }
-        return ret;
+        Response.ResponseBuilder builder;
+        if (mediaType.equals(MediaType.TEXT_HTML_TYPE)) {
+            builder = Response.ok(renderTemplate("listResourceWithType", ret), mediaType);
+        } else {
+            GenericEntity<List<ResourceWithType>> list = new GenericEntity<List<ResourceWithType>>(ret) {
+            };
+            builder = Response.ok(list);
+        }
+
+        return builder.build();
+
     }
 
 
     @Override
-    @PUT
-    @Path("favorites/r/{id}")
-    public void addFavoriteResource(@PathParam("id") int id) {
+    public void addFavoriteResource(int id) {
         Set<Integer> favIds = getResourceIdsForFavorites();
         if (!favIds.contains(id)) {
             favIds.add(id);
@@ -111,9 +112,7 @@ public class UserHandlerBean extends AbstractRestBean implements UserHandlerLoca
     }
 
     @Override
-    @DELETE
-    @Path("favorites/r/{id}")
-    public void removeResourceFromFavorites(@PathParam("id") int id) {
+    public void removeResourceFromFavorites(int id) {
         Set<Integer> favIds = getResourceIdsForFavorites();
         if (favIds.contains(id)) {
             favIds.remove(id);
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/UserHandlerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/UserHandlerLocal.java
index 8c5abae..05ef280 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/UserHandlerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/UserHandlerLocal.java
@@ -18,8 +18,6 @@
  */
 package org.rhq.enterprise.server.rest;
 
-import java.util.List;
-
 import javax.ejb.Local;
 import javax.ws.rs.DELETE;
 import javax.ws.rs.GET;
@@ -40,14 +38,12 @@ import com.wordnik.swagger.annotations.ApiParam;
 
 import org.jboss.resteasy.annotations.cache.Cache;
 
-import org.rhq.enterprise.server.rest.domain.ResourceWithType;
-import org.rhq.enterprise.server.rest.domain.UserRest;
 
 /**
  * Bean that deals with user specific stuff
  * @author Heiko W. Rupp
  */
- at Produces({"application/json","application/xml","text/plain"})
+ at Produces({"application/json","application/xml","text/plain","text/html"})
 @Path("/user")
 @Local
 @Api(value="Api that deals with user related stuff")
@@ -55,12 +51,12 @@ public interface UserHandlerLocal {
 
     @GET
     @Path("favorites/resource")
-    @ApiOperation(value = "Return a list of favorite resources", multiValueResponse = true)
-    public List<ResourceWithType> getFavorites(@Context UriInfo uriInfo);
+    @ApiOperation(value = "Return a list of favorite resources of the caller", multiValueResponse = true)
+    Response getFavorites(@Context UriInfo uriInfo, at Context HttpHeaders headers);
 
     @PUT
     @Path("favorites/resource/{id}")
-    @ApiOperation(value = "Add a resource as favorite")
+    @ApiOperation(value = "Add a resource as favorite for the caller")
     public void addFavoriteResource(
             @ApiParam(name = "id", value = "Id of the resource")
             @PathParam("id") int id);
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/AlertRest.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/AlertRest.java
index 71687c0..d09f5b8 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/AlertRest.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/AlertRest.java
@@ -18,6 +18,9 @@
  */
 package org.rhq.enterprise.server.rest.domain;
 
+import java.util.ArrayList;
+import java.util.List;
+
 import javax.xml.bind.annotation.XmlElementRef;
 import javax.xml.bind.annotation.XmlRootElement;
 
@@ -39,6 +42,7 @@ public class AlertRest {
     long ackTime;
     long alertTime;
     String description;
+    List<Link> links = new ArrayList<Link>();
 
     public void setResource(ResourceWithType resource) {
         this.resource = resource;
@@ -69,7 +73,6 @@ public class AlertRest {
         return alertDefinition;
     }
 
-
     public boolean isDefinitionEnabled() {
         return definitionEnabled;
     }
@@ -113,4 +116,16 @@ public class AlertRest {
     public ResourceWithType getResource() {
         return resource;
     }
+
+    public List<Link> getLinks() {
+        return links;
+    }
+
+    public void setLinks(List<Link> links) {
+        this.links = links;
+    }
+
+    public void addLink(Link link) {
+        links.add(link);
+    }
 }
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/ResourceWithType.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/ResourceWithType.java
index a0c3527..10030a9 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/ResourceWithType.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/ResourceWithType.java
@@ -140,4 +140,17 @@ public class ResourceWithType {
     public String getAncestry() {
         return ancestry;
     }
+
+    @Override
+    public String toString() {
+        return "ResourceWithType{" +
+                "resourceName='" + resourceName + '\'' +
+                ", resourceId=" + resourceId +
+                ", typeName='" + typeName + '\'' +
+                ", typeId=" + typeId +
+                ", pluginName='" + pluginName + '\'' +
+                ", parentId=" + parentId +
+                ", ancestry='" + ancestry + '\'' +
+                '}';
+    }
 }
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/UserRest.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/UserRest.java
index cf5da69..4cf9f70 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/UserRest.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/UserRest.java
@@ -90,4 +90,16 @@ public class UserRest {
     public void setLastName(String lastName) {
         this.lastName = lastName;
     }
+
+    @Override
+    public String toString() {
+        return "UserRest{" +
+                "id=" + id +
+                ", login='" + login + '\'' +
+                ", firstName='" + firstName + '\'' +
+                ", lastName='" + lastName + '\'' +
+                ", tel='" + tel + '\'' +
+                ", email='" + email + '\'' +
+                '}';
+    }
 }
diff --git a/modules/enterprise/server/jar/src/main/resources/rest_templates/alert.ftl b/modules/enterprise/server/jar/src/main/resources/rest_templates/alert.ftl
new file mode 100644
index 0000000..60be9fc
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/resources/rest_templates/alert.ftl
@@ -0,0 +1,57 @@
+<#ftl >
+<#--
+/*
+ * 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 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.
+ */
+-->
+<#-- @ftlvariable name="var" type="org.rhq.enterprise.server.rest.domain.AlertRest" -->
+<table>
+    <tr>
+        <th>Name</th>
+        <th>Value</th>
+    </tr>
+    <tr>
+        <td>Name</td>
+        <td>${var.name}</td>
+    </tr>
+    <tr>
+        <td>Id</td>
+        <td>${var.id}</td>
+    </tr>
+    <tr>
+        <td>Description</td>
+        <td>${var.description}</td>
+    </tr>
+    <tr>
+        <td>Acknowledged</td>
+        <td>
+            <#if (var.ackTime &gt; 0)>
+                by ${var.ackBy} on ${var.ackTime?number_to_date}
+            <#else>
+                No
+            </#if>
+        </td>
+    </tr>
+    <tr>
+        <td>Definition enabled</td>
+        <td>${var.definitionEnabled?string("Yes","No")}</td>
+    </tr>
+</table>
+<a href="/rest/1/alert/${var.id?c}/definition.html">Alert Definition</a>
+<a href="/rest/1/alert/${var.id?c}/conditions.html">Condition Logs</a>
+<a href="/rest/1/alert/${var.id?c}/notifications.html">Notification Logs</a>
diff --git a/modules/enterprise/server/jar/src/main/resources/rest_templates/genericStringList.ftl b/modules/enterprise/server/jar/src/main/resources/rest_templates/genericStringList.ftl
new file mode 100644
index 0000000..d0ad8a2
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/resources/rest_templates/genericStringList.ftl
@@ -0,0 +1,31 @@
+<#ftl >
+<#--
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 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.
+ */
+-->
+<#-- @ftlvariable name="var" type="java.util.List<String>" -->
+<ul>
+    <#if var.isEmpty()>
+        <i>Nothing to display</i>
+    <#else>
+        <#list var as line>
+            <li>${line}</li>
+        </#list>
+    </#if>
+</ul>
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/main/resources/rest_templates/listAlerts.ftl b/modules/enterprise/server/jar/src/main/resources/rest_templates/listAlerts.ftl
new file mode 100644
index 0000000..c8f4be8
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/resources/rest_templates/listAlerts.ftl
@@ -0,0 +1,32 @@
+<#ftl >
+<#--
+/*
+ * 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 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.
+ */
+-->
+<#-- @ftlvariable name="var" type="java.util.List<org.rhq.enterprise.server.rest.domain.AlertRest>" -->
+<html>
+<ul>
+    <#-- the next looks odd, but the incoming var is a list -->
+    <#list var as var>
+    <li>
+        <#include "alert.ftl"/>
+    </li>
+    </#list>
+</ul>
+<html>
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/main/resources/rest_templates/metricSchedule.ftl b/modules/enterprise/server/jar/src/main/resources/rest_templates/metricSchedule.ftl
index e05012e..ae7b559 100644
--- a/modules/enterprise/server/jar/src/main/resources/rest_templates/metricSchedule.ftl
+++ b/modules/enterprise/server/jar/src/main/resources/rest_templates/metricSchedule.ftl
@@ -22,11 +22,9 @@
 <#-- @ftlvariable name="var" type="org.rhq.enterprise.server.rest.domain.MetricSchedule" -->
 <html>
     <table border=1>
-        <thead>
-            <tr>
-                <td>Name</td><td>Value</td>
-            </tr>
-        </thead>
+        <tr>
+            <th>Name</th><th>Value</th>
+        </tr>
         <tr>
             <td>Id</td><td>${var.scheduleId}</td>
         </tr>
@@ -45,11 +43,13 @@
         <tr>
             <td>Units</td><td>${var.unit}</td>
         </tr>
+        <tr>
+            <td>Links</td>
+            <td>
+                <#list var.links as link>
+                    <li><a href="${link.href}.html">${link.rel}</a> </li>
+                </#list>
+            </td>
+        </tr>
     </table>
-    Links<br/>
-    <ul>
-        <#list var.links as link>
-            <li><a href="${link.href}.html">${link.rel}</a> </li>
-        </#list>
-    </ul>
 </html>
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/main/resources/rest_templates/resourceWithType.ftl b/modules/enterprise/server/jar/src/main/resources/rest_templates/resourceWithType.ftl
index 2adf78a..bb8f717 100644
--- a/modules/enterprise/server/jar/src/main/resources/rest_templates/resourceWithType.ftl
+++ b/modules/enterprise/server/jar/src/main/resources/rest_templates/resourceWithType.ftl
@@ -2,7 +2,7 @@
 <#--
 /*
  * RHQ Management Platform
- * Copyright (C) 2005-2011 Red Hat, Inc.
+ * Copyright (C) 2005-2012 Red Hat, Inc.
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
@@ -22,11 +22,9 @@
 <#-- @ftlvariable name="var" type="org.rhq.enterprise.server.rest.domain.ResourceWithType" -->
 
     <table>
-        <thead>
         <tr>
-            <td>Name</td><td>Value</td>
+            <th>Name</th><th>Value</th>
         </tr>
-        </thead>
         <tr>
             <td>Name</td><td>${var.resourceName}</td>
         </tr>


commit 9d5fbbe47b62800abc8919aa0b6239f85f9534a7
Author: Heiko W. Rupp <hwr at redhat.com>
Date:   Thu Jun 14 11:01:24 2012 +0200

    Add support for jsonp.
    Return application/javascript with explicit encoding

diff --git a/modules/enterprise/gui/rest-war/src/main/java/org/rhq/enterprise/rest/HeaderDumperFilter.java b/modules/enterprise/gui/rest-war/src/main/java/org/rhq/enterprise/rest/HeaderDumperFilter.java
new file mode 100644
index 0000000..6ceab48
--- /dev/null
+++ b/modules/enterprise/gui/rest-war/src/main/java/org/rhq/enterprise/rest/HeaderDumperFilter.java
@@ -0,0 +1,61 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 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.rest;
+
+import java.io.IOException;
+import java.util.Enumeration;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * Simple servlet filter to dump http headers
+ * @author Heiko W. Rupp
+ */
+public class HeaderDumperFilter implements Filter {
+    public void destroy() {
+    }
+
+    public void doFilter(ServletRequest req, ServletResponse resp,
+                         FilterChain chain) throws ServletException, IOException {
+
+        HttpServletRequest req1 = (HttpServletRequest) req;
+        String requestedType = req1.getHeader("accept");
+        System.out.println(" RT: " + requestedType);
+        Enumeration headers = req1.getHeaderNames();
+        while (headers.hasMoreElements()) {
+            String elem = (String) headers.nextElement();
+            String val = req1.getHeader(elem);
+            System.out.println("  H " + elem + "=" + val);
+        }
+
+        chain.doFilter(req, resp);
+    }
+
+    public void init(FilterConfig config) throws ServletException {
+
+    }
+
+}
diff --git a/modules/enterprise/gui/rest-war/src/main/java/org/rhq/enterprise/rest/JsonPFilter.java b/modules/enterprise/gui/rest-war/src/main/java/org/rhq/enterprise/rest/JsonPFilter.java
new file mode 100644
index 0000000..5d812dc
--- /dev/null
+++ b/modules/enterprise/gui/rest-war/src/main/java/org/rhq/enterprise/rest/JsonPFilter.java
@@ -0,0 +1,257 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 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.rest;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletInputStream;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpServletResponseWrapper;
+
+/**
+ * A filter to wrap json answers as jsonp
+ * @author Heiko W. Rupp
+ */
+public class JsonPFilter implements Filter {
+    private String callbackName;
+
+    public void destroy() {
+    }
+
+    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException,
+        IOException {
+
+        if (!(request instanceof HttpServletRequest)) {
+            throw new ServletException("This filter can " + " only process HttpServletRequest requests");
+        }
+
+        HttpServletRequest httpRequest = (HttpServletRequest) request;
+        HttpServletResponse httpResponse = (HttpServletResponse) response;
+
+        String requestedType = httpRequest.getHeader("accept");
+        if ("application/jsonp".equals(requestedType) && hasCallback(httpRequest)) {
+
+            String callback = getCallback(httpRequest);
+
+            // We need to wrap request and response, as we need to do some re-writing on both
+            // We want to get json data inside, so change the accept header
+            JsonPRequestWrapper requestWrapper = new JsonPRequestWrapper(httpRequest);
+            requestWrapper.setHeader("accept", "application/json");
+            requestWrapper.setContentType("application/json");
+
+            JsonPResponseWrapper responseWrapper = new JsonPResponseWrapper(httpResponse);
+
+            chain.doFilter(requestWrapper, responseWrapper);
+            response.setContentType("application/javascript; charset=utf-8");
+            ServletOutputStream outputStream = response.getOutputStream();
+            outputStream.write((callback + "(").getBytes());
+            responseWrapper.getByteArrayOutputStream().writeTo(outputStream);
+            outputStream.write(");".getBytes());
+            outputStream.flush();
+
+        } else {
+            chain.doFilter(request, response);
+        }
+    }
+
+    public void init(FilterConfig config) throws ServletException {
+        callbackName = config.getInitParameter("filter.jsonp.callback");
+    }
+
+    private boolean hasCallback(ServletRequest request) {
+        String cb = request.getParameter(callbackName);
+        return (cb != null && !cb.isEmpty());
+    }
+
+    private String getCallback(HttpServletRequest request) {
+        return request.getParameter(callbackName);
+    }
+
+    private static class JsonPResponseWrapper extends HttpServletResponseWrapper {
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+        private JsonPResponseWrapper(HttpServletResponse response) {
+            super(response);
+        }
+
+        ByteArrayOutputStream getByteArrayOutputStream() {
+            return baos;
+        }
+
+        @Override
+        public ServletOutputStream getOutputStream() throws IOException {
+            return new ServletOutputStream() {
+                @Override
+                public void write(int b) throws IOException {
+                    baos.write(b);
+                }
+            };
+        }
+
+        @Override
+        public PrintWriter getWriter() throws IOException {
+            return new PrintWriter(baos);
+        }
+    }
+
+    private static class JsonPRequestWrapper extends HttpServletRequestWrapper {
+        int contentLength;
+        BufferedReader reader;
+        String method;
+        ByteArrayInputStream bais;
+        Map<String, String> headers = new HashMap<String, String>();
+
+
+        public JsonPRequestWrapper(HttpServletRequest request) {
+            super(request);
+            copyHeaders(request);
+        }
+
+        private void copyHeaders(HttpServletRequest request) {
+
+            Enumeration headers = request.getHeaderNames();
+            while (headers.hasMoreElements()) {
+                String key = (String) headers.nextElement();
+                String value = request.getHeader(key);
+                this.headers.put(key, value);
+            }
+        }
+
+        public void setHeader(String key, String value) {
+            headers.put(key, value);
+        }
+
+
+/*
+        public void setBody(String body) {
+            bais = new ByteArrayInputStream(body.getBytes());
+            contentLength = body.length();
+            headers.put("content-length", Integer.toString(contentLength));
+        }
+*/
+
+        @Override
+        public BufferedReader getReader() throws IOException {
+            reader = new BufferedReader(new InputStreamReader(bais));
+            return reader;
+        }
+
+        @Override
+        public ServletInputStream getInputStream() throws IOException {
+            return new ServletInputStream() {
+                @Override
+                public int read() throws IOException {
+                    return bais.read();
+                }
+            };
+        }
+
+        private String contentType;
+
+        public void setContentType(String contentType) {
+            this.contentType = contentType;
+            headers.put("content-type", contentType);
+        }
+
+        @Override
+        public String getContentType() {
+            return contentType;
+        }
+
+        @Override
+        public int getContentLength() {
+            return contentLength;
+        }
+
+        @Override
+        public String getHeader(String name) {
+            String val = headers.get(name);
+            if (val != null) {
+                return val;
+            }
+            return super.getHeader(name);
+        }
+
+        @Override
+        public Enumeration getHeaders(final String name) {
+            final String val = headers.get(name);
+            return new Enumeration() {
+                boolean first = true;
+
+                @Override
+                public boolean hasMoreElements() {
+                    return first;
+                }
+
+                @Override
+                public Object nextElement() {
+                    if (first) {
+                        first = false;
+                        return val;
+                    } else
+                        return null;
+                }
+            };
+        }
+
+        @Override
+        public Enumeration getHeaderNames() {
+            final Iterator it = headers.keySet().iterator();
+            return new Enumeration() {
+                public boolean hasMoreElements() {
+                    return it.hasNext();
+                }
+
+                public Object nextElement() {
+                    return it.hasNext() ? it.next() : null;
+                }
+            };
+        }
+
+        @Override
+        public int getIntHeader(String name) {
+            String val = headers.get(name);
+            if (val == null) {
+                return 0; // TODO ??
+            } else {
+                return Integer.parseInt(val);
+            }
+        }
+    }
+}
diff --git a/modules/enterprise/gui/rest-war/src/main/webapp/WEB-INF/web.xml b/modules/enterprise/gui/rest-war/src/main/webapp/WEB-INF/web.xml
index d9d7587..7e5d52e 100644
--- a/modules/enterprise/gui/rest-war/src/main/webapp/WEB-INF/web.xml
+++ b/modules/enterprise/gui/rest-war/src/main/webapp/WEB-INF/web.xml
@@ -24,19 +24,46 @@
         <param-name>resteasy.media.type.mappings</param-name>
         <param-value>html : text/html, json : application/json, xml : application/xml, csv : text/csv, txt: text/plain, yaml: application/yaml</param-value>
     </context-param>
+    <filter>
+      <filter-name>JsonPFilter</filter-name>
+      <filter-class>org.rhq.enterprise.rest.JsonPFilter</filter-class>
+      <init-param>
+        <param-name>filter.jsonp.callback</param-name>
+        <param-value>callback</param-value>
+        <description>Name of the callback to use for JsonP (?callback=...)</description>
+      </init-param>
+    </filter>
 
-    <!--
-        <filter>
+<!-- Simple request header dumper for debugging purposes
+  <filter>
+    <filter-name>DumperFilter</filter-name>
+    <filter-class>org.rhq.enterprise.rest.HeaderDumperFilter</filter-class>
+  </filter>
+-->
+
+  <!--
+      <filter>
+
+          <filter-name>AuthFilter</filter-name>
+          <filter-class>org.rhq.enterprise.rest.AuthFilter</filter-class>
+      </filter>
+      <filter-mapping>
+          <filter-name>AuthFilter</filter-name>
+          <servlet-name>Resteasy</servlet-name>
+      </filter-mapping>
+  -->
 
-            <filter-name>AuthFilter</filter-name>
-            <filter-class>org.rhq.enterprise.rest.AuthFilter</filter-class>
-        </filter>
-        <filter-mapping>
-            <filter-name>AuthFilter</filter-name>
-            <servlet-name>Resteasy</servlet-name>
-        </filter-mapping>
-    -->
 
+    <filter-mapping>
+      <filter-name>JsonPFilter</filter-name>
+      <url-pattern>/1/*</url-pattern>
+    </filter-mapping>
+<!--
+  <filter-mapping>
+    <filter-name>DumperFilter</filter-name>
+    <url-pattern>/1/*</url-pattern>
+  </filter-mapping>
+-->
 
     <servlet>
         <servlet-name>Resteasy</servlet-name>


commit 1667f9730e4d547b399e1b30ad9965d8773d11a5
Author: Jay Shaughnessy <jshaughn at redhat.com>
Date:   Wed Jun 13 21:45:58 2012 -0400

    [831254 - resource tree's right-mouse context menu item "Import" is empty]
    [814305 - Dealing with singletons in inventory]
    Fix the context menu issue which was introduced with the original fix for
    the singleton filtering support.  There were a few issues here. In
    the changes made to the context menu:
    - fix confusion around and lack of complete support for both create child and import
    - consolidate duplicate server calls, narrow the results with more criteria,
      and avoid the call when not needed.
    Additionally, the analogous change was not made to the Inventory->Child Resources
    view which also offers Create Child and Import.  The change here ended up being
    tricky because it involved Table's TableActions, and filtering the menu
    button values in the footer.  This led to a ** CHANGE IN Table **, to add more
    robust support for subclasses overriding default InitializableView support. In
    short, Table subclasses can now perfom async calls in onInit() if they
    properly override isInitialized() and be assured that configureTable() will
    be called after initialization is complete.

diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/table/Table.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/table/Table.java
index b76a7da..70e29d4 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/table/Table.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/table/Table.java
@@ -27,6 +27,7 @@ import java.util.Map;
 import java.util.Set;
 
 import com.google.gwt.event.dom.client.KeyCodes;
+import com.google.gwt.user.client.Timer;
 import com.smartgwt.client.data.Criteria;
 import com.smartgwt.client.data.DSCallback;
 import com.smartgwt.client.data.DSRequest;
@@ -372,14 +373,47 @@ public class Table<DS extends RPCDataSource> extends LocatableHLayout implements
         return SelectionStyle.MULTIPLE;
     }
 
+    // Table is an InitializableView. This onDraw() waits until we're sure we're initialized and then 
+    // lays down the canvas.  This gives subclasses a chance to perform initialization (including async calls)
+    // required to support the overrides (like configureTable()) they may have provided and that are called in 
+    // doOnDraw().
     @Override
     protected void onDraw() {
-        try {
-            super.onDraw();
+        super.onDraw();
+
+        if (isInitialized()) {
+            doOnDraw();
+
+        } else {
+            new Timer() {
+                final long startTime = System.currentTimeMillis();
 
+                public void run() {
+                    if (isInitialized()) {
+                        doOnDraw();
+                        cancel();
+
+                    } else {
+                        // if after 10s we still aren't initialized just keep going, else try again
+                        long elapsedMillis = System.currentTimeMillis() - startTime;
+                        if (elapsedMillis < 10000L) {
+                            schedule(100); // Reschedule the timer.
+
+                        } else {
+                            doOnDraw();
+                            cancel();
+                        }
+                    }
+                }
+            }.run(); // fire the timer immediately    
+        }
+    }
+
+    protected void doOnDraw() {
+        try {
             // I'm not sure this is necessary as I'm not sure it's the case that draw()/onDraw() will get called
             // multiple times. But if it did/does, this protects us by removing the current members before they
-            // get set below.  Note that by having this here we *can non* add members in onInit, because they will
+            // get set below.  Note that by having this here we *can not* add members in onInit, because they will
             // immediately get removed. -jshaughn
             for (Canvas child : contents.getMembers()) {
                 contents.removeChild(child);
@@ -463,6 +497,8 @@ public class Table<DS extends RPCDataSource> extends LocatableHLayout implements
         } catch (Exception e) {
             CoreGUI.getErrorHandler().handleError(MSG.view_table_drawFail(this.toString()), e);
         }
+
+        markForRedraw();
     }
 
     private void refreshRowCount() {
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceCompositeSearchView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceCompositeSearchView.java
index 001eb3c..bb43f26 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceCompositeSearchView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceCompositeSearchView.java
@@ -22,6 +22,7 @@
  */
 package org.rhq.enterprise.gui.coregui.client.inventory.resource;
 
+import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.LinkedHashMap;
 import java.util.List;
@@ -35,12 +36,14 @@ import com.smartgwt.client.data.Criteria;
 import com.smartgwt.client.data.SortSpecifier;
 import com.smartgwt.client.widgets.grid.ListGridRecord;
 
+import org.rhq.core.domain.criteria.ResourceCriteria;
 import org.rhq.core.domain.resource.CannotConnectToAgentException;
 import org.rhq.core.domain.resource.DeleteResourceHistory;
 import org.rhq.core.domain.resource.Resource;
 import org.rhq.core.domain.resource.ResourceType;
 import org.rhq.core.domain.resource.composite.ResourceComposite;
 import org.rhq.core.domain.resource.composite.ResourcePermission;
+import org.rhq.core.domain.util.PageList;
 import org.rhq.enterprise.gui.coregui.client.CoreGUI;
 import org.rhq.enterprise.gui.coregui.client.components.table.AbstractTableAction;
 import org.rhq.enterprise.gui.coregui.client.components.table.TableActionEnablement;
@@ -48,6 +51,7 @@ import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
 import org.rhq.enterprise.gui.coregui.client.gwt.ResourceGWTServiceAsync;
 import org.rhq.enterprise.gui.coregui.client.inventory.resource.factory.ResourceFactoryCreateWizard;
 import org.rhq.enterprise.gui.coregui.client.inventory.resource.factory.ResourceFactoryImportWizard;
+import org.rhq.enterprise.gui.coregui.client.util.Log;
 import org.rhq.enterprise.gui.coregui.client.util.RPCDataSource;
 import org.rhq.enterprise.gui.coregui.client.util.TableUtility;
 import org.rhq.enterprise.gui.coregui.client.util.message.Message;
@@ -59,11 +63,19 @@ import org.rhq.enterprise.gui.coregui.client.util.message.Message.Severity;
 public class ResourceCompositeSearchView extends ResourceSearchView {
 
     private final ResourceComposite parentResourceComposite;
+    private boolean initialized;
+    private List<Resource> singletonChildren;
+    private Set<ResourceType> creatableChildTypes;
+    private Set<ResourceType> importableChildTypes;
+    private boolean hasCreatableTypes;
+    private boolean hasImportableTypes;
+    private boolean canCreate;
 
     public ResourceCompositeSearchView(String locatorId, ResourceComposite parentResourceComposite, Criteria criteria,
         String title, SortSpecifier[] sortSpecifier, String[] excludeFields, String... headerIcons) {
         super(locatorId, criteria, title, sortSpecifier, excludeFields, headerIcons);
         this.parentResourceComposite = parentResourceComposite;
+        this.canCreate = this.parentResourceComposite.getResourcePermission().isCreateChildResources();
         setInitialCriteriaFixed(true);
     }
 
@@ -72,6 +84,56 @@ public class ResourceCompositeSearchView extends ResourceSearchView {
         this(locatorId, parentResourceComposite, criteria, title, null, null, headerIcons);
     }
 
+    @Override
+    protected void onInit() {
+        super.onInit();
+
+        // To properly filter Create Child and Import menus we need existing singleton child resources. If the
+        // user has creat permission and the parent type has singleton child types and creatable or importable child
+        // types, perform an async call to fetch the singleton children. If we make the async call don't declare this
+        // instance initialized until after it completesas we must  have the children before the menu buttons can be drawn.
+
+        final Resource parentResource = parentResourceComposite.getResource();
+        ResourceType parentType = parentResource.getResourceType();
+
+        creatableChildTypes = getCreatableChildTypes(parentType);
+        importableChildTypes = getImportableChildTypes(parentType);
+        hasCreatableTypes = !creatableChildTypes.isEmpty();
+        hasImportableTypes = !importableChildTypes.isEmpty();
+        singletonChildren = new ArrayList(); // initialize to non-null
+
+        Integer[] singletonChildTypes = getSingletonChildTypes(parentType);
+
+        if (canCreate && singletonChildTypes.length > 0 && (hasCreatableTypes || hasImportableTypes)) {
+            ResourceCriteria criteria = new ResourceCriteria();
+            criteria.addFilterParentResourceId(parentResource.getId());
+            criteria.addFilterResourceTypeIds(singletonChildTypes);
+            GWTServiceLookup.getResourceService().findResourcesByCriteria(criteria,
+                new AsyncCallback<PageList<Resource>>() {
+
+                    @Override
+                    public void onSuccess(PageList<Resource> result) {
+                        singletonChildren = result;
+                        initialized = true;
+                    }
+
+                    @Override
+                    public void onFailure(Throwable caught) {
+                        Log.error("Failed to load child resources for [" + parentResource + "]", caught);
+                        initialized = true;
+                    }
+                });
+
+        } else {
+            initialized = true;
+        }
+    }
+
+    @Override
+    public boolean isInitialized() {
+        return super.isInitialized() && this.initialized;
+    }
+
     // suppress unchecked warnings because the superclass has different generic types for the datasource
     @SuppressWarnings("unchecked")
     @Override
@@ -81,107 +143,161 @@ public class ResourceCompositeSearchView extends ResourceSearchView {
 
     @Override
     protected void configureTable() {
-        addTableAction(extendLocatorId("Delete"), MSG.common_button_delete(), MSG
-            .view_inventory_resources_deleteConfirm(), new AbstractTableAction(TableActionEnablement.ANY) {
-
-            // only enabled if all selected are a deletable type and if the user has delete permission
-            // on the resources. 
-            public boolean isEnabled(ListGridRecord[] selection) {
-                boolean isEnabled = super.isEnabled(selection);
-
-                if (isEnabled) {
-                    for (ListGridRecord record : selection) {
-                        ResourceComposite resComposite = (ResourceComposite) record
-                            .getAttributeAsObject("resourceComposite");
-                        Resource res = resComposite.getResource();
-                        if (!(isEnabled = res.getResourceType().isDeletable())) {
-                            break;
-                        }
-                        ResourcePermission resPermission = resComposite.getResourcePermission();
-                        if (!(isEnabled = resPermission.isDeleteResource())) {
-                            break;
+        addTableAction(extendLocatorId("Delete"), MSG.common_button_delete(),
+            MSG.view_inventory_resources_deleteConfirm(), new AbstractTableAction(TableActionEnablement.ANY) {
+
+                // only enabled if all selected are a deletable type and if the user has delete permission
+                // on the resources. 
+                public boolean isEnabled(ListGridRecord[] selection) {
+                    boolean isEnabled = super.isEnabled(selection);
+
+                    if (isEnabled) {
+                        for (ListGridRecord record : selection) {
+                            ResourceComposite resComposite = (ResourceComposite) record
+                                .getAttributeAsObject("resourceComposite");
+                            Resource res = resComposite.getResource();
+                            if (!(isEnabled = res.getResourceType().isDeletable())) {
+                                break;
+                            }
+                            ResourcePermission resPermission = resComposite.getResourcePermission();
+                            if (!(isEnabled = resPermission.isDeleteResource())) {
+                                break;
+                            }
                         }
                     }
+                    return isEnabled;
                 }
-                return isEnabled;
-            }
 
-            public void executeAction(ListGridRecord[] selection, Object actionValue) {
-                int[] resourceIds = TableUtility.getIds(selection);
-                ResourceGWTServiceAsync resourceManager = GWTServiceLookup.getResourceService();
+                public void executeAction(ListGridRecord[] selection, Object actionValue) {
+                    int[] resourceIds = TableUtility.getIds(selection);
+                    ResourceGWTServiceAsync resourceManager = GWTServiceLookup.getResourceService();
 
-                resourceManager.deleteResources(resourceIds, new AsyncCallback<List<DeleteResourceHistory>>() {
-                    public void onFailure(Throwable caught) {
-                        if (caught instanceof CannotConnectToAgentException) {
-                            CoreGUI.getMessageCenter().notify(new Message(MSG.view_inventory_resources_deleteFailed2(),
-                                Severity.Warning));
-                        } else {
-                            CoreGUI.getErrorHandler().handleError(MSG.view_inventory_resources_deleteFailed(), caught);
+                    resourceManager.deleteResources(resourceIds, new AsyncCallback<List<DeleteResourceHistory>>() {
+                        public void onFailure(Throwable caught) {
+                            if (caught instanceof CannotConnectToAgentException) {
+                                CoreGUI.getMessageCenter().notify(
+                                    new Message(MSG.view_inventory_resources_deleteFailed2(), Severity.Warning));
+                            } else {
+                                CoreGUI.getErrorHandler().handleError(MSG.view_inventory_resources_deleteFailed(),
+                                    caught);
+                            }
                         }
-                    }
 
-                    public void onSuccess(List<DeleteResourceHistory> result) {
-                        CoreGUI.getMessageCenter().notify(
-                            new Message(MSG.view_inventory_resources_deleteSuccessful(), Severity.Info));
+                        public void onSuccess(List<DeleteResourceHistory> result) {
+                            CoreGUI.getMessageCenter().notify(
+                                new Message(MSG.view_inventory_resources_deleteSuccessful(), Severity.Info));
 
-                        refresh(true);
-                        // refresh the entire gui so it encompasses any relevant tree view. Don't just call this.refresh(),
-                        // because CoreGUI.refresh is more comprehensive.
-                        CoreGUI.refresh();
-                    }
-                });
-            }
-        });
+                            refresh(true);
+                            // refresh the entire gui so it encompasses any relevant tree view. Don't just call this.refresh(),
+                            // because CoreGUI.refresh is more comprehensive.
+                            CoreGUI.refresh();
+                        }
+                    });
+                }
+            });
 
-        if (this.parentResourceComposite.getResourcePermission().isCreateChildResources()) {
-            addImportButton();
-        }
+        addImportAndCreateButtons();
 
         super.configureTable();
     }
 
     @SuppressWarnings("unchecked")
-    private void addImportButton() {
-        ResourceType parentType = parentResourceComposite.getResource().getResourceType();
+    private void addImportAndCreateButtons() {
+
+        final Resource parentResource = parentResourceComposite.getResource();
+        ResourceType parentType = parentResource.getResourceType();
+
+        // Create Child Menu and Manual Import Menu
+        if (canCreate && (hasCreatableTypes || hasImportableTypes)) {
+
+            if (hasCreatableTypes) {
+                Map<String, ResourceType> displayNameMap = getDisplayNames(creatableChildTypes);
+                LinkedHashMap<String, ResourceType> createTypeValueMap = new LinkedHashMap<String, ResourceType>(
+                    displayNameMap);
+                removeExistingSingletons(singletonChildren, createTypeValueMap);
+                addTableAction(extendLocatorId("CreateChild"), MSG.common_button_create_child(), null,
+                    createTypeValueMap, new AbstractTableAction(TableActionEnablement.ALWAYS) {
+                        public void executeAction(ListGridRecord[] selection, Object actionValue) {
+                            ResourceFactoryCreateWizard.showCreateWizard(parentResource, (ResourceType) actionValue);
+                            // we can refresh the table buttons immediately since the wizard is a dialog, the
+                            // user can't access enabled buttons anyway.
+                            ResourceCompositeSearchView.this.refreshTableInfo();
+                        }
+                    });
+            }
 
-        // manual import type menu
-        Set<ResourceType> importableChildTypes = getImportableChildTypes(parentType);
-        if (!importableChildTypes.isEmpty()) {
-            Map<String, ResourceType> displayNames = getDisplayNames(importableChildTypes);
-            LinkedHashMap<String, ResourceType> importTypeValueMap = new LinkedHashMap<String, ResourceType>(displayNames);
+            if (hasImportableTypes) {
+                Map<String, ResourceType> displayNameMap = getDisplayNames(importableChildTypes);
+                LinkedHashMap<String, ResourceType> importTypeValueMap = new LinkedHashMap<String, ResourceType>(
+                    displayNameMap);
+                removeExistingSingletons(singletonChildren, importTypeValueMap);
+                addTableAction(extendLocatorId("Import"), MSG.common_button_import(), null, importTypeValueMap,
+                    new AbstractTableAction(TableActionEnablement.ALWAYS) {
+                        public void executeAction(ListGridRecord[] selection, Object actionValue) {
+                            ResourceFactoryImportWizard.showImportWizard(parentResource, (ResourceType) actionValue);
+                            // we can refresh the table buttons immediately since the wizard is a dialog, the
+                            // user can't access enabled buttons anyway.
+                            ResourceCompositeSearchView.this.refreshTableInfo();
+                        }
+                    });
+            }
 
-            addTableAction(extendLocatorId("Import"), MSG.common_button_import(), null, importTypeValueMap,
-                new AbstractTableAction(TableActionEnablement.ALWAYS) {
+        } else {
+            if (!canCreate && hasCreatableTypes) {
+                addTableAction(extendLocatorId("CreateChild"), MSG.common_button_create_child(),
+                    new AbstractTableAction(TableActionEnablement.NEVER) {
+                        public void executeAction(ListGridRecord[] selection, Object actionValue) {
+                            // never called
+                        }
+                    });
+            }
+            if (!canCreate && hasImportableTypes) {
+                addTableAction(extendLocatorId("Import"), MSG.common_button_import(), new AbstractTableAction(
+                    TableActionEnablement.NEVER) {
                     public void executeAction(ListGridRecord[] selection, Object actionValue) {
-                        ResourceFactoryImportWizard.showImportWizard(parentResourceComposite.getResource(),
-                            (ResourceType) actionValue);
-                        // we can refresh the table buttons immediately since the wizard is a dialog, the
-                        // user can't access enabled buttons anyway.
-                        ResourceCompositeSearchView.this.refreshTableInfo();
+                        // never called
                     }
                 });
+            }
         }
+    }
 
-        // creatable child type menu
-        Set<ResourceType> creatableChildTypes = getCreatableChildTypes(parentType);
-        if (!creatableChildTypes.isEmpty()) {
-            Map<String, ResourceType> displayNames = getDisplayNames(creatableChildTypes);
-            LinkedHashMap<String, ResourceType> createTypeValueMap = new LinkedHashMap<String, ResourceType>(displayNames);
+    private void removeExistingSingletons(List<Resource> singletonChildren, Map<String, ResourceType> displayNameMap) {
 
-            addTableAction(extendLocatorId("CreateChild"), MSG.common_button_create_child(), null, createTypeValueMap,
-                new AbstractTableAction(TableActionEnablement.ALWAYS) {
+        List<String> existingSingletons = new ArrayList<String>();
 
-                    public void executeAction(ListGridRecord[] selection, Object actionValue) {
-                        ResourceFactoryCreateWizard.showCreateWizard(parentResourceComposite.getResource(),
-                            (ResourceType) actionValue);
-                        // we can refresh the table buttons immediately since the wizard is a dialog, the
-                        // user can't access enabled buttons anyway.
-                        ResourceCompositeSearchView.this.refreshTableInfo();
+        Set<String> displayNames = displayNameMap.keySet();
+        for (final String displayName : displayNames) {
+            final ResourceType type = displayNameMap.get(displayName);
+            boolean exists = false;
+
+            if (type.isSingleton()) {
+                for (Resource child : singletonChildren) {
+                    exists = child.getResourceType().equals(displayNameMap.get(displayName));
+                    if (exists) {
+                        existingSingletons.add(displayName);
+                        break;
                     }
-                });
+                }
+            }
+        }
+        for (String existing : existingSingletons) {
+            displayNameMap.remove(existing);
         }
     }
 
+    private static Integer[] getSingletonChildTypes(ResourceType type) {
+        Set<Integer> results = new TreeSet<Integer>();
+        Set<ResourceType> childTypes = type.getChildResourceTypes();
+        for (ResourceType childType : childTypes) {
+            if (childType.isSingleton()) {
+                results.add(childType.getId());
+            }
+        }
+
+        return results.toArray(new Integer[results.size()]);
+    }
+
     private static Set<ResourceType> getImportableChildTypes(ResourceType type) {
         Set<ResourceType> results = new TreeSet<ResourceType>();
         Set<ResourceType> childTypes = type.getChildResourceTypes();
@@ -240,8 +356,8 @@ public class ResourceCompositeSearchView extends ResourceSearchView {
     // -------- Static Utility loaders ------------
 
     public static ResourceCompositeSearchView getChildrenOf(String locatorId, ResourceComposite parentResourceComposite) {
-        return new ResourceCompositeSearchView(locatorId, parentResourceComposite, new Criteria("parentId", String
-            .valueOf(parentResourceComposite.getResource().getId())), MSG.view_tabs_common_child_resources());
+        return new ResourceCompositeSearchView(locatorId, parentResourceComposite, new Criteria("parentId",
+            String.valueOf(parentResourceComposite.getResource().getId())), MSG.view_tabs_common_child_resources());
     }
 
 }
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeView.java
index 0f37f65..2393f8d 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeView.java
@@ -93,6 +93,7 @@ import org.rhq.enterprise.gui.coregui.client.inventory.groups.detail.ResourceGro
 import org.rhq.enterprise.gui.coregui.client.inventory.groups.detail.ResourceGroupDetailView;
 import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.ResourceTreeDatasource.AutoGroupTreeNode;
 import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.ResourceTreeDatasource.ResourceTreeNode;
+import org.rhq.enterprise.gui.coregui.client.inventory.resource.factory.ResourceFactoryCreateWizard;
 import org.rhq.enterprise.gui.coregui.client.inventory.resource.factory.ResourceFactoryImportWizard;
 import org.rhq.enterprise.gui.coregui.client.inventory.resource.type.ResourceTypeRepository;
 import org.rhq.enterprise.gui.coregui.client.util.Log;
@@ -257,8 +258,8 @@ public class ResourceTreeView extends LocatableVLayout {
                 }
                 // do not update the selection when expanding other tree node (BZ 816086)
                 TreeNode parent = dataArrivedEvent.getParentNode();
-                if  (parent instanceof EnhancedTreeNode && ((EnhancedTreeNode) parent).getID().equals(selectedNodeId)) {
-                        updateSelection();
+                if (parent instanceof EnhancedTreeNode && ((EnhancedTreeNode) parent).getID().equals(selectedNodeId)) {
+                    updateSelection();
                 }
             }
         });
@@ -298,7 +299,8 @@ public class ResourceTreeView extends LocatableVLayout {
                     resourceGroupService.createPrivateResourceGroup(backingGroup, childIds,
                         new AsyncCallback<ResourceGroup>() {
                             public void onFailure(Throwable caught) {
-                                callback.onFailure(new RuntimeException(MSG.view_tree_common_loadFailed_create(), caught));
+                                callback.onFailure(new RuntimeException(MSG.view_tree_common_loadFailed_create(),
+                                    caught));
                             }
 
                             public void onSuccess(ResourceGroup result) {
@@ -320,7 +322,8 @@ public class ResourceTreeView extends LocatableVLayout {
                     resourceGroupService.setAssignedResources(backingGroup.getId(), childIds, false,
                         new AsyncCallback<Void>() {
                             public void onFailure(Throwable caught) {
-                                callback.onFailure(new RuntimeException(MSG.view_tree_common_loadFailed_update(), caught));
+                                callback.onFailure(new RuntimeException(MSG.view_tree_common_loadFailed_update(),
+                                    caught));
                             }
 
                             public void onSuccess(Void result) {
@@ -419,8 +422,7 @@ public class ResourceTreeView extends LocatableVLayout {
                             new ResourceTypeRepository.TypeLoadedCallback() {
 
                                 public void onTypesLoaded(ResourceType type) {
-                                    buildResourceContextMenu(node, resourceComposite, type);
-                                    resourceContextMenu.showContextMenu();
+                                    buildAndShowResourceContextMenu(node, resourceComposite, type);
                                 }
                             });
                     }
@@ -428,8 +430,8 @@ public class ResourceTreeView extends LocatableVLayout {
             });
     }
 
-    private void buildResourceContextMenu(final ResourceTreeNode node, final ResourceComposite resourceComposite,
-        final ResourceType resourceType) {
+    private void buildAndShowResourceContextMenu(final ResourceTreeNode node,
+        final ResourceComposite resourceComposite, final ResourceType resourceType) {
         final Resource resource = resourceComposite.getResource();
         final ResourcePermission resourcePermission = resourceComposite.getResourcePermission();
 
@@ -540,105 +542,134 @@ public class ResourceTreeView extends LocatableVLayout {
         // Metric graph addition menu
         resourceContextMenu.addItem(buildMetricsMenu(resourceType, resource));
 
-        // Create Child Menu
-        Set<ResourceType> creatableChildTypes = getCreatableChildTypes(resourceType);
-        if (!creatableChildTypes.isEmpty()) {
-            final MenuItem createChildMenu = new MenuItem(MSG.common_button_create_child());
-            boolean hasCreateChildPermission = resourcePermission.isCreateChildResources();
-            createChildMenu.setEnabled(hasCreateChildPermission);
-            if (hasCreateChildPermission) {
-                final Menu createChildSubMenu = new Menu();
-                final Map<String, ResourceType> displayNameMap = getDisplayNames(creatableChildTypes);
-
-                ResourceCriteria criteria = new ResourceCriteria();
-                criteria.addFilterParentResourceId(resource.getId());
-                GWTServiceLookup.getResourceService().findResourcesByCriteria(criteria,
-                    new AsyncCallback<PageList<Resource>>() {
-
-                        @Override
-                        public void onSuccess(PageList<Resource> result) {
-                            Menu filteredSubmenu = checkForSingletons(result, resource, displayNameMap,
-                                createChildSubMenu);
-                            createChildMenu.setSubmenu(filteredSubmenu);
-                            resourceContextMenu.addItem(createChildMenu);
+        // Create Child Menu and Manual Import Menu
+        final Set<ResourceType> creatableChildTypes = getCreatableChildTypes(resourceType);
+        final Set<ResourceType> importableChildTypes = getImportableChildTypes(resourceType);
+        final boolean hasCreatableTypes = !creatableChildTypes.isEmpty();
+        final boolean hasImportableTypes = !importableChildTypes.isEmpty();
+        boolean canCreate = resourcePermission.isCreateChildResources();
+
+        Integer[] singletonChildTypes = getSingletonChildTypes(resourceType);
+
+        // To properly filter Create Child and Import menus we need existing singleton child resources. If the
+        // user has creat permission and the parent type has singleton child types and creatable or importable child
+        // types, perform an async call to fetch the singleton children.
+        if (canCreate && singletonChildTypes.length > 0 && (hasCreatableTypes || hasImportableTypes)) {
+
+            ResourceCriteria criteria = new ResourceCriteria();
+            criteria.addFilterParentResourceId(resource.getId());
+            criteria.addFilterResourceTypeIds(singletonChildTypes);
+            GWTServiceLookup.getResourceService().findResourcesByCriteria(criteria,
+                new AsyncCallback<PageList<Resource>>() {
+
+                    @Override
+                    public void onSuccess(PageList<Resource> singletonChildren) {
+                        if (hasCreatableTypes) {
+                            Map<String, ResourceType> displayNameMap = getDisplayNames(creatableChildTypes);
+                            addMenu(MSG.common_button_create_child(), true, singletonChildren, resource, displayNameMap);
                         }
 
-                        @Override
-                        public void onFailure(Throwable caught) {
-                            Log.error("Error resources with parentId:" + resource.getId(), caught);
+                        if (hasImportableTypes) {
+                            Map<String, ResourceType> displayNameMap = getDisplayNames(importableChildTypes);
+                            addMenu(MSG.common_button_import(), true, singletonChildren, resource, displayNameMap);
                         }
-                    });
 
-            } else {
-                resourceContextMenu.addItem(createChildMenu);
+                        resourceContextMenu.showContextMenu();
+                    }
+
+                    @Override
+                    public void onFailure(Throwable caught) {
+                        Log.error("Error resources with parentId:" + resource.getId(), caught);
+                        resourceContextMenu.showContextMenu();
+                    }
+                });
+        } else if (canCreate && singletonChildTypes.length == 0 && (hasCreatableTypes || hasImportableTypes)) {
+            if (hasCreatableTypes) {
+                Map<String, ResourceType> displayNameMap = getDisplayNames(creatableChildTypes);
+                addMenu(MSG.common_button_create_child(), true, null, resource, displayNameMap);
             }
-        }
 
-        // Manual Import Menu
-        Set<ResourceType> importableChildTypes = getImportableChildTypes(resourceType);
-
-        if (!importableChildTypes.isEmpty()) {
-            final MenuItem importChildMenu = new MenuItem(MSG.common_button_import());
-            boolean hasManualImportPermission = resourcePermission.isCreateChildResources();
-            importChildMenu.setEnabled(hasManualImportPermission);
-            if (hasManualImportPermission) {
-                final Menu importChildSubMenu = new Menu();
-                final Map<String, ResourceType> displayNameMap = getDisplayNames(creatableChildTypes);
-
-                ResourceCriteria criteria = new ResourceCriteria();
-                criteria.addFilterParentResourceId(resource.getId());
-                GWTServiceLookup.getResourceService().findResourcesByCriteria(criteria,
-                    new AsyncCallback<PageList<Resource>>() {
-
-                        @Override
-                        public void onSuccess(PageList<Resource> result) {
-                            Menu filteredSubmenu = checkForSingletons(result, resource, displayNameMap,
-                                importChildSubMenu);
-                            importChildMenu.setSubmenu(filteredSubmenu);
-                            resourceContextMenu.addItem(importChildMenu);
-                        }
+            if (hasImportableTypes) {
+                Map<String, ResourceType> displayNameMap = getDisplayNames(importableChildTypes);
+                addMenu(MSG.common_button_import(), true, null, resource, displayNameMap);
+            }
 
-                        @Override
-                        public void onFailure(Throwable caught) {
-                            Log.error("Error resources with parentId:" + resource.getId(), caught);
-                        }
-                    });
+            resourceContextMenu.showContextMenu();
 
-            } else {
-                resourceContextMenu.addItem(importChildMenu);
+        } else {
+            if (!canCreate && hasCreatableTypes) {
+                addMenu(MSG.common_button_create_child(), false, null, null, null);
+            }
+            if (!canCreate && hasImportableTypes) {
+                addMenu(MSG.common_button_import(), false, null, null, null);
             }
+
+            resourceContextMenu.showContextMenu();
+        }
+    }
+
+    private void addMenu(String name, boolean enabled, List<Resource> singletonChildren, Resource resource,
+        Map<String, ResourceType> displayNameMap) {
+        MenuItem menu = new MenuItem(name);
+        if (enabled) {
+            Menu subMenu = new Menu();
+            singletonChildren = (null == singletonChildren) ? new ArrayList() : singletonChildren;
+            Menu filteredSubMenu = checkForSingletons(singletonChildren, resource, displayNameMap, subMenu, true);
+            menu.setSubmenu(filteredSubMenu);
+        } else {
+            menu.setEnabled(false);
         }
+        resourceContextMenu.addItem(menu);
     }
 
-    private Menu checkForSingletons(PageList<Resource> siblings, final Resource resource,
-        Map<String, ResourceType> displayNameMap, Menu submentuToAdd) {
+    private static Integer[] getSingletonChildTypes(ResourceType type) {
+        Set<Integer> results = new TreeSet<Integer>();
+        Set<ResourceType> childTypes = type.getChildResourceTypes();
+        for (ResourceType childType : childTypes) {
+            if (childType.isSingleton()) {
+                results.add(childType.getId());
+            }
+        }
+
+        return results.toArray(new Integer[results.size()]);
+    }
+
+    private Menu checkForSingletons(List<Resource> singletonChildren, final Resource resource,
+        Map<String, ResourceType> displayNameMap, Menu subMenu, final boolean isCreate) {
+
         Set<String> displayNames = displayNameMap.keySet();
         for (final String displayName : displayNames) {
             MenuItem itemToAdd = new MenuItem(displayName);
-            final ResourceType childType = displayNameMap.get(displayName);
-            boolean disabled = false;
-            // for each already added child, check if the type is the same.
-            // If yes, disable the menu item
-            if (displayNameMap.get(displayName).isSingleton()) {
-                for (Resource sibling : siblings) {
-                    if (sibling.getResourceType().equals(displayNameMap.get(displayName))) {
-                        disabled = true;
+            final ResourceType type = displayNameMap.get(displayName);
+            boolean exists = false;
+
+            // disable the menu item for a singleton type that already has a singleton child resource
+            if (type.isSingleton()) {
+                for (Resource child : singletonChildren) {
+                    exists = child.getResourceType().equals(displayNameMap.get(displayName));
+                    if (exists) {
                         break;
                     }
                 }
             }
-            // if the condition obove is not satisfied, add the menu item
-            if (!disabled) {
+
+            // omit the type's menu item if the singleton already exists, otherwise add the necessary click handler.
+            // note: we omit as opposed to disable the menu item to match the behavior of the buttons in the Inventory
+            // -> Child Resources view, which has no facility to do the anologous disabling.
+            if (!exists) {
                 itemToAdd.addClickHandler(new ClickHandler() {
                     public void onClick(MenuItemClickEvent event) {
-                        ResourceFactoryImportWizard.showImportWizard(resource, childType);
+                        if (isCreate) {
+                            ResourceFactoryCreateWizard.showCreateWizard(resource, type);
+                        } else {
+                            ResourceFactoryImportWizard.showImportWizard(resource, type);
+                        }
                     }
                 });
-                submentuToAdd.addItem(itemToAdd);
+                subMenu.addItem(itemToAdd);
             }
-            
         }
-        return submentuToAdd;
+        return subMenu;
     }
 
     /**
@@ -1029,31 +1060,6 @@ public class ResourceTreeView extends LocatableVLayout {
         }
     }
 
-    /*private List<Resource> preload(final List<Resource> lineage) {
-
-            final ArrayList<Resource> list = new ArrayList<Resource>(lineage);
-
-            ResourceGWTServiceAsync resourceService = ResourceGWTServiceAsync.Util.getInstance();
-
-                ResourceCriteria c = new ResourceCriteria();
-                c.addFilterParentResourceId(lineage.get(0).getId());
-                resourceService.findResourcesByCriteria(CoreGUI.getSessionSubject(), c, new AsyncCallback<PageList<Resource>>() {
-                    public void onFailure(Throwable caught) {
-                        SC.say("NotGood");
-                    }
-
-                    public void onSuccess(PageList<Resource> result) {
-                        SC.say("GotONE");
-
-                        if (lineage.size() > 1) {
-                             result.addAll(preload(lineage.subList(1, lineage.size())));
-                        }
-                    }
-                });
-            }
-        }
-    */
-
     public void renderView(ViewPath viewPath) {
 
         ViewId currentViewId = viewPath.getCurrent();


commit 38d06cb32c41fa525269c564278a163613509441
Author: Jay Shaughnessy <jshaughn at redhat.com>
Date:   Wed Jun 13 21:26:16 2012 -0400

    Fix a couple of I18N issues.  Remove some newly inroduced duplicates of
    common values. And convert commented czech to commented english.

diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/ConfigurationEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/ConfigurationEditor.java
index 8a12549..5748811 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/ConfigurationEditor.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/ConfigurationEditor.java
@@ -32,7 +32,6 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
-import com.google.gwt.i18n.client.LocalizableResource.Description;
 import com.google.gwt.user.client.rpc.AsyncCallback;
 import com.smartgwt.client.types.Alignment;
 import com.smartgwt.client.types.AutoFitWidthApproach;
@@ -575,13 +574,13 @@ public class ConfigurationEditor extends LocatableVLayout {
         fields.add(unsetHeader);
 
         StaticTextItem valueHeader = new StaticTextItem();
-        valueHeader.setValue(MSG.view_configEdit_value());
+        valueHeader.setValue(MSG.common_title_value());
         valueHeader.setShowTitle(false);
         valueHeader.setCellStyle(CELL_STYLE);
         fields.add(valueHeader);
 
         StaticTextItem descriptionHeader = new StaticTextItem();
-        descriptionHeader.setValue(MSG.view_configEdit_description());
+        descriptionHeader.setValue(MSG.common_title_description());
         descriptionHeader.setShowTitle(false);
         descriptionHeader.setCellStyle(CELL_STYLE);
         fields.add(descriptionHeader);
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
index 4852efc..0e948cd 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
@@ -1167,7 +1167,6 @@ view_configEdit_addItem = Add Item to List
 view_configEdit_confirm_1 = Are you sure you want to delete the selected properties from the set?
 view_configEdit_confirm_2 = Are you sure you want to delete this row?
 view_configEdit_confirm_3 = Are you sure you want to delete the [{0}]  selected [{1}]?
-view_configEdit_description = Description
 view_configEdit_editRow = Edit Row
 view_configEdit_enterPropName = Enter the name of the property to be added.
 view_configEdit_error_1 = Configuration is not supported by this Resource.
@@ -1185,7 +1184,6 @@ view_configEdit_property = Property
 view_configEdit_tooltip_1 = Delete the selected items from the list.
 view_configEdit_tooltip_2 = Add an item to the list.
 view_configEdit_unset = Unset?
-view_configEdit_value = Value
 view_configEdit_viewRow = View Row
 view_configurationDetails_allPropertiesValid = All configuration properties have valid values, so the configuration can now be saved.
 view_configurationDetails_configNotUpdatedDueToNoChange = Configuration was not updated, since the new configuration is equivalent to the current configuration.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
index 67a0445..a5d71dd 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
@@ -1186,7 +1186,6 @@ view_configEdit_addItem = Přidat položku do seznamu
 view_configEdit_confirm_1 = Jste si jisti, že chcete smazat vybrané vlastnosti z množiny?
 view_configEdit_confirm_2 = Jste si jisti, že chcete smazat tento řádek?
 view_configEdit_confirm_3 = Jste si jisti, že chcete smazat [{0}] vybrané [{1}]?
-view_configEdit_description = Popis
 view_configEdit_editRow = Editovat řádek
 view_configEdit_enterPropName = Vložte platné jméno vlastnosti, která má být přidána.
 view_configEdit_error_1 = Konfigurace pro tento zdroj není podporována.
@@ -1204,7 +1203,6 @@ view_configEdit_property = Vlastnost
 view_configEdit_tooltip_1 = Smazat vybrané položky ze seznamu.
 view_configEdit_tooltip_2 = Přidat položku do seznamu.
 view_configEdit_unset = Nenastaveno?
-view_configEdit_value = Hodnota
 view_configEdit_viewRow = Zobrazit řádek
 view_configurationDetails_allPropertiesValid = Všechny vlastnosti konfigurace mají platné hodnoty, takže konfigurace bude uložena.
 view_configurationDetails_configNotUpdatedDueToNoChange = Konfigurace nebyla změněna, protože nová konfigurace je ekvivalentní té stávající.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
index 43c6479..57ffe8d 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
@@ -1051,7 +1051,6 @@ view_configEdit_addItem = Eintrag zur Liste hinzufügen
 ##view_configEdit_confirm_1 = Are you sure you want to delete the selected properties from the set?
 view_configEdit_confirm_2 = Sind Sie sicher dass sie diese Zeile löschen wollen?
 ##view_configEdit_confirm_3 = Are you sure you want to delete the [{0}]  selected [{1}]?
-##view_configEdit_description = Description
 ##view_configEdit_editRow = Edit Configuration Row
 ##view_configEdit_enterPropName = Enter the name of the property to be added.
 ##view_configEdit_error_1 = Configuration is not supported by this Resource.
@@ -1065,11 +1064,10 @@ view_configEdit_msg_1 = Eigentschaft [{0}] zur Menge hinzugefügt
 view_configEdit_msg_3 = [{0} {1}] aus der Liste gelöscht.
 view_configEdit_msg_4 = Eintrag zur Liste hinzugefügt.
 view_configEdit_properties = Eigenschaften
-##view_configEdit_property = Vlastnost
+##view_configEdit_property = Property
 view_configEdit_tooltip_1 = Die ausgewählten Einträge aus der Liste löschen.
 view_configEdit_tooltip_2 = Einen Eintrag zur Liste hinzufügen.
 ##view_configEdit_unset = Unset?
-##view_configEdit_value = Value
 ##view_configurationDetails_allPropertiesValid = All configuration properties have valid values, so the configuration can now be saved.
 view_configurationDetails_error_updateFailure = Konnte die Konfiguration nicht aktualisieren
 view_configurationDetails_messageConcise = Konfiguration aktualisiert - aktuelle Version is {0}
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
index 9380390..0644243 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
@@ -1163,7 +1163,6 @@ view_configEdit_addItem = リストに項目を追加
 view_configEdit_confirm_1 = その集まりから選択されたプロパティを削除してもよろしいですか?
 view_configEdit_confirm_2 = この行を削除してもよろしいですか?
 view_configEdit_confirm_3 = [{1}] が選択された [{0}] を削除してもよろしいですか?
-##view_configEdit_description = Description
 view_configEdit_editRow = 行の編集
 view_configEdit_enterPropName = 追加するプロパティの名前を入力してください
 view_configEdit_error_1 = 構成はこのリソースでサポートされていません
@@ -1177,11 +1176,10 @@ view_configEdit_msg_2 = セットからプロパティを取り除きました
 view_configEdit_msg_3 = [{0} {1}] がリストから削除されました
 view_configEdit_msg_4 = リストに追加されたアイテム
 view_configEdit_properties = プロパティ
-##view_configEdit_property = Vlastnost
+##view_configEdit_property = Property
 view_configEdit_tooltip_1 = リストから選択されたアイテムが削除します
 view_configEdit_tooltip_2 = リストにアイテムを追加します
 ##view_configEdit_unset = Unset?
-##view_configEdit_value = Value
 view_configEdit_viewRow = 行の閲覧
 view_configurationDetails_allPropertiesValid = すべての構成プロパティは正しい値なので、この構成は保存可能です
 view_configurationDetails_configNotUpdatedDueToNoChange = 構成は更新されませんでした。なぜなら新しい構成は現在の構成と同一だからです
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
index b167577..923ace3 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
@@ -1173,7 +1173,6 @@ view_configEdit_addItem = Adicionar Item \u00E0 Lista
 view_configEdit_confirm_1 = Tem certeza de que deseja excluir as propriedades selecionadas?
 view_configEdit_confirm_2 = Tem certeza de que deseja excluir esta linha?
 view_configEdit_confirm_3 = Tem certeza de que deseja excluir [{0}] selecionado [{1}]?
-##view_configEdit_description = Description
 view_configEdit_editRow = Editar Linha de Configura\u00E7\u00E3o
 view_configEdit_enterPropName = Informe o nome da propriedade a ser adicionada.
 view_configEdit_error_1 = Este recurso n\u00E3o suporta Configura\u00E7\u00E3o.
@@ -1187,11 +1186,10 @@ view_configEdit_msg_2 = Propriedades removidas do conjunto.
 view_configEdit_msg_3 = [{0} {1}] removido da lista.
 view_configEdit_msg_4 = Item adicionado \u00E0 lista.
 view_configEdit_properties = Propriedades
-##view_configEdit_property = Vlastnost
+##view_configEdit_property = Property
 view_configEdit_tooltip_1 = Remove os itens selecionados da lista.
 view_configEdit_tooltip_2 = Adiciona um item \u00E0 lista.
 ##view_configEdit_unset = Unset?
-##view_configEdit_value = Value
 view_configEdit_viewRow = Visualizar linha
 view_configurationDetails_allPropertiesValid = Todas as propriedades de configura\u00E7\u00E3o s\u00E3o v\u00E1lidas, portanto a configura\u00E7\u00E3o pode ser salva.
 view_configurationDetails_configNotUpdatedDueToNoChange = A configura��o n�o foi atualizada, pois a nova configura��o � equivalente � atual.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
index faeb808..f34cb82 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
@@ -2454,10 +2454,8 @@ view_admin_downloads_cli_version = Версия CLI
 ##view_alert_details_field_resource_ancestry = Resource Ancestry
 ##view_alert_details_field_watched_resource = Watched Resource
 ##view_bundle_revertWizard_getInfoStep_revertDeployDescFull = [REVERT From] {0} [REVERT To] {1}
-##view_configEdit_description = Description
-##view_configEdit_property = Vlastnost
+##view_configEdit_property = Property
 ##view_configEdit_unset = Unset?
-##view_configEdit_value = Value
 ##view_messageCenter_messageRootCause = Root Cause
 ##view_operationHistoryList_cancelConfirm = Are you sure you want to cancel the selected operations? NOTE: Only those selected operations that are currently "in progress" will be attempted to be canceled.
 ##view_operationHistoryList_cancelFailure = The cancel request failed for the operation with the history ID of [{0}].
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
index 51b4ab1..bafb045 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
@@ -1157,7 +1157,6 @@ view_configEdit_addItem = \u6dfb\u52a0\u6761\u76ee\u81f3\u5217\u8868.
 view_configEdit_confirm_1 = \u786e\u5b9a\u8981\u4ece\u96c6\u5408\u4e2d\u5220\u9664\u6307\u5b9a\u7684\u5c5e\u6027?
 view_configEdit_confirm_2 = \u786e\u5b9a\u8981\u5220\u9664\u8be5\u884c?
 view_configEdit_confirm_3 = \u786e\u5b9a\u8981\u5220\u9664 [{0}]\u9879\u9009\u4e2d\u7684 [{1}]?
-##view_configEdit_description = Description
 view_configEdit_editRow = \u7f16\u8f91\u884c
 view_configEdit_enterPropName = \u8f93\u5165\u8981\u6dfb\u52a0\u7684\u5c5e\u6027\u540d\u79f0.
 view_configEdit_error_1 = \u6b64\u8d44\u6e90\u65e0\u6cd5\u914d\u7f6e.
@@ -1171,11 +1170,10 @@ view_configEdit_msg_2 = \u79fb\u9664\u96c6\u5408\u5185\u6240\u6709\u7684\u5c5e\u
 view_configEdit_msg_3 = \u4ece\u5217\u8868\u4e2d\u5220\u9664[{0} {1}]\u6210\u529f.
 view_configEdit_msg_4 = \u6dfb\u52a0\u6761\u76ee\u81f3\u5217\u8868.
 view_configEdit_properties = \u5c5e\u6027
-##view_configEdit_property = Vlastnost
+##view_configEdit_property = Property
 view_configEdit_tooltip_1 = \u4ece\u5217\u8868\u4e2d\u5220\u9664\u9009\u4e2d\u7684\u6761\u76ee.
 view_configEdit_tooltip_2 = \u6dfb\u52a0\u4e00\u9879\u6761\u76ee\u5230\u5217\u8868.
 ##view_configEdit_unset = Unset?
-##view_configEdit_value = Value
 view_configEdit_viewRow = \u67e5\u770b\u884c
 view_configurationDetails_allPropertiesValid = \u6240\u6709\u7684\u914d\u7f6e\u4fe1\u606f\u5df2\u7ecf\u586b\u5199\u4e86\u6709\u6548\u7684\u503c, \u73b0\u5728\u4fdd\u5b58\u914d\u7f6e.
 view_configurationDetails_configNotUpdatedDueToNoChange = \u7531\u4e8e\u65b0\u65e7\u914d\u7f6e\u4e00\u81f4\uff0c\u6240\u4ee5\u914d\u7f6e\u6ca1\u6709\u66f4\u65b0.


commit f869281799f6a50eea6c5ef0e4b37bbc82070f76
Author: John Mazzitelli <mazz at redhat.com>
Date:   Wed Jun 13 13:52:37 2012 -0400

    extract two test methods that are mysteriously failing in AgentComm2Test - put them in their own separate test classes. These are now passing more regularly on my box. Let's see how jenkins likes this.

diff --git a/modules/enterprise/agent/src/test/java/org/rhq/enterprise/agent/AgentComm2Test.java b/modules/enterprise/agent/src/test/java/org/rhq/enterprise/agent/AgentComm2Test.java
index 1f1160c..add5e82 100644
--- a/modules/enterprise/agent/src/test/java/org/rhq/enterprise/agent/AgentComm2Test.java
+++ b/modules/enterprise/agent/src/test/java/org/rhq/enterprise/agent/AgentComm2Test.java
@@ -285,80 +285,6 @@ public class AgentComm2Test extends AgentCommTestBase {
     }
 
     /**
-     * Sends a secure message from one remote server to another - there will be full authentication including server and
-     * client authentication.
-     *
-     * @throws Exception
-     */
-    @Test(enabled = ENABLE_TESTS)
-    public void testSendSecureMessageFullAuth() throws Exception {
-        // each keystore is the other's truststore
-        Properties props1 = new Properties();
-        setServerLocatorUriProperties(props1, "sslsocket", "127.0.0.1", AGENT2_SERVER_BIND_PORT, null);
-        props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_TRANSPORT, "sslsocket");
-        props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_BIND_PORT, AGENT1_COMM_CONNECTOR_BIND_PORT);
-        props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_SECURITY_TRUSTSTORE_FILE,
-            "target/testdata2/keystore.dat");
-        props1.setProperty(AgentConfigurationConstants.CLIENT_SENDER_SECURITY_TRUSTSTORE_FILE,
-            "target/testdata2/keystore.dat");
-        props1.setProperty(AgentConfigurationConstants.CLIENT_SENDER_SECURITY_SERVER_AUTH_MODE, "true");
-        props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_SECURITY_CLIENT_AUTH_MODE,
-            SSLSocketBuilder.CLIENT_AUTH_MODE_NEED);
-
-        m_agent1Test.setConfigurationOverrides(props1);
-
-        Properties props2 = new Properties();
-        setServerLocatorUriProperties(props2, "sslsocket", "127.0.0.1", AGENT1_SERVER_BIND_PORT, null);
-        props2.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_TRANSPORT, "sslsocket");
-        props2.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_BIND_PORT, AGENT2_COMM_CONNECTOR_BIND_PORT);
-        props2.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_SECURITY_TRUSTSTORE_FILE,
-            "target/testdata/keystore.dat");
-        props2.setProperty(AgentConfigurationConstants.CLIENT_SENDER_SECURITY_TRUSTSTORE_FILE,
-            "target/testdata/keystore.dat");
-        props2.setProperty(AgentConfigurationConstants.CLIENT_SENDER_SECURITY_SERVER_AUTH_MODE, "true");
-        props2.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_SECURITY_CLIENT_AUTH_MODE,
-            SSLSocketBuilder.CLIENT_AUTH_MODE_NEED);
-
-        m_agent2Test.setConfigurationOverrides(props2);
-
-        AgentMain agent1 = m_agent1Test.createAgent(true);
-        AgentMain agent2 = m_agent2Test.createAgent(true);
-
-        assert agent1.getConfiguration().getServerLocatorUri().startsWith("sslsocket:");
-        assert agent2.getConfiguration().getServerLocatorUri().startsWith("sslsocket:");
-
-        assert agent1.getServiceContainer().getConfiguration().getConnectorTransport().equals("sslsocket");
-        assert agent2.getServiceContainer().getConfiguration().getConnectorTransport().equals("sslsocket");
-
-        assert agent1.getConfiguration().isClientSenderSecurityServerAuthMode();
-        assert agent2.getConfiguration().isClientSenderSecurityServerAuthMode();
-
-        assert agent1.getServiceContainer().getConfiguration().getConnectorSecurityClientAuthMode().equals(
-            SSLSocketBuilder.CLIENT_AUTH_MODE_NEED);
-        assert agent2.getServiceContainer().getConfiguration().getConnectorSecurityClientAuthMode().equals(
-            SSLSocketBuilder.CLIENT_AUTH_MODE_NEED);
-
-        IdentifyCommand command = new IdentifyCommand();
-        CommandResponse cmdresponse;
-        IdentifyCommandResponse response;
-
-        cmdresponse = agent1.getClientCommandSender().sendSynch(command);
-        assert cmdresponse.isSuccessful() : "Failed to send command from agent1 to agent2: " + cmdresponse;
-        response = (IdentifyCommandResponse) cmdresponse;
-        assert new InvokerLocator(response.getIdentification().getInvokerLocator()).getPort() == agent2
-            .getServiceContainer().getConfiguration().getConnectorBindPort() : "Didn't get the identify of agent2 - what remoting server did we just communicate with??";
-
-        // JBoss Remoting 2 doesn't seem to like me doing bi-directional messaging within the same VM
-        //      cmdresponse = agent2.getClientCommandSender().sendSynch( command );
-        //      assert cmdresponse.isSuccessful() : "Failed to send command from agent2 to agent1: " + cmdresponse;
-        //      response = (IdentifyCommandResponse) cmdresponse;
-        //      assert new InvokerLocator( response.getIdentification().getInvokerLocator() ).getPort()
-        //             == agent1.getServiceContainer().getConfiguration().getConnectorBindPort() : "Didn't get the identity of agent1 - what remoting server did we just communicate with??";
-
-        return;
-    }
-
-    /**
      * Prepares to send a secure message from one remote server to another - there will be full authentication including
      * server and client authentication but the keystore passwords will be invalid thus causing errors.
      *
@@ -417,80 +343,6 @@ public class AgentComm2Test extends AgentCommTestBase {
     }
 
     /**
-     * Sends a secure message from one remote server to another where both servers want client authentication and both
-     * clients have truststores with the appropriate keys (therefore, the clients should be able to successfully send).
-     *
-     * @throws Exception
-     */
-    @Test(enabled = ENABLE_TESTS)
-    public void testSendSecureMessageClientAuthWantWithTruststore() throws Exception {
-        // each keystore is the other's truststore
-        Properties props1 = new Properties();
-        setServerLocatorUriProperties(props1, "sslsocket", "127.0.0.1", AGENT2_SERVER_BIND_PORT, null);
-        props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_TRANSPORT, "sslsocket");
-        props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_BIND_PORT, AGENT1_COMM_CONNECTOR_BIND_PORT);
-        props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_SECURITY_TRUSTSTORE_FILE,
-            "target/testdata2/keystore.dat");
-        props1.setProperty(AgentConfigurationConstants.CLIENT_SENDER_SECURITY_TRUSTSTORE_FILE,
-            "target/testdata2/keystore.dat");
-        props1.setProperty(AgentConfigurationConstants.CLIENT_SENDER_SECURITY_SERVER_AUTH_MODE, "true");
-        props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_SECURITY_CLIENT_AUTH_MODE,
-            SSLSocketBuilder.CLIENT_AUTH_MODE_WANT);
-
-        m_agent1Test.setConfigurationOverrides(props1);
-
-        Properties props2 = new Properties();
-        setServerLocatorUriProperties(props2, "sslsocket", "127.0.0.1", AGENT1_SERVER_BIND_PORT, null);
-        props2.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_TRANSPORT, "sslsocket");
-        props2.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_BIND_PORT, AGENT2_COMM_CONNECTOR_BIND_PORT);
-        props2.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_SECURITY_TRUSTSTORE_FILE,
-            "target/testdata/keystore.dat");
-        props2.setProperty(AgentConfigurationConstants.CLIENT_SENDER_SECURITY_TRUSTSTORE_FILE,
-            "target/testdata/keystore.dat");
-        props2.setProperty(AgentConfigurationConstants.CLIENT_SENDER_SECURITY_SERVER_AUTH_MODE, "true");
-        props2.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_SECURITY_CLIENT_AUTH_MODE,
-            SSLSocketBuilder.CLIENT_AUTH_MODE_WANT);
-
-        m_agent2Test.setConfigurationOverrides(props2);
-
-        AgentMain agent1 = m_agent1Test.createAgent(true);
-        AgentMain agent2 = m_agent2Test.createAgent(true);
-
-        assert agent1.getConfiguration().getServerLocatorUri().startsWith("sslsocket:");
-        assert agent2.getConfiguration().getServerLocatorUri().startsWith("sslsocket:");
-
-        assert agent1.getServiceContainer().getConfiguration().getConnectorTransport().equals("sslsocket");
-        assert agent2.getServiceContainer().getConfiguration().getConnectorTransport().equals("sslsocket");
-
-        assert agent1.getConfiguration().isClientSenderSecurityServerAuthMode();
-        assert agent2.getConfiguration().isClientSenderSecurityServerAuthMode();
-
-        assert agent1.getServiceContainer().getConfiguration().getConnectorSecurityClientAuthMode().equals(
-            SSLSocketBuilder.CLIENT_AUTH_MODE_WANT);
-        assert agent2.getServiceContainer().getConfiguration().getConnectorSecurityClientAuthMode().equals(
-            SSLSocketBuilder.CLIENT_AUTH_MODE_WANT);
-
-        IdentifyCommand command = new IdentifyCommand();
-        CommandResponse cmdresponse;
-        IdentifyCommandResponse response;
-
-        cmdresponse = agent1.getClientCommandSender().sendSynch(command);
-        assert cmdresponse.isSuccessful() : "Failed to send command from agent1 to agent2: " + cmdresponse;
-        response = (IdentifyCommandResponse) cmdresponse;
-        assert new InvokerLocator(response.getIdentification().getInvokerLocator()).getPort() == agent2
-            .getServiceContainer().getConfiguration().getConnectorBindPort() : "Didn't get the identify of agent2 - what remoting server did we just communicate with??";
-
-        // JBoss Remoting 2.2.SP4 doesn't seem to like me doing bi-directional messaging within the same VM
-        //      cmdresponse = agent2.getClientCommandSender().sendSynch( command );
-        //      assert cmdresponse.isSuccessful() : "Failed to send command from agent2 to agent1: " + cmdresponse;
-        //      response = (IdentifyCommandResponse) cmdresponse;
-        //      assert new InvokerLocator( response.getIdentification().getInvokerLocator() ).getPort()
-        //             == agent1.getServiceContainer().getConfiguration().getConnectorBindPort() : "Didn't get the identity of agent1 - what remoting server did we just communicate with??";
-
-        return;
-    }
-
-    /**
      * Sends a secure message from one remote server to another with the secure protocol being different for each remote
      * server (cool, huh?) - there will be no authentication, just encryption.
      *
diff --git a/modules/enterprise/agent/src/test/java/org/rhq/enterprise/agent/AgentComm5Test.java b/modules/enterprise/agent/src/test/java/org/rhq/enterprise/agent/AgentComm5Test.java
new file mode 100644
index 0000000..14585da
--- /dev/null
+++ b/modules/enterprise/agent/src/test/java/org/rhq/enterprise/agent/AgentComm5Test.java
@@ -0,0 +1,112 @@
+/*
+ * 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.agent;
+
+import java.util.Properties;
+
+import org.testng.annotations.Test;
+
+import org.jboss.remoting.InvokerLocator;
+import org.jboss.remoting.security.SSLSocketBuilder;
+
+import org.rhq.enterprise.communications.ServiceContainerConfigurationConstants;
+import org.rhq.enterprise.communications.command.CommandResponse;
+import org.rhq.enterprise.communications.command.impl.identify.IdentifyCommand;
+import org.rhq.enterprise.communications.command.impl.identify.IdentifyCommandResponse;
+
+/**
+ * This tests the communications layer in the agent.
+ *
+ * @author John Mazzitelli
+ */
+ at Test(groups = "agent.comm")
+public class AgentComm5Test extends AgentCommTestBase {
+    /**
+     * Sends a secure message from one remote server to another where both servers want client authentication and both
+     * clients have truststores with the appropriate keys (therefore, the clients should be able to successfully send).
+     *
+     * @throws Exception
+     */
+    public void testSendSecureMessageClientAuthWantWithTruststore() throws Exception {
+        // each keystore is the other's truststore
+        Properties props1 = new Properties();
+        setServerLocatorUriProperties(props1, "sslsocket", "127.0.0.1", AGENT2_SERVER_BIND_PORT, null);
+        props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_TRANSPORT, "sslsocket");
+        props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_BIND_PORT, AGENT1_COMM_CONNECTOR_BIND_PORT);
+        props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_SECURITY_TRUSTSTORE_FILE,
+            "target/testdata2/keystore.dat");
+        props1.setProperty(AgentConfigurationConstants.CLIENT_SENDER_SECURITY_TRUSTSTORE_FILE,
+            "target/testdata2/keystore.dat");
+        props1.setProperty(AgentConfigurationConstants.CLIENT_SENDER_SECURITY_SERVER_AUTH_MODE, "true");
+        props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_SECURITY_CLIENT_AUTH_MODE,
+            SSLSocketBuilder.CLIENT_AUTH_MODE_WANT);
+
+        m_agent1Test.setConfigurationOverrides(props1);
+
+        Properties props2 = new Properties();
+        setServerLocatorUriProperties(props2, "sslsocket", "127.0.0.1", AGENT1_SERVER_BIND_PORT, null);
+        props2.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_TRANSPORT, "sslsocket");
+        props2.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_BIND_PORT, AGENT2_COMM_CONNECTOR_BIND_PORT);
+        props2.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_SECURITY_TRUSTSTORE_FILE,
+            "target/testdata/keystore.dat");
+        props2.setProperty(AgentConfigurationConstants.CLIENT_SENDER_SECURITY_TRUSTSTORE_FILE,
+            "target/testdata/keystore.dat");
+        props2.setProperty(AgentConfigurationConstants.CLIENT_SENDER_SECURITY_SERVER_AUTH_MODE, "true");
+        props2.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_SECURITY_CLIENT_AUTH_MODE,
+            SSLSocketBuilder.CLIENT_AUTH_MODE_WANT);
+
+        m_agent2Test.setConfigurationOverrides(props2);
+
+        AgentMain agent1 = m_agent1Test.createAgent(true);
+        AgentMain agent2 = m_agent2Test.createAgent(true);
+
+        assert agent1.getConfiguration().getServerLocatorUri().startsWith("sslsocket:");
+        assert agent2.getConfiguration().getServerLocatorUri().startsWith("sslsocket:");
+
+        assert agent1.getServiceContainer().getConfiguration().getConnectorTransport().equals("sslsocket");
+        assert agent2.getServiceContainer().getConfiguration().getConnectorTransport().equals("sslsocket");
+
+        assert agent1.getConfiguration().isClientSenderSecurityServerAuthMode();
+        assert agent2.getConfiguration().isClientSenderSecurityServerAuthMode();
+
+        assert agent1.getServiceContainer().getConfiguration().getConnectorSecurityClientAuthMode().equals(
+            SSLSocketBuilder.CLIENT_AUTH_MODE_WANT);
+        assert agent2.getServiceContainer().getConfiguration().getConnectorSecurityClientAuthMode().equals(
+            SSLSocketBuilder.CLIENT_AUTH_MODE_WANT);
+
+        IdentifyCommand command = new IdentifyCommand();
+        CommandResponse cmdresponse;
+        IdentifyCommandResponse response;
+
+        cmdresponse = agent1.getClientCommandSender().sendSynch(command);
+        assert cmdresponse.isSuccessful() : "Failed to send command from agent1 to agent2: " + cmdresponse;
+        response = (IdentifyCommandResponse) cmdresponse;
+        assert new InvokerLocator(response.getIdentification().getInvokerLocator()).getPort() == agent2
+            .getServiceContainer().getConfiguration().getConnectorBindPort() : "Didn't get the identify of agent2 - what remoting server did we just communicate with??";
+
+        // JBoss Remoting 2.2.SP4 doesn't seem to like me doing bi-directional messaging within the same VM
+        //      cmdresponse = agent2.getClientCommandSender().sendSynch( command );
+        //      assert cmdresponse.isSuccessful() : "Failed to send command from agent2 to agent1: " + cmdresponse;
+        //      response = (IdentifyCommandResponse) cmdresponse;
+        //      assert new InvokerLocator( response.getIdentification().getInvokerLocator() ).getPort()
+        //             == agent1.getServiceContainer().getConfiguration().getConnectorBindPort() : "Didn't get the identity of agent1 - what remoting server did we just communicate with??";
+
+        return;
+    }
+}
\ No newline at end of file
diff --git a/modules/enterprise/agent/src/test/java/org/rhq/enterprise/agent/AgentComm6Test.java b/modules/enterprise/agent/src/test/java/org/rhq/enterprise/agent/AgentComm6Test.java
new file mode 100644
index 0000000..3516c38
--- /dev/null
+++ b/modules/enterprise/agent/src/test/java/org/rhq/enterprise/agent/AgentComm6Test.java
@@ -0,0 +1,112 @@
+/*
+ * 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.agent;
+
+import java.util.Properties;
+
+import org.testng.annotations.Test;
+
+import org.jboss.remoting.InvokerLocator;
+import org.jboss.remoting.security.SSLSocketBuilder;
+
+import org.rhq.enterprise.communications.ServiceContainerConfigurationConstants;
+import org.rhq.enterprise.communications.command.CommandResponse;
+import org.rhq.enterprise.communications.command.impl.identify.IdentifyCommand;
+import org.rhq.enterprise.communications.command.impl.identify.IdentifyCommandResponse;
+
+/**
+ * This tests the communications layer in the agent.
+ *
+ * @author John Mazzitelli
+ */
+ at Test(groups = "agent.comm")
+public class AgentComm6Test extends AgentCommTestBase {
+    /**
+     * Sends a secure message from one remote server to another - there will be full authentication including server and
+     * client authentication.
+     *
+     * @throws Exception
+     */
+    public void testSendSecureMessageFullAuth() throws Exception {
+        // each keystore is the other's truststore
+        Properties props1 = new Properties();
+        setServerLocatorUriProperties(props1, "sslsocket", "127.0.0.1", AGENT2_SERVER_BIND_PORT, null);
+        props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_TRANSPORT, "sslsocket");
+        props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_BIND_PORT, AGENT1_COMM_CONNECTOR_BIND_PORT);
+        props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_SECURITY_TRUSTSTORE_FILE,
+            "target/testdata2/keystore.dat");
+        props1.setProperty(AgentConfigurationConstants.CLIENT_SENDER_SECURITY_TRUSTSTORE_FILE,
+            "target/testdata2/keystore.dat");
+        props1.setProperty(AgentConfigurationConstants.CLIENT_SENDER_SECURITY_SERVER_AUTH_MODE, "true");
+        props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_SECURITY_CLIENT_AUTH_MODE,
+            SSLSocketBuilder.CLIENT_AUTH_MODE_NEED);
+
+        m_agent1Test.setConfigurationOverrides(props1);
+
+        Properties props2 = new Properties();
+        setServerLocatorUriProperties(props2, "sslsocket", "127.0.0.1", AGENT1_SERVER_BIND_PORT, null);
+        props2.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_TRANSPORT, "sslsocket");
+        props2.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_BIND_PORT, AGENT2_COMM_CONNECTOR_BIND_PORT);
+        props2.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_SECURITY_TRUSTSTORE_FILE,
+            "target/testdata/keystore.dat");
+        props2.setProperty(AgentConfigurationConstants.CLIENT_SENDER_SECURITY_TRUSTSTORE_FILE,
+            "target/testdata/keystore.dat");
+        props2.setProperty(AgentConfigurationConstants.CLIENT_SENDER_SECURITY_SERVER_AUTH_MODE, "true");
+        props2.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_SECURITY_CLIENT_AUTH_MODE,
+            SSLSocketBuilder.CLIENT_AUTH_MODE_NEED);
+
+        m_agent2Test.setConfigurationOverrides(props2);
+
+        AgentMain agent1 = m_agent1Test.createAgent(true);
+        AgentMain agent2 = m_agent2Test.createAgent(true);
+
+        assert agent1.getConfiguration().getServerLocatorUri().startsWith("sslsocket:");
+        assert agent2.getConfiguration().getServerLocatorUri().startsWith("sslsocket:");
+
+        assert agent1.getServiceContainer().getConfiguration().getConnectorTransport().equals("sslsocket");
+        assert agent2.getServiceContainer().getConfiguration().getConnectorTransport().equals("sslsocket");
+
+        assert agent1.getConfiguration().isClientSenderSecurityServerAuthMode();
+        assert agent2.getConfiguration().isClientSenderSecurityServerAuthMode();
+
+        assert agent1.getServiceContainer().getConfiguration().getConnectorSecurityClientAuthMode().equals(
+            SSLSocketBuilder.CLIENT_AUTH_MODE_NEED);
+        assert agent2.getServiceContainer().getConfiguration().getConnectorSecurityClientAuthMode().equals(
+            SSLSocketBuilder.CLIENT_AUTH_MODE_NEED);
+
+        IdentifyCommand command = new IdentifyCommand();
+        CommandResponse cmdresponse;
+        IdentifyCommandResponse response;
+
+        cmdresponse = agent1.getClientCommandSender().sendSynch(command);
+        assert cmdresponse.isSuccessful() : "Failed to send command from agent1 to agent2: " + cmdresponse;
+        response = (IdentifyCommandResponse) cmdresponse;
+        assert new InvokerLocator(response.getIdentification().getInvokerLocator()).getPort() == agent2
+            .getServiceContainer().getConfiguration().getConnectorBindPort() : "Didn't get the identify of agent2 - what remoting server did we just communicate with??";
+
+        // JBoss Remoting 2 doesn't seem to like me doing bi-directional messaging within the same VM
+        //      cmdresponse = agent2.getClientCommandSender().sendSynch( command );
+        //      assert cmdresponse.isSuccessful() : "Failed to send command from agent2 to agent1: " + cmdresponse;
+        //      response = (IdentifyCommandResponse) cmdresponse;
+        //      assert new InvokerLocator( response.getIdentification().getInvokerLocator() ).getPort()
+        //             == agent1.getServiceContainer().getConfiguration().getConnectorBindPort() : "Didn't get the identity of agent1 - what remoting server did we just communicate with??";
+
+        return;
+    }
+}
\ No newline at end of file


commit f2ad6f8e10a004d3eae44fd762e118a65bd3ea47
Author: Stefan Negrea <snegrea at redhat.com>
Date:   Wed Jun 13 12:37:31 2012 -0500

    [BZ 831757] Mark memory-pool-names list property as read-only.

diff --git a/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml
index 19bccaa..4e3f4da 100644
--- a/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml
@@ -7011,7 +7011,7 @@
         <metric property="valid" dataType="trait" description="Whether this this memory manager is valid in the Java virtual machine."/>
 
         <resource-configuration>
-          <c:list-property name="memory-pool-names" required="true" description="The name of memory pools that this garbage collector manages.">
+          <c:list-property name="memory-pool-names" required="true" readOnly="true" description="The name of memory pools that this garbage collector manages.">
             <c:simple-property name="memory-pool-names" readOnly="true"/>
           </c:list-property>
         </resource-configuration>


commit 4fcfaf0e28be1a579a6de16ab78321ca8b8fb1f2
Author: Heiko W. Rupp <hwr at redhat.com>
Date:   Wed Jun 13 15:18:08 2012 +0200

    BZ 831513 Fill some defaults, as otherwise destination creation fails

diff --git a/modules/plugins/jboss-as-5/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/jboss-as-5/src/main/resources/META-INF/rhq-plugin.xml
index 15a55d2..92370cb 100644
--- a/modules/plugins/jboss-as-5/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/jboss-as-5/src/main/resources/META-INF/rhq-plugin.xml
@@ -223,7 +223,7 @@
     <c:map-property name="metadata" required="false" description="Metadata properties.">
         <c:simple-property required="false" name="typeMapping">
             <c:description>
-                The name of the corresponding type-mapping in conf/standardjbosscmp-jdbc.xml. The type mappings provided by default: DB2, InformixDB, MaxDB, mySQL, Oracle9i, PointBase, InterBase, Mimer SQL, McKoi, SapDB, DB2/400, SOLID, Hypersonic SQL, FirstSQL/J, MS SQLSERVER2000, MS SQLSERVER, Cloudscape, Derby, Firebird, PostgreSQL 8.0, PostgreSQL, Sybase, Ingres. 
+                The name of the corresponding type-mapping in conf/standardjbosscmp-jdbc.xml. The type mappings provided by default: DB2, InformixDB, MaxDB, mySQL, Oracle9i, PointBase, InterBase, Mimer SQL, McKoi, SapDB, DB2/400, SOLID, Hypersonic SQL, FirstSQL/J, MS SQLSERVER2000, MS SQLSERVER, Cloudscape, Derby, Firebird, PostgreSQL 8.0, PostgreSQL, Sybase, Ingres.
                 Note, there may be custom type mappings defined in addition to these predefined mappings.
             </c:description>
         </c:simple-property>
@@ -286,7 +286,7 @@
 
     <c:simple-property name="type-mapping" displayName="Type Mapping" required="false">
         <c:description>
-            The name of the corresponding type-mapping in conf/standardjbosscmp-jdbc.xml. The type mappings provided by default: DB2, InformixDB, MaxDB, mySQL, Oracle9i, PointBase, InterBase, Mimer SQL, McKoi, SapDB, DB2/400, SOLID, Hypersonic SQL, FirstSQL/J, MS SQLSERVER2000, MS SQLSERVER, Cloudscape, Derby, Firebird, PostgreSQL 8.0, PostgreSQL, Sybase, Ingres. 
+            The name of the corresponding type-mapping in conf/standardjbosscmp-jdbc.xml. The type mappings provided by default: DB2, InformixDB, MaxDB, mySQL, Oracle9i, PointBase, InterBase, Mimer SQL, McKoi, SapDB, DB2/400, SOLID, Hypersonic SQL, FirstSQL/J, MS SQLSERVER2000, MS SQLSERVER, Cloudscape, Derby, Firebird, PostgreSQL 8.0, PostgreSQL, Sybase, Ingres.
                 Note, there may be custom type mappings defined in addition to these predefined mappings.
         </c:description>
     </c:simple-property>
@@ -561,11 +561,11 @@
             category="performance"/>
 
     <metric property="connectionCreatedCount" measurementType="dynamic" displayType="detail"
-            displayName="Connection Created Count" 
+            displayName="Connection Created Count"
             dataType="measurement" category="performance"/>
 
     <metric property="connectionDestroyedCount" measurementType="dynamic" displayType="detail"
-            displayName="Connection Destroyed Count" 
+            displayName="Connection Destroyed Count"
             dataType="measurement" category="performance"/>
 
     <metric property="inUseConnectionCount" measurementType="dynamic" displayType="detail"
@@ -1470,7 +1470,7 @@
           <c:simple-property name="isSameRM-override-value" default="false" />
           <c:simple-property name="xa-datasource-class" default="oracle.jdbc.xa.client.OracleXADataSource" />
           <c:simple-property name="exception-sorter-class-name" default="org.jboss.resource.adapter.jdbc.vendor.OracleExceptionSorter" />
-          <!-- Oracle's XA datasource cannot reuse a connection outside a transaction once enlisted in a global transaction 
+          <!-- Oracle's XA datasource cannot reuse a connection outside a transaction once enlisted in a global transaction
             and vice-versa. -->
           <c:simple-property name="no-tx-separate-pools" default="true" />
           <c:simple-property name="use-try-lock" default="60000" />
@@ -1852,7 +1852,7 @@
             </c:constraint>
           </c:simple-property>
 
-          <c:simple-property required="false" name="DLQ">
+          <c:simple-property required="false" name="DLQ" default="jboss.messaging.destination:service=Queue,name=DLQ">
             <c:description>
               The JMX ObjectName of the dead letter queue (DLQ) for this queue (e.g.
               "jboss.messaging.destination:service=Queue,name=PrivateDLQ") - overrides the default DLQ on the
@@ -1863,7 +1863,7 @@
             </c:constraint>
           </c:simple-property>
 
-          <c:simple-property required="false" name="expiryQueue">
+          <c:simple-property required="false" name="expiryQueue" default="jboss.messaging.destination:service=Queue,name=ExpiryQueue">
             <c:description>
               The JMX ObjectName of the expiry queue for this queue (e.g.
               "jboss.messaging.destination:service=Queue,name=PrivateExpiryQueue") - overrides the default
@@ -1874,7 +1874,7 @@
             </c:constraint>
           </c:simple-property>
 
-          <c:simple-property required="false" name="serverPeer">
+          <c:simple-property required="false" name="serverPeer" default="jboss.messaging:service=ServerPeer" >
             <c:description>
               The JMX ObjectName of the server peer this queue was deployed on (e.g.
               "jboss.messaging:service=ServerPeer"). Updates to this property will not go into effect until
@@ -2169,7 +2169,7 @@
             </c:constraint>
           </c:simple-property>
 
-          <c:simple-property required="false" name="DLQ">
+          <c:simple-property required="false" name="DLQ" default="jboss.messaging.destination:service=Queue,name=DLQ">
             <c:description>
               The JMX ObjectName of the dead letter queue (DLQ) for this topic (e.g.
               "jboss.messaging.destination:service=Queue,name=PrivateDLQ") - overrides the default DLQ on the
@@ -2180,7 +2180,7 @@
             </c:constraint>
           </c:simple-property>
 
-          <c:simple-property required="false" name="expiryQueue">
+          <c:simple-property required="false" name="expiryQueue" default="jboss.messaging.destination:service=Queue,name=ExpiryQueue">
             <c:description>
               The JMX ObjectName of the expiry queue for this topic (e.g.
               "jboss.messaging.destination:service=Queue,name=PrivateExpiryQueue") - overrides the default
@@ -2191,7 +2191,7 @@
             </c:constraint>
           </c:simple-property>
 
-          <c:simple-property required="false" name="serverPeer">
+          <c:simple-property required="false" name="serverPeer" default="jboss.messaging:service=ServerPeer">
             <c:description>
               The JMX ObjectName of the server peer this topic was deployed on (e.g.
               "jboss.messaging:service=ServerPeer"). Updates to this property will not go into effect until
@@ -2808,13 +2808,13 @@
 The name of the binding set the Service Binding Manager should use when resolving bindings.
 Note to JBoss ON or Jopr users (does not apply to JBoss AS admin console):
 CHANGING THIS PROPERTY IS POTENTIALLY DANGEROUS because if there are any port conflicts
-on the machine the Application Server is running on, the server will not start up again and 
+on the machine the Application Server is running on, the server will not start up again and
 it will not be possible to monitor it.
 To be able to monitor the server again after the restart you have to update the "Naming Provider Url"
 in the "Connection" subtab in the "Inventory" of the Application Server to the value
 of "jboss:service=Naming:Port" binding of the active binding set.
 I.e. if the "jboss:service=Naming:Port" binding of the active binding set has the port set to 4099 and hostname to 127.0.0.1,
-you have to set the "Naming Provider Url" to jnp://127.0.0.1:4099.                    
+you have to set the "Naming Provider Url" to jnp://127.0.0.1:4099.
                     ]]></c:description>
         </c:simple-property>
         <c:list-property name="standardBindings" description="The standard port bindings inherited by the binding sets.">


commit 96e8f5ac7da14b9df928c80940d1ffd40967b894
Author: John Sanda <jsanda at redhat.com>
Date:   Tue Jun 12 23:52:38 2012 -0400

    [BZ 823691] removing debug code

diff --git a/modules/enterprise/agent/src/test/java/org/rhq/enterprise/agent/AgentCommTestBase.java b/modules/enterprise/agent/src/test/java/org/rhq/enterprise/agent/AgentCommTestBase.java
index 647bbb4..bb9a789 100644
--- a/modules/enterprise/agent/src/test/java/org/rhq/enterprise/agent/AgentCommTestBase.java
+++ b/modules/enterprise/agent/src/test/java/org/rhq/enterprise/agent/AgentCommTestBase.java
@@ -30,7 +30,6 @@ import org.testng.ITestResult;
 import org.testng.annotations.AfterClass;
 import org.testng.annotations.AfterMethod;
 import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Listeners;
 
 import org.rhq.enterprise.communications.ServiceContainerConfiguration;
 import org.rhq.enterprise.communications.ServiceContainerConfigurationConstants;
@@ -41,7 +40,6 @@ import org.rhq.enterprise.communications.util.SecurityUtil;
  *
  * @author John Mazzitelli
  */
- at Listeners(AgentCommTestBase.class)
 public class AgentCommTestBase implements IInvokedMethodListener {
     protected static final int LARGE_STRING_SIZE = 100000;
     protected static final String LARGE_STRING;
@@ -108,8 +106,6 @@ public class AgentCommTestBase implements IInvokedMethodListener {
         // make sure we create keystore files - some tests needs both existing at the same time as soon as they begin
         File keystore_file1 = new File("target/testdata/keystore.dat");
 
-        //Assert.assertFalse(keystore_file1 + " should not exist", keystore_file1.exists());
-        keystore_file1.delete();
         if (!keystore_file1.exists()) {
             keystore_file1.getParentFile().mkdirs();
             m_agent1Test.createAgent(false);
@@ -123,8 +119,6 @@ public class AgentCommTestBase implements IInvokedMethodListener {
         }
 
         File keystore_file2 = new File("target/testdata2/keystore.dat");
-        //Assert.assertFalse(keystore_file2 + " should not exist", keystore_file2.exists());
-        keystore_file2.delete();
         if (!keystore_file2.exists()) {
             keystore_file2.getParentFile().mkdirs();
             m_agent2Test.createAgent(false);
@@ -142,7 +136,7 @@ public class AgentCommTestBase implements IInvokedMethodListener {
      * Ensures any agent that was started is shutdown and all configuration is cleared so as not to retain overridden
      * preferences left over by the tests.
      */
-    @AfterMethod(alwaysRun = true)
+    @AfterMethod
     public void tearDown() {
         if (m_agent1Test != null) {
             AgentMain agent = m_agent1Test.getAgent();


commit 85b39a87c4df4c5669a05ee421a2e107f4e495c9
Author: Stefan Negrea <snegrea at redhat.com>
Date:   Tue Jun 12 18:10:43 2012 -0500

    Added ignored operations and also pass in a configuration even if no params are available for the operation (to mach real application behaviour).

diff --git a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/ResourcesStandaloneServerTest.java b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/ResourcesStandaloneServerTest.java
index cc03979..4eb3519 100644
--- a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/ResourcesStandaloneServerTest.java
+++ b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/ResourcesStandaloneServerTest.java
@@ -71,7 +71,7 @@ public class ResourcesStandaloneServerTest extends AbstractJBossAS7PluginTest  {
             StandaloneServerComponentTest.RESOURCE_KEY);
         inventoryManager.activateResource(server, platformContainer, false);
 
-        Thread.sleep(100 * 1000L);
+        Thread.sleep(20 * 1000L);
     }
 
 
@@ -136,9 +136,13 @@ public class ResourcesStandaloneServerTest extends AbstractJBossAS7PluginTest  {
 
     @Test(priority = 11)
     public void executeNoArgOperations() throws Exception {
-        final List<String> ignoredSubsystems = new ArrayList<String>();
+        List<String> ignoredSubsystems = new ArrayList<String>();
         ignoredSubsystems.add("ModCluster Standalone Service");
 
+        List<String> ignoredOperations = new ArrayList<String>();
+        ignoredOperations.add("subsystem:force-failover");
+        ignoredOperations.add("enable");
+
         Resource platform = this.pluginContainer.getInventoryManager().getPlatform();
         Resource server = getResourceByTypeAndKey(platform, StandaloneServerComponentTest.RESOURCE_TYPE,
             StandaloneServerComponentTest.RESOURCE_KEY);
@@ -161,9 +165,12 @@ public class ResourcesStandaloneServerTest extends AbstractJBossAS7PluginTest  {
             }
 
             for (OperationDefinition operationUnderTest : resourceUnderTest.getResourceType().getOperationDefinitions()) {
-                if (operationUnderTest.getParametersConfigurationDefinition() == null
-                    || operationUnderTest.getParametersConfigurationDefinition().getPropertyDefinitions().isEmpty()) {
-                    this.invokeOperationAndAssertSuccess(resourceUnderTest, operationUnderTest.getName(), null);
+                if (!ignoredOperations.contains(operationUnderTest.getName())) {
+                    if (operationUnderTest.getParametersConfigurationDefinition() == null
+                        || operationUnderTest.getParametersConfigurationDefinition().getPropertyDefinitions().isEmpty()) {
+                        this.invokeOperationAndAssertSuccess(resourceUnderTest, operationUnderTest.getName(),
+                            new Configuration());
+                    }
                 }
             }
         }


commit 66f46cb857466d948b548675dcd73f42ad307b26
Author: John Mazzitelli <mazz at redhat.com>
Date:   Tue Jun 12 18:51:12 2012 -0400

    [BZ 831297] canceled operations that actually were able to be interrupted and canceled will now show a status of canceled with the canceled icon in the history view

diff --git a/modules/common/jboss-as/src/main/java/com/jboss/jbossnetwork/product/jbpm/handlers/ControlActionHandler.java b/modules/common/jboss-as/src/main/java/com/jboss/jbossnetwork/product/jbpm/handlers/ControlActionHandler.java
index 577eea8..708beba 100644
--- a/modules/common/jboss-as/src/main/java/com/jboss/jbossnetwork/product/jbpm/handlers/ControlActionHandler.java
+++ b/modules/common/jboss-as/src/main/java/com/jboss/jbossnetwork/product/jbpm/handlers/ControlActionHandler.java
@@ -23,6 +23,7 @@
 package com.jboss.jbossnetwork.product.jbpm.handlers;
 
 import org.jbpm.graph.exe.ExecutionContext;
+
 import org.rhq.core.pluginapi.operation.OperationServicesResult;
 import org.rhq.core.pluginapi.operation.OperationServicesResultCode;
 
@@ -106,6 +107,11 @@ public class ControlActionHandler extends BaseHandler {
                 break;
             }
 
+        case CANCELED: {
+            error(executionContext, operationError, "Canceled [" + actionName + "] action on server.", TRANSITION_ERROR);
+            break;
+        }
+
             case TIMED_OUT: {
                 error(executionContext, operationError, "Action [" + actionName +
                     "] timed out while executing on server.", TRANSITION_ERROR);
diff --git a/modules/core/client-api/src/main/java/org/rhq/core/clientapi/server/operation/OperationServerService.java b/modules/core/client-api/src/main/java/org/rhq/core/clientapi/server/operation/OperationServerService.java
index e3ce084..f1e76cb 100644
--- a/modules/core/client-api/src/main/java/org/rhq/core/clientapi/server/operation/OperationServerService.java
+++ b/modules/core/client-api/src/main/java/org/rhq/core/clientapi/server/operation/OperationServerService.java
@@ -56,6 +56,20 @@ public interface OperationServerService {
         long completionTime);
 
     /**
+     * Called by the agent when a server-scheduled operation was canceled.
+     *
+     * @param jobId          the server-assigned unique job id for this operation
+     * @param result         a result object that can be used to capture any information available
+     *                       up to the point of cancelation.
+     * @param error          an exception describing the cancelation
+     * @param invocationTime the time at which the agent was asked to invoke the operation (epoch millis)
+     * @param canceledTime   the time at which the operation was canceled (epoch millis)
+     */
+    @Asynchronous(guaranteedDelivery = true)
+    void operationCanceled(String jobId, Configuration result, ExceptionPackage error, long invocationTime,
+        long canceledTime);
+
+    /**
      * Called by the agent when a server-scheduled operation times out.
      *
      * @param jobId          the server-assigned unique job id for this operation
diff --git a/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/operation/OperationServicesResultCode.java b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/operation/OperationServicesResultCode.java
index fff2ae8..608b0e2 100644
--- a/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/operation/OperationServicesResultCode.java
+++ b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/operation/OperationServicesResultCode.java
@@ -28,5 +28,5 @@ package org.rhq.core.pluginapi.operation;
  * @author Jason Dobies
  */
 public enum OperationServicesResultCode {
-    SUCCESS, FAILURE, TIMED_OUT
+    SUCCESS, FAILURE, TIMED_OUT, CANCELED
 }
\ No newline at end of file
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/StandaloneContainer.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/StandaloneContainer.java
index 7008fac..730effc 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/StandaloneContainer.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/StandaloneContainer.java
@@ -347,6 +347,8 @@ public class StandaloneContainer {
             System.err.println("Failure executing the operation: \n" + res.getErrorStackTrace());
         } else if (res.getResultCode() == OperationServicesResultCode.TIMED_OUT) {
             System.err.println("Operation timed out ");
+        } else if (res.getResultCode() == OperationServicesResultCode.CANCELED) {
+            System.err.println("Operation was canceled ");
         } else {
             Configuration result = res.getComplexResults();
             if (result == null)
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/operation/OperationInvocation.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/operation/OperationInvocation.java
index 5e772a1..59bc941 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/operation/OperationInvocation.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/operation/OperationInvocation.java
@@ -302,7 +302,13 @@ public class OperationInvocation implements Runnable {
                     }
 
                     try {
-                        operationServerService.operationFailed(jobId, null, errorResults, invocationTime, finishedTime);
+                        if (status.contains(Status.CANCELED)) {
+                            operationServerService.operationCanceled(jobId, null, errorResults, invocationTime,
+                                finishedTime);
+                        } else {
+                            operationServerService.operationFailed(jobId, null, errorResults, invocationTime,
+                                finishedTime);
+                        }
                     } catch (Throwable t) {
                         log.error("Failed to send operation failed message to server. resource=[" + resourceId
                             + "], operation=[" + operationName + "], jobId=[" + jobId + "], operation-error=["
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/operation/OperationServicesAdapter.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/operation/OperationServicesAdapter.java
index 5828a04..8048a93 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/operation/OperationServicesAdapter.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/operation/OperationServicesAdapter.java
@@ -132,6 +132,19 @@ public class OperationServicesAdapter implements OperationServices, OperationSer
         }
     }
 
+    public void operationCanceled(String jobId, Configuration result, ExceptionPackage error, long invocationTime,
+        long canceledTime) {
+        OperationServicesResult operationServicesResult = new OperationServicesResult(
+            OperationServicesResultCode.CANCELED);
+        operationServicesResult.setComplexResults(result);
+        operationServicesResult.setErrorStackTrace(error.getStackTraceString());
+
+        completedJobs.put(jobId, operationServicesResult);
+        synchronized (callbackLock) {
+            callbackLock.notifyAll();
+        }
+    }
+
     public void operationTimedOut(String jobId, long invocationTime, long timeoutTime) {
         OperationServicesResult operationServicesResult = new OperationServicesResult(
             OperationServicesResultCode.TIMED_OUT);
diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/operation/OperationManagerTest.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/operation/OperationManagerTest.java
index accc547..e215fd7 100644
--- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/operation/OperationManagerTest.java
+++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/operation/OperationManagerTest.java
@@ -596,6 +596,13 @@ public class OperationManagerTest {
             jobsCompleted.put(jobId, timeoutTime);
             opResults.put(jobId, "TIMEOUT");
         }
+
+        public void operationCanceled(String jobId, Configuration result, ExceptionPackage error, long invocationTime,
+            long canceledTime) {
+            //println( "~~~~~~~~~~~~~~ server service - canceled: " + jobId + " : " + formatTime( timeoutTime ) );
+            jobsCompleted.put(jobId, canceledTime);
+            opResults.put(jobId, "CANCELED");
+        }
     }
 
     private static void println(String msg) {
diff --git a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/operation/ParallelOperationsTest.java b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/operation/ParallelOperationsTest.java
index 887ba0f..a1713d7 100644
--- a/modules/core/plugin-container/src/test/java/org/rhq/core/pc/operation/ParallelOperationsTest.java
+++ b/modules/core/plugin-container/src/test/java/org/rhq/core/pc/operation/ParallelOperationsTest.java
@@ -230,6 +230,13 @@ public class ParallelOperationsTest {
             jobsCompleted.put(jobId, timeoutTime);
             opResults.put(jobId, "TIMEOUT");
         }
+
+        public void operationCanceled(String jobId, Configuration result, ExceptionPackage error, long invocationTime,
+            long canceledTime) {
+            //println( "~~~~~~~~~~~~~~ server service - timed out: " + jobId + " : " + formatTime( timeoutTime ) );
+            jobsCompleted.put(jobId, canceledTime);
+            opResults.put(jobId, "CANCELED");
+        }
     }
 
     private static void println(String msg) {
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/operation/OperationServerServiceImpl.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/operation/OperationServerServiceImpl.java
index 152974c..05ac1cc 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/operation/OperationServerServiceImpl.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/operation/OperationServerServiceImpl.java
@@ -39,6 +39,7 @@ import org.rhq.enterprise.server.util.LookupUtil;
  * <ul>
  *   <li>an operation successfully completed</li>
  *   <li>an operation was invoked but failed</li>
+ *   <li>an operation was invoked but canceled</li>
  *   <li>an operation was invoked but timed out before completing</li>
  * </ul>
  *
@@ -47,6 +48,48 @@ import org.rhq.enterprise.server.util.LookupUtil;
 public class OperationServerServiceImpl implements OperationServerService {
     private static final Log LOG = LogFactory.getLog(OperationServerServiceImpl.class);
 
+    public void operationCanceled(String jobId, Configuration result, ExceptionPackage error, long invocationTime,
+        long completionTime) {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("Operation invocation [" + jobId + "] was canceled [" + error + "] "
+                + getFromStartToEndTimestampString(invocationTime, completionTime));
+        }
+
+        try {
+            Subject superuser = LookupUtil.getSubjectManager().getOverlord();
+            OperationManagerLocal operationManager = LookupUtil.getOperationManager();
+            ResourceOperationHistory history = null;
+
+            history = (ResourceOperationHistory) operationManager.getOperationHistoryByJobId(superuser, jobId);
+
+            // I think this will only ever occur if the server-side timed this out but the long running
+            // operation finally got back to us afterwards. We will still go ahead and
+            // persist the failure data because, obviously, the operation really didn't time out.
+            // I think, in reality, this condition will never occur (since the server-side will only ever
+            // timeout ridiculously long-lived operations, which is typically only when an agent shutdown occurred).
+            if (history.getStatus() != OperationRequestStatus.INPROGRESS) {
+                LOG.debug("Was told an operation was canceled but, curiously, it was not in progress: " + "job-id=["
+                    + jobId + "], op-history=[" + history + "]");
+            }
+
+            if (error != null) {
+                history.setErrorMessage(error.getStackTraceString());
+            } else {
+                history.setErrorMessage("Operation was canceled at " + new Date(completionTime));
+            }
+
+            history.setResults(result);
+            history.setStatus(OperationRequestStatus.CANCELED);
+
+            operationManager.updateOperationHistory(superuser, history);
+            operationManager.checkForCompletedGroupOperation(history.getId());
+        } catch (Exception e) {
+            LOG.error("Failed to update history from canceled operation, jobId=[" + jobId + "]. Cause: " + e, e);
+            LOG.error("The canceled operation [" + jobId + "] had an error of: "
+                + ((error != null) ? error.getStackTraceString() : "?"));
+        }
+    }
+
     public void operationFailed(String jobId, Configuration result, ExceptionPackage error, long invocationTime,
         long completionTime) {
         if (LOG.isDebugEnabled()) {


commit 2b7e819927ec18f13bd75c49246c1f837fa96aeb
Author: Stefan Negrea <snegrea at redhat.com>
Date:   Tue Jun 12 17:04:32 2012 -0500

    [BZ 831377] Updated the plugin descriptor to allow decimal numbers for retry-interval-multiplier of a HornetQ cluster connection because AS7 allows it.

diff --git a/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml
index 282ee93..19bccaa 100644
--- a/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml
@@ -4577,7 +4577,7 @@
             <c:simple-property name="min-large-message-size" required="false" type="integer" readOnly="true" defaultValue="102400" description="The minimum size (in bytes) for a message before it is considered as a large message. The default value is 102400."/>
             <c:simple-property name="reconnect-attempts" required="false" type="integer" readOnly="true" defaultValue="&#45;1" description="The total number of reconnect attempts the bridge will make before giving up and shutting down. A value of &#45;1 signifies an unlimited number of attempts. The default value is &#45;1."/>
             <c:simple-property name="retry-interval" required="false" type="long" readOnly="true" defaultValue="500" description="The period in milliseconds between subsequent reconnection attempts, if the connection to the target server has failed. The default value is 500."/>
-            <c:simple-property name="retry-interval-multiplier" required="false" type="long" readOnly="true" defaultValue="1.0" description="A multiplier to apply to the time since the last retry to compute the time to the next retry. This allows you to implement an exponential backoff between retry attempts. The default value is 1.0."/>
+            <c:simple-property name="retry-interval-multiplier" required="false" type="double" readOnly="true" defaultValue="1.0" description="A multiplier to apply to the time since the last retry to compute the time to the next retry. This allows you to implement an exponential backoff between retry attempts. The default value is 1.0."/>
             <c:list-property name="static-connectors" required="false" readOnly="true" description="The statically defined list of connectors to which this cluster connection will make connections. Must be undefined (null) if &apos;discovery&#45;group&#45;name&apos; is defined." >
                 <c:simple-property name="static-connectors" readOnly="true"/>
             </c:list-property>
@@ -6662,7 +6662,7 @@
             <c:simple-property name="min-large-message-size" required="false" type="integer" readOnly="false" defaultValue="102400" description="The minimum size (in bytes) for a message before it is considered as a large message. The default value is 102400."/>
             <c:simple-property name="reconnect-attempts" required="false" type="integer" readOnly="false" defaultValue="&#45;1" description="The total number of reconnect attempts the bridge will make before giving up and shutting down. A value of &#45;1 signifies an unlimited number of attempts. The default value is &#45;1."/>
             <c:simple-property name="retry-interval" required="false" type="long" readOnly="false" defaultValue="500" description="The period in milliseconds between subsequent reconnection attempts, if the connection to the target server has failed. The default value is 500."/>
-            <c:simple-property name="retry-interval-multiplier" required="false" type="long" readOnly="false" defaultValue="1.0" description="A multiplier to apply to the time since the last retry to compute the time to the next retry. This allows you to implement an exponential backoff between retry attempts. The default value is 1.0."/>
+            <c:simple-property name="retry-interval-multiplier" required="false" type="double" readOnly="false" defaultValue="1.0" description="A multiplier to apply to the time since the last retry to compute the time to the next retry. This allows you to implement an exponential backoff between retry attempts. The default value is 1.0."/>
             <c:list-property name="static-connectors" required="false" description="The statically defined list of connectors to which this cluster connection will make connections. Must be undefined (null) if &apos;discovery&#45;group&#45;name&apos; is defined." >
                 <c:simple-property name="static-connectors" />
             </c:list-property>
@@ -12689,7 +12689,7 @@
           <c:simple-property name="min-large-message-size" required="false" type="integer" readOnly="false" defaultValue="102400" description="The minimum size (in bytes) for a message before it is considered as a large message. The default value is 102400."/>
           <c:simple-property name="reconnect-attempts" required="false" type="integer" readOnly="false" defaultValue="&#45;1" description="The total number of reconnect attempts the bridge will make before giving up and shutting down. A value of &#45;1 signifies an unlimited number of attempts. The default value is &#45;1."/>
           <c:simple-property name="retry-interval" required="false" type="long" readOnly="false" defaultValue="500" description="The period in milliseconds between subsequent reconnection attempts, if the connection to the target server has failed. The default value is 500."/>
-          <c:simple-property name="retry-interval-multiplier" required="false" type="long" readOnly="false" defaultValue="1.0" description="A multiplier to apply to the time since the last retry to compute the time to the next retry. This allows you to implement an exponential backoff between retry attempts. The default value is 1.0."/>
+          <c:simple-property name="retry-interval-multiplier" required="false" type="double" readOnly="false" defaultValue="1.0" description="A multiplier to apply to the time since the last retry to compute the time to the next retry. This allows you to implement an exponential backoff between retry attempts. The default value is 1.0."/>
           <c:list-property name="static-connectors" required="false" description="The statically defined list of connectors to which this cluster connection will make connections. Must be undefined (null) if &apos;discovery&#45;group&#45;name&apos; is defined.">
             <c:simple-property name="static-connectors"/>
           </c:list-property>


commit 9f4bbacfa3212f412db718311ad7c2bd0343cc2f
Author: Stefan Negrea <snegrea at redhat.com>
Date:   Tue Jun 12 16:23:15 2012 -0500

    [BZ 831369] Use :whoami to retrieve server state because it does not require any parameters and is present on all resources. This will avoid warnings printed by using :read-attribute.

diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseComponent.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseComponent.java
index dac0218..2851128 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseComponent.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseComponent.java
@@ -278,7 +278,7 @@ public class BaseComponent<T extends ResourceComponent<?>> implements AS7Compone
         Configuration configuration = delegate.loadResourceConfiguration();
 
         // Read server state
-        ReadAttribute op = new ReadAttribute(getAddress(), "name");
+        Operation op = new Operation("whoami", getAddress());
         Result res = getASConnection().execute(op);
         if (res.isReloadRequired()) {
             PropertySimple oobMessage = new PropertySimple("__OOB","The server needs a reload for the latest changes to come effective.");


commit 6b83005b22c4d44f76fc15c5e38f33a39c6f2bc2
Author: John Sanda <jsanda at redhat.com>
Date:   Tue Jun 12 15:56:19 2012 -0400

    [BZ 823691] parameterize properties in agent config files

diff --git a/modules/enterprise/agent/src/test/resources/test-agent1-cfg-mvn.xml b/modules/enterprise/agent/src/test/resources/test-agent1-cfg-mvn.xml
index 2d8c91f..59dbb6b 100644
--- a/modules/enterprise/agent/src/test/resources/test-agent1-cfg-mvn.xml
+++ b/modules/enterprise/agent/src/test/resources/test-agent1-cfg-mvn.xml
@@ -60,7 +60,7 @@
    <entry key="rhq.communications.multicast-detector.enabled"                        value="true" />
    <entry key="rhq.communications.multicast-detector.multicast-address"              value="224.16.16.16" />
    <entry key="rhq.communications.multicast-detector.bind-address"                   value="0.0.0.0" />
-   <entry key="rhq.communications.multicast-detector.port"                           value="16162" />
+   <entry key="rhq.communications.multicast-detector.port"                           value="${agent1.communications.multicast-detector.port}" />
    <entry key="rhq.communications.multicast-detector.default-time-delay"             value="5000" />
    <entry key="rhq.communications.multicast-detector.heartbeat-time-delay"           value="1000" />
    <entry key="rhq.communications.connector.rhqtype"                                 value="agent" />
diff --git a/modules/enterprise/agent/src/test/resources/test-agent2-cfg-mvn.xml b/modules/enterprise/agent/src/test/resources/test-agent2-cfg-mvn.xml
index 7321e5b..1957034 100644
--- a/modules/enterprise/agent/src/test/resources/test-agent2-cfg-mvn.xml
+++ b/modules/enterprise/agent/src/test/resources/test-agent2-cfg-mvn.xml
@@ -79,7 +79,7 @@
    <entry key="rhq.communications.multicast-detector.enabled"                        value="true" />
    <entry key="rhq.communications.multicast-detector.multicast-address"              value="224.16.16.16" />
    <entry key="rhq.communications.multicast-detector.bind-address"                   value="0.0.0.0" />
-   <entry key="rhq.communications.multicast-detector.port"                           value="16162" />
+   <entry key="rhq.communications.multicast-detector.port"                           value="${agent2.communications.multicast-detector.port}" />
    <entry key="rhq.communications.multicast-detector.default-time-delay"             value="5000" />
    <entry key="rhq.communications.multicast-detector.heartbeat-time-delay"           value="1000" />
    <entry key="rhq.communications.connector.rhqtype"                                 value="agent" />


commit fee4a6441651e5f6e30f6d3f87ea5de1a6fabb67
Author: John Sanda <jsanda at redhat.com>
Date:   Tue Jun 12 15:44:20 2012 -0400

    [BZ 823691] Parameterize hard coded ports

diff --git a/modules/enterprise/agent/pom.xml b/modules/enterprise/agent/pom.xml
index 6fa0902..892a1c0 100644
--- a/modules/enterprise/agent/pom.xml
+++ b/modules/enterprise/agent/pom.xml
@@ -16,6 +16,15 @@
   <name>RHQ Enterprise Agent</name>
   <description>RHQ Agent</description>
 
+  <properties>
+    <agent1.server.bind-port>11111</agent1.server.bind-port>
+    <agent2.server.bind-port>22222</agent2.server.bind-port>
+    <agent1.communications.connector.bind-port>11111</agent1.communications.connector.bind-port>
+    <agent2.communications.connector.bind-port>22222</agent2.communications.connector.bind-port>
+    <agent1.communications.multicast-detector.port>17777</agent1.communications.multicast-detector.port>
+    <agent2.communications.multicast-detector.port>18888</agent2.communications.multicast-detector.port>
+  </properties>
+
   <dependencies>
 
     <!-- Internal Deps -->
@@ -223,6 +232,14 @@ Build-Number=${buildNumber}
       <plugin>
         <artifactId>maven-surefire-plugin</artifactId>
         <configuration>
+          <systemPropertyVariables>
+            <agent1.server.bind-port>${agent1.server.bind-port}</agent1.server.bind-port>
+            <agent2.server.bind-port>${agent2.server.bind-port}</agent2.server.bind-port>
+            <agent1.communications.connector.bind-port>${agent1.communications.connector.bind-port}</agent1.communications.connector.bind-port>
+            <agent2.communications.connector.bind-port>${agent2.communications.connector.bind-port}</agent2.communications.connector.bind-port>
+            <agent1.communications.multicast-detector.port>${agent1.communications.multicast-detector.port}</agent1.communications.multicast-detector.port>
+            <agent2.communications.multicast-detector.port>${agent2.communications.multicast-detector.port}</agent2.communications.multicast-detector.port>
+          </systemPropertyVariables>
           <excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
         </configuration>
       </plugin>
diff --git a/modules/enterprise/agent/src/test/java/org/rhq/enterprise/agent/AgentComm1Test.java b/modules/enterprise/agent/src/test/java/org/rhq/enterprise/agent/AgentComm1Test.java
index 9e9ab59..f4cdca0 100644
--- a/modules/enterprise/agent/src/test/java/org/rhq/enterprise/agent/AgentComm1Test.java
+++ b/modules/enterprise/agent/src/test/java/org/rhq/enterprise/agent/AgentComm1Test.java
@@ -100,9 +100,9 @@ public class AgentComm1Test extends AgentCommTestBase {
     @Test(enabled = ENABLE_TESTS)
     public void testAgentStreamingDataToPojoWithPreprocessorAuthenticatorOverSSL() throws Exception {
         Properties props1 = new Properties();
-        setServerLocatorUriProperties(props1, "sslsocket", "127.0.0.1", 22222, null);
+        setServerLocatorUriProperties(props1, "sslsocket", "127.0.0.1", AGENT2_SERVER_BIND_PORT, null);
         props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_TRANSPORT, "sslsocket");
-        props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_BIND_PORT, "11111");
+        props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_BIND_PORT, AGENT1_COMM_CONNECTOR_BIND_PORT);
         props1.setProperty(AgentConfigurationConstants.CLIENT_SENDER_SECURITY_SOCKET_PROTOCOL, "SSL");
         props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_SECURITY_SOCKET_PROTOCOL, "SSL");
         props1.setProperty(AgentConfigurationConstants.CLIENT_SENDER_SECURITY_SERVER_AUTH_MODE, "true");
@@ -120,9 +120,9 @@ public class AgentComm1Test extends AgentCommTestBase {
         m_agent1Test.setConfigurationOverrides(props1);
 
         Properties props2 = new Properties();
-        setServerLocatorUriProperties(props2, "sslsocket", "127.0.0.1", 11111, null);
+        setServerLocatorUriProperties(props2, "sslsocket", "127.0.0.1", AGENT1_SERVER_BIND_PORT, null);
         props2.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_TRANSPORT, "sslsocket");
-        props2.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_BIND_PORT, "22222");
+        props2.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_BIND_PORT, AGENT2_COMM_CONNECTOR_BIND_PORT);
         props2.setProperty(AgentConfigurationConstants.CLIENT_SENDER_SECURITY_SOCKET_PROTOCOL, "SSL");
         props2.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_SECURITY_SOCKET_PROTOCOL, "SSL");
         props2.setProperty(AgentConfigurationConstants.CLIENT_SENDER_SECURITY_SERVER_AUTH_MODE, "true");
@@ -458,9 +458,9 @@ public class AgentComm1Test extends AgentCommTestBase {
         // set up the SSL configuration.
         // note a side test - see that the internal remote pojo service is created even with dynamic discovery turned off
         Properties props1 = new Properties();
-        setServerLocatorUriProperties(props1, "sslsocket", "127.0.0.1", 22222, null);
+        setServerLocatorUriProperties(props1, "sslsocket", "127.0.0.1", AGENT2_SERVER_BIND_PORT, null);
         props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_TRANSPORT, "sslsocket");
-        props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_BIND_PORT, "11111");
+        props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_BIND_PORT, AGENT1_COMM_CONNECTOR_BIND_PORT);
         props1.setProperty(AgentConfigurationConstants.CLIENT_SENDER_SECURITY_SOCKET_PROTOCOL, "SSL");
         props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_SECURITY_SOCKET_PROTOCOL, "SSL");
         props1.setProperty(AgentConfigurationConstants.CLIENT_SENDER_SECURITY_SERVER_AUTH_MODE, "false");
@@ -471,9 +471,9 @@ public class AgentComm1Test extends AgentCommTestBase {
         m_agent1Test.setConfigurationOverrides(props1);
 
         Properties props2 = new Properties();
-        setServerLocatorUriProperties(props2, "sslsocket", "127.0.0.1", 11111, null);
+        setServerLocatorUriProperties(props2, "sslsocket", "127.0.0.1", AGENT1_SERVER_BIND_PORT, null);
         props2.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_TRANSPORT, "sslsocket");
-        props2.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_BIND_PORT, "22222");
+        props2.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_BIND_PORT, AGENT2_COMM_CONNECTOR_BIND_PORT);
         props2.setProperty(AgentConfigurationConstants.CLIENT_SENDER_SECURITY_SOCKET_PROTOCOL, "SSL");
         props2.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_SECURITY_SOCKET_PROTOCOL, "SSL");
         props2.setProperty(AgentConfigurationConstants.CLIENT_SENDER_SECURITY_SERVER_AUTH_MODE, "true");
@@ -643,9 +643,9 @@ public class AgentComm1Test extends AgentCommTestBase {
     public void testAgentStreamingDataToPojoOverSSLBigData() throws Exception {
         // set up the SSL configuration.
         Properties props1 = new Properties();
-        setServerLocatorUriProperties(props1, "sslsocket", "127.0.0.1", 22222, null);
+        setServerLocatorUriProperties(props1, "sslsocket", "127.0.0.1", AGENT2_SERVER_BIND_PORT, null);
         props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_TRANSPORT, "sslsocket");
-        props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_BIND_PORT, "11111");
+        props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_BIND_PORT, AGENT1_COMM_CONNECTOR_BIND_PORT);
         props1.setProperty(AgentConfigurationConstants.CLIENT_SENDER_SECURITY_SOCKET_PROTOCOL, "SSL");
         props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_SECURITY_SOCKET_PROTOCOL, "SSL");
         props1.setProperty(AgentConfigurationConstants.CLIENT_SENDER_SECURITY_SERVER_AUTH_MODE, "false");
@@ -655,9 +655,9 @@ public class AgentComm1Test extends AgentCommTestBase {
         m_agent1Test.setConfigurationOverrides(props1);
 
         Properties props2 = new Properties();
-        setServerLocatorUriProperties(props2, "sslsocket", "127.0.0.1", 11111, null);
+        setServerLocatorUriProperties(props2, "sslsocket", "127.0.0.1", AGENT1_SERVER_BIND_PORT, null);
         props2.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_TRANSPORT, "sslsocket");
-        props2.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_BIND_PORT, "22222");
+        props2.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_BIND_PORT, AGENT2_COMM_CONNECTOR_BIND_PORT);
         props2.setProperty(AgentConfigurationConstants.CLIENT_SENDER_SECURITY_SOCKET_PROTOCOL, "SSL");
         props2.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_SECURITY_SOCKET_PROTOCOL, "SSL");
         props2.setProperty(AgentConfigurationConstants.CLIENT_SENDER_SECURITY_SERVER_AUTH_MODE, "true");
diff --git a/modules/enterprise/agent/src/test/java/org/rhq/enterprise/agent/AgentComm2Test.java b/modules/enterprise/agent/src/test/java/org/rhq/enterprise/agent/AgentComm2Test.java
index b1920e5..1f1160c 100644
--- a/modules/enterprise/agent/src/test/java/org/rhq/enterprise/agent/AgentComm2Test.java
+++ b/modules/enterprise/agent/src/test/java/org/rhq/enterprise/agent/AgentComm2Test.java
@@ -48,9 +48,9 @@ public class AgentComm2Test extends AgentCommTestBase {
     @Test(enabled = ENABLE_TESTS)
     public void testCreateKeystoreSecureAgent() throws Exception {
         Properties props1 = new Properties();
-        setServerLocatorUriProperties(props1, "socket", "127.0.0.1", 22222, null);
+        setServerLocatorUriProperties(props1, "socket", "127.0.0.1", AGENT2_SERVER_BIND_PORT, null);
         props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_TRANSPORT, "sslsocket");
-        props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_BIND_PORT, "11111");
+        props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_BIND_PORT, AGENT1_COMM_CONNECTOR_BIND_PORT);
 
         m_agent1Test.setConfigurationOverrides(props1);
 
@@ -71,9 +71,9 @@ public class AgentComm2Test extends AgentCommTestBase {
     @Test(enabled = ENABLE_TESTS)
     public void testCreateKeystoreSecureServer() throws Exception {
         Properties props1 = new Properties();
-        setServerLocatorUriProperties(props1, "sslsocket", "127.0.0.1", 22222, null);
+        setServerLocatorUriProperties(props1, "sslsocket", "127.0.0.1", AGENT2_SERVER_BIND_PORT, null);
         props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_TRANSPORT, "socket");
-        props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_BIND_PORT, "11111");
+        props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_BIND_PORT, AGENT1_COMM_CONNECTOR_BIND_PORT);
 
         m_agent1Test.setConfigurationOverrides(props1);
 
@@ -95,9 +95,9 @@ public class AgentComm2Test extends AgentCommTestBase {
     @Test(enabled = ENABLE_TESTS)
     public void testSendSecureMessageServerAuthFailure() throws Exception {
         Properties props1 = new Properties();
-        setServerLocatorUriProperties(props1, "sslsocket", "127.0.0.1", 22222, null);
+        setServerLocatorUriProperties(props1, "sslsocket", "127.0.0.1", AGENT2_SERVER_BIND_PORT, null);
         props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_TRANSPORT, "sslsocket");
-        props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_BIND_PORT, "11111");
+        props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_BIND_PORT, AGENT1_COMM_CONNECTOR_BIND_PORT);
         props1.setProperty(AgentConfigurationConstants.CLIENT_SENDER_SECURITY_SOCKET_PROTOCOL, "SSL");
         props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_SECURITY_SOCKET_PROTOCOL, "SSL");
         props1.setProperty(AgentConfigurationConstants.CLIENT_SENDER_SECURITY_SERVER_AUTH_MODE, "false");
@@ -107,9 +107,9 @@ public class AgentComm2Test extends AgentCommTestBase {
         m_agent1Test.setConfigurationOverrides(props1);
 
         Properties props2 = new Properties();
-        setServerLocatorUriProperties(props2, "sslsocket", "127.0.0.1", 11111, null);
+        setServerLocatorUriProperties(props2, "sslsocket", "127.0.0.1", AGENT1_SERVER_BIND_PORT, null);
         props2.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_TRANSPORT, "sslsocket");
-        props2.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_BIND_PORT, "22222");
+        props2.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_BIND_PORT, AGENT2_COMM_CONNECTOR_BIND_PORT);
         props2.setProperty(AgentConfigurationConstants.CLIENT_SENDER_SECURITY_SOCKET_PROTOCOL, "SSL");
         props2.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_SECURITY_SOCKET_PROTOCOL, "SSL");
         props2.setProperty(AgentConfigurationConstants.CLIENT_SENDER_SECURITY_SERVER_AUTH_MODE, "true");
@@ -157,9 +157,9 @@ public class AgentComm2Test extends AgentCommTestBase {
     @Test(enabled = ENABLE_TESTS)
     public void testSendSecureMessageClientAuthFailure() throws Exception {
         Properties props1 = new Properties();
-        setServerLocatorUriProperties(props1, "sslsocket", "127.0.0.1", 22222, null);
+        setServerLocatorUriProperties(props1, "sslsocket", "127.0.0.1", AGENT2_SERVER_BIND_PORT, null);
         props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_TRANSPORT, "sslsocket");
-        props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_BIND_PORT, "11111");
+        props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_BIND_PORT, AGENT1_COMM_CONNECTOR_BIND_PORT);
         props1.setProperty(AgentConfigurationConstants.CLIENT_SENDER_SECURITY_KEYSTORE_FILE, "");
         props1.setProperty(AgentConfigurationConstants.CLIENT_SENDER_SECURITY_SOCKET_PROTOCOL, "SSL");
         props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_SECURITY_SOCKET_PROTOCOL, "SSL");
@@ -170,9 +170,9 @@ public class AgentComm2Test extends AgentCommTestBase {
         m_agent1Test.setConfigurationOverrides(props1);
 
         Properties props2 = new Properties();
-        setServerLocatorUriProperties(props2, "sslsocket", "127.0.0.1", 11111, null);
+        setServerLocatorUriProperties(props2, "sslsocket", "127.0.0.1", AGENT1_SERVER_BIND_PORT, null);
         props2.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_TRANSPORT, "sslsocket");
-        props2.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_BIND_PORT, "22222");
+        props2.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_BIND_PORT, AGENT2_COMM_CONNECTOR_BIND_PORT);
         props2.setProperty(AgentConfigurationConstants.CLIENT_SENDER_SECURITY_SOCKET_PROTOCOL, "SSL");
         props2.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_SECURITY_SOCKET_PROTOCOL, "SSL");
         props2.setProperty(AgentConfigurationConstants.CLIENT_SENDER_SECURITY_SERVER_AUTH_MODE, "false");
@@ -221,9 +221,9 @@ public class AgentComm2Test extends AgentCommTestBase {
     @Test(enabled = ENABLE_TESTS)
     public void testSendSecureMessageNoAuth() throws Exception {
         Properties props1 = new Properties();
-        setServerLocatorUriProperties(props1, "sslsocket", "127.0.0.1", 22222, null);
+        setServerLocatorUriProperties(props1, "sslsocket", "127.0.0.1", AGENT2_SERVER_BIND_PORT, null);
         props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_TRANSPORT, "sslsocket");
-        props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_BIND_PORT, "11111");
+        props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_BIND_PORT, AGENT1_COMM_CONNECTOR_BIND_PORT);
         props1.setProperty(AgentConfigurationConstants.CLIENT_SENDER_SECURITY_SOCKET_PROTOCOL, "SSL");
         props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_SECURITY_SOCKET_PROTOCOL, "SSL");
         props1.setProperty(AgentConfigurationConstants.CLIENT_SENDER_SECURITY_SERVER_AUTH_MODE, "false");
@@ -233,9 +233,9 @@ public class AgentComm2Test extends AgentCommTestBase {
         m_agent1Test.setConfigurationOverrides(props1);
 
         Properties props2 = new Properties();
-        setServerLocatorUriProperties(props2, "sslsocket", "127.0.0.1", 11111, null);
+        setServerLocatorUriProperties(props2, "sslsocket", "127.0.0.1", AGENT1_SERVER_BIND_PORT, null);
         props2.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_TRANSPORT, "sslsocket");
-        props2.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_BIND_PORT, "22222");
+        props2.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_BIND_PORT, AGENT2_COMM_CONNECTOR_BIND_PORT);
         props2.setProperty(AgentConfigurationConstants.CLIENT_SENDER_SECURITY_SOCKET_PROTOCOL, "SSL");
         props2.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_SECURITY_SOCKET_PROTOCOL, "SSL");
         props2.setProperty(AgentConfigurationConstants.CLIENT_SENDER_SECURITY_SERVER_AUTH_MODE, "false");
@@ -294,9 +294,9 @@ public class AgentComm2Test extends AgentCommTestBase {
     public void testSendSecureMessageFullAuth() throws Exception {
         // each keystore is the other's truststore
         Properties props1 = new Properties();
-        setServerLocatorUriProperties(props1, "sslsocket", "127.0.0.1", 22222, null);
+        setServerLocatorUriProperties(props1, "sslsocket", "127.0.0.1", AGENT2_SERVER_BIND_PORT, null);
         props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_TRANSPORT, "sslsocket");
-        props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_BIND_PORT, "11111");
+        props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_BIND_PORT, AGENT1_COMM_CONNECTOR_BIND_PORT);
         props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_SECURITY_TRUSTSTORE_FILE,
             "target/testdata2/keystore.dat");
         props1.setProperty(AgentConfigurationConstants.CLIENT_SENDER_SECURITY_TRUSTSTORE_FILE,
@@ -308,9 +308,9 @@ public class AgentComm2Test extends AgentCommTestBase {
         m_agent1Test.setConfigurationOverrides(props1);
 
         Properties props2 = new Properties();
-        setServerLocatorUriProperties(props2, "sslsocket", "127.0.0.1", 11111, null);
+        setServerLocatorUriProperties(props2, "sslsocket", "127.0.0.1", AGENT1_SERVER_BIND_PORT, null);
         props2.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_TRANSPORT, "sslsocket");
-        props2.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_BIND_PORT, "22222");
+        props2.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_BIND_PORT, AGENT2_COMM_CONNECTOR_BIND_PORT);
         props2.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_SECURITY_TRUSTSTORE_FILE,
             "target/testdata/keystore.dat");
         props2.setProperty(AgentConfigurationConstants.CLIENT_SENDER_SECURITY_TRUSTSTORE_FILE,
@@ -368,9 +368,9 @@ public class AgentComm2Test extends AgentCommTestBase {
     public void testSendSecureMessageFullAuthWrongKeystorePassword() throws Exception {
         // each keystore is the other's truststore
         Properties props1 = new Properties();
-        setServerLocatorUriProperties(props1, "sslsocket", "127.0.0.1", 22222, null);
+        setServerLocatorUriProperties(props1, "sslsocket", "127.0.0.1", AGENT2_SERVER_BIND_PORT, null);
         props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_TRANSPORT, "sslsocket");
-        props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_BIND_PORT, "11111");
+        props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_BIND_PORT, AGENT1_COMM_CONNECTOR_BIND_PORT);
         props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_SECURITY_KEYSTORE_PASSWORD,
             "invalidpassword");
         props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_SECURITY_TRUSTSTORE_FILE,
@@ -384,9 +384,9 @@ public class AgentComm2Test extends AgentCommTestBase {
         m_agent1Test.setConfigurationOverrides(props1);
 
         Properties props2 = new Properties();
-        setServerLocatorUriProperties(props2, "sslsocket", "127.0.0.1", 11111, null);
+        setServerLocatorUriProperties(props2, "sslsocket", "127.0.0.1", AGENT1_SERVER_BIND_PORT, null);
         props2.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_TRANSPORT, "sslsocket");
-        props2.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_BIND_PORT, "22222");
+        props2.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_BIND_PORT, AGENT2_COMM_CONNECTOR_BIND_PORT);
         props2.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_SECURITY_KEYSTORE_PASSWORD,
             "invalidpassword2");
         props2.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_SECURITY_TRUSTSTORE_FILE,
@@ -426,9 +426,9 @@ public class AgentComm2Test extends AgentCommTestBase {
     public void testSendSecureMessageClientAuthWantWithTruststore() throws Exception {
         // each keystore is the other's truststore
         Properties props1 = new Properties();
-        setServerLocatorUriProperties(props1, "sslsocket", "127.0.0.1", 22222, null);
+        setServerLocatorUriProperties(props1, "sslsocket", "127.0.0.1", AGENT2_SERVER_BIND_PORT, null);
         props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_TRANSPORT, "sslsocket");
-        props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_BIND_PORT, "11111");
+        props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_BIND_PORT, AGENT1_COMM_CONNECTOR_BIND_PORT);
         props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_SECURITY_TRUSTSTORE_FILE,
             "target/testdata2/keystore.dat");
         props1.setProperty(AgentConfigurationConstants.CLIENT_SENDER_SECURITY_TRUSTSTORE_FILE,
@@ -440,9 +440,9 @@ public class AgentComm2Test extends AgentCommTestBase {
         m_agent1Test.setConfigurationOverrides(props1);
 
         Properties props2 = new Properties();
-        setServerLocatorUriProperties(props2, "sslsocket", "127.0.0.1", 11111, null);
+        setServerLocatorUriProperties(props2, "sslsocket", "127.0.0.1", AGENT1_SERVER_BIND_PORT, null);
         props2.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_TRANSPORT, "sslsocket");
-        props2.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_BIND_PORT, "22222");
+        props2.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_BIND_PORT, AGENT2_COMM_CONNECTOR_BIND_PORT);
         props2.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_SECURITY_TRUSTSTORE_FILE,
             "target/testdata/keystore.dat");
         props2.setProperty(AgentConfigurationConstants.CLIENT_SENDER_SECURITY_TRUSTSTORE_FILE,
@@ -504,9 +504,9 @@ public class AgentComm2Test extends AgentCommTestBase {
     @Test(enabled = ENABLE_TESTS)
     public void testSendSecureMessageNoAuthDifferentProtocol() throws Exception {
         Properties props1 = new Properties();
-        setServerLocatorUriProperties(props1, "sslsocket", "127.0.0.1", 22222, null);
+        setServerLocatorUriProperties(props1, "sslsocket", "127.0.0.1", AGENT2_SERVER_BIND_PORT, null);
         props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_TRANSPORT, "sslsocket");
-        props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_BIND_PORT, "11111");
+        props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_BIND_PORT, AGENT1_COMM_CONNECTOR_BIND_PORT);
         props1.setProperty(AgentConfigurationConstants.CLIENT_SENDER_SECURITY_SOCKET_PROTOCOL, "TLS");
         props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_SECURITY_SOCKET_PROTOCOL, "SSL");
         props1.setProperty(AgentConfigurationConstants.CLIENT_SENDER_SECURITY_SERVER_AUTH_MODE, "false");
@@ -516,9 +516,9 @@ public class AgentComm2Test extends AgentCommTestBase {
         m_agent1Test.setConfigurationOverrides(props1);
 
         Properties props2 = new Properties();
-        setServerLocatorUriProperties(props2, "sslsocket", "127.0.0.1", 11111, null);
+        setServerLocatorUriProperties(props2, "sslsocket", "127.0.0.1", AGENT1_SERVER_BIND_PORT, null);
         props2.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_TRANSPORT, "sslsocket");
-        props2.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_BIND_PORT, "22222");
+        props2.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_BIND_PORT, AGENT2_COMM_CONNECTOR_BIND_PORT);
         props2.setProperty(AgentConfigurationConstants.CLIENT_SENDER_SECURITY_SOCKET_PROTOCOL, "SSL");
         props2.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_SECURITY_SOCKET_PROTOCOL, "TLS");
         props2.setProperty(AgentConfigurationConstants.CLIENT_SENDER_SECURITY_SERVER_AUTH_MODE, "false");
diff --git a/modules/enterprise/agent/src/test/java/org/rhq/enterprise/agent/AgentComm3Test.java b/modules/enterprise/agent/src/test/java/org/rhq/enterprise/agent/AgentComm3Test.java
index 945bdce..da1ba6d 100644
--- a/modules/enterprise/agent/src/test/java/org/rhq/enterprise/agent/AgentComm3Test.java
+++ b/modules/enterprise/agent/src/test/java/org/rhq/enterprise/agent/AgentComm3Test.java
@@ -65,12 +65,14 @@ public class AgentComm3Test extends AgentCommTestBase {
         // make it so the server auto-detection features do not detect anything
         Properties props1 = new Properties();
         props1.setProperty(AgentConfigurationConstants.SERVER_AUTO_DETECTION, "true");
-        props1.setProperty(ServiceContainerConfigurationConstants.MULTICASTDETECTOR_PORT, "17777");
+        props1.setProperty(ServiceContainerConfigurationConstants.MULTICASTDETECTOR_PORT,
+            AGENT1_COMM_MULTICAST_DECTECTOR_PORT);
         props1.setProperty(AgentConfigurationConstants.CLIENT_SENDER_SERVER_POLLING_INTERVAL, "-1");
 
         Properties props2 = new Properties();
         props2.setProperty(AgentConfigurationConstants.SERVER_AUTO_DETECTION, "true");
-        props2.setProperty(ServiceContainerConfigurationConstants.MULTICASTDETECTOR_PORT, "18888");
+        props2.setProperty(ServiceContainerConfigurationConstants.MULTICASTDETECTOR_PORT,
+            AGENT2_COMM_MULTICAST_DECTECTOR_PORT);
         props2.setProperty(AgentConfigurationConstants.CLIENT_SENDER_SERVER_POLLING_INTERVAL, "-1");
 
         m_agent1Test.setConfigurationOverrides(props1);
diff --git a/modules/enterprise/agent/src/test/java/org/rhq/enterprise/agent/AgentComm4Test.java b/modules/enterprise/agent/src/test/java/org/rhq/enterprise/agent/AgentComm4Test.java
index 6519da3..691361c 100644
--- a/modules/enterprise/agent/src/test/java/org/rhq/enterprise/agent/AgentComm4Test.java
+++ b/modules/enterprise/agent/src/test/java/org/rhq/enterprise/agent/AgentComm4Test.java
@@ -72,12 +72,12 @@ public class AgentComm4Test extends AgentCommTestBase {
     public void testAgentConfigurationOverride() throws Exception {
         Properties props1 = new Properties();
         setServerLocatorUriProperties(props1, "socket", "127.0.0.1", 22345, null);
-        props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_BIND_PORT, "12345");
+        props1.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_BIND_PORT, AGENT1_SERVER_BIND_PORT);
         m_agent1Test.setConfigurationOverrides(props1);
 
         Properties props2 = new Properties();
         setServerLocatorUriProperties(props2, "socket", "127.0.0.1", 12345, null);
-        props2.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_BIND_PORT, "22345");
+        props2.setProperty(ServiceContainerConfigurationConstants.CONNECTOR_BIND_PORT, AGENT2_SERVER_BIND_PORT);
         m_agent2Test.setConfigurationOverrides(props2);
 
         AgentMain agent1 = m_agent1Test.createAgent(true);
@@ -86,8 +86,8 @@ public class AgentComm4Test extends AgentCommTestBase {
         assert agent1.isStarted() : "agent1 should have been started";
         assert agent2.isStarted() : "agent2 should have been started";
 
-        assert agent1.getServiceContainer().getConfiguration().getConnectorBindPort() == 12345;
-        assert agent2.getServiceContainer().getConfiguration().getConnectorBindPort() == 22345;
+        assert agent1.getServiceContainer().getConfiguration().getConnectorBindPort() == Integer.parseInt(AGENT1_SERVER_BIND_PORT);
+        assert agent2.getServiceContainer().getConfiguration().getConnectorBindPort() == Integer.parseInt(AGENT2_SERVER_BIND_PORT);
 
         agent1.shutdown();
         agent2.shutdown();
diff --git a/modules/enterprise/agent/src/test/java/org/rhq/enterprise/agent/AgentCommTestBase.java b/modules/enterprise/agent/src/test/java/org/rhq/enterprise/agent/AgentCommTestBase.java
index e6b3196..647bbb4 100644
--- a/modules/enterprise/agent/src/test/java/org/rhq/enterprise/agent/AgentCommTestBase.java
+++ b/modules/enterprise/agent/src/test/java/org/rhq/enterprise/agent/AgentCommTestBase.java
@@ -24,9 +24,13 @@ import java.util.Iterator;
 import java.util.Map;
 import java.util.Properties;
 
+import org.testng.IInvokedMethod;
+import org.testng.IInvokedMethodListener;
+import org.testng.ITestResult;
 import org.testng.annotations.AfterClass;
 import org.testng.annotations.AfterMethod;
 import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Listeners;
 
 import org.rhq.enterprise.communications.ServiceContainerConfiguration;
 import org.rhq.enterprise.communications.ServiceContainerConfigurationConstants;
@@ -37,11 +41,25 @@ import org.rhq.enterprise.communications.util.SecurityUtil;
  *
  * @author John Mazzitelli
  */
-public class AgentCommTestBase {
+ at Listeners(AgentCommTestBase.class)
+public class AgentCommTestBase implements IInvokedMethodListener {
     protected static final int LARGE_STRING_SIZE = 100000;
     protected static final String LARGE_STRING;
     protected static final byte[] LARGE_STRING_BYTES;
 
+    protected static final String AGENT1_SERVER_BIND_PORT = System.getProperty("agent1.server.bind-port", "11111");
+    protected static final String AGENT2_SERVER_BIND_PORT = System.getProperty("agent2.server.bind-port", "22222");
+
+    protected static final String AGENT1_COMM_CONNECTOR_BIND_PORT = System.getProperty(
+        "agent1.communications.connector.bind-port", "11111");
+    protected static final String AGENT2_COMM_CONNECTOR_BIND_PORT = System.getProperty(
+        "agent2.communications.connector.bind-port", "22222");
+
+    protected static final String AGENT1_COMM_MULTICAST_DECTECTOR_PORT = System.getProperty(
+        "agent1.communications.multicast-detector.port", "17777");
+    protected static final String AGENT2_COMM_MULTICAST_DECTECTOR_PORT = System.getProperty(
+        "agent2.communications.multicast-detector.port", "18888");
+
     static {
         StringBuffer stream_data_buf = new StringBuffer(LARGE_STRING_SIZE);
 
@@ -58,6 +76,20 @@ public class AgentCommTestBase {
     protected AgentTestClass m_agent1Test;
     protected AgentTestClass m_agent2Test;
 
+    @Override
+    public void beforeInvocation(IInvokedMethod method, ITestResult testResult) {
+        System.out.println("before " + getTestMethod(method));
+    }
+
+    @Override
+    public void afterInvocation(IInvokedMethod method, ITestResult testResult) {
+        System.out.println("after " + getTestMethod(method));
+    }
+
+    private String getTestMethod(IInvokedMethod method) {
+        return method.getTestMethod().getTestClass().getName() + "." + method.getTestMethod().getMethodName();
+    }
+
     /**
      * Creates new agent test classes.
      *
@@ -76,6 +108,8 @@ public class AgentCommTestBase {
         // make sure we create keystore files - some tests needs both existing at the same time as soon as they begin
         File keystore_file1 = new File("target/testdata/keystore.dat");
 
+        //Assert.assertFalse(keystore_file1 + " should not exist", keystore_file1.exists());
+        keystore_file1.delete();
         if (!keystore_file1.exists()) {
             keystore_file1.getParentFile().mkdirs();
             m_agent1Test.createAgent(false);
@@ -89,6 +123,8 @@ public class AgentCommTestBase {
         }
 
         File keystore_file2 = new File("target/testdata2/keystore.dat");
+        //Assert.assertFalse(keystore_file2 + " should not exist", keystore_file2.exists());
+        keystore_file2.delete();
         if (!keystore_file2.exists()) {
             keystore_file2.getParentFile().mkdirs();
             m_agent2Test.createAgent(false);
@@ -106,7 +142,7 @@ public class AgentCommTestBase {
      * Ensures any agent that was started is shutdown and all configuration is cleared so as not to retain overridden
      * preferences left over by the tests.
      */
-    @AfterMethod
+    @AfterMethod(alwaysRun = true)
     public void tearDown() {
         if (m_agent1Test != null) {
             AgentMain agent = m_agent1Test.getAgent();
@@ -177,6 +213,25 @@ public class AgentCommTestBase {
     }
 
     /**
+     * This will set the appropriate properties in <code>props</code> to define the server locator URI.
+     *
+     * @param props
+     * @param transport
+     * @param addr
+     * @param port
+     * @param transport_params
+     */
+    protected void setServerLocatorUriProperties(Properties props, String transport, String addr, String port,
+                                                 String transport_params) {
+        props.setProperty(AgentConfigurationConstants.SERVER_TRANSPORT, transport);
+        props.setProperty(AgentConfigurationConstants.SERVER_BIND_ADDRESS, addr);
+        props.setProperty(AgentConfigurationConstants.SERVER_BIND_PORT, port);
+        if (transport_params != null) {
+            props.setProperty(AgentConfigurationConstants.SERVER_TRANSPORT_PARAMS, transport_params);
+        }
+    }
+
+    /**
      * Creates a very large file that we can use for testing streaming of large data.
      *
      * @return the file


commit 6bd2fa80f4871209de16e6560b374a24cd308666
Author: Lukas Krejci <lkrejci at redhat.com>
Date:   Wed May 30 20:13:46 2012 +0200

    Experimental and unfinished support for python in the CLI.
    
    There's no support for custom script sources and code completion.

diff --git a/modules/enterprise/scripting/python/pom.xml b/modules/enterprise/scripting/python/pom.xml
new file mode 100644
index 0000000..4b48e52
--- /dev/null
+++ b/modules/enterprise/scripting/python/pom.xml
@@ -0,0 +1,187 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <artifactId>rhq-scripting-parent</artifactId>
+        <groupId>org.rhq</groupId>
+        <version>4.5.0-SNAPSHOT</version>
+    </parent>
+    <artifactId>rhq-scripting-python</artifactId>
+    <version>4.5.0-SNAPSHOT</version>
+    <name>RHQ Python support</name>
+    <description>Provides RHQ scripting in Python using Jython</description>
+
+    <dependencies>
+       <dependency>
+          <groupId>${project.groupId}</groupId>
+          <artifactId>rhq-scripting-api</artifactId>
+          <version>${project.version}</version>
+       </dependency>
+       
+       <dependency>
+          <groupId>org.python</groupId>
+          <artifactId>jython-standalone</artifactId>
+          <version>2.5.2</version>
+       </dependency>       
+    </dependencies>
+    
+    <build>
+        <plugins>
+            <plugin>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <configuration>
+                    <excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+    <profiles>
+
+        <profile>
+            <id>dev</id>
+
+            <properties>
+                <rhq.rootDir>../../..</rhq.rootDir>
+                <rhq.containerDir>${rhq.rootDir}/${rhq.defaultDevContainerPath}</rhq.containerDir>
+                <rhq.deploymentDir>${rhq.containerDir}/jbossas/server/default/deploy/${rhq.earName}/lib</rhq.deploymentDir>
+            </properties>
+
+            <build>
+                <plugins>
+
+                    <plugin>
+                        <artifactId>maven-antrun-plugin</artifactId>
+                        <version>1.1</version>
+                        <executions>
+
+                            <execution>
+                                <id>deploy</id>
+                                <phase>compile</phase>
+                                <configuration>
+                                    <tasks>
+                                        <mkdir dir="${rhq.deploymentDir}" />
+                                        <property name="deployment.file" location="${rhq.deploymentDir}/${project.build.finalName}.jar" />
+                                        <echo>*** Updating
+                                            ${deployment.file}...</echo>
+                                        <jar destfile="${deployment.file}" basedir="${project.build.outputDirectory}" />
+                                    </tasks>
+                                </configuration>
+                                <goals>
+                                    <goal>run</goal>
+                                </goals>
+                            </execution>
+
+                            <execution>
+                                <id>undeploy</id>
+                                <phase>clean</phase>
+                                <configuration>
+                                    <tasks>
+                                        <property name="deployment.file" location="${rhq.deploymentDir}/${project.build.finalName}.jar" />
+                                        <echo>*** Deleting
+                                            ${deployment.file}...</echo>
+                                        <delete file="${deployment.file}" />
+                                    </tasks>
+                                </configuration>
+                                <goals>
+                                    <goal>run</goal>
+                                </goals>
+                            </execution>
+
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+
+        <profile>
+            <id>cobertura-plugins</id>
+            <activation>
+                <activeByDefault>false</activeByDefault>
+            </activation>
+            <build>
+                <plugins>
+                    <plugin>
+                        <artifactId>maven-antrun-plugin</artifactId>
+                        <dependencies>
+                            <dependency>
+                                <groupId>net.sourceforge.cobertura</groupId>
+                                <artifactId>cobertura</artifactId>
+                                <version>1.9.4.1</version>
+                            </dependency>
+                        </dependencies>
+                        <executions>
+                            <execution>
+                                <id>cobertura-instrument</id>
+                                <phase>pre-integration-test</phase>
+                                <configuration>
+                                    <tasks>
+                                        <!-- prepare directory structure 
+                                            for cobertura -->
+                                        <mkdir dir="target/cobertura" />
+                                        <mkdir dir="target/cobertura/backup" />
+                                        <!-- backup all classes so that we 
+                                            can instrument the original classes -->
+                                        <copy toDir="target/cobertura/backup" verbose="true" overwrite="true">
+                                            <fileset dir="target/classes">
+                                                <include name="**/*.class" />
+                                            </fileset>
+                                        </copy>
+                                        <!-- create a properties file and 
+                                            save there location of cobertura data file -->
+                                        <touch file="target/classes/cobertura.properties" />
+                                        <echo file="target/classes/cobertura.properties">net.sourceforge.cobertura.datafile=${project.build.directory}/cobertura/cobertura.ser</echo>
+                                        <taskdef classpathref="maven.plugin.classpath" resource="tasks.properties" />
+                                        <!-- instrument all classes in target/classes 
+                                            directory -->
+                                        <cobertura-instrument datafile="${project.build.directory}/cobertura/cobertura.ser" todir="${project.build.directory}/classes">
+                                            <fileset dir="${project.build.directory}/classes">
+                                                <include name="**/*.class" />
+                                            </fileset>
+                                        </cobertura-instrument>
+                                    </tasks>
+                                </configuration>
+                                <goals>
+                                    <goal>run</goal>
+                                </goals>
+                            </execution>
+                            <execution>
+                                <id>cobertura-report</id>
+                                <phase>post-integration-test</phase>
+                                <configuration>
+                                    <tasks>
+                                        <taskdef classpathref="maven.plugin.classpath" resource="tasks.properties" />
+                                        <!-- prepare directory structure 
+                                            for cobertura -->
+                                        <mkdir dir="target/cobertura" />
+                                        <mkdir dir="target/site/cobertura" />
+                                        <!-- restore classes from backup 
+                                            folder to classes folder -->
+                                        <copy toDir="target/classes" verbose="true" overwrite="true">
+                                            <fileset dir="target/cobertura/backup">
+                                                <include name="**/*.class" />
+                                            </fileset>
+                                        </copy>
+                                        <!-- delete backup folder -->
+                                        <delete dir="target/cobertura/backup" />
+                                        <!-- create a code coverage report -->
+                                        <cobertura-report format="html" datafile="${project.build.directory}/cobertura/cobertura.ser" destdir="${project.build.directory}/site/cobertura">
+                                            <fileset dir="${basedir}/src/main/java">
+                                                <include name="**/*.java" />
+                                            </fileset>
+                                        </cobertura-report>
+                                        <!-- delete cobertura.properties 
+                                            file -->
+                                        <delete file="target/classes/cobertura.properties" />
+                                    </tasks>
+                                </configuration>
+                                <goals>
+                                    <goal>run</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
+</project>
diff --git a/modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonScriptEngineInitializer.java b/modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonScriptEngineInitializer.java
new file mode 100644
index 0000000..9ee50b8
--- /dev/null
+++ b/modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonScriptEngineInitializer.java
@@ -0,0 +1,101 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 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.scripting.python;
+
+import java.lang.reflect.Method;
+import java.security.PermissionCollection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+import javax.script.ScriptException;
+
+import org.rhq.scripting.ScriptEngineInitializer;
+import org.rhq.scripting.ScriptSourceProvider;
+import org.rhq.scripting.util.SandboxedScriptEngine;
+
+/**
+ * 
+ *
+ * @author Lukas Krejci
+ */
+public class PythonScriptEngineInitializer implements ScriptEngineInitializer {
+
+    private ScriptEngineManager engineManager = new ScriptEngineManager();
+
+    @Override
+    public ScriptEngine instantiate(Set<String> packages, ScriptSourceProvider scriptSourceProvider,
+        PermissionCollection permissions) throws ScriptException {
+
+        ScriptEngine eng = engineManager.getEngineByName("python");
+
+        for (String pkg : packages) {
+            eng.eval("from " + pkg + " import *\n");
+        }
+
+        //TODO add support for script source providers... possibly using http://www.python.org/dev/peps/pep-0302/
+        
+        //fingers crossed we can secure jython like this
+        return new SandboxedScriptEngine(eng, permissions);
+    }
+
+    @Override
+    public Set<String> generateIndirectionMethods(String boundObjectName, Set<Method> overloadedMethods) {
+        if (overloadedMethods == null || overloadedMethods.isEmpty()) {
+            return Collections.emptySet();
+        }
+
+        Set<Integer> argCnts = new HashSet<Integer>();
+        for(Method m : overloadedMethods) {
+            argCnts.add(m.getParameterTypes().length);
+        }
+        
+        String methodName = overloadedMethods.iterator().next().getName();
+        StringBuilder functionBody = new StringBuilder();
+
+        functionBody.append("def ").append(methodName).append("(*args, **kwargs):\n");
+        functionBody.append("\t").append("if len(kwargs) > 0:\n");
+        functionBody.append("\t\t").append("raise ValueError(\"Named arguments not supported for Java methods\")\n");
+        functionBody.append("\t").append("argCnt = len(args)\n");
+                
+        for(Integer argCnt : argCnts) {
+            functionBody.append("\t").append("if argCnt == ").append(argCnt).append(":\n");
+            functionBody.append("\t\treturn ").append(boundObjectName).append(".").append(methodName).append("(");
+            int last = argCnt - 1;
+            for(int i = 0; i < argCnt; ++i) {
+                functionBody.append("args[").append(i).append("]");
+                if (i < last) {
+                    functionBody.append(", ");
+                }
+            }
+            functionBody.append(")\n");            
+        }
+
+        return Collections.singleton(functionBody.toString());
+    }
+
+    @Override
+    public String extractUserFriendlyErrorMessage(ScriptException e) {
+        return e.getMessage();
+    }
+
+}
diff --git a/modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonScriptEngineProvider.java b/modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonScriptEngineProvider.java
new file mode 100644
index 0000000..c0bfcac
--- /dev/null
+++ b/modules/enterprise/scripting/python/src/main/java/org/rhq/scripting/python/PythonScriptEngineProvider.java
@@ -0,0 +1,49 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 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.scripting.python;
+
+import org.rhq.scripting.CodeCompletion;
+import org.rhq.scripting.ScriptEngineInitializer;
+import org.rhq.scripting.ScriptEngineProvider;
+
+/**
+ * 
+ *
+ * @author Lukas Krejci
+ */
+public class PythonScriptEngineProvider implements ScriptEngineProvider {
+
+    @Override
+    public String getSupportedLanguage() {
+        return "python";
+    }
+
+    @Override
+    public ScriptEngineInitializer getInitializer() {
+        return new PythonScriptEngineInitializer();
+    }
+
+    @Override
+    public CodeCompletion getCodeCompletion() {
+        // XXX are we gonna support code completion for multiple langs in the CLI?
+        return null;
+    }
+
+}
diff --git a/modules/enterprise/scripting/python/src/main/resources/META-INF/services/org.rhq.scripting.ScriptEngineProvider b/modules/enterprise/scripting/python/src/main/resources/META-INF/services/org.rhq.scripting.ScriptEngineProvider
new file mode 100644
index 0000000..3882776
--- /dev/null
+++ b/modules/enterprise/scripting/python/src/main/resources/META-INF/services/org.rhq.scripting.ScriptEngineProvider
@@ -0,0 +1 @@
+org.rhq.scripting.python.PythonScriptEngineProvider


commit 6515d4f28dfddde094d20b72bad3b2f038d70b13
Author: Lukas Krejci <lkrejci at redhat.com>
Date:   Wed May 30 20:08:03 2012 +0200

    Initial impl of modules in the javascript CLI.
    
    All should be hooked up apart from the actual bundling of now standalone
    javascript support with the CLI. This will going to need some pom.xml love.
    
    We now bundle our own ScriptEngine implementation based on the Phobos
    javascript engine with modifications inspired by the version of the script
    engine in JDK 1.6.30.

diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/SandboxedScriptEngine.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/SandboxedScriptEngine.java
deleted file mode 100644
index f994f09..0000000
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/SandboxedScriptEngine.java
+++ /dev/null
@@ -1,204 +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 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.bindings;
-
-import java.io.Reader;
-import java.security.AccessControlContext;
-import java.security.AccessController;
-import java.security.CodeSource;
-import java.security.Permission;
-import java.security.PermissionCollection;
-import java.security.Permissions;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
-import java.security.ProtectionDomain;
-import java.security.cert.Certificate;
-import java.util.Arrays;
-import java.util.Collection;
-
-import javax.script.Bindings;
-import javax.script.ScriptContext;
-import javax.script.ScriptEngine;
-import javax.script.ScriptEngineFactory;
-import javax.script.ScriptException;
-
-/**
- * <b>DO NOT USE THIS CLASS DIRECTLY!!!!</b> Use {@link org.rhq.bindings.ScriptEngineFactory#getSecuredScriptEngine(String, org.rhq.bindings.util.PackageFinder, StandardBindings, PermissionCollection)}
- * method instead for a reliably secured script engine.
- * <p>
- * This is a decorator class for any other {@link ScriptEngine} implementation
- * that runs any of the eval methods with the defined set of {@link Permission}s. 
- * <p>
- * For the permissions to have any effect, a SecurityManager has to be installed 
- * in the current VM.
- * 
- * @author Lukas Krejci
- */
-public class SandboxedScriptEngine implements ScriptEngine {
-
-    private ScriptEngine engine;
-    private AccessControlContext accessControlContext;
-        
-    public SandboxedScriptEngine(ScriptEngine engine) {
-        this.engine = engine;
-    }
-    
-    public SandboxedScriptEngine(ScriptEngine engine, PermissionCollection permissions) {
-        this(engine);
-        setPermissions(permissions);
-    }
-
-    public SandboxedScriptEngine(ScriptEngine engine, Collection<? extends Permission> permissions) {
-        this(engine);
-        setPermissions(permissions);
-    }
-
-    public void setPermissions(Permission... permissions) {
-        setPermissions(Arrays.asList(permissions));
-    }
-    
-    public void setPermissions(Collection<? extends Permission> permissions) {
-        Permissions ps = new Permissions();
-        for(Permission p : permissions) {
-            ps.add(p);
-        }
-        
-        setPermissions(ps);
-    }
-    
-    public void setPermissions(PermissionCollection permissions) {
-        CodeSource cs = new CodeSource(null, (Certificate[]) null);
-        
-        ProtectionDomain domain = new ProtectionDomain(cs, permissions);        
-        accessControlContext = new AccessControlContext(new ProtectionDomain[] { domain });
-    }
-    
-    public Object eval(final String script, final ScriptContext context) throws ScriptException {
-        try {
-            return AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
-                public Object run() throws Exception {
-                    return engine.eval(script, context);
-                }
-            }, accessControlContext);
-        } catch (PrivilegedActionException e) {
-            throw transfer(e);
-        }        
-    }
-
-    public Object eval(final Reader reader, final ScriptContext context) throws ScriptException {
-        try {
-            return AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
-                public Object run() throws Exception {
-                    return engine.eval(reader, context);
-                }
-            }, accessControlContext);
-        } catch (PrivilegedActionException e) {
-            throw transfer(e);
-        }        
-    }
-
-    public Object eval(final String script) throws ScriptException {
-        try {
-            return AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
-                public Object run() throws Exception {
-                    return engine.eval(script);
-                }
-            }, accessControlContext);
-        } catch (PrivilegedActionException e) {
-            throw transfer(e);
-        }        
-    }
-
-    public Object eval(final Reader reader) throws ScriptException {
-        try {
-            return AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
-                public Object run() throws Exception {
-                    return engine.eval(reader);
-                }
-            }, accessControlContext);
-        } catch (PrivilegedActionException e) {
-            throw transfer(e);
-        }        
-    }
-
-    public Object eval(final String script, final Bindings n) throws ScriptException {
-        try {
-            return AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
-                public Object run() throws Exception {
-                    return engine.eval(script, n);
-                }
-            }, accessControlContext);
-        } catch (PrivilegedActionException e) {
-            throw transfer(e);
-        }        
-    }
-
-    public Object eval(final Reader reader, final Bindings n) throws ScriptException {
-        try {
-            return AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
-                public Object run() throws Exception {
-                    return engine.eval(reader, n);
-                }
-            }, accessControlContext);
-        } catch (PrivilegedActionException e) {
-            throw transfer(e);
-        }        
-    }
-
-    public void put(String key, Object value) {
-        engine.put(key, value);
-    }
-
-    public Object get(String key) {
-        return engine.get(key);
-    }
-
-    public Bindings getBindings(int scope) {
-        return engine.getBindings(scope);
-    }
-
-    public void setBindings(Bindings bindings, int scope) {
-        engine.setBindings(bindings, scope);
-    }
-
-    public Bindings createBindings() {
-        return engine.createBindings();
-    }
-
-    public ScriptContext getContext() {
-        return engine.getContext();
-    }
-
-    public void setContext(ScriptContext context) {
-        engine.setContext(context);
-    }
-
-    public ScriptEngineFactory getFactory() {
-        return engine.getFactory();
-    }
-    
-    private static ScriptException transfer(PrivilegedActionException e) {
-        if (e.getCause() instanceof ScriptException) {
-            return (ScriptException) e.getCause();
-        } else {
-            return new ScriptException(e);
-        }
-    }
-}
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/ScriptEngineFactory.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/ScriptEngineFactory.java
index 73ffc9d..df78b41 100644
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/ScriptEngineFactory.java
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/ScriptEngineFactory.java
@@ -25,15 +25,7 @@ import java.beans.Introspector;
 import java.beans.MethodDescriptor;
 import java.io.IOException;
 import java.lang.reflect.Method;
-import java.net.URL;
-import java.security.AccessControlContext;
-import java.security.AccessController;
-import java.security.CodeSource;
 import java.security.PermissionCollection;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
-import java.security.ProtectionDomain;
-import java.security.cert.Certificate;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
@@ -50,6 +42,7 @@ import org.apache.commons.logging.LogFactory;
 
 import org.rhq.bindings.util.NoTopLevelIndirection;
 import org.rhq.bindings.util.PackageFinder;
+import org.rhq.scripting.CodeCompletion;
 import org.rhq.scripting.ScriptEngineInitializer;
 import org.rhq.scripting.ScriptEngineProvider;
 
@@ -131,19 +124,8 @@ public class ScriptEngineFactory {
      */
     public static ScriptEngine getScriptEngine(String language, PackageFinder packageFinder, StandardBindings bindings)
         throws ScriptException, IOException {
-        ScriptEngineInitializer initializer = getInitializer(language);
-
-        if (initializer == null) {
-            return null;
-        }
-
-        ScriptEngine engine = initializer.instantiate(packageFinder.findPackages("org.rhq.core.domain"));
-
-        if (bindings != null) {
-            injectStandardBindings(engine, bindings, true);
-        }
-
-        return engine;
+        
+        return getSecuredScriptEngine(language, packageFinder, bindings, null);         
     }
 
     /**
@@ -155,45 +137,22 @@ public class ScriptEngineFactory {
      */
     public static ScriptEngine getSecuredScriptEngine(final String language, final PackageFinder packageFinder,
         final StandardBindings bindings, final PermissionCollection permissions) throws ScriptException, IOException {
-        CodeSource src = new CodeSource(new URL("http://rhq-project.org/scripting"), (Certificate[]) null);
-        ProtectionDomain scriptDomain = new ProtectionDomain(src, permissions);
-        AccessControlContext ctx = new AccessControlContext(new ProtectionDomain[] { scriptDomain });
-        try {
-            return AccessController.doPrivileged(new PrivilegedExceptionAction<ScriptEngine>() {
-                @Override
-                public ScriptEngine run() throws Exception {
-                    //This might seem a bit excessive but is necessary due to the 
-                    //change in security handling in the rhino script engine
-                    //that occured in Java6u27 (due to a CVE desribed here:
-                    //https://bugzilla.redhat.com/show_bug.cgi?id=CVE-2011-3544)
-
-                    //In Java 6u26 and earlier, it was enough to wrap a script engine
-                    //in the sandbox and everything would work.
-
-                    //Java 6u27 introduced new behavior where the rhino script engine
-                    //remembers the access control context with which it has been 
-                    //constructed and combines that with the callers protection domain
-                    //when a script is executed. Because this class has all perms and
-                    //all the code in RHQ that called ScriptEngine.eval* also
-                    //had all perms, the scripts would never be sandboxed even if the call
-                    //was pushed through the SandboxedScriptEngine.
-
-                    //This means that the below wrapping is necessary for the security
-                    //to work in java6 pre u27 while the surrounding privileged block 
-                    //is necessary for the security to be applied in java6 u27 and later.
-                    return new SandboxedScriptEngine(getScriptEngine(language, packageFinder, bindings), permissions);
-                }
-            }, ctx);
-        } catch (PrivilegedActionException e) {
-            Throwable cause = e.getCause();
-            if (cause instanceof IOException) {
-                throw (IOException) cause;
-            } else if (cause instanceof ScriptException) {
-                throw (ScriptException) cause;
-            } else {
-                throw new ScriptException(e);
-            }
+        
+        ScriptEngineInitializer initializer = getInitializer(language);
+
+        if (initializer == null) {
+            return null;
+        }
+
+        //TODO change this so that we support supplying a custom module source provider so that callers
+        //have control over the location of the loadable scripts.
+        ScriptEngine engine = initializer.instantiate(packageFinder.findPackages("org.rhq.core.domain"), null, permissions);
+
+        if (bindings != null) {
+            injectStandardBindings(engine, bindings, true);
         }
+
+        return engine;
     }
 
     /**
@@ -297,6 +256,12 @@ public class ScriptEngineFactory {
         return provider == null ? null : provider.getInitializer();
     }
 
+    public static CodeCompletion getCodeCompletion(String language) {
+        ScriptEngineProvider provider = KNOWN_PROVIDERS.get(language);
+        
+        return provider == null ? null : provider.getCodeCompletion();
+    }
+    
     private static boolean shouldIndirect(Method method) {
         return method.getAnnotation(NoTopLevelIndirection.class) == null;
     }
diff --git a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java
index 308d6c1..5021434 100644
--- a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java
+++ b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/ClientMain.java
@@ -26,15 +26,20 @@ import gnu.getopt.Getopt;
 import gnu.getopt.LongOpt;
 
 import java.io.ByteArrayInputStream;
+import java.io.File;
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.io.PrintWriter;
 import java.io.StreamTokenizer;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import javax.script.ScriptEngine;
+import javax.script.ScriptException;
+
 import jline.ArgumentCompletor;
 import jline.Completor;
 import jline.ConsoleReader;
@@ -42,6 +47,8 @@ import jline.MultiCompletor;
 import jline.SimpleCompletor;
 import mazz.i18n.Msg;
 
+import org.rhq.bindings.ScriptEngineFactory;
+import org.rhq.bindings.util.PackageFinder;
 import org.rhq.core.domain.auth.Subject;
 import org.rhq.enterprise.client.commands.ClientCommand;
 import org.rhq.enterprise.client.commands.ScriptCommand;
@@ -81,20 +88,23 @@ public class ClientMain {
     private int port = 7080;
     private String user;
     private String pass;
+    private String language;
     private ArrayList<String> notes = new ArrayList<String>();
-
+    
     // reference to the webservice reference factory
     private RemoteClient remoteClient;
 
     // The subject that will be used to carry out all requested actions
     private Subject subject;
-
+    
     private InteractiveJavascriptCompletor serviceCompletor;
 
     private boolean interactiveMode = true;
 
     private Recorder recorder = new NoOpRecorder();
 
+    private ScriptEngine engine;
+    
     private class StartupConfiguration {
         public boolean askForPassword;
         public boolean displayUsage;
@@ -187,8 +197,7 @@ public class ClientMain {
     }
     
     private void initServiceCompletor() {
-        ScriptCommand sc = (ScriptCommand) commands.get("exec");
-        this.serviceCompletor.setContext(sc.getContext());
+        this.serviceCompletor.setContext(getScriptEngine().getContext());
 
         if (remoteClient != null) {
             this.serviceCompletor.setServices(remoteClient.getManagers());
@@ -363,7 +372,7 @@ public class ClientMain {
         } else {
             boolean result = commands.get("exec").execute(this, args);
             if (loggedIn()) {
-                this.serviceCompletor.setContext(((ScriptCommand) commands.get("exec")).getContext());
+                this.serviceCompletor.setContext(getScriptEngine().getContext());
             }
 
             return result;
@@ -460,6 +469,7 @@ public class ClientMain {
             new LongOpt("command", LongOpt.REQUIRED_ARGUMENT, null, 'c'),
             new LongOpt("file", LongOpt.NO_ARGUMENT, null, 'f'),
             new LongOpt("version", LongOpt.NO_ARGUMENT, null, 'v'),
+            new LongOpt("language", LongOpt.REQUIRED_ARGUMENT, null, 'l'),
             new LongOpt("args-style", LongOpt.REQUIRED_ARGUMENT, null, -2) };
 
         Getopt getopt = new Getopt("Cli", args, sopts, lopts, false);
@@ -540,6 +550,9 @@ public class ClientMain {
                 }
                 break;
             }
+            case 'l':
+                this.language = getopt.getOptarg();
+                break;
             }
         }
 
@@ -619,12 +632,31 @@ public class ClientMain {
         this.outputWriter = writer;
     }
 
+    public String getLanguage() {
+        return this.language == null ? "javascript" : this.language;
+    }
+    
     public int getConsoleWidth() {
         //the console reader might be null when this method is asked for the output
         //width in non-interactive mode where we don't attach to stdin.
         return this.consoleReader == null ? DEFAULT_CONSOLE_WIDTH : this.consoleReader.getTermwidth();
     }
 
+    public ScriptEngine getScriptEngine() {
+        if (engine == null) {
+            try {
+                engine = ScriptEngineFactory.getScriptEngine(getLanguage(),
+                    new PackageFinder(Arrays.asList(getLibDir())), null);
+            } catch (ScriptException e) {
+                e.printStackTrace();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+
+        return engine;
+    }
+    
     public Map<String, ClientCommand> getCommands() {
         return commands;
     }
@@ -655,4 +687,9 @@ public class ClientMain {
     public void setRecorder(Recorder recorder) {
         this.recorder = recorder;
     }
+    
+    private static File getLibDir() {
+        String cwd = System.getProperty("user.dir");
+        return new File(cwd, "lib");
+    }
 }
diff --git a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/ScriptCommand.java b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/ScriptCommand.java
index 4e7e79a..f3084d1 100644
--- a/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/ScriptCommand.java
+++ b/modules/enterprise/remoting/cli/src/main/java/org/rhq/enterprise/client/commands/ScriptCommand.java
@@ -56,7 +56,6 @@ import org.rhq.enterprise.client.script.ScriptCmdLine;
  */
 public class ScriptCommand implements ClientCommand {
 
-    private ScriptEngine jsEngine;
     private StandardBindings bindings;
 
     private final Log log = LogFactory.getLog(ScriptCommand.class);
@@ -66,21 +65,6 @@ public class ScriptCommand implements ClientCommand {
     private boolean isMultilineScript = false;
     private boolean inMultilineScript = false;
 
-    public ScriptEngine getScriptEngine() {
-        if (jsEngine == null) {
-            try {
-                jsEngine = ScriptEngineFactory.getScriptEngine("JavaScript",
-                    new PackageFinder(Arrays.asList(getLibDir())), null);
-            } catch (ScriptException e) {
-                e.printStackTrace();
-            } catch (IOException e) {
-                e.printStackTrace();
-            }
-        }
-
-        return jsEngine;
-    }
-
     public String getPromptCommandString() {
         return "exec";
     }
@@ -100,8 +84,8 @@ public class ScriptCommand implements ClientCommand {
                 CmdLineParser cmdLineParser = new CmdLineParser();
                 ScriptCmdLine scriptCmdLine = cmdLineParser.parse(args);
 
-                bindScriptArgs(scriptCmdLine);
-                executeUtilScripts();
+                bindScriptArgs(client, scriptCmdLine);
+                executeUtilScripts(client);
 
                 FileReader reader = new FileReader(scriptCmdLine.getScriptFileName());
                 try {
@@ -153,7 +137,7 @@ public class ScriptCommand implements ClientCommand {
 
         try {
 
-            Object result = getScriptEngine().eval(script.toString());
+            Object result = client.getScriptEngine().eval(script.toString());
             inMultilineScript = false;
             script = new StringBuilder();
             if (result != null) {
@@ -199,7 +183,7 @@ public class ScriptCommand implements ClientCommand {
         bindings.put("configurationEditor", new ConfigurationEditor(client));
         bindings.put("rhq", new Controller(client));
 
-        ScriptEngine engine = getScriptEngine();
+        ScriptEngine engine = client.getScriptEngine();
 
         ScriptEngineFactory.injectStandardBindings(engine, bindings, false);
 
@@ -212,7 +196,7 @@ public class ScriptCommand implements ClientCommand {
             initBindings(client);
 
         } else {
-            ScriptEngine engine = getScriptEngine();
+            ScriptEngine engine = client.getScriptEngine();
 
             // remove any current manager bindings from the engine, they may not be valid for the
             // new client. The new standard bindings will include any new managers.
@@ -228,12 +212,12 @@ public class ScriptCommand implements ClientCommand {
         return;
     }
 
-    private void executeUtilScripts() {
+    private void executeUtilScripts(ClientMain client) {
         InputStream stream = getClass().getResourceAsStream("test_utils.js");
         InputStreamReader reader = new InputStreamReader(stream);
 
         try {
-            getScriptEngine().eval(reader);
+            client.getScriptEngine().eval(reader);
         } catch (ScriptException e) {
             log.warn("An error occurred while executing test_utils.js", e);
         }
@@ -254,17 +238,17 @@ public class ScriptCommand implements ClientCommand {
 
     }
 
-    private void bindScriptArgs(ScriptCmdLine cmdLine) {
-        bindArgsArray(cmdLine);
+    private void bindScriptArgs(ClientMain client, ScriptCmdLine cmdLine) {
+        bindArgsArray(client, cmdLine);
 
         if (cmdLine.getArgType() == ScriptCmdLine.ArgType.NAMED) {
-            bindNamedArgs(cmdLine);
+            bindNamedArgs(client, cmdLine);
         }
 
-        getScriptEngine().put("script", new File(cmdLine.getScriptFileName()).getName());
+        client.getScriptEngine().put("script", new File(cmdLine.getScriptFileName()).getName());
     }
 
-    private void bindArgsArray(ScriptCmdLine cmdLine) {
+    private void bindArgsArray(ClientMain client, ScriptCmdLine cmdLine) {
         String[] args = new String[cmdLine.getArgs().size()];
         int i = 0;
 
@@ -272,19 +256,19 @@ public class ScriptCommand implements ClientCommand {
             args[i++] = arg.getValue();
         }
 
-        getScriptEngine().put("args", args);
+        client.getScriptEngine().put("args", args);
     }
 
-    private void bindNamedArgs(ScriptCmdLine cmdLine) {
+    private void bindNamedArgs(ClientMain client, ScriptCmdLine cmdLine) {
         for (ScriptArg arg : cmdLine.getArgs()) {
             NamedScriptArg namedArg = (NamedScriptArg) arg;
-            getScriptEngine().put(namedArg.getName(), namedArg.getValue());
+            client.getScriptEngine().put(namedArg.getName(), namedArg.getValue());
         }
     }
 
-    private boolean executeScriptFile(Reader reader, ClientMain client) {
+    private boolean executeScriptFile( Reader reader, ClientMain client) {
         try {
-            Object result = getScriptEngine().eval(reader);
+            Object result = client.getScriptEngine().eval(reader);
             if (result != null) {
                 if (client.isInteractiveMode()) {
                     new TabularWriter(client.getPrintWriter()).print(result);
@@ -313,13 +297,4 @@ public class ScriptCommand implements ClientCommand {
         return "Execute a statement or a script. The following service managers are available: "
             + Arrays.toString(RhqManagers.values());
     }
-
-    public ScriptContext getContext() {
-        return getScriptEngine().getContext();
-    }
-
-    private File getLibDir() {
-        String cwd = System.getProperty("user.dir");
-        return new File(cwd, "lib");
-    }
 }
diff --git a/modules/enterprise/remoting/cli/src/test/java/org/rhq/enterprise/client/commands/ScriptCommandTest.java b/modules/enterprise/remoting/cli/src/test/java/org/rhq/enterprise/client/commands/ScriptCommandTest.java
index 4120f2d..fe109a8 100644
--- a/modules/enterprise/remoting/cli/src/test/java/org/rhq/enterprise/client/commands/ScriptCommandTest.java
+++ b/modules/enterprise/remoting/cli/src/test/java/org/rhq/enterprise/client/commands/ScriptCommandTest.java
@@ -35,10 +35,11 @@ import javax.script.Bindings;
 public class ScriptCommandTest {
 
     ScriptCommand cmd;
+    ClientMain client;
     
     @Test(enabled=false)
     public void executeShouldSetDefaultBindings() throws Exception {
-        ClientMain client = createClient();
+        client = createClient();
         cmd = new ScriptCommand();
         String script = "exec var x = 1;";
         String[] args = asList(script).toArray(new String[] {});
@@ -61,7 +62,7 @@ public class ScriptCommandTest {
     }
 
     void assertSubjectBoundToScript() {
-        ScriptEngine scriptEngine = cmd.getScriptEngine();
+        ScriptEngine scriptEngine = client.getScriptEngine();
         Object subject = scriptEngine.getBindings(ScriptContext.ENGINE_SCOPE).get("subject");
 
         assertNotNull(subject, "Expected variable 'subject' to be bound to script in global scope");
@@ -72,7 +73,7 @@ public class ScriptCommandTest {
     }
 
     void assertManagersBoundToScript() {
-        ScriptEngine scriptEngine = cmd.getScriptEngine();
+        ScriptEngine scriptEngine = client.getScriptEngine();
         List<String> mgrsNotBound = new ArrayList<String>();
 
         for (RhqManagers mgr : RhqManagers.values()) {
@@ -88,7 +89,7 @@ public class ScriptCommandTest {
     }
 
     void assertPrettyWriterBoundToScript() {
-        ScriptEngine scriptEngine = cmd.getScriptEngine();
+        ScriptEngine scriptEngine = client.getScriptEngine();
         Object writer = scriptEngine.getBindings(ScriptContext.ENGINE_SCOPE).get("pretty");
 
         assertNotNull(writer, "Expected variable 'pretty' to be bound to script in global scope");
@@ -99,7 +100,7 @@ public class ScriptCommandTest {
     }
 
     void assertScriptUtilsBoundToScript() {
-        ScriptEngine scriptEngine = cmd.getScriptEngine();
+        ScriptEngine scriptEngine = client.getScriptEngine();
         Object scriptUtil = scriptEngine.get("scriptUtil");
 
         assertNotNull(scriptUtil, "Expected variable 'scriptUtil' to be bound to script in engine scope");
@@ -110,7 +111,7 @@ public class ScriptCommandTest {
     }
 
     void assertIsDefinedFunctionBoundToScript() {
-        ScriptEngine scriptEngine = cmd.getScriptEngine();
+        ScriptEngine scriptEngine = client.getScriptEngine();
         Object function = scriptEngine.get("isDefined");
 
         assertNotNull(function, "Expected function 'isDefined' to be bound to script in engine scope");
diff --git a/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/CodeCompletion.java b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/CodeCompletion.java
index 1569896..f8beb28 100644
--- a/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/CodeCompletion.java
+++ b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/CodeCompletion.java
@@ -19,11 +19,28 @@
 
 package org.rhq.scripting;
 
+import java.util.List;
+
 /**
- * TODO This will hook into the interactive code completion provided by the CLI.
- *
+ * An interface for performing code completion in a given language.
+ * This inspired by the jline's <code>Completor</code> interface but
+ * is defined separately so that we don't introduce a dependency on 
+ * jline where it doesn't make sense.
+ * 
  * @author Lukas Krejci
  */
 public interface CodeCompletion {
 
+    /**
+     * Generates the completion candidates and fills the supplied list with them.
+     * 
+     * @param context the context of the code completion, usually that is the current
+     * statement being edited by the user
+     * @param cursorPosition the position of the cursor inside the context
+     * @param completions this should be a list of strings but is intentionally left raw
+     * so that this interface is compatible with jline's <code>Completor</code>.
+     * @return the character index in the context for which the completion candidates were
+     * actually generated (might be different from the cursorPosition).
+     */
+    int complete(String context, int cursorPosition, @SuppressWarnings("rawtypes") List candidates);
 }
diff --git a/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptEngineInitializer.java b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptEngineInitializer.java
index 3286f39..9365304 100644
--- a/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptEngineInitializer.java
+++ b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptEngineInitializer.java
@@ -20,6 +20,7 @@
 package org.rhq.scripting;
 
 import java.lang.reflect.Method;
+import java.security.PermissionCollection;
 import java.util.Set;
 
 import javax.script.ScriptEngine;
@@ -33,7 +34,20 @@ import javax.script.ScriptException;
  */
 public interface ScriptEngineInitializer {
 
-    ScriptEngine instantiate(Set<String> packages) throws ScriptException;
+    /**
+     * Instantiates a new script engine, makes the provided java packages "imported" into the context
+     * (i.e. classes from those packages can be instantiated without providing the full class name)
+     * and makes the script engine use the scriptSourceProvider to locate scripts.
+     * 
+     * @param packages the list of java packages to be imported in the context
+     * @param scriptSourceProvider the provider of the sources of scripts - can be null to use no
+     * script source provider and depend on the default module loading mechanisms of the script language
+     * @param permissions the security permissions the script engine should execute the script with, can be null
+     * in which case the script engine is unsecured
+     * @return a newly instantiated script engine configured as above
+     * @throws ScriptException
+     */
+    ScriptEngine instantiate(Set<String> packages, ScriptSourceProvider scriptSourceProvider, PermissionCollection permissions) throws ScriptException;
     
     /**
      * This function returns a definition string in the script engine's language
diff --git a/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptSourceProvider.java b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptSourceProvider.java
new file mode 100644
index 0000000..276e385
--- /dev/null
+++ b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptSourceProvider.java
@@ -0,0 +1,35 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 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.scripting;
+
+import java.io.Reader;
+import java.net.URI;
+
+/**
+ * Scripts in RHQ can be stored in various locations or maybe not even in the filesystem.
+ * Implementations of this interface can be used to provide the contents of the scripts
+ * based on URIs. 
+ *
+ * @author Lukas Krejci
+ */
+public interface ScriptSourceProvider {
+
+    Reader getScriptSource(URI location);
+}
diff --git a/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/util/SandboxedScriptEngine.java b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/util/SandboxedScriptEngine.java
new file mode 100644
index 0000000..857c6f1
--- /dev/null
+++ b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/util/SandboxedScriptEngine.java
@@ -0,0 +1,224 @@
+/*
+ * 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 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.scripting.util;
+
+import java.io.Reader;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.CodeSource;
+import java.security.Permission;
+import java.security.PermissionCollection;
+import java.security.Permissions;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.security.ProtectionDomain;
+import java.security.cert.Certificate;
+import java.util.Arrays;
+import java.util.Collection;
+
+import javax.script.Bindings;
+import javax.script.ScriptContext;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineFactory;
+import javax.script.ScriptException;
+
+/**
+ * This is a decorator class for any other {@link ScriptEngine} implementation
+ * that runs any of the eval methods with the defined set of {@link Permission}s. 
+ * <p>
+ * For the permissions to have any effect, a SecurityManager has to be installed 
+ * in the current VM.
+ * <p>
+ * This class is provided in hopes that it can help provide security to script engines
+ * that do not directly implement some kind of security measures.
+ * 
+ * @author Lukas Krejci
+ */
+public class SandboxedScriptEngine implements ScriptEngine {
+
+    private ScriptEngine engine;
+    private AccessControlContext accessControlContext;
+        
+    public SandboxedScriptEngine(ScriptEngine engine) {
+        this.engine = engine;
+    }
+    
+    public SandboxedScriptEngine(ScriptEngine engine, PermissionCollection permissions) {
+        this(engine);
+        setPermissions(permissions);
+    }
+
+    public SandboxedScriptEngine(ScriptEngine engine, Collection<? extends Permission> permissions) {
+        this(engine);
+        setPermissions(permissions);
+    }
+
+    public void setPermissions(Permission... permissions) {
+        setPermissions(Arrays.asList(permissions));
+    }
+    
+    public void setPermissions(Collection<? extends Permission> permissions) {
+        Permissions ps = new Permissions();
+        for(Permission p : permissions) {
+            ps.add(p);
+        }
+        
+        setPermissions(ps);
+    }
+    
+    public void setPermissions(PermissionCollection permissions) {
+        CodeSource cs = new CodeSource(null, (Certificate[]) null);
+        
+        ProtectionDomain domain = new ProtectionDomain(cs, permissions);        
+        accessControlContext = new AccessControlContext(new ProtectionDomain[] { domain });
+    }
+    
+    @Override
+    public Object eval(final String script, final ScriptContext context) throws ScriptException {
+        try {
+            return AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
+                @Override
+                public Object run() throws Exception {
+                    return engine.eval(script, context);
+                }
+            }, accessControlContext);
+        } catch (PrivilegedActionException e) {
+            throw transfer(e);
+        }        
+    }
+
+    @Override
+    public Object eval(final Reader reader, final ScriptContext context) throws ScriptException {
+        try {
+            return AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
+                @Override
+                public Object run() throws Exception {
+                    return engine.eval(reader, context);
+                }
+            }, accessControlContext);
+        } catch (PrivilegedActionException e) {
+            throw transfer(e);
+        }        
+    }
+
+    @Override
+    public Object eval(final String script) throws ScriptException {
+        try {
+            return AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
+                @Override
+                public Object run() throws Exception {
+                    return engine.eval(script);
+                }
+            }, accessControlContext);
+        } catch (PrivilegedActionException e) {
+            throw transfer(e);
+        }        
+    }
+
+    @Override
+    public Object eval(final Reader reader) throws ScriptException {
+        try {
+            return AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
+                @Override
+                public Object run() throws Exception {
+                    return engine.eval(reader);
+                }
+            }, accessControlContext);
+        } catch (PrivilegedActionException e) {
+            throw transfer(e);
+        }        
+    }
+
+    @Override
+    public Object eval(final String script, final Bindings n) throws ScriptException {
+        try {
+            return AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
+                @Override
+                public Object run() throws Exception {
+                    return engine.eval(script, n);
+                }
+            }, accessControlContext);
+        } catch (PrivilegedActionException e) {
+            throw transfer(e);
+        }        
+    }
+
+    @Override
+    public Object eval(final Reader reader, final Bindings n) throws ScriptException {
+        try {
+            return AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
+                @Override
+                public Object run() throws Exception {
+                    return engine.eval(reader, n);
+                }
+            }, accessControlContext);
+        } catch (PrivilegedActionException e) {
+            throw transfer(e);
+        }        
+    }
+
+    @Override
+    public void put(String key, Object value) {
+        engine.put(key, value);
+    }
+
+    @Override
+    public Object get(String key) {
+        return engine.get(key);
+    }
+
+    @Override
+    public Bindings getBindings(int scope) {
+        return engine.getBindings(scope);
+    }
+
+    @Override
+    public void setBindings(Bindings bindings, int scope) {
+        engine.setBindings(bindings, scope);
+    }
+
+    @Override
+    public Bindings createBindings() {
+        return engine.createBindings();
+    }
+
+    @Override
+    public ScriptContext getContext() {
+        return engine.getContext();
+    }
+
+    @Override
+    public void setContext(ScriptContext context) {
+        engine.setContext(context);
+    }
+
+    @Override
+    public ScriptEngineFactory getFactory() {
+        return engine.getFactory();
+    }
+    
+    private static ScriptException transfer(PrivilegedActionException e) {
+        if (e.getCause() instanceof ScriptException) {
+            return (ScriptException) e.getCause();
+        } else {
+            return new ScriptException(e);
+        }
+    }
+}
diff --git a/modules/enterprise/scripting/javascript/pom.xml b/modules/enterprise/scripting/javascript/pom.xml
index 8a5d96a..e813d3b 100644
--- a/modules/enterprise/scripting/javascript/pom.xml
+++ b/modules/enterprise/scripting/javascript/pom.xml
@@ -23,7 +23,8 @@
           <version>1.7R3</version>
        </dependency>
        
-       <!-- JSR 223 support for Rhino -->
+<!-- we no longer depend on Phobos because we now bundle the Phobos script engine with
+     our own modifications. 
        <dependency>
           <groupId>com.sun.phobos</groupId>
           <artifactId>phobos-js</artifactId>
@@ -35,7 +36,7 @@
              </exclusion>
           </exclusions>
        </dependency>
-       
+ -->              
     </dependencies>
     
     <build>
@@ -44,6 +45,9 @@
                 <artifactId>maven-surefire-plugin</artifactId>
                 <configuration>
                     <excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
+                    <argLine>-Djava.security.manager -Djava.security.policy==${project.build.testOutputDirectory}/allow-all.policy</argLine>    
+                    <!-- This is important, because some of the tests try to exit the JVM. -->
+                    <failIfNoTests>true</failIfNoTests>                    
                 </configuration>
             </plugin>
         </plugins>
diff --git a/modules/enterprise/scripting/javascript/src/main/java/com/sun/phobos/script/javascript/PrintHavingRhinoScriptEngine.java b/modules/enterprise/scripting/javascript/src/main/java/com/sun/phobos/script/javascript/PrintHavingRhinoScriptEngine.java
deleted file mode 100644
index 5a176fd..0000000
--- a/modules/enterprise/scripting/javascript/src/main/java/com/sun/phobos/script/javascript/PrintHavingRhinoScriptEngine.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2012 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 com.sun.phobos.script.javascript;
-
-import javax.script.ScriptContext;
-
-import org.mozilla.javascript.Context;
-import org.mozilla.javascript.Scriptable;
-
-/**
- * We want our script engine to mimic the real JDK one as close as
- * possible.
- * 
- * The Phobos impl of the script engine leaves out the predefined 
- * print() and println() functions, but we really want them.
- * 
- * To add them back we need to override a package-private method
- * in the phobos script engine.
- *
- * @author Lukas Krejci
- */
-public class PrintHavingRhinoScriptEngine extends RhinoScriptEngine {
-
-    //copied over from the JDK's impl of RhinoScriptEngine
-    private static final String printSource =
-        "function print(str, newline) {                \n" +
-        "    if (typeof(str) == 'undefined') {         \n" +
-        "        str = 'undefined';                    \n" +
-        "    } else if (str == null) {                 \n" +
-        "        str = 'null';                         \n" +
-        "    }                                         \n" +
-        "    var out = context.getWriter();            \n" +
-        "    out.print(String(str));                   \n" +
-        "    if (newline) out.print('\\n');            \n" +
-        "    out.flush();                              \n" +
-        "}\n" +
-        "function println(str) {                       \n" +
-        "    print(str, true);                         \n" +
-        "}";
-    
-    @Override
-    Scriptable getRuntimeScope(ScriptContext ctxt) {
-        Scriptable newScope = super.getRuntimeScope(ctxt);
-        
-        Context cx = enterContext();
-        try {
-            cx.evaluateString(newScope, printSource, "print", 1, null);
-            
-            return newScope;
-        } finally {
-            Context.exit();
-        }
-    }
-}
diff --git a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineInitializer.java b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineInitializer.java
index 803225f..771ec1f 100644
--- a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineInitializer.java
+++ b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineInitializer.java
@@ -20,6 +20,14 @@
 package org.rhq.scripting.javascript;
 
 import java.lang.reflect.Method;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.CodeSource;
+import java.security.PermissionCollection;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.security.ProtectionDomain;
+import java.security.cert.Certificate;
 import java.util.Collections;
 import java.util.Set;
 
@@ -28,6 +36,9 @@ import javax.script.ScriptEngineManager;
 import javax.script.ScriptException;
 
 import org.rhq.scripting.ScriptEngineInitializer;
+import org.rhq.scripting.ScriptSourceProvider;
+import org.rhq.scripting.javascript.engine.RhinoScriptEngine;
+import org.rhq.scripting.javascript.util.ScriptSourceToModuleSourceProviderAdapter;
 
 /**
  * 
@@ -39,16 +50,34 @@ public class JsEngineInitializer implements ScriptEngineInitializer {
     private static final String WRAPPED_EXCEPTION_PREFIX = "Wrapped ";
 
     private ScriptEngineManager engineManager = new ScriptEngineManager();
-    
+
     @Override
-    public ScriptEngine instantiate(Set<String> packages) throws ScriptException {
-        ScriptEngine eng = engineManager.getEngineByName("rhino-nonjdk");
+    public ScriptEngine instantiate(final Set<String> packages, final ScriptSourceProvider scriptSourceProvider,
+        PermissionCollection permissions) throws ScriptException {
         
-        for(String pkg : packages) {
-            eng.eval("importPackage(" + pkg + ")");
+        if (permissions == null) {
+            return instantiateUnsecured(packages, scriptSourceProvider);
+        } else {
+            try {
+                CodeSource cs = new CodeSource(null, (Certificate[]) null);
+                ProtectionDomain securityDomain = new ProtectionDomain(cs, permissions);
+
+                AccessControlContext acc = new AccessControlContext(new ProtectionDomain[] { securityDomain });
+
+                return AccessController.doPrivileged(new PrivilegedExceptionAction<ScriptEngine>() {
+                    @Override
+                    public ScriptEngine run() throws Exception {
+                        return instantiateUnsecured(packages, scriptSourceProvider);
+                    }
+                }, acc);
+            } catch (PrivilegedActionException e) {
+                if (e.getCause() instanceof ScriptException) {
+                    throw (ScriptException) e.getCause();
+                } else {
+                    throw new ScriptException("Script execution failed.");
+                }
+            }
         }
-        
-        return eng;
     }
 
     @Override
@@ -56,50 +85,69 @@ public class JsEngineInitializer implements ScriptEngineInitializer {
         if (methods.size() == 0) {
             return Collections.emptySet();
         }
-        
+
         String methodName = methods.iterator().next().getName();
-                
+
         StringBuilder functionBuilder = new StringBuilder("function ");
         functionBuilder.append(methodName).append("() { switch(arguments.length) { ");
-        
-        for(Method method : methods) {
+
+        for (Method method : methods) {
             int argCnt = method.getParameterTypes().length;
             functionBuilder.append("case ").append(argCnt).append(": ");
             functionBuilder.append("return ").append(boundObjectName).append(".").append(methodName).append("(");
-            for(int i = 0; i < argCnt; ++i) {
+            for (int i = 0; i < argCnt; ++i) {
                 if (i > 0) {
                     functionBuilder.append(", ");
                 }
-                
+
                 functionBuilder.append("arguments[").append(i).append("]");
             }
-            
+
             functionBuilder.append("); break; ");
         }
-        
+
         functionBuilder.append(" default: throw \"Unsupported number of parameters.\"; } }");
-        
+
         return Collections.singleton(functionBuilder.toString());
     }
-    
+
     @Override
     public String extractUserFriendlyErrorMessage(ScriptException e) {
         String errorMessage = e.getMessage();
-        
+
         int wrappedIdx = errorMessage.lastIndexOf(WRAPPED_EXCEPTION_PREFIX);
-        
+
         if (wrappedIdx < 0) {
             return errorMessage;
         }
-        
-        errorMessage = errorMessage.substring(wrappedIdx + WRAPPED_EXCEPTION_PREFIX.length());        
-        
+
+        errorMessage = errorMessage.substring(wrappedIdx + WRAPPED_EXCEPTION_PREFIX.length());
+
         int sourceInfoStartIdx = errorMessage.indexOf(" (<Unknown source>#");
-        
+
         if (sourceInfoStartIdx >= 0) {
             errorMessage = errorMessage.substring(0, sourceInfoStartIdx);
         }
-        
+
         return errorMessage;
     }
+
+    private ScriptEngine instantiateUnsecured(Set<String> packages, ScriptSourceProvider scriptSourceProvider)
+        throws ScriptException {
+        RhinoScriptEngine eng = (RhinoScriptEngine) engineManager.getEngineByName("rhino-nonjdk");
+        
+        if (eng == null) {
+            throw new IllegalStateException("Failed to instantiate the 'rhino-nonjdk' script engine. This means that either the required library is missing from the classpath or that there are some security issues preventing it from being instantiated.");
+        }
+        
+        if (scriptSourceProvider != null) {
+            eng.setModuleSourceProvider(new ScriptSourceToModuleSourceProviderAdapter(scriptSourceProvider));
+        }
+
+        for (String pkg : packages) {
+            eng.eval("importPackage(" + pkg + ")");
+        }
+
+        return eng;
+    }
 }
diff --git a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineProvider.java b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineProvider.java
index 8d9e4b7..984e5fc 100644
--- a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineProvider.java
+++ b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineProvider.java
@@ -32,7 +32,7 @@ public class JsEngineProvider implements ScriptEngineProvider {
 
     @Override
     public String getSupportedLanguage() {
-        return "JavaScript";
+        return "javascript";
     }
 
     @Override
diff --git a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/Main.java b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/Main.java
deleted file mode 100644
index 6bbf542..0000000
--- a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/Main.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2012 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.scripting.javascript;
-
-import java.io.PrintWriter;
-
-import javax.script.ScriptEngine;
-import javax.script.ScriptEngineManager;
-
-/**
- * 
- *
- * @author Lukas Krejci
- */
-public class Main {
-
-    public static void main(String[] args) throws Exception {
-        ScriptEngineManager manager = new ScriptEngineManager();
-        ScriptEngine engine = manager.getEngineByName("rhino-nonjdk");               
-        
-        engine.getContext().setWriter(new PrintWriter(System.out, true));
-        engine.eval("importPackage(java.lang); println('ahoj')");
-    }
-}
diff --git a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/ScriptEngine.java b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/ScriptEngine.java
deleted file mode 100644
index ed8a33f..0000000
--- a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/ScriptEngine.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2012 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.scripting.javascript;
-
-import com.sun.phobos.script.javascript.PrintHavingRhinoScriptEngine;
-
-/**
- * 
- *
- * @author Lukas Krejci
- */
-public class ScriptEngine extends PrintHavingRhinoScriptEngine {
-
-    private ScriptEngineFactory factory;
-    
-    @Override
-    public ScriptEngineFactory getFactory() {
-        if (factory == null) {
-            factory = new ScriptEngineFactory();
-        }
-            
-        return factory;
-    }
-    
-    void setFactory(ScriptEngineFactory factory) {
-        this.factory = factory;
-    }
-}
diff --git a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/ScriptEngineFactory.java b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/ScriptEngineFactory.java
deleted file mode 100644
index 824f97a..0000000
--- a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/ScriptEngineFactory.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2012 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.scripting.javascript;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-import javax.script.ScriptEngine;
-
-import com.sun.phobos.script.javascript.RhinoScriptEngineFactory;
-
-import org.mozilla.javascript.Context;
-
-/**
- * 
- *
- * @author Lukas Krejci
- */
-public class ScriptEngineFactory extends RhinoScriptEngineFactory {
-    
-    private static final List<String> NAMES;
-    private static final String ENGINE_VERSION;
-    private static final String LANGUAGE_VERSION;
-    static {
-        Context.enter();
-        ENGINE_VERSION = Context.getCurrentContext().getImplementationVersion();
-        int ver = Context.getCurrentContext().getLanguageVersion();
-        Context.exit();
-        
-        String version = null;
-        if (ver == 0) {
-            version = "1.7";
-        } else {
-            //the versions are formatted like 170 for 1.7, 180 for 1.8, etc
-            int major = ver / 100;
-            int minor = (ver - 100) / 10;
-            version = major + "." + minor;
-        }
-        
-        LANGUAGE_VERSION = version;
-        
-        NAMES = Collections.unmodifiableList(Arrays.asList("rhino-nonjdk"));
-        
-    }
-    
-    @Override
-    public List<String> getNames() {
-        return NAMES;
-    }
-    
-    @Override
-    public Object getParameter(String key) {
-        if (ScriptEngine.ENGINE_VERSION.equals(key)) {
-            return ENGINE_VERSION;
-        } else if (ScriptEngine.LANGUAGE_VERSION.equals(key)) {
-            return LANGUAGE_VERSION;
-        } else {
-            return super.getParameter(key);
-        }
-    }   
-    
-    @Override
-    public ScriptEngine getScriptEngine() {
-        org.rhq.scripting.javascript.ScriptEngine engine = new org.rhq.scripting.javascript.ScriptEngine();
-        engine.setFactory(this);
-        return engine;
-    }
-}
diff --git a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/ExternalScriptable.java b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/ExternalScriptable.java
new file mode 100644
index 0000000..e14dc4b
--- /dev/null
+++ b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/ExternalScriptable.java
@@ -0,0 +1,496 @@
+/*
+ * Copyright (C) 2006 Sun Microsystems, Inc. All rights reserved. 
+ * Use is subject to license terms.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are 
+ * permitted provided that the following conditions are met: Redistributions of source code 
+ * must retain the above copyright notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice, this list of 
+ * conditions and the following disclaimer in the documentation and/or other materials 
+ * provided with the distribution. Neither the name of the Sun Microsystems nor the names of 
+ * is contributors may be used to endorse or promote products derived from this software 
+ * without specific prior written permission. 
+
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.rhq.scripting.javascript.engine;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.script.Bindings;
+import javax.script.ScriptContext;
+
+import org.mozilla.javascript.Context;
+import org.mozilla.javascript.Function;
+import org.mozilla.javascript.NativeJavaClass;
+import org.mozilla.javascript.ScriptRuntime;
+import org.mozilla.javascript.Scriptable;
+import org.mozilla.javascript.ScriptableObject;
+import org.mozilla.javascript.Wrapper;
+
+/**
+ * ExternalScriptable is an implementation of Scriptable 
+ * backed by a JSR 223 Bindings instance.
+ *
+ * @author Mike Grogan
+ * @author A. Sundararajan
+ * @since 1.6
+ */
+final class ExternalScriptable implements Scriptable {
+    /* Underlying ScriptContext that we use to store
+     * named variables of this scope.
+     */
+    private ScriptContext context;
+
+    /* JavaScript allows variables to be named as numbers (indexed
+     * properties). This way arrays, objects (scopes) are treated uniformly. 
+     * Note that JSR 223 API supports only String named variables and 
+     * so we can't store these in Bindings. Also, JavaScript allows name 
+     * of the property name to be even empty String! Again, JSR 223 API 
+     * does not support empty name. So, we use the following fallback map 
+     * to store such variables of this scope. This map is not exposed to
+     * JSR 223 API. We can just script objects "as is" and need not convert.
+     */
+    private Map indexedProps;
+
+    // my prototype
+    private Scriptable prototype;
+    // my parent scope, if any
+    private Scriptable parent;
+
+    ExternalScriptable(ScriptContext context) {
+        this(context, new HashMap());
+    }
+
+    ExternalScriptable(ScriptContext context, Map indexedProps) {
+        if (context == null) {
+            throw new NullPointerException("context is null");
+        }
+        this.context = context;
+        this.indexedProps = indexedProps;
+    }
+
+    ScriptContext getContext() {
+        return context;
+    }
+
+    private boolean isInIndexedProps(Object key) {
+        return indexedProps != null && indexedProps.containsKey(key);
+    }
+
+    private boolean isEmpty(String name) {
+        return name.equals("");
+    }
+
+    /**
+     * Return the name of the class.   
+     */
+    @Override
+    public String getClassName() {
+        return "Global";
+    }
+
+    /**
+     * Returns the value of the named property or NOT_FOUND.
+     *
+     * If the property was created using defineProperty, the
+     * appropriate getter method is called.
+     *
+     * @param name the name of the property
+     * @param start the object in which the lookup began
+     * @return the value of the property (may be null), or NOT_FOUND
+     */
+    @Override
+    public synchronized Object get(String name, Scriptable start) {
+        if (isEmpty(name)) {
+            if (indexedProps.containsKey(name)) {                
+                return indexedProps.get(name);
+            } else {
+                return NOT_FOUND;
+            }
+        } else {
+            synchronized (context) {
+                int scope = context.getAttributesScope(name);
+                if (scope != -1) {
+                    Object value = context.getAttribute(name, scope);
+                    return Context.javaToJS(value, this);
+                } else {
+                    return NOT_FOUND;
+                }
+            }
+        }
+    }
+
+    /**
+     * Returns the value of the indexed property or NOT_FOUND.
+     *
+     * @param index the numeric index for the property
+     * @param start the object in which the lookup began
+     * @return the value of the property (may be null), or NOT_FOUND
+     */
+    @Override
+    public synchronized Object get(int index, Scriptable start) {
+        Integer key = new Integer(index);
+        if (indexedProps.containsKey(index)) {
+            return indexedProps.get(key);
+        } else {
+            return NOT_FOUND;
+        }            
+    }
+
+    /**
+     * Returns true if the named property is defined.
+     *
+     * @param name the name of the property
+     * @param start the object in which the lookup began
+     * @return true if and only if the property was found in the object
+     */
+    @Override
+    public synchronized boolean has(String name, Scriptable start) {
+        if (isEmpty(name)) {
+            return indexedProps.containsKey(name);
+        } else {
+            synchronized (context) {
+                return context.getAttributesScope(name) != -1;
+            }
+        }
+    }
+
+    /**
+     * Returns true if the property index is defined.
+     *
+     * @param index the numeric index for the property
+     * @param start the object in which the lookup began
+     * @return true if and only if the property was found in the object
+     */
+    @Override
+    public synchronized boolean has(int index, Scriptable start) {
+        Integer key = new Integer(index);
+        return indexedProps.containsKey(key);
+    }
+
+    /**
+     * Sets the value of the named property, creating it if need be.
+     *    
+     * @param name the name of the property
+     * @param start the object whose property is being set
+     * @param value value to set the property to
+     */
+    @Override
+    public void put(String name, Scriptable start, Object value) {
+        if (start == this) {
+            synchronized (this) {
+                if (isEmpty(name)) {
+                    indexedProps.put(name, value);
+                } else {
+                    synchronized (context) {
+                        int scope = context.getAttributesScope(name);
+                        if (scope == -1) {
+                            scope = ScriptContext.ENGINE_SCOPE;
+                        }
+                        context.setAttribute(name, jsToJava(value), scope);
+                    }
+                }
+            }
+        } else {
+            start.put(name, start, value);
+        }
+    }
+
+    /**
+     * Sets the value of the indexed property, creating it if need be.
+     *
+     * @param index the numeric index for the property
+     * @param start the object whose property is being set
+     * @param value value to set the property to
+     */
+    @Override
+    public void put(int index, Scriptable start, Object value) {
+        if (start == this) {
+            synchronized (this) {
+                indexedProps.put(new Integer(index), value);
+            }
+        } else {
+            start.put(index, start, value);
+        }
+    }
+
+    /**
+     * Removes a named property from the object.
+     *
+     * If the property is not found, no action is taken.
+     *
+     * @param name the name of the property
+     */
+    @Override
+    public synchronized void delete(String name) {
+        if (isEmpty(name)) {
+            indexedProps.remove(name);
+        } else {
+            synchronized (context) {
+                int scope = context.getAttributesScope(name);
+                if (scope != -1) {
+                    context.removeAttribute(name, scope);
+                }
+            }
+        }
+    }
+
+    /**
+     * Removes the indexed property from the object.
+     *
+     * If the property is not found, no action is taken.
+     *
+     * @param index the numeric index for the property
+     */
+    @Override
+    public void delete(int index) {
+        indexedProps.remove(new Integer(index));
+    }
+
+    /**
+     * Get the prototype of the object.
+     * @return the prototype
+     */
+    @Override
+    public Scriptable getPrototype() {
+        return prototype;
+    }
+
+    /**
+     * Set the prototype of the object.
+     * @param prototype the prototype to set
+     */
+    @Override
+    public void setPrototype(Scriptable prototype) {
+        this.prototype = prototype;
+    }
+
+    /**
+     * Get the parent scope of the object.
+     * @return the parent scope
+     */
+    @Override
+    public Scriptable getParentScope() {
+        return parent;
+    }
+
+    /**
+     * Set the parent scope of the object.
+     * @param parent the parent scope to set
+     */
+    @Override
+    public void setParentScope(Scriptable parent) {
+        this.parent = parent;
+    }
+
+     /**
+     * Get an array of property ids.
+     *
+     * Not all property ids need be returned. Those properties
+     * whose ids are not returned are considered non-enumerable.
+     *
+     * @return an array of Objects. Each entry in the array is either
+     *         a java.lang.String or a java.lang.Number
+     */
+    @Override
+    public synchronized Object[] getIds() {
+        String[] keys = getAllKeys();
+        int size = keys.length + indexedProps.size();
+        Object[] res = new Object[size];
+        System.arraycopy(keys, 0, res, 0, keys.length);
+        int i = keys.length;
+        // now add all indexed properties
+        for (Object index : indexedProps.keySet()) {
+            res[i++] = index;
+        }
+        return res;
+    }
+
+    /**
+     * Get the default value of the object with a given hint.
+     * The hints are String.class for type String, Number.class for type
+     * Number, Scriptable.class for type Object, and Boolean.class for
+     * type Boolean. <p>
+     *
+     * A <code>hint</code> of null means "no hint".
+     *
+     * See ECMA 8.6.2.6.
+     *
+     * @param hint the type hint
+     * @return the default value
+     */
+    @Override
+    public Object getDefaultValue(Class typeHint) {
+        for (int i=0; i < 2; i++) {
+            boolean tryToString;
+            if (typeHint == ScriptRuntime.StringClass) {
+                tryToString = (i == 0);
+            } else {
+                tryToString = (i == 1);
+            }
+
+            String methodName;
+            Object[] args;
+            if (tryToString) {
+                methodName = "toString";
+                args = ScriptRuntime.emptyArgs;
+            } else {
+                methodName = "valueOf";
+                args = new Object[1];
+                String hint;
+                if (typeHint == null) {
+                    hint = "undefined";
+                } else if (typeHint == ScriptRuntime.StringClass) {
+                    hint = "string";
+                } else if (typeHint == ScriptRuntime.ScriptableClass) {
+                    hint = "object";
+                } else if (typeHint == ScriptRuntime.FunctionClass) {
+                    hint = "function";
+                } else if (typeHint == ScriptRuntime.BooleanClass
+                           || typeHint == Boolean.TYPE)
+                {
+                    hint = "boolean";
+                } else if (typeHint == ScriptRuntime.NumberClass ||
+                         typeHint == ScriptRuntime.ByteClass ||
+                         typeHint == Byte.TYPE ||
+                         typeHint == ScriptRuntime.ShortClass ||
+                         typeHint == Short.TYPE ||
+                         typeHint == ScriptRuntime.IntegerClass ||
+                         typeHint == Integer.TYPE ||
+                         typeHint == ScriptRuntime.FloatClass ||
+                         typeHint == Float.TYPE ||
+                         typeHint == ScriptRuntime.DoubleClass ||
+                         typeHint == Double.TYPE)
+                {
+                    hint = "number";
+                } else {
+                    throw Context.reportRuntimeError(
+                        "Invalid JavaScript value of type " + 
+                        typeHint.toString());
+                }
+                args[0] = hint;
+            }
+            Object v = ScriptableObject.getProperty(this, methodName);
+            if (!(v instanceof Function))
+                continue;
+            Function fun = (Function) v;
+            Context cx = RhinoScriptEngine.enterContext();
+            try {
+                v = fun.call(cx, fun.getParentScope(), this, args);
+            } finally {
+                cx.exit();
+            }
+            if (v != null) {
+                if (!(v instanceof Scriptable)) {
+                    return v;
+                }
+                if (typeHint == ScriptRuntime.ScriptableClass
+                    || typeHint == ScriptRuntime.FunctionClass)
+                {
+                    return v;
+                }
+                if (tryToString && v instanceof Wrapper) {
+                    // Let a wrapped java.lang.String pass for a primitive
+                    // string.
+                    Object u = ((Wrapper)v).unwrap();
+                    if (u instanceof String)
+                        return u;
+                }
+            }
+        }
+        // fall through to error
+        String arg = (typeHint == null) ? "undefined" : typeHint.getName();
+        throw Context.reportRuntimeError(
+                  "Cannot find default value for object " + arg); 
+    }
+
+    /**  
+     * Implements the instanceof operator.
+     *
+     * @param instance The value that appeared on the LHS of the instanceof
+     *              operator
+     * @return true if "this" appears in value's prototype chain
+     *
+     */
+    @Override
+    public boolean hasInstance(Scriptable instance) {
+        // Default for JS objects (other than Function) is to do prototype
+        // chasing.
+        Scriptable proto = instance.getPrototype();
+        while (proto != null) {
+            if (proto.equals(this)) return true;
+            proto = proto.getPrototype();
+        }
+        return false;
+    }
+
+    private String[] getAllKeys() {
+        ArrayList<String> list = new ArrayList<String>();
+        synchronized (context) {
+            for (int scope : context.getScopes()) {
+                Bindings bindings = context.getBindings(scope);
+                if (bindings != null) {
+                    list.ensureCapacity(bindings.size());
+                    for (String key : bindings.keySet()) {
+                        list.add(key);
+                    }
+                }
+            }
+        }
+        String[] res = new String[list.size()];
+        list.toArray(res);
+        return res;
+    }
+
+   /**
+    * We convert script values to the nearest Java value.
+    * We unwrap wrapped Java objects so that access from
+    * Bindings.get() would return "workable" value for Java.
+    * But, at the same time, we need to make few special cases
+    * and hence the following function is used.
+    */
+    private Object jsToJava(Object jsObj) {
+        if (jsObj instanceof Wrapper) {
+            Wrapper njb = (Wrapper) jsObj;
+            /* importClass feature of ImporterTopLevel puts
+             * NativeJavaClass in global scope. If we unwrap
+             * it, importClass won't work.
+             */
+            if (njb instanceof NativeJavaClass) {
+                return njb;
+            }
+
+            /* script may use Java primitive wrapper type objects
+             * (such as java.lang.Integer, java.lang.Boolean etc)
+             * explicitly. If we unwrap, then these script objects
+             * will become script primitive types. For example,
+             * 
+             *    var x = new java.lang.Double(3.0); print(typeof x);
+             * 
+             * will print 'number'. We don't want that to happen.
+             */
+            Object obj = njb.unwrap();
+            if (obj instanceof Number || obj instanceof String ||
+                obj instanceof Boolean || obj instanceof Character) {
+                // special type wrapped -- we just leave it as is.
+                return njb;
+            } else {
+                // return unwrapped object for any other object.
+                return obj;
+            }
+        } else { // not-a-Java-wrapper
+            return jsObj;
+        }
+    }
+}
diff --git a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/JSAdapter.java b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/JSAdapter.java
new file mode 100644
index 0000000..b56bab7
--- /dev/null
+++ b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/JSAdapter.java
@@ -0,0 +1,361 @@
+/*
+ * Copyright (C) 2006 Sun Microsystems, Inc. All rights reserved. 
+ * Use is subject to license terms.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are 
+ * permitted provided that the following conditions are met: Redistributions of source code 
+ * must retain the above copyright notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice, this list of 
+ * conditions and the following disclaimer in the documentation and/or other materials 
+ * provided with the distribution. Neither the name of the Sun Microsystems nor the names of 
+ * is contributors may be used to endorse or promote products derived from this software 
+ * without specific prior written permission. 
+
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+ 
+package org.rhq.scripting.javascript.engine;
+
+import org.mozilla.javascript.Context;
+import org.mozilla.javascript.Function;
+import org.mozilla.javascript.NativeArray;
+import org.mozilla.javascript.NativeJavaArray;
+import org.mozilla.javascript.RhinoException;
+import org.mozilla.javascript.Scriptable;
+import org.mozilla.javascript.ScriptableObject;
+
+/**
+ * JSAdapter is java.lang.reflect.Proxy equivalent for JavaScript. JSAdapter
+ * calls specially named JavaScript methods on an adaptee object when property
+ * access is attempted on it.
+ *
+ * Example:
+ *
+ *    var y = {
+ *                __get__    : function (name) { ... }
+ *                __has__    : function (name) { ... }
+ *                __put__    : function (name, value) {...}
+ *                __delete__ : function (name) { ... }
+ *                __getIds__ : function () { ... }
+ *            };
+ *
+ *    var x = new JSAdapter(y);
+ *
+ *    x.i;                        // calls y.__get__
+ *    i in x;                     // calls y.__has__
+ *    x.p = 10;                   // calls y.__put__
+ *    delete x.p;                 // calls y.__delete__
+ *    for (i in x) { print(i); }  // calls y.__getIds__
+ *
+ * If a special JavaScript method is not found in the adaptee, then JSAdapter
+ * forwards the property access to the adaptee itself.
+ *
+ * JavaScript caller of adapter object is isolated from the fact that
+ * the property access/mutation/deletion are really calls to
+ * JavaScript methods on adaptee.  Use cases include 'smart'
+ * properties, property access tracing/debugging, encaptulation with
+ * easy client access - in short JavaScript becomes more "Self" like.
+ *
+ * Note that Rhino already supports special properties like __proto__
+ * (to set, get prototype), __parent__ (to set, get parent scope). We
+ * follow the same double underscore nameing convention here. Similarly
+ * the name JSAdapter is derived from JavaAdapter -- which is a facility
+ * to extend, implement Java classes/interfaces by JavaScript.
+ *
+ * @version 1.0
+ * @author A. Sundararajan
+ * @since 1.6
+ */
+public final class JSAdapter implements Scriptable, Function {
+    private JSAdapter(Scriptable obj) {
+        setAdaptee(obj);
+    }
+    
+    // initializer to setup JSAdapter prototype in the given scope
+    public static void init(Context cx, Scriptable scope, boolean sealed)
+    throws RhinoException {
+        JSAdapter obj = new JSAdapter(cx.newObject(scope));
+        obj.setParentScope(scope);
+        obj.setPrototype(getFunctionPrototype(scope));
+        obj.isPrototype = true;
+        ScriptableObject.defineProperty(scope, "JSAdapter",  obj,
+                ScriptableObject.DONTENUM);
+    }
+    
+    @Override
+    public String getClassName() {
+        return "JSAdapter";
+    }
+    
+    @Override
+    public Object get(String name, Scriptable start) {
+        Function func = getAdapteeFunction(GET_PROP);
+        if (func != null) {
+            return call(func, new Object[] { name });
+        } else {
+            start = getAdaptee();
+            return start.get(name, start);
+        }
+    }
+    
+    @Override
+    public Object get(int index, Scriptable start) {
+        Function func = getAdapteeFunction(GET_PROP);
+        if (func != null) {
+            return call(func, new Object[] { new Integer(index) });
+        } else {
+            start = getAdaptee();
+            return start.get(index, start);
+        }
+    }
+    
+    @Override
+    public boolean has(String name, Scriptable start) {
+        Function func = getAdapteeFunction(HAS_PROP);
+        if (func != null) {
+            Object res = call(func, new Object[] { name });
+            return Context.toBoolean(res);
+        } else {
+            start = getAdaptee();
+            return start.has(name, start);
+        }
+    }
+    
+    @Override
+    public boolean has(int index, Scriptable start) {
+        Function func = getAdapteeFunction(HAS_PROP);
+        if (func != null) {
+            Object res = call(func, new Object[] { new Integer(index) });
+            return Context.toBoolean(res);
+        } else {
+            start = getAdaptee();
+            return start.has(index, start);
+        }
+    }
+    
+    @Override
+    public void put(String name, Scriptable start, Object value) {
+        if (start == this) {
+            Function func = getAdapteeFunction(PUT_PROP);
+            if (func != null) {
+                call(func, new Object[] { name, value });
+            } else {
+                start = getAdaptee();
+                start.put(name, start, value);
+            }
+        } else {
+            start.put(name, start, value);
+        }
+    }
+    
+    @Override
+    public void put(int index, Scriptable start, Object value) {
+        if (start == this) {
+            Function func = getAdapteeFunction(PUT_PROP);
+            if( func != null) {
+                call(func, new Object[] { new Integer(index), value });
+            } else {
+                start = getAdaptee();
+                start.put(index, start, value);
+            }
+        } else {
+            start.put(index, start, value);
+        }
+    }
+    
+    @Override
+    public void delete(String name) {
+        Function func = getAdapteeFunction(DEL_PROP);
+        if (func != null) {
+            call(func, new Object[] { name });
+        } else {
+            getAdaptee().delete(name);
+        }
+    }
+    
+    @Override
+    public void delete(int index) {
+        Function func = getAdapteeFunction(DEL_PROP);
+        if (func != null) {
+            call(func, new Object[] { new Integer(index) });
+        } else {
+            getAdaptee().delete(index);
+        }
+    }
+    
+    @Override
+    public Scriptable getPrototype() {
+        return prototype;
+    }
+    
+    @Override
+    public void setPrototype(Scriptable prototype) {
+        this.prototype = prototype;
+    }
+    
+    @Override
+    public Scriptable getParentScope() {
+        return parent;
+    }
+    
+    @Override
+    public void setParentScope(Scriptable parent) {
+        this.parent = parent;
+    }
+    
+    @Override
+    public Object[] getIds() {
+        Function func = getAdapteeFunction(GET_PROPIDS);
+        if (func != null) {
+            Object val = call(func, new Object[0]);
+            // in most cases, adaptee would return native JS array
+            if (val instanceof NativeArray) {
+                NativeArray array = (NativeArray) val;
+                Object[] res = new Object[(int)array.getLength()];
+                for (int index = 0; index < res.length; index++) {
+                    res[index] = mapToId(array.get(index, array));
+                }
+                return res;
+            } else if (val instanceof NativeJavaArray) {
+                // may be attempt wrapped Java array
+                Object tmp = ((NativeJavaArray)val).unwrap();
+                Object[] res;
+                if (tmp.getClass() == Object[].class) {
+                    Object[]  array = (Object[]) tmp;
+                    res = new Object[array.length];
+                    for (int index = 0; index < array.length; index++) {
+                        res[index] = mapToId(array[index]);
+                    }
+                } else {
+                    // just return an empty array
+                    res = Context.emptyArgs;
+                }
+                return res;
+            } else {
+                // some other return type, just return empty array
+                return Context.emptyArgs;
+            }
+        } else {
+            return getAdaptee().getIds();
+        }
+    }
+    
+    @Override
+    public boolean hasInstance(Scriptable scriptable) {
+        if (scriptable instanceof JSAdapter) {
+            return true;
+        } else {
+            Scriptable proto = scriptable.getPrototype();
+            while (proto != null) {
+                if (proto.equals(this)) return true;
+                proto = proto.getPrototype();
+            }
+            return false;
+        }
+    }
+    
+    @Override
+    public Object getDefaultValue(Class hint) {
+        return getAdaptee().getDefaultValue(hint);
+    }
+    
+    @Override
+    public Object call(Context cx, Scriptable scope, Scriptable thisObj,
+            Object[] args)
+            throws RhinoException {
+        if (isPrototype) {
+            return construct(cx, scope, args);
+        } else {
+            Scriptable tmp = getAdaptee();
+            if (tmp instanceof Function) {
+                return ((Function)tmp).call(cx, scope, tmp, args);
+            } else {
+                throw Context.reportRuntimeError("TypeError: not a function");
+            }
+        }
+    }
+    
+    @Override
+    public Scriptable construct(Context cx, Scriptable scope, Object[] args)
+    throws RhinoException {
+        if (isPrototype) {
+            Scriptable topLevel = ScriptableObject.getTopLevelScope(scope);
+            JSAdapter newObj;
+            if (args.length > 0) {
+                newObj = new JSAdapter(Context.toObject(args[0], topLevel));
+            } else {
+                throw Context.reportRuntimeError("JSAdapter requires adaptee");
+            }
+            return newObj;
+        } else {
+            Scriptable tmp = getAdaptee();
+            if (tmp instanceof Function) {
+                return ((Function)tmp).construct(cx, scope, args);
+            } else {
+                throw Context.reportRuntimeError("TypeError: not a constructor");
+            }
+        }
+    }
+    
+    public Scriptable getAdaptee() {
+        return adaptee;
+    }
+    
+    public void setAdaptee(Scriptable adaptee) {
+        if (adaptee == null) {
+            throw new NullPointerException("adaptee can not be null");
+        }
+        this.adaptee = adaptee;
+    }
+    
+    //-- internals only below this point
+    
+    // map a property id. Property id can only be an Integer or String
+    private Object mapToId(Object tmp) {
+        if (tmp instanceof Double) {
+            return new Integer(((Double)tmp).intValue());
+        } else {
+            return Context.toString(tmp);
+        }
+    }
+    
+    private static Scriptable getFunctionPrototype(Scriptable scope) {
+        return ScriptableObject.getFunctionPrototype(scope);
+    }
+    
+    private Function getAdapteeFunction(String name) {
+        Object o = ScriptableObject.getProperty(getAdaptee(), name);
+        return (o instanceof Function)? (Function)o : null;
+    }
+    
+    private Object call(Function func, Object[] args) {
+        Context cx = Context.getCurrentContext();
+        Scriptable thisObj = getAdaptee();
+        Scriptable scope = func.getParentScope();
+        try {
+            return func.call(cx, scope, thisObj, args);
+        } catch (RhinoException re) {
+            throw Context.reportRuntimeError(re.getMessage());
+        }
+    }
+    
+    private Scriptable prototype;
+    private Scriptable parent;
+    private Scriptable adaptee;
+    private boolean isPrototype;
+    
+    // names of adaptee JavaScript functions
+    private static final String GET_PROP = "__get__";
+    private static final String HAS_PROP = "__has__";
+    private static final String PUT_PROP = "__put__";
+    private static final String DEL_PROP = "__delete__";
+    private static final String GET_PROPIDS = "__getIds__";
+}
diff --git a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/RhinoCompiledScript.java b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/RhinoCompiledScript.java
new file mode 100644
index 0000000..23d6b3c
--- /dev/null
+++ b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/RhinoCompiledScript.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2006 Sun Microsystems, Inc. All rights reserved. 
+ * Use is subject to license terms.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are 
+ * permitted provided that the following conditions are met: Redistributions of source code 
+ * must retain the above copyright notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice, this list of 
+ * conditions and the following disclaimer in the documentation and/or other materials 
+ * provided with the distribution. Neither the name of the Sun Microsystems nor the names of 
+ * is contributors may be used to endorse or promote products derived from this software 
+ * without specific prior written permission. 
+
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.rhq.scripting.javascript.engine;
+import javax.script.CompiledScript;
+import javax.script.ScriptContext;
+import javax.script.ScriptEngine;
+import javax.script.ScriptException;
+
+import org.mozilla.javascript.Context;
+import org.mozilla.javascript.JavaScriptException;
+import org.mozilla.javascript.RhinoException;
+import org.mozilla.javascript.Script;
+import org.mozilla.javascript.Scriptable;
+
+import org.rhq.scripting.javascript.engine.util.ExtendedScriptException;
+
+/**
+ * Represents compiled JavaScript code.
+ *
+ * @author Mike Grogan
+ * @version 1.0
+ * @since 1.6
+ */
+final class RhinoCompiledScript extends CompiledScript {
+    
+    private RhinoScriptEngine engine;
+    private Script script;
+    private final static boolean DEBUG = RhinoScriptEngine.DEBUG;
+    
+    RhinoCompiledScript(RhinoScriptEngine engine, Script script) {
+        this.engine = engine;
+        this.script = script;
+    }
+    
+    @Override
+    public Object eval(ScriptContext context) throws ScriptException {
+        
+        Object result = null;
+        Context cx = RhinoScriptEngine.enterContext();
+        try {
+            
+            Scriptable scope = engine.getRuntimeScope(context);
+            Object ret = script.exec(cx, scope);
+            result = engine.unwrapReturnValue(ret);
+        } catch (JavaScriptException jse) {
+            if (DEBUG) jse.printStackTrace();
+            int line = (line = jse.lineNumber()) == 0 ? -1 : line;
+            Object value = jse.getValue();
+            String str = (value != null && value.getClass().getName().equals("org.mozilla.javascript.NativeError") ?
+                          value.toString() :
+                          jse.toString());
+            throw new ExtendedScriptException(jse, str, jse.sourceName(), line);
+        } catch (RhinoException re) {
+            if (DEBUG) re.printStackTrace();
+            int line = (line = re.lineNumber()) == 0 ? -1 : line;
+            throw new ExtendedScriptException(re, re.toString(), re.sourceName(), line);
+        } finally {
+            Context.exit();
+        }
+        
+        return result;
+    }
+    
+    @Override
+    public ScriptEngine getEngine() {
+        return engine;
+    }
+    
+}
diff --git a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/RhinoScriptEngine.java b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/RhinoScriptEngine.java
new file mode 100644
index 0000000..a2dca22
--- /dev/null
+++ b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/RhinoScriptEngine.java
@@ -0,0 +1,687 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright (c) 2006-2011 Oracle and/or its affiliates. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common Development
+ * and Distribution License("CDDL") (collectively, the "License").  You
+ * may not use this file except in compliance with the License.  You can
+ * obtain a copy of the License at
+ * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
+ * or packager/legal/LICENSE.txt.  See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ * When distributing the software, include this License Header Notice in each
+ * file and include the License file at packager/legal/LICENSE.txt.
+ *
+ * GPL Classpath Exception:
+ * Oracle designates this particular file as subject to the "Classpath"
+ * exception as provided by Oracle in the GPL Version 2 section of the License
+ * file that accompanied this code.
+ *
+ * Modifications:
+ * If applicable, add the following below the License Header, with the fields
+ * enclosed by brackets [] replaced by your own identifying information:
+ * "Portions Copyright [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ * If you wish your version of this file to be governed by only the CDDL or
+ * only the GPL Version 2, indicate your decision by adding "[Contributor]
+ * elects to include this software in this distribution under the [CDDL or GPL
+ * Version 2] license."  If you don't indicate a single choice of license, a
+ * recipient has the option to distribute your version of this file under
+ * either the CDDL, the GPL Version 2 or to extend the choice of license to
+ * its licensees as provided above.  However, if you add GPL Version 2 code
+ * and therefore, elected the GPL Version 2 license, then the option applies
+ * only if the new code is made subject to such option by the copyright
+ * holder.
+ */
+
+/*
+ * Portions Copyright 2012 RHQ Management Platform 
+ */
+
+/*
+ * RHQ Management Platform elects to include this software in this distribution 
+ * under the GPL Version 2 license.
+ */
+
+
+ 
+package org.rhq.scripting.javascript.engine;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.StringReader;
+import java.lang.reflect.Method;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.script.AbstractScriptEngine;
+import javax.script.Bindings;
+import javax.script.Compilable;
+import javax.script.CompiledScript;
+import javax.script.Invocable;
+import javax.script.ScriptContext;
+import javax.script.ScriptEngineFactory;
+import javax.script.ScriptException;
+import javax.script.SimpleBindings;
+import javax.script.SimpleScriptContext;
+
+import org.mozilla.javascript.Callable;
+import org.mozilla.javascript.Context;
+import org.mozilla.javascript.ContextFactory;
+import org.mozilla.javascript.Function;
+import org.mozilla.javascript.ImporterTopLevel;
+import org.mozilla.javascript.JavaScriptException;
+import org.mozilla.javascript.LazilyLoadedCtor;
+import org.mozilla.javascript.RhinoException;
+import org.mozilla.javascript.Script;
+import org.mozilla.javascript.Scriptable;
+import org.mozilla.javascript.ScriptableObject;
+import org.mozilla.javascript.Synchronizer;
+import org.mozilla.javascript.Undefined;
+import org.mozilla.javascript.Wrapper;
+import org.mozilla.javascript.commonjs.module.RequireBuilder;
+import org.mozilla.javascript.commonjs.module.provider.ModuleSourceProvider;
+import org.mozilla.javascript.commonjs.module.provider.SoftCachingModuleScriptProvider;
+import org.mozilla.javascript.commonjs.module.provider.UrlModuleSourceProvider;
+
+import org.rhq.scripting.javascript.engine.util.ExtendedScriptException;
+import org.rhq.scripting.javascript.engine.util.InterfaceImplementor;
+
+
+/**
+ * Implementation of <code>ScriptEngine</code> using the Mozilla Rhino
+ * interpreter.
+ *
+ * @author Mike Grogan
+ * @author A. Sundararajan
+ * @version 1.0
+ * @since 1.6
+ *
+ * Modified for phobos to remove some of the restrictions.
+ * Modified to allow subclassing and preprocessing of script source code.
+ * Modified to avoid using the RhinoTopLevel class, since that introduces
+ * a circularity that prevents objects from being garbage collected.
+ *
+ * @author Roberto Chinnici
+ * 
+ * Modified so that the top level scope is an ImportTopLevel instance so 
+ * that importClass and importPackage functions are available.
+ * Modified so that the "print" and "println" functions work the same as with
+ * the stock javascript script engine provided by the JVM.
+ * Modified to include the "require()" function by default.
+ * Modified to tighten the security of the script execution by running it in an
+ * AccessControlContext active at the time of the script engine creation.
+ * 
+ * @author Lukas Krejci
+ */
+public class RhinoScriptEngine  extends AbstractScriptEngine
+        implements  Invocable, Compilable {
+    
+    public static final boolean DEBUG = false;
+    private static final String TOPLEVEL_SCRIPT_NAME = "META-INF/toplevel.js";
+
+    private static class TopLevelScope extends ImporterTopLevel {
+
+        private static final long serialVersionUID = 1L;
+
+        private AccessControlContext acc;
+        
+        public TopLevelScope(AccessControlContext acc, Context cx, boolean sealed) {
+            super(cx, sealed);
+            this.acc = acc;
+        }
+        
+        public AccessControlContext getAccessControlContext() {
+            return acc;
+        }
+    }
+    
+    /* Scope where standard JavaScript objects and our
+     * extensions to it are stored. Note that these are not
+     * user defined engine level global variables. These are
+     * variables have to be there on all compliant ECMAScript
+     * scopes. We put these standard objects in this top level.
+     */
+    private TopLevelScope topLevel;
+
+    /* map used to store indexed properties in engine scope
+     * refer to comment on 'indexedProps' in ExternalScriptable.java.
+     */
+    private Map<?, ?> indexedProps;
+
+    private ScriptEngineFactory factory;
+    private InterfaceImplementor implementor;
+
+    //LK - added support for CommonJS modules
+    private RequireBuilder requireBuilder;
+    
+    //LK - make all the scripts run in an access control context
+    static {
+        ContextFactory.initGlobal(new ContextFactory() {
+            @Override
+            protected Object doTopCall(final Callable callable,
+                               final Context cx, final Scriptable scope,
+                               final Scriptable thisObj, final Object[] args) {
+                AccessControlContext accCtxt = null;
+                Scriptable global = ScriptableObject.getTopLevelScope(scope);
+                Scriptable globalProto = global.getPrototype();
+                if (globalProto instanceof TopLevelScope) {
+                    accCtxt = ((TopLevelScope)globalProto).getAccessControlContext();
+                }
+
+                if (accCtxt != null) {
+                    return AccessController.doPrivileged(new PrivilegedAction<Object>() {
+                        @Override
+                        public Object run() {
+                            return superDoTopCall(callable, cx, scope, thisObj, args);
+                        }
+                    }, accCtxt);
+                } else {
+                    return superDoTopCall(callable, cx, scope, thisObj, args);
+                }
+            }
+                        
+            private Object superDoTopCall(final Callable callable,
+                final Context cx, final Scriptable scope,
+                final Scriptable thisObj, final Object[] args) {
+                
+                return super.doTopCall(callable, cx, scope, thisObj, args);
+            }            
+        });
+    }
+    
+    /*
+    // in Phobos we want to support all javascript features
+    static {
+        ContextFactory.initGlobal(new ContextFactory() {
+            protected Context makeContext() {
+                Context cx = super.makeContext();
+                cx.setClassShutter(RhinoClassShutter.getInstance());
+                cx.setWrapFactory(RhinoWrapFactory.getInstance());                
+                return cx;
+            }
+
+            public boolean hasFeature(Context cx, int feature) {
+                // we do not support E4X (ECMAScript for XML)!
+                if (feature == Context.FEATURE_E4X) {
+                    return false;
+                } else {
+                    return super.hasFeature(cx, feature);
+                }
+            }
+        });
+    }
+
+    static {
+        if (USE_INTERPRETER) {
+            ContextFactory.initGlobal(new ContextFactory() {
+                protected Context makeContext() {
+                    Context cx = super.makeContext();
+                    cx.setOptimizationLevel(-1);
+                    return cx;
+                }
+            });
+        }
+    }
+    */
+    
+    public RhinoScriptEngine() {
+        this(new UrlModuleSourceProvider(null, Arrays.asList(new File("./").toURI())));
+    }
+    
+    /**
+     * Creates a new instance of RhinoScriptEngine with given moduleSourceProvider as the "locator"
+     * for the CommonJS modules.
+     * 
+     * @param moduleSourceProvider the implementation able to locate sources of modules for CommonJS.
+     */
+    public RhinoScriptEngine(ModuleSourceProvider moduleSourceProvider) {
+       
+        Context cx = enterContext();
+
+        try { 
+            /*
+             * RRC - modified this code to register JSAdapter and some functions
+             * directly, without using a separate RhinoTopLevel class
+             */
+            /*
+             * LK - made the topLevel at the the ImporterTopLevel so that
+             * the circular reference to this script engine is avoided but
+             * all the functions (importClass, importPackage) are available.
+             * Also provide the security features similar to the bundled script engine.
+             */
+            topLevel = new TopLevelScope(AccessController.getContext(), cx, System.getSecurityManager() != null);
+            
+            requireBuilder = new RequireBuilder();            
+            setModuleSourceProvider(moduleSourceProvider);
+                        
+            new LazilyLoadedCtor(topLevel, "JSAdapter",
+                "org.rhq.scripting.javascript.engine.JSAdapter",
+                false);
+            // add top level functions
+            String names[] = { "bindings", "scope", "sync"  };
+            topLevel.defineFunctionProperties(names, RhinoScriptEngine.class, ScriptableObject.DONTENUM);
+            
+            processAllTopLevelScripts(cx);
+        } finally {
+            Context.exit();
+        }
+        
+        indexedProps = new HashMap<Object, Object>();
+ 
+        //construct object used to implement getInterface
+        implementor = new InterfaceImplementor(this) {
+                @Override
+                protected Object convertResult(Method method, Object res)
+                                            throws ScriptException {
+                    Class<?> desiredType = method.getReturnType();
+                    if (desiredType == Void.TYPE) {
+                        return null;
+                    } else {
+                        return Context.jsToJava(res, desiredType);
+                    }
+                }
+        };
+    }
+    
+    public void setModuleSourceProvider(ModuleSourceProvider provider) {
+        requireBuilder.setModuleScriptProvider(new SoftCachingModuleScriptProvider(provider));
+    }
+    
+    @Override
+    public Object eval(Reader reader, ScriptContext ctxt)
+    throws ScriptException {
+        Object ret;
+        
+        Context cx = enterContext();
+        try {
+            Scriptable scope = getRuntimeScope(ctxt);
+            scope.put("context", scope, ctxt);
+
+            // NOTE (RRC) - why does it look straight into the engine instead of asking
+            // the given ScriptContext object?
+            // Modified to use the context
+            // String filename = (String) get(ScriptEngine.FILENAME);
+            String filename = null;
+            if (ctxt != null && ctxt.getBindings(ScriptContext.ENGINE_SCOPE) != null) {
+                filename = (String) ctxt.getBindings(ScriptContext.ENGINE_SCOPE).get(RhinoScriptEngine.FILENAME);
+            }
+            if (filename == null) {
+                filename = (String) get(RhinoScriptEngine.FILENAME);
+            }
+            
+            filename = filename == null ? "<Unknown source>" : filename;
+            ret = cx.evaluateReader(scope, preProcessScriptSource(reader), filename , 1,  null);
+        } catch (JavaScriptException jse) {
+            if (DEBUG) jse.printStackTrace();
+            int line = (line = jse.lineNumber()) == 0 ? -1 : line;
+            Object value = jse.getValue();
+            String str = (value != null && value.getClass().getName().equals("org.mozilla.javascript.NativeError") ?
+                          value.toString() :
+                          jse.toString());
+            throw new ExtendedScriptException(jse, str, jse.sourceName(), line);
+        } catch (RhinoException re) {
+            if (DEBUG) re.printStackTrace();
+            int line = (line = re.lineNumber()) == 0 ? -1 : line;
+            throw new ExtendedScriptException(re, re.toString(), re.sourceName(), line);
+        } catch (IOException ee) {
+            throw new ScriptException(ee);
+        } finally {
+            Context.exit();
+        }
+        
+        return unwrapReturnValue(ret);
+    }
+    
+    @Override
+    public Object eval(String script, ScriptContext ctxt) throws ScriptException {
+        if (script == null) {
+            throw new NullPointerException("null script");
+        }
+        return eval(new StringReader(script), ctxt);
+    }
+    
+    @Override
+    public ScriptEngineFactory getFactory() {
+        if (factory != null) {
+            return factory;
+        } else {
+            return new RhinoScriptEngineFactory();
+        }
+    }
+    
+    @Override
+    public Bindings createBindings() {
+        return new SimpleBindings();
+    }
+    
+    //Invocable methods
+    @Override
+    public Object invokeFunction(String name, Object... args)
+    throws ScriptException, NoSuchMethodException {
+        return invokeMethod(null, name, args);
+    }
+    
+    @Override
+    public Object invokeMethod(Object thiz, String name, Object... args)
+    throws ScriptException, NoSuchMethodException {
+        
+        Context cx = enterContext();
+        try {
+            if (name == null) {
+                throw new NullPointerException("method name is null");
+            }
+
+            if (thiz != null && !(thiz instanceof Scriptable)) {
+                thiz = Context.toObject(thiz, topLevel);
+            }
+            
+            Scriptable engineScope = getRuntimeScope(context);
+            Scriptable localScope = (thiz != null)? (Scriptable) thiz :
+                                                    engineScope;
+            Object obj = ScriptableObject.getProperty(localScope, name);
+            if (! (obj instanceof Function)) {
+                throw new NoSuchMethodException("no such method: " + name);
+            }
+
+            Function func = (Function) obj;
+            Scriptable scope = func.getParentScope();
+            if (scope == null) {
+                scope = engineScope;
+            }
+            Object result = func.call(cx, scope, localScope, 
+                                      wrapArguments(args));
+            return unwrapReturnValue(result);
+        } catch (JavaScriptException jse) {
+            if (DEBUG) jse.printStackTrace();
+            int line = (line = jse.lineNumber()) == 0 ? -1 : line;
+            Object value = jse.getValue();
+            String str = (value != null && value.getClass().getName().equals("org.mozilla.javascript.NativeError") ?
+                          value.toString() :
+                          jse.toString());
+            throw new ExtendedScriptException(jse, str, jse.sourceName(), line);
+        } catch (RhinoException re) {
+            if (DEBUG) re.printStackTrace();
+            int line = (line = re.lineNumber()) == 0 ? -1 : line;
+            throw new ExtendedScriptException(re, re.toString(), re.sourceName(), line);
+        } finally {
+            Context.exit();
+        }
+    }
+   
+    @Override
+    public <T> T getInterface(Class<T> clasz) {
+        try {
+            return implementor.getInterface(null, clasz);
+        } catch (ScriptException e) {
+            return null;
+        }
+    }
+    
+    @Override
+    public <T> T getInterface(Object thiz, Class<T> clasz) {
+        if (thiz == null) {
+            throw new IllegalArgumentException("script object can not be null");
+        }
+
+        try {
+            return implementor.getInterface(thiz, clasz);
+        } catch (ScriptException e) {
+            return null;
+        }
+    }
+
+    // RRC - not used
+    // LK - make it used again and modified to conform to the JVM version.
+    private static final String printSource =
+        "function print(str, newline) {                \n" +
+        "    if (typeof(str) == 'undefined') {         \n" +
+        "        str = 'undefined';                    \n" +
+        "    } else if (str == null) {                 \n" +
+        "        str = 'null';                         \n" +
+        "    }                                         \n" +
+        "    var out = context.getWriter();            \n" +
+        "    out.print(String(str));                   \n" +
+        "    if (newline) out.print('\\n');            \n" +
+        "    out.flush();                              \n" +
+        "}\n" +
+        "function println(str) {                       \n" +
+        "    print(str, true);                         \n" +
+        "}";
+    
+    Scriptable getRuntimeScope(ScriptContext ctxt) {
+        if (ctxt == null) {
+            throw new NullPointerException("null script context");
+        }
+
+        // we create a scope for the given ScriptContext
+        Scriptable newScope = new ExternalScriptable(ctxt, indexedProps);
+
+        // Set the prototype of newScope to be 'topLevel' so that
+        // JavaScript standard objects are visible from the scope.
+        newScope.setPrototype(topLevel);
+
+        // define "context" variable in the new scope
+        newScope.put("context", newScope, ctxt);
+       
+        
+        // RRC - save some time and don't define print
+        // LK - these functions are assumed by a lot of code so let's
+        //      make them available
+        // define "print" function in the new scope
+        Context cx = enterContext();
+        try {
+            cx.evaluateString(newScope, printSource, "print", 1, null);
+            requireBuilder.createRequire(cx, topLevel).install(newScope);
+        } finally {
+            Context.exit();
+        }
+        
+        return newScope;
+    }
+    
+    
+    //Compilable methods
+    @Override
+    public CompiledScript compile(String script) throws ScriptException {
+        return compile(new StringReader(script));
+    }
+    
+    @Override
+    public CompiledScript compile(java.io.Reader script) throws ScriptException {
+        CompiledScript ret = null;
+        Context cx = enterContext();
+        
+        try {
+            String filename = (String) get(RhinoScriptEngine.FILENAME);
+            if (filename == null) {
+                filename = "<Unknown Source>";
+            }
+            
+            Script scr = cx.compileReader(preProcessScriptSource(script), filename, 1, null);
+            ret = new RhinoCompiledScript(this, scr);
+        } catch (Exception e) {
+            if (DEBUG) e.printStackTrace();
+            throw new ScriptException(e);
+        } finally {
+            Context.exit();
+        }
+        return ret;
+    }
+    
+    
+    //package-private helpers
+
+    static Context enterContext() {
+        // call this always so that initializer of this class runs
+        // and initializes custom wrap factory and class shutter.
+        return Context.enter();
+    }
+
+    void setEngineFactory(ScriptEngineFactory fac) {
+        factory = fac;
+    }
+
+    Object[] wrapArguments(Object[] args) {
+        if (args == null) {
+            return Context.emptyArgs;
+        }
+        Object[] res = new Object[args.length];
+        for (int i = 0; i < res.length; i++) {
+            res[i] = Context.javaToJS(args[i], topLevel);
+        }
+        return res;
+    }
+    
+    Object unwrapReturnValue(Object result) {
+        if (result instanceof Wrapper) {
+            result = ( (Wrapper) result).unwrap();
+        }
+        
+        return result instanceof Undefined ? null : result;
+    }
+    
+    protected Reader preProcessScriptSource(Reader reader) throws ScriptException {
+        return reader;
+    }
+
+    protected void processAllTopLevelScripts(Context cx) {
+        processTopLevelScript(TOPLEVEL_SCRIPT_NAME, cx);
+    }
+
+    protected void processTopLevelScript(String scriptName, Context cx) {    
+        InputStream toplevelScript = this.getClass().getClassLoader().getResourceAsStream(scriptName);
+        if (toplevelScript != null) {
+            Reader reader = new InputStreamReader(toplevelScript);
+            try {
+                cx.evaluateReader(topLevel, reader, scriptName, 1, null);
+            }
+            catch (Exception e) {
+                if (DEBUG) e.printStackTrace();
+            }
+            finally {
+                try {
+                    toplevelScript.close();
+                }
+                catch (IOException e) {
+                }
+            }
+        }
+    }
+        
+    /**
+     * The bindings function takes a JavaScript scope object 
+     * of type ExternalScriptable and returns the underlying Bindings
+     * instance.
+     *
+     *    var page = scope(pageBindings);
+     *    with (page) {
+     *       // code that uses page scope 
+     *    } 
+     *    var b = bindings(page);
+     *    // operate on bindings here.
+     */
+    public static Object bindings(Context cx, Scriptable thisObj, Object[] args,
+            Function funObj) {
+        if (args.length == 1) {
+            Object arg = args[0];
+            if (arg instanceof Wrapper) {
+                arg = ((Wrapper)arg).unwrap();
+            }
+            if (arg instanceof ExternalScriptable) {
+                ScriptContext ctx = ((ExternalScriptable)arg).getContext();
+                Bindings bind = ctx.getBindings(ScriptContext.ENGINE_SCOPE);
+                return Context.javaToJS(bind, 
+                           ScriptableObject.getTopLevelScope(thisObj));
+            }
+        }
+        return Context.getUndefinedValue();
+    }
+   
+    /** 
+     * The scope function creates a new JavaScript scope object 
+     * with given Bindings object as backing store. This can be used
+     * to create a script scope based on arbitrary Bindings instance.
+     * For example, in webapp scenario, a 'page' level Bindings instance
+     * may be wrapped as a scope and code can be run in JavaScripe 'with'
+     * statement:
+     *
+     *    var page = scope(pageBindings);
+     *    with (page) {
+     *       // code that uses page scope 
+     *    } 
+     */
+    public static Object scope(Context cx, Scriptable thisObj, Object[] args,
+            Function funObj) {
+        if (args.length == 1) {
+            Object arg = args[0];
+            if (arg instanceof Wrapper) {
+                arg = ((Wrapper)arg).unwrap();
+            }
+            if (arg instanceof Bindings) {
+                ScriptContext ctx = new SimpleScriptContext();
+                ctx.setBindings((Bindings)arg, ScriptContext.ENGINE_SCOPE);
+                Scriptable res = new ExternalScriptable(ctx);
+                res.setPrototype(ScriptableObject.getObjectPrototype(thisObj));
+                res.setParentScope(ScriptableObject.getTopLevelScope(thisObj));
+                return res;
+            }
+        }
+        return Context.getUndefinedValue();
+    }
+ 
+    /**
+     * The sync function creates a synchronized function (in the sense
+     * of a Java synchronized method) from an existing function. The
+     * new function synchronizes on the <code>this</code> object of
+     * its invocation.
+     * js> var o = { f : sync(function(x) {
+     *       print("entry");
+     *       Packages.java.lang.Thread.sleep(x*1000);
+     *       print("exit");
+     *     })};
+     * js> thread(function() {o.f(5);});
+     * entry
+     * js> thread(function() {o.f(5);});
+     * js>
+     * exit
+     * entry
+     * exit
+     */
+    public static Object sync(Context cx, Scriptable thisObj, Object[] args,
+            Function funObj) {
+        if (args.length == 1 && args[0] instanceof Function) {
+            return new Synchronizer((Function)args[0]);
+        } else {
+            throw Context.reportRuntimeError("wrong argument(s) for sync");
+        }
+    }
+    
+    public static void main(String[] args) throws Exception {
+        if (args.length == 0) {
+            System.out.println("No file specified");
+            return;
+        }
+        
+        InputStreamReader r = new InputStreamReader(new FileInputStream(args[0]));
+        RhinoScriptEngine engine = new RhinoScriptEngine();
+        
+        SimpleScriptContext context = new SimpleScriptContext();
+        engine.put(RhinoScriptEngine.FILENAME, args[0]);
+        engine.eval(r, context);
+        // added this statement to save some typing to most script authors
+        context.getWriter().flush();
+    }
+}
diff --git a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/RhinoScriptEngineFactory.java b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/RhinoScriptEngineFactory.java
new file mode 100644
index 0000000..2db613b
--- /dev/null
+++ b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/RhinoScriptEngineFactory.java
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2006 Sun Microsystems, Inc. All rights reserved. 
+ * Use is subject to license terms.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are 
+ * permitted provided that the following conditions are met: Redistributions of source code 
+ * must retain the above copyright notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice, this list of 
+ * conditions and the following disclaimer in the documentation and/or other materials 
+ * provided with the distribution. Neither the name of the Sun Microsystems nor the names of 
+ * is contributors may be used to endorse or promote products derived from this software 
+ * without specific prior written permission. 
+
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.rhq.scripting.javascript.engine;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Properties;
+
+import javax.script.ScriptEngine;
+
+import org.mozilla.javascript.Context;
+import org.mozilla.javascript.ContextFactory;
+
+import org.rhq.scripting.javascript.engine.util.ScriptEngineFactoryBase;
+
+/**
+ * Factory to create RhinoScriptEngine
+ *
+ * @version 1.0
+ * @author Mike Grogan
+ * @since 1.6
+ */
+public class RhinoScriptEngineFactory extends ScriptEngineFactoryBase {
+    
+    public static final String USE_INTERPRETER_SYSTEM_PROPERTY = "org.rhq.scrpipting.javascript.useInterpreter";
+    
+    private Properties properties;
+    private boolean initialized;
+    private ContextFactory.Listener listener;
+
+    public RhinoScriptEngineFactory() {
+    }
+        
+    public RhinoScriptEngineFactory(ContextFactory.Listener listener) {
+        this.listener = listener;
+    }
+    
+    @Override
+    public List<String> getExtensions() {
+        return extensions;
+    }
+    
+    @Override
+    public List<String> getMimeTypes() {
+        return mimeTypes;
+    }
+    
+    @Override
+    public List<String> getNames() {
+        return names;
+    }
+    
+    @Override
+    public Object getParameter(String key) {
+        if (key.equals(ScriptEngine.NAME)) {
+            return "javascript";
+        } else if (key.equals(ScriptEngine.ENGINE)) {
+            return "Mozilla Rhino";
+        } else if (key.equals(ScriptEngine.ENGINE_VERSION)) {
+            return "1.6R7";
+        } else if (key.equals(ScriptEngine.LANGUAGE)) {
+            return "ECMAScript";
+        } else if (key.equals(ScriptEngine.LANGUAGE_VERSION)) {
+            return "1.6";
+        } else if (key.equals("THREADING")) {
+            return "MULTITHREADED";
+        } else {
+            throw new IllegalArgumentException("Invalid key");
+        }
+    }
+    
+    @Override
+    public ScriptEngine getScriptEngine() {
+        RhinoScriptEngine ret = new RhinoScriptEngine();
+        ret.setEngineFactory(this);
+        return ret;
+    }
+    
+    public void initialize() {
+        if (!initialized) {
+            if ("true".equals(getProperty(USE_INTERPRETER_SYSTEM_PROPERTY))) {
+                if (!ContextFactory.hasExplicitGlobal()) {
+                    ContextFactory.initGlobal(new ContextFactory() {
+                        @Override
+                        protected Context makeContext() {
+                            Context cx = super.makeContext();
+                            cx.setOptimizationLevel(-1);
+                            return cx;
+                        }
+                    });
+                }
+            }
+            if (listener != null) {
+                ContextFactory.getGlobal().addListener(listener);
+            }
+            initialized = true;
+        }
+    }
+
+    public void destroy() {
+        if (initialized) {
+            if (listener != null) {
+                ContextFactory.getGlobal().removeListener(listener);
+            }
+            initialized = false;
+        }
+    }
+        
+    public void setProperties(Properties properties) {
+        this.properties = properties;
+    }
+    
+    private String getProperty(String key) {
+        String value = null;
+        if (properties != null) {
+            value = properties.getProperty(key);
+        }
+        if (value == null) {
+            value = System.getProperty(key);
+        }
+        return value;
+    }
+
+    private String getProperty(String name, String defaultValue) {
+        String s = getProperty(name);
+        return (s == null ? defaultValue : s);
+    }
+    
+    @Override
+    public String getMethodCallSyntax(String obj, String method, String... args) {
+        
+        String ret = obj + "." + method + "(";
+        int len = args.length;
+        if (len == 0) {
+            ret += ")";
+            return ret;
+        }
+        
+        for (int i = 0; i < len; i++) {
+            ret += args[i];
+            if (i != len - 1) {
+                ret += ",";
+            } else {
+                ret += ")";
+            }
+        }
+        return ret;
+    }
+    
+    @Override
+    public String getOutputStatement(String toDisplay) {
+        return "print(" + toDisplay + ")";
+    }
+    
+    @Override
+    public String getProgram(String... statements) {
+        int len = statements.length;
+        String ret = "";
+        for (int i = 0; i < len; i++) {
+            ret += statements[i] + ";";
+        }
+        
+        return ret;
+    }
+    
+    public static void main(String[] args) {
+        RhinoScriptEngineFactory fact = new RhinoScriptEngineFactory();
+        System.out.println(fact.getParameter(ScriptEngine.ENGINE_VERSION));
+    }
+
+    private static List<String> names;
+    private static List<String> mimeTypes;
+    private static List<String> extensions;
+    
+    static {
+        names = new ArrayList<String>(7);
+        names.add("rhino-nonjdk");
+        names.add("js");
+        names.add("rhino");
+        names.add("JavaScript");
+        names.add("javascript");
+        names.add("ECMAScript");
+        names.add("ecmascript");
+        names = Collections.unmodifiableList(names);
+
+        mimeTypes = new ArrayList<String>(4);
+        mimeTypes.add("application/javascript");
+        mimeTypes.add("application/ecmascript");
+        mimeTypes.add("text/javascript");
+        mimeTypes.add("text/ecmascript");
+        mimeTypes = Collections.unmodifiableList(mimeTypes);
+
+        extensions = new ArrayList<String>(1);
+        extensions.add("js");
+        extensions = Collections.unmodifiableList(extensions);
+    }
+}
diff --git a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/util/ExtendedScriptException.java b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/util/ExtendedScriptException.java
new file mode 100644
index 0000000..2979682
--- /dev/null
+++ b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/util/ExtendedScriptException.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2006 Sun Microsystems, Inc. All rights reserved. 
+ * Use is subject to license terms.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are 
+ * permitted provided that the following conditions are met: Redistributions of source code 
+ * must retain the above copyright notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice, this list of 
+ * conditions and the following disclaimer in the documentation and/or other materials 
+ * provided with the distribution. Neither the name of the Sun Microsystems nor the names of 
+ * is contributors may be used to endorse or promote products derived from this software 
+ * without specific prior written permission. 
+
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.rhq.scripting.javascript.engine.util;
+
+import javax.script.ScriptException;
+
+/**
+ * An extension of javax.script.ScriptException that allows
+ * the cause of an exception to be set.
+ */
+public class ExtendedScriptException extends ScriptException {
+    
+    private static final long serialVersionUID = 1L;
+    
+    private Throwable cause;
+    
+    public ExtendedScriptException(
+            Throwable cause,
+            String message,
+            String fileName,
+            int lineNumber,
+            int columnNumber) {
+        super(message, fileName, lineNumber, columnNumber);
+        this.cause = cause;
+    }
+
+    public ExtendedScriptException(String s) {
+        super(s);
+    }
+    
+    public ExtendedScriptException(Exception e) {
+        super(e);
+    }
+    
+    public ExtendedScriptException(String message, String fileName, int lineNumber) {
+        super(message, fileName, lineNumber);
+    }
+    
+    public ExtendedScriptException(Throwable cause, String message, String fileName, int lineNumber) {
+        super(message, fileName, lineNumber);
+        this.cause = cause;
+    }
+
+    public ExtendedScriptException(String message,
+            String fileName,
+            int lineNumber,
+            int columnNumber) {
+        super(message, fileName, lineNumber, columnNumber);
+    }
+    
+    public Throwable getCause() {
+        return cause;
+    }
+}
diff --git a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/util/InterfaceImplementor.java b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/util/InterfaceImplementor.java
new file mode 100644
index 0000000..b4880a7
--- /dev/null
+++ b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/util/InterfaceImplementor.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2006 Sun Microsystems, Inc. All rights reserved. 
+ * Use is subject to license terms.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are 
+ * permitted provided that the following conditions are met: Redistributions of source code 
+ * must retain the above copyright notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice, this list of 
+ * conditions and the following disclaimer in the documentation and/or other materials 
+ * provided with the distribution. Neither the name of the Sun Microsystems nor the names of 
+ * is contributors may be used to endorse or promote products derived from this software 
+ * without specific prior written permission. 
+
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.rhq.scripting.javascript.engine.util;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+
+import javax.script.Invocable;
+import javax.script.ScriptException;
+
+/*
+ * java.lang.reflect.Proxy based interface implementor. This is meant
+ * to be used to implement Invocable.getInterface.
+ *
+ * @version 1.0
+ * @author Mike Grogan
+ * @since 1.6
+ */
+public class InterfaceImplementor {
+    
+    private Invocable engine;
+    
+    /** Creates a new instance of Invocable */
+    public InterfaceImplementor(Invocable engine) {
+        this.engine = engine;
+    }
+    
+    public class InterfaceImplementorInvocationHandler implements InvocationHandler {
+        private Invocable engine;
+        private Object thiz;
+        public InterfaceImplementorInvocationHandler(Invocable engine, Object thiz) {
+            
+            this.engine = engine;
+            this.thiz = thiz;
+        }
+        
+        @Override
+        public Object invoke(Object proxy , Method method, Object[] args)
+        throws java.lang.Throwable {
+            // give chance to convert input args
+            args = convertArguments(method, args);
+            Object result = engine.invokeMethod(thiz, method.getName(), args);
+            // give chance to convert the method result
+            return convertResult(method, result);
+        }
+    }
+    
+    public <T> T getInterface(Object thiz, Class<T> iface)
+    throws ScriptException {
+        if (iface == null || !iface.isInterface()) {
+            throw new IllegalArgumentException("interface Class expected");
+        }
+        return iface.cast(Proxy.newProxyInstance(iface.getClassLoader(),
+                new Class[]{iface},
+                new InterfaceImplementorInvocationHandler(engine, thiz)));
+    }
+
+    // called to convert method result after invoke
+    protected Object convertResult(Method method, Object res) 
+                                   throws ScriptException {
+        // default is identity conversion
+        return res;
+    }
+
+    // called to convert method arguments before invoke
+    protected Object[] convertArguments(Method method, Object[] args)
+                                      throws ScriptException {
+        // default is identity conversion
+        return args;
+    }
+}
diff --git a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/util/ScriptEngineFactoryBase.java b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/util/ScriptEngineFactoryBase.java
new file mode 100644
index 0000000..89f12a9
--- /dev/null
+++ b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/engine/util/ScriptEngineFactoryBase.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2006 Sun Microsystems, Inc. All rights reserved. 
+ * Use is subject to license terms.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are 
+ * permitted provided that the following conditions are met: Redistributions of source code 
+ * must retain the above copyright notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice, this list of 
+ * conditions and the following disclaimer in the documentation and/or other materials 
+ * provided with the distribution. Neither the name of the Sun Microsystems nor the names of 
+ * is contributors may be used to endorse or promote products derived from this software 
+ * without specific prior written permission. 
+
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.rhq.scripting.javascript.engine.util;
+
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineFactory;
+
+/*
+ * Abstract super class for factory implementations.
+ *
+ * @version 1.0
+ * @author Mike Grogan
+ * @since 1.6
+ */
+public abstract class ScriptEngineFactoryBase implements ScriptEngineFactory {
+    
+    public String getName() {
+        return (String)getParameter(ScriptEngine.NAME);
+    }
+    
+    @Override
+    public String getEngineName() {
+        return (String)getParameter(ScriptEngine.ENGINE);
+    }
+    
+    @Override
+    public String getEngineVersion() {
+        return (String)getParameter(ScriptEngine.ENGINE_VERSION);
+    }
+    
+    @Override
+    public String getLanguageName() {
+        return (String)getParameter(ScriptEngine.LANGUAGE);
+    }
+    
+    @Override
+    public String getLanguageVersion() {
+        return (String)getParameter(ScriptEngine.LANGUAGE_VERSION);
+    }
+}
diff --git a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/util/ScriptSourceToModuleSourceProviderAdapter.java b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/util/ScriptSourceToModuleSourceProviderAdapter.java
new file mode 100644
index 0000000..fb3926b
--- /dev/null
+++ b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/util/ScriptSourceToModuleSourceProviderAdapter.java
@@ -0,0 +1,75 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 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.scripting.javascript.util;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import org.mozilla.javascript.commonjs.module.provider.ModuleSource;
+import org.mozilla.javascript.commonjs.module.provider.ModuleSourceProviderBase;
+
+import org.rhq.scripting.ScriptSourceProvider;
+
+/**
+ * 
+ *
+ * @author Lukas Krejci
+ */
+public class ScriptSourceToModuleSourceProviderAdapter extends ModuleSourceProviderBase {
+    private static final long serialVersionUID = 1L;
+    
+    private ScriptSourceProvider scriptSourceProvider;
+    
+    public ScriptSourceToModuleSourceProviderAdapter(ScriptSourceProvider provider) {
+        scriptSourceProvider = provider;
+    }
+    
+    @Override
+    protected ModuleSource loadFromPrivilegedLocations(String moduleId, Object validator) throws IOException,
+        URISyntaxException {
+
+        //if the URI is absolute, we make sure to define the ModuleSource as sandboxed.
+        //this is done by making the URI a "subpath" of the base.
+        URI uri = new URI(moduleId);
+        URI base = null;
+        if (uri.isAbsolute()) {
+            base = uri;
+        }
+        return loadFromUri(uri, base, validator);
+    }
+
+    @Override
+    protected ModuleSource loadFromUri(URI uri, URI base, Object validator) throws IOException, URISyntaxException {
+        URI fullUri = uri;
+        if (base != null) {
+            fullUri = uri.resolve(base);
+        }
+        
+        Reader sourceReader = scriptSourceProvider.getScriptSource(fullUri);
+        
+        if (sourceReader == null) {
+            return null;
+        } else {
+            return new ModuleSource(sourceReader, null, uri, base, validator);
+        }
+    }
+}
diff --git a/modules/enterprise/scripting/javascript/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory b/modules/enterprise/scripting/javascript/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory
index ab267fe..1480e04 100644
--- a/modules/enterprise/scripting/javascript/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory
+++ b/modules/enterprise/scripting/javascript/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory
@@ -1 +1 @@
-org.rhq.scripting.javascript.ScriptEngineFactory
+org.rhq.scripting.javascript.engine.RhinoScriptEngineFactory
diff --git a/modules/enterprise/scripting/javascript/src/test/java/org/rhq/scripting/javascript/EngineTest.java b/modules/enterprise/scripting/javascript/src/test/java/org/rhq/scripting/javascript/EngineTest.java
new file mode 100644
index 0000000..7ccde17
--- /dev/null
+++ b/modules/enterprise/scripting/javascript/src/test/java/org/rhq/scripting/javascript/EngineTest.java
@@ -0,0 +1,98 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 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.scripting.javascript;
+
+import static org.testng.Assert.*;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+
+import org.testng.annotations.Test;
+
+/**
+ * 
+ *
+ * @author Lukas Krejci
+ */
+ at Test
+public class EngineTest {
+
+    public void engineAvailable() throws Exception {
+        assertNotNull(getScriptEngine(), "Failed to obtain the script engine.");
+    }
+    
+    public void printFunctionsAvailable() throws Exception {
+        String output = captureScriptOutput("print('a'); println('b');");
+        assertEquals(output, "ab\n", "Unexpected output printed by the print functions.");
+    }
+    
+    public void importClassAndImportPackageAvailable() throws Exception {
+        String script = "importClass(java.lang.System); print(System.currentTimeMillis());";
+        String output = captureScriptOutput(script);
+        assertFalse(output.isEmpty(), "importClass function doesn't seem to work.");
+        
+        script = "importPackage(java.util); println(new Date);";
+        output = captureScriptOutput(script);
+        assertFalse(output.isEmpty());
+    }
+    
+    public void requireFunctionDefined() throws Exception {
+        String output = captureScriptOutput("print(typeof(require))");
+        assertEquals(output, "function", "The require function doesn't seem to be defined.");
+    }
+    
+    public void modulesCanBeLoaded() throws Exception {
+        String script = "" + 
+        "var m1 = require('target/test-classes/test-module1.js'); \n" + 
+        "var m2 = require('target/test-classes/test-module2.js'); \n" + 
+        "println(typeof(m1.func1));\n" + 
+        "println(typeof(m1.func2));\n" + 
+        "println(typeof(m2.func3));\n" + 
+        "println(typeof(m2.func4));\n" +
+        "println(typeof(m2.func1));\n" + 
+        "println(typeof(m2.func2));\n" + 
+        "println(typeof(m1.func3));\n" + 
+        "println(typeof(m1.func4));\n";
+        String output = "function\nfunction\nfunction\nfunction\nundefined\nundefined\nundefined\nundefined\n";
+        
+        assertEquals(captureScriptOutput(script), output, "Unexpected functions found in modules");
+    }
+
+    private ScriptEngine getScriptEngine() {
+        ScriptEngineManager manager = new ScriptEngineManager();
+        return manager.getEngineByName("rhino-nonjdk");               
+    }
+    
+    private String captureScriptOutput(String script) throws Exception {
+        ScriptEngine engine = getScriptEngine();
+        
+        StringWriter stdOut = new StringWriter();
+        PrintWriter wrt = new PrintWriter(stdOut);
+        
+        engine.getContext().setWriter(wrt);
+        
+        engine.eval(script);
+        
+        return stdOut.toString();
+    }
+}
diff --git a/modules/enterprise/scripting/javascript/src/test/java/org/rhq/scripting/javascript/InitializerTest.java b/modules/enterprise/scripting/javascript/src/test/java/org/rhq/scripting/javascript/InitializerTest.java
new file mode 100644
index 0000000..3a50839
--- /dev/null
+++ b/modules/enterprise/scripting/javascript/src/test/java/org/rhq/scripting/javascript/InitializerTest.java
@@ -0,0 +1,189 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 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.scripting.javascript;
+
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+import java.io.FilePermission;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.lang.reflect.Method;
+import java.net.URI;
+import java.security.Permissions;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.PropertyPermission;
+import java.util.Set;
+
+import javax.script.ScriptEngine;
+import javax.script.ScriptException;
+
+import org.testng.annotations.Test;
+
+import org.rhq.scripting.ScriptEngineInitializer;
+import org.rhq.scripting.ScriptSourceProvider;
+
+/**
+ * 
+ *
+ * @author Lukas Krejci
+ */
+ at Test
+public class InitializerTest {
+
+    //for Rhino to see this class, it must be public
+    public static class TestClass {
+        public boolean[] functionsCalled;
+        
+        public TestClass() {
+            functionsCalled = new boolean[6];
+        }
+        
+        public void func1() {
+            functionsCalled[0] = true;
+        }
+        
+        public void func2() {
+            functionsCalled[1] = true;
+        }
+        
+        public void func3() {
+            functionsCalled[2] = true;
+        }
+        
+        public void func3(int a, int b) {
+            functionsCalled[3] = true;
+        }
+        
+        public void func3(String a, String b) {
+            functionsCalled[4] = true;
+        }
+        
+        public void func3(int a, int b, int c) {
+            functionsCalled[5] = true;
+        }                
+    }
+    
+    public void engineSecured() throws Exception {
+        Permissions perms = new Permissions();
+        //we need to be able to read files and props so that the default module source provider can work
+        perms.add(new FilePermission("<<ALL FILES>>", "read"));
+        perms.add(new PropertyPermission("*", "read"));
+        
+        ScriptEngine eng = new JsEngineInitializer().instantiate(Collections.<String>emptySet(), null, perms);
+        
+        try {
+            eng.eval("java.lang.System.exit(1)");
+        } catch (Exception e) {
+            assertSecurityExceptionPresent(e);
+        }
+    }
+    
+    public void scriptSourceProviderApplied() throws Exception {
+        
+        String script = "var m = require('rhq://test-module1.js'); m.func1();";
+        
+        //first let's try to find the scripts with the default source provider...
+        ScriptEngine eng = new JsEngineInitializer().instantiate(Collections.<String>emptySet(), null, null);
+        try {
+            eng.eval(script);
+            fail("The module should not have been loaded using the default source provider.");
+        } catch (ScriptException e) {
+            //expected
+        }
+        
+        eng = new JsEngineInitializer().instantiate(Collections.<String>emptySet(), new ScriptSourceProvider() {            
+            @Override
+            public Reader getScriptSource(URI location) {
+                if (!"rhq".equals(location.getScheme())) {
+                    return null;
+                }
+                String scriptName = location.getSchemeSpecificPart().substring(2); //remove the '//'
+                InputStream src =  getClass().getClassLoader().getResourceAsStream(scriptName);
+                return new InputStreamReader(src);
+            }
+        }, null);
+
+        try {
+            eng.eval(script);
+        } catch (ScriptException e) {
+            fail("The module should have been loaded using the custom source provider. Error message: " + e.getMessage(), e);
+        }
+    }
+    
+    public void indirectionMethodsValid() throws Exception {
+        JsEngineInitializer initializer = new JsEngineInitializer();
+        
+        ScriptEngine eng = initializer.instantiate(Collections.<String>emptySet(), null, null);
+        
+        TestClass myObject = new TestClass();
+                
+        eng.put("myObject", myObject);
+        
+        generateIndirectionMethods(initializer, eng, myObject, "myObject", "func1");
+        generateIndirectionMethods(initializer, eng, myObject, "myObject", "func2");
+        generateIndirectionMethods(initializer, eng, myObject, "myObject", "func3");
+        
+        eng.eval("func1(); func2(); func3(); func3(1, 1); func3('a', 'b'); func3(1, 1, 1);");
+        
+        assertTrue(myObject.functionsCalled[0], "Function func1() should have been called.");
+        assertTrue(myObject.functionsCalled[1], "Function func2() should have been called.");
+        assertTrue(myObject.functionsCalled[2], "Function func3() should have been called.");
+        assertTrue(myObject.functionsCalled[3], "Function func3(int, int) should have been called.");
+        assertTrue(myObject.functionsCalled[4], "Function func3(String, String) should have been called.");
+        assertTrue(myObject.functionsCalled[5], "Function func3(int, int, int) should have been called.");
+    }
+    
+    private void assertSecurityExceptionPresent(Throwable t) {
+        boolean ok = false;
+        while (t != null) {
+            if (t instanceof SecurityException) {
+                ok = true;
+                break;
+            } else if ((t instanceof ScriptException) && 
+                (t.getMessage().contains("java.security.AccessControlException")
+                 || t.getMessage().contains("java.lang.SecurityException"))) {
+                ok = true;
+                break;
+            }
+            
+            t = t.getCause();
+        }
+        
+        assertTrue(ok, "Didn't find a SecurityException, which should have occured.");
+    }
+    
+    private void generateIndirectionMethods(ScriptEngineInitializer initializer, ScriptEngine eng,  Object object, String objectName, String methodName) throws ScriptException {
+        Set<Method> methods = new HashSet<Method>();
+        for(Method m : object.getClass().getDeclaredMethods()) {
+            if (methodName.equals(m.getName())) {
+                methods.add(m);
+            }
+        }
+        
+        eng.put(objectName, object);
+        
+        for(String m : initializer.generateIndirectionMethods(objectName, methods)) {
+            eng.eval(m);
+        }
+    }
+}
diff --git a/modules/enterprise/scripting/javascript/src/test/resources/allow-all.policy b/modules/enterprise/scripting/javascript/src/test/resources/allow-all.policy
new file mode 100644
index 0000000..cb9dbed
--- /dev/null
+++ b/modules/enterprise/scripting/javascript/src/test/resources/allow-all.policy
@@ -0,0 +1,3 @@
+grant {
+    permission java.security.AllPermission;
+};
diff --git a/modules/enterprise/scripting/javascript/src/test/resources/test-module1.js b/modules/enterprise/scripting/javascript/src/test/resources/test-module1.js
new file mode 100644
index 0000000..7cc760b
--- /dev/null
+++ b/modules/enterprise/scripting/javascript/src/test/resources/test-module1.js
@@ -0,0 +1,7 @@
+exports.func1 = function() {
+	return "func1";
+}
+
+exports.func2 = function() {
+	return "func2";
+}
\ No newline at end of file
diff --git a/modules/enterprise/scripting/javascript/src/test/resources/test-module2.js b/modules/enterprise/scripting/javascript/src/test/resources/test-module2.js
new file mode 100644
index 0000000..b2ad389
--- /dev/null
+++ b/modules/enterprise/scripting/javascript/src/test/resources/test-module2.js
@@ -0,0 +1,7 @@
+exports.func3 = function() {
+	return "func3";
+}
+
+exports.func4 = function() {
+	return "func4";
+}
\ No newline at end of file
diff --git a/modules/enterprise/scripting/pom.xml b/modules/enterprise/scripting/pom.xml
index 92b72d4..c786cdc 100644
--- a/modules/enterprise/scripting/pom.xml
+++ b/modules/enterprise/scripting/pom.xml
@@ -13,7 +13,6 @@
 
    <modules>
       <module>api</module>
-      <module>factory</module>
       <module>javascript</module>      
    </modules>
    


commit ff78b1e7cf7b64f78fd155752222fba7ad4261f4
Author: Lukas Krejci <lkrejci at redhat.com>
Date:   Fri May 18 13:39:27 2012 +0200

    An attempt to use Rhino 1.7R3 as a script engine. This will most probably
    not work because of the number of changes in behavior between phobos-based
    ScriptEngine and the JDK-bundled ScriptEngine.

diff --git a/modules/enterprise/scripting/javascript/pom.xml b/modules/enterprise/scripting/javascript/pom.xml
index bd0d585..8a5d96a 100644
--- a/modules/enterprise/scripting/javascript/pom.xml
+++ b/modules/enterprise/scripting/javascript/pom.xml
@@ -22,6 +22,20 @@
           <artifactId>rhino</artifactId>
           <version>1.7R3</version>
        </dependency>
+       
+       <!-- JSR 223 support for Rhino -->
+       <dependency>
+          <groupId>com.sun.phobos</groupId>
+          <artifactId>phobos-js</artifactId>
+          <version>0.6.2</version>
+          <exclusions>
+             <exclusion>
+                <groupId>com.sun.phobos</groupId>
+                <artifactId>phobos-rhino</artifactId>
+             </exclusion>
+          </exclusions>
+       </dependency>
+       
     </dependencies>
     
     <build>
diff --git a/modules/enterprise/scripting/javascript/src/main/java/com/sun/phobos/script/javascript/PrintHavingRhinoScriptEngine.java b/modules/enterprise/scripting/javascript/src/main/java/com/sun/phobos/script/javascript/PrintHavingRhinoScriptEngine.java
new file mode 100644
index 0000000..5a176fd
--- /dev/null
+++ b/modules/enterprise/scripting/javascript/src/main/java/com/sun/phobos/script/javascript/PrintHavingRhinoScriptEngine.java
@@ -0,0 +1,71 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 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 com.sun.phobos.script.javascript;
+
+import javax.script.ScriptContext;
+
+import org.mozilla.javascript.Context;
+import org.mozilla.javascript.Scriptable;
+
+/**
+ * We want our script engine to mimic the real JDK one as close as
+ * possible.
+ * 
+ * The Phobos impl of the script engine leaves out the predefined 
+ * print() and println() functions, but we really want them.
+ * 
+ * To add them back we need to override a package-private method
+ * in the phobos script engine.
+ *
+ * @author Lukas Krejci
+ */
+public class PrintHavingRhinoScriptEngine extends RhinoScriptEngine {
+
+    //copied over from the JDK's impl of RhinoScriptEngine
+    private static final String printSource =
+        "function print(str, newline) {                \n" +
+        "    if (typeof(str) == 'undefined') {         \n" +
+        "        str = 'undefined';                    \n" +
+        "    } else if (str == null) {                 \n" +
+        "        str = 'null';                         \n" +
+        "    }                                         \n" +
+        "    var out = context.getWriter();            \n" +
+        "    out.print(String(str));                   \n" +
+        "    if (newline) out.print('\\n');            \n" +
+        "    out.flush();                              \n" +
+        "}\n" +
+        "function println(str) {                       \n" +
+        "    print(str, true);                         \n" +
+        "}";
+    
+    @Override
+    Scriptable getRuntimeScope(ScriptContext ctxt) {
+        Scriptable newScope = super.getRuntimeScope(ctxt);
+        
+        Context cx = enterContext();
+        try {
+            cx.evaluateString(newScope, printSource, "print", 1, null);
+            
+            return newScope;
+        } finally {
+            Context.exit();
+        }
+    }
+}
diff --git a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineInitializer.java b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineInitializer.java
index 3ad2296..803225f 100644
--- a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineInitializer.java
+++ b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineInitializer.java
@@ -42,7 +42,7 @@ public class JsEngineInitializer implements ScriptEngineInitializer {
     
     @Override
     public ScriptEngine instantiate(Set<String> packages) throws ScriptException {
-        ScriptEngine eng = engineManager.getEngineByName("JavaScript");
+        ScriptEngine eng = engineManager.getEngineByName("rhino-nonjdk");
         
         for(String pkg : packages) {
             eng.eval("importPackage(" + pkg + ")");
diff --git a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/Main.java b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/Main.java
new file mode 100644
index 0000000..6bbf542
--- /dev/null
+++ b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/Main.java
@@ -0,0 +1,41 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 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.scripting.javascript;
+
+import java.io.PrintWriter;
+
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+
+/**
+ * 
+ *
+ * @author Lukas Krejci
+ */
+public class Main {
+
+    public static void main(String[] args) throws Exception {
+        ScriptEngineManager manager = new ScriptEngineManager();
+        ScriptEngine engine = manager.getEngineByName("rhino-nonjdk");               
+        
+        engine.getContext().setWriter(new PrintWriter(System.out, true));
+        engine.eval("importPackage(java.lang); println('ahoj')");
+    }
+}
diff --git a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/ScriptEngine.java b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/ScriptEngine.java
new file mode 100644
index 0000000..ed8a33f
--- /dev/null
+++ b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/ScriptEngine.java
@@ -0,0 +1,45 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 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.scripting.javascript;
+
+import com.sun.phobos.script.javascript.PrintHavingRhinoScriptEngine;
+
+/**
+ * 
+ *
+ * @author Lukas Krejci
+ */
+public class ScriptEngine extends PrintHavingRhinoScriptEngine {
+
+    private ScriptEngineFactory factory;
+    
+    @Override
+    public ScriptEngineFactory getFactory() {
+        if (factory == null) {
+            factory = new ScriptEngineFactory();
+        }
+            
+        return factory;
+    }
+    
+    void setFactory(ScriptEngineFactory factory) {
+        this.factory = factory;
+    }
+}
diff --git a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/ScriptEngineFactory.java b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/ScriptEngineFactory.java
new file mode 100644
index 0000000..824f97a
--- /dev/null
+++ b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/ScriptEngineFactory.java
@@ -0,0 +1,86 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 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.scripting.javascript;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import javax.script.ScriptEngine;
+
+import com.sun.phobos.script.javascript.RhinoScriptEngineFactory;
+
+import org.mozilla.javascript.Context;
+
+/**
+ * 
+ *
+ * @author Lukas Krejci
+ */
+public class ScriptEngineFactory extends RhinoScriptEngineFactory {
+    
+    private static final List<String> NAMES;
+    private static final String ENGINE_VERSION;
+    private static final String LANGUAGE_VERSION;
+    static {
+        Context.enter();
+        ENGINE_VERSION = Context.getCurrentContext().getImplementationVersion();
+        int ver = Context.getCurrentContext().getLanguageVersion();
+        Context.exit();
+        
+        String version = null;
+        if (ver == 0) {
+            version = "1.7";
+        } else {
+            //the versions are formatted like 170 for 1.7, 180 for 1.8, etc
+            int major = ver / 100;
+            int minor = (ver - 100) / 10;
+            version = major + "." + minor;
+        }
+        
+        LANGUAGE_VERSION = version;
+        
+        NAMES = Collections.unmodifiableList(Arrays.asList("rhino-nonjdk"));
+        
+    }
+    
+    @Override
+    public List<String> getNames() {
+        return NAMES;
+    }
+    
+    @Override
+    public Object getParameter(String key) {
+        if (ScriptEngine.ENGINE_VERSION.equals(key)) {
+            return ENGINE_VERSION;
+        } else if (ScriptEngine.LANGUAGE_VERSION.equals(key)) {
+            return LANGUAGE_VERSION;
+        } else {
+            return super.getParameter(key);
+        }
+    }   
+    
+    @Override
+    public ScriptEngine getScriptEngine() {
+        org.rhq.scripting.javascript.ScriptEngine engine = new org.rhq.scripting.javascript.ScriptEngine();
+        engine.setFactory(this);
+        return engine;
+    }
+}
diff --git a/modules/enterprise/scripting/javascript/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory b/modules/enterprise/scripting/javascript/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory
new file mode 100644
index 0000000..ab267fe
--- /dev/null
+++ b/modules/enterprise/scripting/javascript/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory
@@ -0,0 +1 @@
+org.rhq.scripting.javascript.ScriptEngineFactory


commit 13e77125213af769de8f72ff5017458ba81a4cea
Author: Lukas Krejci <lkrejci at redhat.com>
Date:   Thu May 17 10:18:13 2012 +0200

    Initial refactoring of the scripting infrastructure to allow language
    support to be defined in a standalone module (and allow multiple script
    langs in the future).
    
    The ScriptEngineFactory now searches for the supported script langs using
    META-INF/services.
    
    The project probably doesn't compile with this commit but this will get
    fixed by the future commits.

diff --git a/modules/enterprise/binding/pom.xml b/modules/enterprise/binding/pom.xml
index 7ca5ea1..6683bd8 100644
--- a/modules/enterprise/binding/pom.xml
+++ b/modules/enterprise/binding/pom.xml
@@ -19,6 +19,12 @@
     <dependencies>
 
         <dependency>
+           <groupId>${project.groupId}</groupId>
+           <artifactId>rhq-scripting-api</artifactId>
+           <version>${project.version}</version>
+        </dependency>
+        
+        <dependency>
             <groupId>${project.groupId}</groupId>
             <artifactId>rhq-core-domain</artifactId>
             <version>${project.version}</version>
@@ -30,6 +36,14 @@
             </exclusions>
         </dependency>
 
+        <!-- Provide a scripting impl for the tests -->
+        <dependency>
+           <groupId>${project.groupId}</groupId>
+           <artifactId>rhq-scripting-javascript</artifactId>
+           <version>${project.version}</version>
+           <scope>test</scope>
+        </dependency>
+        
         <dependency>
             <groupId>${project.groupId}</groupId>
             <artifactId>rhq-core-domain</artifactId>
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/ScriptEngineFactory.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/ScriptEngineFactory.java
index 106c2ae..73ffc9d 100644
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/ScriptEngineFactory.java
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/ScriptEngineFactory.java
@@ -37,6 +37,7 @@ import java.security.cert.Certificate;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
+import java.util.ServiceLoader;
 import java.util.Set;
 
 import javax.script.Bindings;
@@ -47,10 +48,10 @@ import javax.script.ScriptException;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
-import org.rhq.bindings.engine.JsEngineInitializer;
-import org.rhq.bindings.engine.ScriptEngineInitializer;
 import org.rhq.bindings.util.NoTopLevelIndirection;
 import org.rhq.bindings.util.PackageFinder;
+import org.rhq.scripting.ScriptEngineInitializer;
+import org.rhq.scripting.ScriptEngineProvider;
 
 /**
  * This is RHQ specific imitation of ScriptEngineFactory.
@@ -68,13 +69,56 @@ import org.rhq.bindings.util.PackageFinder;
 public class ScriptEngineFactory {
     private static final Log LOG = LogFactory.getLog(ScriptEngineFactory.class);
 
-    private static final ScriptEngineInitializer[] KNOWN_ENGINES = { new JsEngineInitializer() };
+    private static final Map<String, ScriptEngineProvider> KNOWN_PROVIDERS;
+    static {
+        KNOWN_PROVIDERS = new HashMap<String, ScriptEngineProvider>();
+        
+        reloadScriptEngineProviders(null);
+    }
 
     private ScriptEngineFactory() {
 
     }
 
     /**
+     * Reloads the list of the known script engine providers using the given classloader
+     * or the current thread's context classloader if it is null.
+     * 
+     * @param classLoader the classloader used to find the script engine providers on the classpath
+     * 
+     * @throws IllegalStateException if more than 1 script engine provider is found for a single language
+     */
+    public static void reloadScriptEngineProviders(ClassLoader classLoader) {
+        if (classLoader == null) {
+            classLoader = Thread.currentThread().getContextClassLoader();
+        }
+
+        ServiceLoader<ScriptEngineProvider> loader = ServiceLoader.load(ScriptEngineProvider.class, classLoader);
+
+        KNOWN_PROVIDERS.clear();
+
+        for (ScriptEngineProvider provider : loader) {
+            String lang = provider.getSupportedLanguage();
+
+            if (KNOWN_PROVIDERS.containsKey(lang)) {
+                String existing = KNOWN_PROVIDERS.get(lang).getClass().getName();
+                String thisOne = provider.getClass().getName();
+                throw new IllegalStateException("'" + lang + "' scripting language provided by at least 2 providers: '"
+                    + existing + "' and '" + thisOne + "'. Only 1 provider per language is allowed.");
+            }
+
+            KNOWN_PROVIDERS.put(lang, provider);
+        }
+    }
+    
+    /**
+     * @return the set of the scripting languages supported by this factory
+     */
+    public static Set<String> getSupportedLanguages() {
+        return new HashSet<String>(KNOWN_PROVIDERS.keySet());       
+    }
+    
+    /**
      * Initializes the script engine for given language.
      * 
      * @param language the language of the script to instantiate
@@ -248,13 +292,9 @@ public class ScriptEngineFactory {
     }
 
     public static ScriptEngineInitializer getInitializer(String language) {
-        for (ScriptEngineInitializer i : KNOWN_ENGINES) {
-            if (i.implementsLanguage(language)) {
-                return i;
-            }
-        }
-
-        return null;
+        ScriptEngineProvider provider = KNOWN_PROVIDERS.get(language);
+        
+        return provider == null ? null : provider.getInitializer();
     }
 
     private static boolean shouldIndirect(Method method) {
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/StandardBindings.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/StandardBindings.java
index fd84c6d..da544c4 100644
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/StandardBindings.java
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/StandardBindings.java
@@ -72,14 +72,17 @@ public class StandardBindings extends HashMap<String, Object> {
             this.clazz = clazz;
         }
 
+        @Override
         public String getKey() {
             return inner.getKey();
         }
 
+        @Override
         public T getValue() {
             return clazz.cast(inner.getValue());
         }
 
+        @Override
         public T setValue(T value) {
             return clazz.cast(inner.setValue(value));
         }
@@ -130,11 +133,13 @@ public class StandardBindings extends HashMap<String, Object> {
         putAll(managers);
     }
 
+    @Override
     public void preInject(ScriptEngine scriptEngine) {
         ((ScriptUtil) get(SCRIPT_UTIL)).init(scriptEngine);
         ((ScriptAssert) get(ASSERT)).init(scriptEngine);
     }
 
+    @Override
     public void postInject(ScriptEngine scriptEngine) {
         ScriptEngineFactory.bindIndirectionMethods(scriptEngine, SCRIPT_UTIL);
         ScriptEngineFactory.bindIndirectionMethods(scriptEngine, ASSERT);
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/engine/JsEngineInitializer.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/engine/JsEngineInitializer.java
deleted file mode 100644
index e810bfe..0000000
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/engine/JsEngineInitializer.java
+++ /dev/null
@@ -1,104 +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 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.bindings.engine;
-
-import java.lang.reflect.Method;
-import java.util.Collections;
-import java.util.Set;
-
-import javax.script.ScriptEngine;
-import javax.script.ScriptEngineManager;
-import javax.script.ScriptException;
-
-/**
- * 
- *
- * @author Lukas Krejci
- */
-public class JsEngineInitializer implements ScriptEngineInitializer {
-
-    private static final String WRAPPED_EXCEPTION_PREFIX = "Wrapped ";
-
-    private ScriptEngineManager engineManager = new ScriptEngineManager();
-    
-    public boolean implementsLanguage(String language) {
-        return language != null && ("JavaScript".equals(language) || "ECMAScript".equals(language));
-    }
-    
-    public ScriptEngine instantiate(Set<String> packages) throws ScriptException {
-        ScriptEngine eng = engineManager.getEngineByName("JavaScript");
-        
-        for(String pkg : packages) {
-            eng.eval("importPackage(" + pkg + ")");
-        }
-        
-        return eng;
-    }
-
-    public Set<String> generateIndirectionMethods(String boundObjectName, Set<Method> methods) {
-        if (methods.size() == 0) {
-            return Collections.emptySet();
-        }
-        
-        String methodName = methods.iterator().next().getName();
-                
-        StringBuilder functionBuilder = new StringBuilder("function ");
-        functionBuilder.append(methodName).append("() { switch(arguments.length) { ");
-        
-        for(Method method : methods) {
-            int argCnt = method.getParameterTypes().length;
-            functionBuilder.append("case ").append(argCnt).append(": ");
-            functionBuilder.append("return ").append(boundObjectName).append(".").append(methodName).append("(");
-            for(int i = 0; i < argCnt; ++i) {
-                if (i > 0) {
-                    functionBuilder.append(", ");
-                }
-                
-                functionBuilder.append("arguments[").append(i).append("]");
-            }
-            
-            functionBuilder.append("); break; ");
-        }
-        
-        functionBuilder.append(" default: throw \"Unsupported number of parameters.\"; } }");
-        
-        return Collections.singleton(functionBuilder.toString());
-    }
-    
-    public String extractUserFriendlyErrorMessage(ScriptException e) {
-        String errorMessage = e.getMessage();
-        
-        int wrappedIdx = errorMessage.lastIndexOf(WRAPPED_EXCEPTION_PREFIX);
-        
-        if (wrappedIdx < 0) {
-            return errorMessage;
-        }
-        
-        errorMessage = errorMessage.substring(wrappedIdx + WRAPPED_EXCEPTION_PREFIX.length());        
-        
-        int sourceInfoStartIdx = errorMessage.indexOf(" (<Unknown source>#");
-        
-        if (sourceInfoStartIdx >= 0) {
-            errorMessage = errorMessage.substring(0, sourceInfoStartIdx);
-        }
-        
-        return errorMessage;
-    }
-}
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/engine/ScriptEngineInitializer.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/engine/ScriptEngineInitializer.java
deleted file mode 100644
index 968e815..0000000
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/engine/ScriptEngineInitializer.java
+++ /dev/null
@@ -1,82 +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 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.bindings.engine;
-
-import java.lang.reflect.Method;
-import java.util.Set;
-
-import javax.script.ScriptEngine;
-import javax.script.ScriptException;
-
-/**
- * Is able to instantiate a script engine and import packages into the context
- * of the engine. 
- *
- * @author Lukas Krejci
- */
-public interface ScriptEngineInitializer {
-
-    boolean implementsLanguage(String language);
-    
-    ScriptEngine instantiate(Set<String> packages) throws ScriptException;
-    
-    /**
-     * This function returns a definition string in the script engine's language
-     * that provides an indirection to calling the method on the bound object.
-     * 
-     * for example for parameters:
-     * <ul>
-     * <li> <code>boundObjectName = foo</code>
-     * <li> <code> method = &lt;int bar(int)&gt;</code>
-     * </ul>
-     * The method would generate this javascript:<br/>
-     * <code>
-     * function bar(arg) { return foo.bar(arg); }
-     * </code>
-     * <p>
-     * This method gets passed all the overloaded versions of a method on the object (i.e.
-     * all the methods with the same name) and is free to return any number of functions
-     * that will map all the possible overloaded versions.
-     * <p>
-     * This is because different scripting languages have different support for function
-     * overloading and different ways of handling varying number of arguments of a function.
-     *  
-     * @param boundObjectName
-     * @param overloadedMethods
-     * @return a set of strings with top-level function definitions in the scripting language
-     */
-    Set<String> generateIndirectionMethods(String boundObjectName, Set<Method> overloadedMethods);
-    
-    /**
-     * At least the Rhino script engine for java script generates exceptions
-     * whose error messages contain just "too much" information to be easily
-     * decipherable by the end users.
-     * <p>
-     * This method extracts messages from the exception such that they are
-     * presentable to the end user.
-     * <p>
-     * The returned string should only contain the error message. The filename, line
-     * and column information should be stripped from it if at all possible.
-     * 
-     * @param e
-     * @return
-     */
-    String extractUserFriendlyErrorMessage(ScriptException e);
-}
diff --git a/modules/enterprise/pom.xml b/modules/enterprise/pom.xml
index 158709c..e572daf 100644
--- a/modules/enterprise/pom.xml
+++ b/modules/enterprise/pom.xml
@@ -46,6 +46,7 @@
             <module>server/plugins</module>
             <module>server/ear</module>
             <module>binding</module>
+            <module>scripting</module>
             <module>server/client-api</module>            
             <module>server/itests</module>
          </modules>
@@ -67,6 +68,7 @@
             <module>server/safe-invoker</module>
             <module>server/sars</module>
             <module>binding</module>
+            <module>scripting</module>
             <module>remoting</module>
             <module>gui</module>
             <module>server/plugins</module>
diff --git a/modules/enterprise/scripting/api/pom.xml b/modules/enterprise/scripting/api/pom.xml
new file mode 100644
index 0000000..b3d036b
--- /dev/null
+++ b/modules/enterprise/scripting/api/pom.xml
@@ -0,0 +1,173 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <artifactId>rhq-scripting-parent</artifactId>
+        <groupId>org.rhq</groupId>
+        <version>4.5.0-SNAPSHOT</version>
+    </parent>
+    <artifactId>rhq-scripting-api</artifactId>
+    <version>4.5.0-SNAPSHOT</version>
+    <name>RHQ Scripting API</name>
+    <description>Provides API for adding scripting support to RHQ using different javax.scripting - based interpreters</description>
+
+    <build>
+        <plugins>
+            <plugin>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <configuration>
+                    <excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+    <profiles>
+
+        <profile>
+            <id>dev</id>
+
+            <properties>
+                <rhq.rootDir>../../..</rhq.rootDir>
+                <rhq.containerDir>${rhq.rootDir}/${rhq.defaultDevContainerPath}</rhq.containerDir>
+                <rhq.deploymentDir>${rhq.containerDir}/jbossas/server/default/deploy/${rhq.earName}/lib</rhq.deploymentDir>
+            </properties>
+
+            <build>
+                <plugins>
+
+                    <plugin>
+                        <artifactId>maven-antrun-plugin</artifactId>
+                        <version>1.1</version>
+                        <executions>
+
+                            <execution>
+                                <id>deploy</id>
+                                <phase>compile</phase>
+                                <configuration>
+                                    <tasks>
+                                        <mkdir dir="${rhq.deploymentDir}" />
+                                        <property name="deployment.file" location="${rhq.deploymentDir}/${project.build.finalName}.jar" />
+                                        <echo>*** Updating
+                                            ${deployment.file}...</echo>
+                                        <jar destfile="${deployment.file}" basedir="${project.build.outputDirectory}" />
+                                    </tasks>
+                                </configuration>
+                                <goals>
+                                    <goal>run</goal>
+                                </goals>
+                            </execution>
+
+                            <execution>
+                                <id>undeploy</id>
+                                <phase>clean</phase>
+                                <configuration>
+                                    <tasks>
+                                        <property name="deployment.file" location="${rhq.deploymentDir}/${project.build.finalName}.jar" />
+                                        <echo>*** Deleting
+                                            ${deployment.file}...</echo>
+                                        <delete file="${deployment.file}" />
+                                    </tasks>
+                                </configuration>
+                                <goals>
+                                    <goal>run</goal>
+                                </goals>
+                            </execution>
+
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+
+        <profile>
+            <id>cobertura-plugins</id>
+            <activation>
+                <activeByDefault>false</activeByDefault>
+            </activation>
+            <build>
+                <plugins>
+                    <plugin>
+                        <artifactId>maven-antrun-plugin</artifactId>
+                        <dependencies>
+                            <dependency>
+                                <groupId>net.sourceforge.cobertura</groupId>
+                                <artifactId>cobertura</artifactId>
+                                <version>1.9.4.1</version>
+                            </dependency>
+                        </dependencies>
+                        <executions>
+                            <execution>
+                                <id>cobertura-instrument</id>
+                                <phase>pre-integration-test</phase>
+                                <configuration>
+                                    <tasks>
+                                        <!-- prepare directory structure 
+                                            for cobertura -->
+                                        <mkdir dir="target/cobertura" />
+                                        <mkdir dir="target/cobertura/backup" />
+                                        <!-- backup all classes so that we 
+                                            can instrument the original classes -->
+                                        <copy toDir="target/cobertura/backup" verbose="true" overwrite="true">
+                                            <fileset dir="target/classes">
+                                                <include name="**/*.class" />
+                                            </fileset>
+                                        </copy>
+                                        <!-- create a properties file and 
+                                            save there location of cobertura data file -->
+                                        <touch file="target/classes/cobertura.properties" />
+                                        <echo file="target/classes/cobertura.properties">net.sourceforge.cobertura.datafile=${project.build.directory}/cobertura/cobertura.ser</echo>
+                                        <taskdef classpathref="maven.plugin.classpath" resource="tasks.properties" />
+                                        <!-- instrument all classes in target/classes 
+                                            directory -->
+                                        <cobertura-instrument datafile="${project.build.directory}/cobertura/cobertura.ser" todir="${project.build.directory}/classes">
+                                            <fileset dir="${project.build.directory}/classes">
+                                                <include name="**/*.class" />
+                                            </fileset>
+                                        </cobertura-instrument>
+                                    </tasks>
+                                </configuration>
+                                <goals>
+                                    <goal>run</goal>
+                                </goals>
+                            </execution>
+                            <execution>
+                                <id>cobertura-report</id>
+                                <phase>post-integration-test</phase>
+                                <configuration>
+                                    <tasks>
+                                        <taskdef classpathref="maven.plugin.classpath" resource="tasks.properties" />
+                                        <!-- prepare directory structure 
+                                            for cobertura -->
+                                        <mkdir dir="target/cobertura" />
+                                        <mkdir dir="target/site/cobertura" />
+                                        <!-- restore classes from backup 
+                                            folder to classes folder -->
+                                        <copy toDir="target/classes" verbose="true" overwrite="true">
+                                            <fileset dir="target/cobertura/backup">
+                                                <include name="**/*.class" />
+                                            </fileset>
+                                        </copy>
+                                        <!-- delete backup folder -->
+                                        <delete dir="target/cobertura/backup" />
+                                        <!-- create a code coverage report -->
+                                        <cobertura-report format="html" datafile="${project.build.directory}/cobertura/cobertura.ser" destdir="${project.build.directory}/site/cobertura">
+                                            <fileset dir="${basedir}/src/main/java">
+                                                <include name="**/*.java" />
+                                            </fileset>
+                                        </cobertura-report>
+                                        <!-- delete cobertura.properties 
+                                            file -->
+                                        <delete file="target/classes/cobertura.properties" />
+                                    </tasks>
+                                </configuration>
+                                <goals>
+                                    <goal>run</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
+</project>
diff --git a/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/CodeCompletion.java b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/CodeCompletion.java
new file mode 100644
index 0000000..1569896
--- /dev/null
+++ b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/CodeCompletion.java
@@ -0,0 +1,29 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 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.scripting;
+
+/**
+ * TODO This will hook into the interactive code completion provided by the CLI.
+ *
+ * @author Lukas Krejci
+ */
+public interface CodeCompletion {
+
+}
diff --git a/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptEngineInitializer.java b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptEngineInitializer.java
new file mode 100644
index 0000000..3286f39
--- /dev/null
+++ b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptEngineInitializer.java
@@ -0,0 +1,80 @@
+/*
+ * 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 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.scripting;
+
+import java.lang.reflect.Method;
+import java.util.Set;
+
+import javax.script.ScriptEngine;
+import javax.script.ScriptException;
+
+/**
+ * Is able to instantiate a script engine and import packages into the context
+ * of the engine. 
+ *
+ * @author Lukas Krejci
+ */
+public interface ScriptEngineInitializer {
+
+    ScriptEngine instantiate(Set<String> packages) throws ScriptException;
+    
+    /**
+     * This function returns a definition string in the script engine's language
+     * that provides an indirection to calling the method on the bound object.
+     * 
+     * for example for parameters:
+     * <ul>
+     * <li> <code>boundObjectName = foo</code>
+     * <li> <code> method = &lt;int bar(int)&gt;</code>
+     * </ul>
+     * The method would generate this javascript:<br/>
+     * <code>
+     * function bar(arg) { return foo.bar(arg); }
+     * </code>
+     * <p>
+     * This method gets passed all the overloaded versions of a method on the object (i.e.
+     * all the methods with the same name) and is free to return any number of functions
+     * that will map all the possible overloaded versions.
+     * <p>
+     * This is because different scripting languages have different support for function
+     * overloading and different ways of handling varying number of arguments of a function.
+     *  
+     * @param boundObjectName
+     * @param overloadedMethods
+     * @return a set of strings with top-level function definitions in the scripting language
+     */
+    Set<String> generateIndirectionMethods(String boundObjectName, Set<Method> overloadedMethods);
+    
+    /**
+     * At least the Rhino script engine for java script generates exceptions
+     * whose error messages contain just "too much" information to be easily
+     * decipherable by the end users.
+     * <p>
+     * This method extracts messages from the exception such that they are
+     * presentable to the end user.
+     * <p>
+     * The returned string should only contain the error message. The filename, line
+     * and column information should be stripped from it if at all possible.
+     * 
+     * @param e
+     * @return
+     */
+    String extractUserFriendlyErrorMessage(ScriptException e);
+}
diff --git a/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptEngineProvider.java b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptEngineProvider.java
new file mode 100644
index 0000000..db22068
--- /dev/null
+++ b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptEngineProvider.java
@@ -0,0 +1,52 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 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.scripting;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * This is the service interface for scripting language implementations for RHQ
+ * (loaded using the META-INF/services mechanism).
+ *
+ * @author Lukas Krejci
+ */
+public interface ScriptEngineProvider {
+
+    /**
+     * @return the scripting language understood by this provider.
+     */
+    @NotNull
+    String getSupportedLanguage();
+
+    /**
+     * @return an implementation of {@link ScriptEngineInitializer} that can instantiate
+     * and initialize a script engine for the supported language for use with RHQ. 
+     */
+    @NotNull
+    ScriptEngineInitializer getInitializer();
+
+    /**
+     * @return a {@link CodeCompletion} implementation for the supported language or null
+     * if this provider doesn't provide one.
+     */
+    @Nullable
+    CodeCompletion getCodeCompletion();
+}
diff --git a/modules/enterprise/scripting/javascript/pom.xml b/modules/enterprise/scripting/javascript/pom.xml
new file mode 100644
index 0000000..bd0d585
--- /dev/null
+++ b/modules/enterprise/scripting/javascript/pom.xml
@@ -0,0 +1,187 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <artifactId>rhq-scripting-parent</artifactId>
+        <groupId>org.rhq</groupId>
+        <version>4.5.0-SNAPSHOT</version>
+    </parent>
+    <artifactId>rhq-scripting-javascript</artifactId>
+    <version>4.5.0-SNAPSHOT</version>
+    <name>RHQ Javascript support</name>
+    <description>Provides RHQ scripting in Javascript using Rhino</description>
+
+    <dependencies>
+       <dependency>
+          <groupId>${project.groupId}</groupId>
+          <artifactId>rhq-scripting-api</artifactId>
+          <version>${project.version}</version>
+       </dependency>
+       
+       <dependency>
+          <groupId>org.mozilla</groupId>
+          <artifactId>rhino</artifactId>
+          <version>1.7R3</version>
+       </dependency>
+    </dependencies>
+    
+    <build>
+        <plugins>
+            <plugin>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <configuration>
+                    <excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+    <profiles>
+
+        <profile>
+            <id>dev</id>
+
+            <properties>
+                <rhq.rootDir>../../..</rhq.rootDir>
+                <rhq.containerDir>${rhq.rootDir}/${rhq.defaultDevContainerPath}</rhq.containerDir>
+                <rhq.deploymentDir>${rhq.containerDir}/jbossas/server/default/deploy/${rhq.earName}/lib</rhq.deploymentDir>
+            </properties>
+
+            <build>
+                <plugins>
+
+                    <plugin>
+                        <artifactId>maven-antrun-plugin</artifactId>
+                        <version>1.1</version>
+                        <executions>
+
+                            <execution>
+                                <id>deploy</id>
+                                <phase>compile</phase>
+                                <configuration>
+                                    <tasks>
+                                        <mkdir dir="${rhq.deploymentDir}" />
+                                        <property name="deployment.file" location="${rhq.deploymentDir}/${project.build.finalName}.jar" />
+                                        <echo>*** Updating
+                                            ${deployment.file}...</echo>
+                                        <jar destfile="${deployment.file}" basedir="${project.build.outputDirectory}" />
+                                    </tasks>
+                                </configuration>
+                                <goals>
+                                    <goal>run</goal>
+                                </goals>
+                            </execution>
+
+                            <execution>
+                                <id>undeploy</id>
+                                <phase>clean</phase>
+                                <configuration>
+                                    <tasks>
+                                        <property name="deployment.file" location="${rhq.deploymentDir}/${project.build.finalName}.jar" />
+                                        <echo>*** Deleting
+                                            ${deployment.file}...</echo>
+                                        <delete file="${deployment.file}" />
+                                    </tasks>
+                                </configuration>
+                                <goals>
+                                    <goal>run</goal>
+                                </goals>
+                            </execution>
+
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+
+        <profile>
+            <id>cobertura-plugins</id>
+            <activation>
+                <activeByDefault>false</activeByDefault>
+            </activation>
+            <build>
+                <plugins>
+                    <plugin>
+                        <artifactId>maven-antrun-plugin</artifactId>
+                        <dependencies>
+                            <dependency>
+                                <groupId>net.sourceforge.cobertura</groupId>
+                                <artifactId>cobertura</artifactId>
+                                <version>1.9.4.1</version>
+                            </dependency>
+                        </dependencies>
+                        <executions>
+                            <execution>
+                                <id>cobertura-instrument</id>
+                                <phase>pre-integration-test</phase>
+                                <configuration>
+                                    <tasks>
+                                        <!-- prepare directory structure 
+                                            for cobertura -->
+                                        <mkdir dir="target/cobertura" />
+                                        <mkdir dir="target/cobertura/backup" />
+                                        <!-- backup all classes so that we 
+                                            can instrument the original classes -->
+                                        <copy toDir="target/cobertura/backup" verbose="true" overwrite="true">
+                                            <fileset dir="target/classes">
+                                                <include name="**/*.class" />
+                                            </fileset>
+                                        </copy>
+                                        <!-- create a properties file and 
+                                            save there location of cobertura data file -->
+                                        <touch file="target/classes/cobertura.properties" />
+                                        <echo file="target/classes/cobertura.properties">net.sourceforge.cobertura.datafile=${project.build.directory}/cobertura/cobertura.ser</echo>
+                                        <taskdef classpathref="maven.plugin.classpath" resource="tasks.properties" />
+                                        <!-- instrument all classes in target/classes 
+                                            directory -->
+                                        <cobertura-instrument datafile="${project.build.directory}/cobertura/cobertura.ser" todir="${project.build.directory}/classes">
+                                            <fileset dir="${project.build.directory}/classes">
+                                                <include name="**/*.class" />
+                                            </fileset>
+                                        </cobertura-instrument>
+                                    </tasks>
+                                </configuration>
+                                <goals>
+                                    <goal>run</goal>
+                                </goals>
+                            </execution>
+                            <execution>
+                                <id>cobertura-report</id>
+                                <phase>post-integration-test</phase>
+                                <configuration>
+                                    <tasks>
+                                        <taskdef classpathref="maven.plugin.classpath" resource="tasks.properties" />
+                                        <!-- prepare directory structure 
+                                            for cobertura -->
+                                        <mkdir dir="target/cobertura" />
+                                        <mkdir dir="target/site/cobertura" />
+                                        <!-- restore classes from backup 
+                                            folder to classes folder -->
+                                        <copy toDir="target/classes" verbose="true" overwrite="true">
+                                            <fileset dir="target/cobertura/backup">
+                                                <include name="**/*.class" />
+                                            </fileset>
+                                        </copy>
+                                        <!-- delete backup folder -->
+                                        <delete dir="target/cobertura/backup" />
+                                        <!-- create a code coverage report -->
+                                        <cobertura-report format="html" datafile="${project.build.directory}/cobertura/cobertura.ser" destdir="${project.build.directory}/site/cobertura">
+                                            <fileset dir="${basedir}/src/main/java">
+                                                <include name="**/*.java" />
+                                            </fileset>
+                                        </cobertura-report>
+                                        <!-- delete cobertura.properties 
+                                            file -->
+                                        <delete file="target/classes/cobertura.properties" />
+                                    </tasks>
+                                </configuration>
+                                <goals>
+                                    <goal>run</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
+</project>
diff --git a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineInitializer.java b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineInitializer.java
new file mode 100644
index 0000000..3ad2296
--- /dev/null
+++ b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineInitializer.java
@@ -0,0 +1,105 @@
+/*
+ * 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 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.scripting.javascript;
+
+import java.lang.reflect.Method;
+import java.util.Collections;
+import java.util.Set;
+
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+import javax.script.ScriptException;
+
+import org.rhq.scripting.ScriptEngineInitializer;
+
+/**
+ * 
+ *
+ * @author Lukas Krejci
+ */
+public class JsEngineInitializer implements ScriptEngineInitializer {
+
+    private static final String WRAPPED_EXCEPTION_PREFIX = "Wrapped ";
+
+    private ScriptEngineManager engineManager = new ScriptEngineManager();
+    
+    @Override
+    public ScriptEngine instantiate(Set<String> packages) throws ScriptException {
+        ScriptEngine eng = engineManager.getEngineByName("JavaScript");
+        
+        for(String pkg : packages) {
+            eng.eval("importPackage(" + pkg + ")");
+        }
+        
+        return eng;
+    }
+
+    @Override
+    public Set<String> generateIndirectionMethods(String boundObjectName, Set<Method> methods) {
+        if (methods.size() == 0) {
+            return Collections.emptySet();
+        }
+        
+        String methodName = methods.iterator().next().getName();
+                
+        StringBuilder functionBuilder = new StringBuilder("function ");
+        functionBuilder.append(methodName).append("() { switch(arguments.length) { ");
+        
+        for(Method method : methods) {
+            int argCnt = method.getParameterTypes().length;
+            functionBuilder.append("case ").append(argCnt).append(": ");
+            functionBuilder.append("return ").append(boundObjectName).append(".").append(methodName).append("(");
+            for(int i = 0; i < argCnt; ++i) {
+                if (i > 0) {
+                    functionBuilder.append(", ");
+                }
+                
+                functionBuilder.append("arguments[").append(i).append("]");
+            }
+            
+            functionBuilder.append("); break; ");
+        }
+        
+        functionBuilder.append(" default: throw \"Unsupported number of parameters.\"; } }");
+        
+        return Collections.singleton(functionBuilder.toString());
+    }
+    
+    @Override
+    public String extractUserFriendlyErrorMessage(ScriptException e) {
+        String errorMessage = e.getMessage();
+        
+        int wrappedIdx = errorMessage.lastIndexOf(WRAPPED_EXCEPTION_PREFIX);
+        
+        if (wrappedIdx < 0) {
+            return errorMessage;
+        }
+        
+        errorMessage = errorMessage.substring(wrappedIdx + WRAPPED_EXCEPTION_PREFIX.length());        
+        
+        int sourceInfoStartIdx = errorMessage.indexOf(" (<Unknown source>#");
+        
+        if (sourceInfoStartIdx >= 0) {
+            errorMessage = errorMessage.substring(0, sourceInfoStartIdx);
+        }
+        
+        return errorMessage;
+    }
+}
diff --git a/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineProvider.java b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineProvider.java
new file mode 100644
index 0000000..8d9e4b7
--- /dev/null
+++ b/modules/enterprise/scripting/javascript/src/main/java/org/rhq/scripting/javascript/JsEngineProvider.java
@@ -0,0 +1,49 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 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.scripting.javascript;
+
+import org.rhq.scripting.CodeCompletion;
+import org.rhq.scripting.ScriptEngineInitializer;
+import org.rhq.scripting.ScriptEngineProvider;
+
+/**
+ * 
+ *
+ * @author Lukas Krejci
+ */
+public class JsEngineProvider implements ScriptEngineProvider {
+
+    @Override
+    public String getSupportedLanguage() {
+        return "JavaScript";
+    }
+
+    @Override
+    public ScriptEngineInitializer getInitializer() {
+        return new JsEngineInitializer();
+    }
+
+    @Override
+    public CodeCompletion getCodeCompletion() {
+        // TODO copy this over from the CLI
+        return null;
+    }
+
+}
diff --git a/modules/enterprise/scripting/javascript/src/main/resources/META-INF/services/org.rhq.scripting.ScriptEngineProvider b/modules/enterprise/scripting/javascript/src/main/resources/META-INF/services/org.rhq.scripting.ScriptEngineProvider
new file mode 100644
index 0000000..1c55fe7
--- /dev/null
+++ b/modules/enterprise/scripting/javascript/src/main/resources/META-INF/services/org.rhq.scripting.ScriptEngineProvider
@@ -0,0 +1 @@
+org.rhq.scripting.javascript.JsEngineProvider
diff --git a/modules/enterprise/scripting/pom.xml b/modules/enterprise/scripting/pom.xml
new file mode 100644
index 0000000..92b72d4
--- /dev/null
+++ b/modules/enterprise/scripting/pom.xml
@@ -0,0 +1,34 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+   <modelVersion>4.0.0</modelVersion>
+   <parent>
+      <artifactId>rhq-enterprise-parent</artifactId>
+      <groupId>org.rhq</groupId>
+      <version>4.5.0-SNAPSHOT</version>
+   </parent>
+   <artifactId>rhq-scripting-parent</artifactId>
+   <packaging>pom</packaging>
+   
+   <version>4.5.0-SNAPSHOT</version>
+   <name>RHQ Scripting Parent Module</name>
+
+   <modules>
+      <module>api</module>
+      <module>factory</module>
+      <module>javascript</module>      
+   </modules>
+   
+   <profiles>
+      <profile>
+         <id>experimental</id>
+         <activation>
+            <property>
+               <name>experimental-script-languages</name>
+            </property>
+         </activation>
+         
+         <modules>
+            <module>python</module>
+         </modules>
+      </profile>
+   </profiles>
+</project>
diff --git a/modules/enterprise/server/plugins/alert-cli/src/main/java/org/rhq/enterprise/server/plugins/alertCli/CliSender.java b/modules/enterprise/server/plugins/alert-cli/src/main/java/org/rhq/enterprise/server/plugins/alertCli/CliSender.java
index da003f6..09dc8a5 100644
--- a/modules/enterprise/server/plugins/alert-cli/src/main/java/org/rhq/enterprise/server/plugins/alertCli/CliSender.java
+++ b/modules/enterprise/server/plugins/alert-cli/src/main/java/org/rhq/enterprise/server/plugins/alertCli/CliSender.java
@@ -43,7 +43,6 @@ import org.apache.commons.logging.LogFactory;
 import org.rhq.bindings.ScriptEngineFactory;
 import org.rhq.bindings.StandardBindings;
 import org.rhq.bindings.StandardScriptPermissions;
-import org.rhq.bindings.engine.ScriptEngineInitializer;
 import org.rhq.bindings.util.PackageFinder;
 import org.rhq.core.domain.alert.Alert;
 import org.rhq.core.domain.alert.notification.SenderResult;
@@ -61,6 +60,7 @@ import org.rhq.enterprise.server.content.RepoManagerLocal;
 import org.rhq.enterprise.server.plugin.pc.alert.AlertSender;
 import org.rhq.enterprise.server.plugin.pc.alert.AlertSenderValidationResults;
 import org.rhq.enterprise.server.util.LookupUtil;
+import org.rhq.scripting.ScriptEngineInitializer;
 
 /**
  * Uses CLI to perform the alert notification.




More information about the rhq-commits mailing list